微信V3支付

微信小程序支付

1.文档

文档内详细代码移步:https://github.com/ys-1998/WxPay/tree/main

微信官方文档:https://developers.weixin.qq.com/doc/

微信支付文档:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml

小程序接入前准备:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml

小程序接口文档:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml

SDK使用文档:https://github.com/wechatpay-apiv3/wechatpay-javawechatpay-java(推荐)】

SDK例子快速查看:https://github.com/wechatpay-apiv3/wechatpay-java/blob/main/service/src/example/java/com/wechat/pay/java/service/payments/jsapi/JsapiServiceExample.java 【下单 关单 订单查询 】

2.流程

文档说明:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml

1.申请小程序 获取小程序的[appid,secret]
2.申请商户号 获取[1. mchid(商户号)  2. apiV3key(apiv3密钥) 3.merchantSerialNumber(证书序列号) 4.申请证书]
3.绑定小程序和商户号

3.开发

Maven依赖

<dependency>
  <groupId>com.github.wechatpay-apiv3</groupId>
  <artifactId>wechatpay-java</artifactId>
  <version>0.2.7</version>
</dependency>

配置类

1.配置类填入我们需要的参数方便后续使用
yourServiceName:
  wx:
    appid: wx33ca5310e9xxx 小程序appid
    secret: 10c61a693ced428b6e583xxxxxx 小程序密钥
    token-grant-type: client_credential 小程序接口调用凭证请求参数固定值
    token-url: https://api.weixin.qq.com/cgi-bin/token 小程序接口调用凭证请求地址
    pay:
      mchid: xxxx 商户号
      apiV3key:  xxxx apiV3密钥
      merchantSerialNumber:  商户证书序列号
      privateKeyPath: xxxx 存放证书密钥apiclient_key.pem的路径:文档结尾有推荐写法
      notifyUrl: xxxx 支付回调接口

工具类

注:详细内容请见上传的文件

WxUtil:获取(接口调用凭证token)用于获取用户的信息,获取用户手机号,获取openid用于支付

获取用户手机号:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html

获取接口调用凭证token:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html

获取用户openid:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/basic-info/getPluginOpenPId.html

@Data
@Component
@ConfigurationProperties(prefix = "cateen.wx")
@Slf4j
public class WxUtil {
    private String appid;
    private String secret;
    private String tokenGrantType;
    private String tokenUrl;
    private String token;
    private final RestTemplate restTemplate;


    /**
     * 注意需要定时任务刷新token
     *wx获取接口调用凭证 返回数据示例
     * {
     * "access_token":"ACCESS_TOKEN",
     * "expires_in":7200
     * }
     * @return
     */
    public String getToken() {
        //xxxx
    }

    /**
     * wx获取手机号返回数据示例
     * {
     *     "errcode":0,
     *     "errmsg":"ok",
     *     "phone_info": {
     *         "phoneNumber":"xxxxxx",
     *         "purePhoneNumber": "xxxxxx",
     *         "countryCode": 86,
     *         "watermark": {
     *             "timestamp": 1637744274,
     *             "appid": "xxxx"
     *         }
     *     }
     * }
     */
    public String getUserPhoneNumber(String code) {
        //xxx
    }
    
    /**
     * wx获取用户openid
     * {
     *  "errcode": 0,
     *  "errmsg": "ok",
     *  "openpid": "GACo74wkDIkDzEhkwRwgjGt1pqlk",
     * }
     * @param code
     * @return
     */
    public String wxLoginOpenid(String code) {
        //xxxx
    }


}
SpringUtil:用于获取spring容器中的bean
@Component
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext = null;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtil.applicationContext = applicationContext;
    }

    public static <T> T getBean(Class<T> cla) {
        return applicationContext.getBean(cla);
    }

    public static <T> T getBean(String name, Class<T> cal) {
        return applicationContext.getBean(name, cal);
    }

    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    public static String getProperty(String key) {
        return applicationContext.getBean(Environment.class).getProperty(key);
    }

    public static <T> T getProperty(String key, Class<T> targetType) {
        return applicationContext.getBean(Environment.class).getProperty(key, targetType);
    }
}

定时任务

用于刷新接口调用凭据token:注意,token有效期为7200s

说明文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html

@Component
public class Jobs {
    private final WxUtil wxUtil;

    public Jobs(WxUtil wxUtil) {
        this.wxUtil = wxUtil;
    }

    @Scheduled(fixedRate = 60 * 60 * 1000)
    public void refreshToken() {
        wxUtil.getToken();
    }

}

Service

import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import work.yspan.jadeplaces.yspan.work.models.response.BaseResult;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
public interface WeChatPayService {
	//支付
    PrepayWithRequestPaymentResponse pay(BigDecimal bigDecimal,String orderNumber,String description,String notifyUrl,String attach,String code);
	//回调
    Transaction callback(HttpServletRequest request, HttpServletResponse response) throws IOException;
	//微信订单号查询订单
    Transaction findOrderDetails(String wxOrderNo);
	//商户号查询订单
    Transaction findOrderDetailsByOrderNumber(String orderNumber);
	//关单
    BaseResult<?> closeOrder(String canteenOrderNo);
}

ServiceImpl

详情请见上传的文件

import com.alibaba.fastjson2.JSON;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import work.yspan.jadeplaces.yspan.work.mapper.CateenOrderMapper;//自定义的订单类用于查询订单,删除订单
import work.yspan.jadeplaces.yspan.work.models.response.BaseResult;//自定义的返回类
import work.yspan.jadeplaces.yspan.work.service.WeChatPayService;
import work.yspan.jadeplaces.yspan.work.util.components.SpringUtil;
import work.yspan.jadeplaces.yspan.work.util.components.WxUtil;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.math.BigDecimal;

@Slf4j
@Service
public class WeChatPayServiceImpl implements WeChatPayService {

    @Resource
    private WxUtil wxUtil;

    /**
     * 商户号
     */
    @Value("${cateen.wx.pay.mchid}")
    public String merchantId;

	/**
     * 小程序 appid
     */
    @Value("${cateen.wx.appid}")
    public String appid;


    @Resource
    private CateenOrderMapper cateenOrderMapper;

    @Override
    public PrepayWithRequestPaymentResponse pay(BigDecimal bigDecimal, String orderNumber,String description,String notifyUrl,String attach,String code) {
		
    }
    
	@Override
    public Transaction callback(HttpServletRequest request, HttpServletResponse response) throws IOException {
		//xxxx
    }

    @Override
    public Transaction findOrderDetails(String wxOrderNo) {
		//xxxxx
    }

    public Transaction findOrderDetailsByOrderNumber(String orderNumber) {
        //xxxx
    }

    @Override
    public BaseResult<?> closeOrder(String canteenOrderNo) {
        //xxxx
    }
}

4.打包发布

推荐:证书密钥放在与src同级目录下新建的目录key

地址填写:./key/apiclient_key.pem

上传服务器:记得也将证书密钥文件apiclient_key.pem上传至与jar包相同的位置

findOrderDetailsByOrderNumber(String orderNumber) {
        //xxxx
    }

    @Override
    public BaseResult<?> closeOrder(String canteenOrderNo) {
        //xxxx
    }
}

4.打包发布

推荐:证书密钥放在与src同级目录下新建的目录key

地址填写:./key/apiclient_key.pem

上传服务器:记得也将证书密钥文件apiclient_key.pem上传至与jar包相同的位置

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值