JVAV-SDK方式实现微信小程序支付接入

JVAV-SDK方式实现微信小程序支付接入

微信接入文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml

一、获取小程序与支付的接入前准备

1.获取小程序appid

微信小程序后台获取地址 (qq.com)

在这里插入图片描述

2.获取微信支付商户号、证书、密钥

微信支付 - 获取商户号

这里获取因为某些原因就不展示截屏了,下面这个微信文档的接入准备将的很详细

接入前准备-小程序支付

获取证书文档

什么是商户API证书?如何获取商户API证书

我用的是APIV3支付密钥,看自己业务

什么是APIv3密钥?如何设置?

二、后台接入配置

1.yml配置

wx:
    #微信公众号或者小程序等的appid
    appId: xxxxxxxxxxxxxxxxxx
    #应用密钥
    appSecret: xxxxxxxxxxxxxxxxxx
    #微信支付商户号
    merchantId: xxxxxxxxxxxxxxxxxx
    #微信支付商户密钥
    mchKey: xxxxxxxxxxxxxxxxxx
    #商户证书目录
    keyPath: xxxxxxxxxxxxxxxxxx
    #商户API私钥路径 部署到centos后 /etc/wx-pay/apiclient_cert.pem
    privateKeyPath: C:\Users\admin\Desktop\wx\apiclient_cert.pem
    #商户API密钥证书路径 部署到centos后 /etc/wx-pay/apiclient_key.pem
    wechatPayCertificatePath: C:\Users\admin\Desktop\wx\apiclient_key.pem
    #商户证书序列号
    merchantSerialNumber: xxxxxxxxxxxxxxxxxx
    #商户APIV3密钥
    apiV3Key: xxxxxxxxxxxxxxxxxx

2.实体注入配置

@Data
@Primary //覆盖 当有多个这个的WxPayProperties实现类 注入这个
@Configuration()
@PropertySource("classpath:application.yml") //读取配置文件
@ConfigurationProperties(prefix = "wx")
public class WXProperties {
    /** appId : 微信公众号或者小程序等的appid */
    private  String appId;
    /** appSecret : 应用密钥 */
    private  String appSecret;
    /** mchId : 微信支付商户号 */
    private  String merchantId;
    /** mchKey : 微信支付商户密钥 */
    private  String mchKey;
    /** mchKey : 商户证书目录 */
    private  String keyPath ;
    /**商户API私钥路径*/
    private  String privateKeyPath ;
    /**商户API密钥证书路径*/
    private  String wechatPayCertificatePath ;
    /** 商户证书序列号*/
    private  String merchantSerialNumber ;
    /**商户APIV3密钥*/
    private  String apiV3Key ;

}

3.pom依赖

官网GitHub地址,里面的文档可以仔细阅读一下,很有帮助

微信支付 APIv3 的官方 Java Library

使用 SDK 不需要计算请求签名和验证应答签名。详细代码可从 QuickStart 获得。

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

4.微信支付配置

(1)RSAConfig配置
  public static String merchantId = "";
  public static String privateKeyPath = "";
  public static String merchantSerialNumber = "";
  public static String wechatPayCertificatePath = "";
  
  public static void main(String[] args) {
    // 初始化商户配置
    RSAConfig config =
        new RSAConfig.Builder()
            .merchantId(merchantId)
            // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
            .privateKeyFromPath(privateKeyPath)
            .merchantSerialNumber(merchantSerialNumber)
            .wechatPayCertificatesFromPath(wechatPayCertificatePath)
            .build();
  }

(2)RSAAutoCertificateConfig配置(我自己用的配置)
    @Resource
    private WXProperties wxProperties;

    private RSAAutoCertificateConfig rsaAutoCertificateConfig=null;

    public static void main(String[] args) {
        // 初始化商户配置
        RSAAutoCertificateConfig config =
                        new RSAAutoCertificateConfig.Builder()
                                .merchantId(wxProperties.getMerchantId())
                                // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
//                        .privateKeyFromPath(wxProperties.getPrivateKeyPath())
                                .privateKeyFromPath(wxProperties.getWechatPayCertificatePath())
                                .merchantSerialNumber(wxProperties.getMerchantSerialNumber())
//                        .wechatPayCertificatesFromPath(wechatPayCertificatePath)
                                .apiV3Key(wxProperties.getApiV3Key())
                                .build();
    }

这两种配置选择一种,客服人员好像说不能两种同事使用,会抛异常

并且使用这两个配置中的一个那抹这个配置必须为单例的

本人写的方法,虽然懒,无所谓,刚出来的能多强啊
@Component
public class WXPayConfig {
    @Resource
    private WXProperties wxProperties;

    private RSAAutoCertificateConfig rsaAutoCertificateConfig=null;


    private synchronized RSAAutoCertificateConfig rsaAutoCertificateConfig(){
        if (rsaAutoCertificateConfig==null) {
            synchronized (Object.class) {
                // 初始化商户配置
                rsaAutoCertificateConfig =
                        new RSAAutoCertificateConfig.Builder()
                                .merchantId(wxProperties.getMerchantId())
                                // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
//                        .privateKeyFromPath(wxProperties.getPrivateKeyPath())
                                .privateKeyFromPath(wxProperties.getWechatPayCertificatePath())
                                .merchantSerialNumber(wxProperties.getMerchantSerialNumber())
//                        .wechatPayCertificatesFromPath(wechatPayCertificatePath)
                                .apiV3Key(wxProperties.getApiV3Key())
                                .build();
            }
        }
        return this.rsaAutoCertificateConfig;
    }

    /**
     * 转账到零钱
     * @return
     */
    public TransferBatchService transferBatchService(){
        TransferBatchService build = new TransferBatchService.Builder().config(rsaAutoCertificateConfig()).build();
        return build;
    }

    /**
     * 回调解析
     * @return
     */
    public NotificationParser notificationParser(){
        NotificationParser build = new NotificationParser(rsaAutoCertificateConfig());
        return build;
    }

    /**
     * js下单
     * @return
     */
    public JsapiServiceExtension jsapiServiceExtension(){
        JsapiServiceExtension build = new JsapiServiceExtension.Builder()
                .config(rsaAutoCertificateConfig())
                .signType("RSA")
                .build();
        return build;
    }

三、我自己业务的支付实现

JS API 下单
controller
    @Resource
    private TransactionService transactionService;

    /**
     * 用户充值下单
     *
     * @param rechargeInfoLog 自己的业务充值记录表信息
     * @return 微信支付API返回的对象,用于前端支付发起
     */
    @PostMapping("/placeAnOrder")
    private Result placeAnOrder(@Validated RechargeInfoLog rechargeInfoLog, String openid) {
        Map<String, Object> map = transactionService.placeAnOrder(rechargeInfoLog, openid);
        PrepayWithRequestPaymentResponse response = (PrepayWithRequestPaymentResponse) map.get("response");
        return response == null ? error() : success(map);
    }
service

    @Resource
    private WXProperties wxProperties;
    @Resource
    private WXPayConfig wxPayConfig;


/**
 * 充值下单
 *
 * @param recharge
 */
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String,Object> placeAnOrder(RechargeInfoLog recharge, String openid) {
    Map<String,Object> map = new HashMap<>();
    PrepayWithRequestPaymentResponse response = null;
    try {
        /** 自己的业务逻辑*/
        // ... 调用接口
        /** Amount 金额  
        orderNum 自己业务系统的订单号
        description 订单描述
        openid 用户openid
        notifyUrl 回调地址https */
        response = prepayWithRequestPayment(Amount,
                orderNum,
                description,
                openid,
                "https://localhost/callback");
        log.info(response.toString());
        map.put("response",response);
        map.put("orderId",orderNum);
    } catch (HttpException e) { // 发送HTTP请求失败
        // 调用e.getHttpRequest()获取请求打印日志或上报监控,更多方法见HttpException定义
    } catch (com.wechat.pay.java.core.exception.ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
        // 调用e.getResponseBody()获取返回体打印日志或上报监控,更多方法见ServiceException定义
    } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
        // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义
    }
    return map;
}




    /**
     * JSAPI支付下单,并返回JSAPI调起支付数据
      payAmount 金额 单位分  
        orderId 自己业务系统的订单号
        description 订单描述
        openid 用户openid
        notifyUrl 回调地址https
     */

private PrepayWithRequestPaymentResponse prepayWithRequestPayment(int payAmount, 
                                                                  @NotBlank String orderId, 
                                                                  @NotBlank String description, 
                                                                  String openid, 
                                                                  String notifyUrl) {
    	//微信支付SDK请求参数
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(payAmount);
        Payer payer = new Payer();
        payer.setOpenid(openid);
        request.setAppid(wxProperties.getAppId());
        request.setOutTradeNo(orderId);
        request.setMchid(wxProperties.getMerchantId());
        request.setDescription(description);
        request.setNotifyUrl(notifyUrl);
        request.setAmount(amount);
        request.setPayer(payer);
        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
        // 调用接口
        return wxPayConfig.jsapiServiceExtension().prepayWithRequestPayment(request);
    }

支付回调
controller
/**
 * 商户订单号查询订单
 */
@PostMapping("/callback")
public String wxPaySuccessCallback(HttpServletRequest request, HttpServletResponse response) {
    String msg = transactionService.wxPaySuccessCallback(request, response);
    return msg;
}
支付查询与关闭
service

 /**
     * 微信支付订单号查询订单
     */
    public Transaction queryOrderById(String wxTransactionId) {
    //微信支付SDK请求参数
        QueryOrderByIdRequest request = new QueryOrderByIdRequest();
        request.setMchid(wxProperties.getMerchantId());
        request.setTransactionId(wxTransactionId);
        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
        // 调用接口
        return wxPayConfig.jsapiServiceExtension().queryOrderById(request);
    }

    /**
     * 商户订单号查询订单
     */
    public Transaction queryOrderByOutTradeNo(String outTradeNo) {
        //微信支付SDK请求参数
        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
        request.setMchid(wxProperties.getMerchantId());
        request.setOutTradeNo(outTradeNo);
        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
        // 调用接口
        return wxPayConfig.jsapiServiceExtension().queryOrderByOutTradeNo(request);
    }

    /**
     * 关闭订单
     */
    public void closeOrder(String outTradeNo) {
        CloseOrderRequest request = new CloseOrderRequest();
        request.setMchid(wxProperties.getMerchantId());
        request.setOutTradeNo(outTradeNo);
        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
        // 调用接口
        wxPayConfig.jsapiServiceExtension().closeOrder(request);
    }


我的回调因为有点问题,我这边暂时做了一个订单处理接口,

前端支付完成或者取消支付去调用该业务接口处理该订单

@Override
public boolean handleOrderByNo(String orderId) {
    boolean flag = false;
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    //调用微信查询订单api
    Transaction transaction = queryOrderByOutTradeNo(orderId);
    //判罚支付结果
    if (transaction.getTradeState().equals(Transaction.TradeStateEnum.SUCCESS)) {
        flag = handleOrder(transaction);
    }eles{
        //自己业务需求eg:
        closeOrder(transaction.getOutTradeNo());
    }
    return flag;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值