当前位置:   article > 正文

微信支付-开发教程_微信支付开发

微信支付开发

一、JDK版本需要1.8u162+以上版本

  1. <!--微信支付 V3-->
  2. <dependency>
  3. <groupId>com.github.wechatpay-apiv3</groupId>
  4. <artifactId>wechatpay-java</artifactId>
  5. <version>0.2.7</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>com.github.wechatpay-apiv3</groupId>
  9. <artifactId>wechatpay-apache-httpclient</artifactId>
  10. <version>0.4.9</version>
  11. </dependency>

二、前期准备

官网引导:接入前准备-小程序支付 | 微信支付商户平台文档中心

①appid:小程序appid-登录小程序后台获取

②secret:小程序密钥-登录小程序后台获取

登录小程序后台:

③appV3Secret:商户apiV3密钥-登录商户后台获取

④mchid:商户号-登录商户后台获取(商户号要绑定小程序)

⑤certpath:微信平台证书-登录商户后台获取

⑥privateKeyPath:商户私钥证书-登录商户后台获取

⑦merchantSerialNumber:商户证书序列化-登录商户后台获取

登录商户后台:

三、证书存放地

四、配置与加载

  1. # application-dev.yml
  2. wx:
  3. miniapp:
  4. configs:
  5. - appid: wx1fcxxxxxxxx
  6. secret: 1exxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  7. token: #微信小程序消息服务器配置的token
  8. aesKey: #微信小程序消息服务器配置的EncodingAESKey
  9. msgDataFormat: JSON
  10. appV3Secret: ADxxxAas654xxxxxxxxxxxxxxxxxx # V3密钥
  11. mchid: 12345678 # 商户号
  12. certpath: D:/workspace/hxj-miniprogram-java/src/main/resources/wxpay/apiclient_cert.pem # 微信平台证书(发布时换成linux地址)
  13. privateKeyPath: D:/workspace/hxj-miniprogram-java/src/main/resources/wxpay/apiclient_key.pem # 商户私钥证书(发布时换成linux地址)
  14. payCallBackUrl: https://xxxxxxxxxxxxx/wechatPay/payCallback # 支付结束回调地址
  15. timeExpire: 1200000 # 交易过期时间(单位毫秒)
  16. merchantSerialNumber: 37ABCD098765ADCBF124656099AB # 商户证书序列号
  1. import lombok.Data;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. import java.util.List;
  5. /**
  6. * @author xuhj
  7. */
  8. @Slf4j
  9. @Data
  10. @ConfigurationProperties(prefix = "wx.miniapp")
  11. public class WxMaProperties {
  12. private List<Config> configs;
  13. @Data
  14. public static class Config {
  15. /**
  16. * 设置微信小程序的appid
  17. */
  18. private String appid;
  19. /**
  20. * 设置微信小程序的Secret
  21. */
  22. private String secret;
  23. /**
  24. * 设置微信小程序消息服务器配置的token
  25. */
  26. private String token;
  27. /**
  28. * 设置微信小程序消息服务器配置的EncodingAESKey
  29. */
  30. private String aesKey;
  31. /**
  32. * 消息格式,XML或者JSON
  33. */
  34. private String msgDataFormat;
  35. /**
  36. * appV3Secret V3密钥
  37. */
  38. private String appV3Secret;
  39. /**
  40. * mchid 商户号
  41. */
  42. private String mchid;
  43. /**
  44. * 微信支付平台证书地址,注意 windows地址与linux地址不同
  45. */
  46. private String certpath;
  47. /**
  48. * 商户API证书的路径(一般和上边的certpath在一起下载)
  49. */
  50. private String privateKeyPath;
  51. /**
  52. * 支付回调地址
  53. */
  54. private String payCallBackUrl;
  55. /**
  56. * 交易过期时间(单位毫秒)
  57. */
  58. private Long timeExpire;
  59. /**
  60. * 商户证书序列号
  61. */
  62. private String merchantSerialNumber;
  63. }
  64. }

五、证书自动更新

  1. import com.wechat.pay.java.core.RSAAutoCertificateConfig;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. @Configuration
  6. public class WxPayConfig {
  7. @Autowired
  8. private WxMaProperties properties;
  9. /**
  10. * 初始化商户配置(只能加载一次)
  11. * 确保是单例
  12. *
  13. * @return
  14. */
  15. @Bean
  16. public RSAAutoCertificateConfig rsaAutoCertificateConfig() {
  17. RSAAutoCertificateConfig config = new RSAAutoCertificateConfig.Builder()
  18. .merchantId(properties.getConfigs().get(0).getMchid())
  19. .privateKeyFromPath(properties.getConfigs().get(0).getPrivateKeyPath())
  20. .merchantSerialNumber(properties.getConfigs().get(0).getMerchantSerialNumber())
  21. .apiV3Key(properties.getConfigs().get(0).getAppV3Secret())
  22. .build();
  23. return config;
  24. }
  25. }

六、预支付和回调

  1. import com.wechat.pay.java.core.Config;
  2. import com.wechat.pay.java.core.RSAAutoCertificateConfig;
  3. import com.wechat.pay.java.core.notification.NotificationConfig;
  4. import com.wechat.pay.java.core.notification.NotificationParser;
  5. import com.wechat.pay.java.core.notification.RequestParam;
  6. import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
  7. import com.wechat.pay.java.service.payments.jsapi.model.*;
  8. import com.wechat.pay.java.service.payments.model.Transaction;
  9. import io.swagger.annotations.Api;
  10. import io.swagger.annotations.ApiImplicitParam;
  11. import io.swagger.annotations.ApiImplicitParams;
  12. import io.swagger.annotations.ApiOperation;
  13. import lombok.extern.slf4j.Slf4j;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.util.Assert;
  16. import org.springframework.validation.annotation.Validated;
  17. import org.springframework.web.bind.annotation.PostMapping;
  18. import org.springframework.web.bind.annotation.RequestMapping;
  19. import org.springframework.web.bind.annotation.RestController;
  20. import javax.servlet.http.HttpServletRequest;
  21. import java.io.IOException;
  22. import java.util.List;
  23. import static com.wechat.pay.contrib.apache.httpclient.constant.WechatPayHttpHeaders.WECHAT_PAY_SIGNATURE;
  24. import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_NONCE;
  25. import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_TIMESTAMP;
  26. /**
  27. * <p>
  28. * 微信支付 前端控制器
  29. * </p>
  30. *
  31. * @author sunziwen
  32. * @since 2023-03-23
  33. */
  34. @Api(tags = {"微信支付"})
  35. @Slf4j
  36. @RestController
  37. @RequestMapping("/wechatPay")
  38. @Validated
  39. public class PayController extends BaseController {
  40. /**
  41. * 配置文件
  42. */
  43. @Autowired
  44. private WxMaProperties properties;
  45. @Autowired
  46. private RSAAutoCertificateConfig rsaAutoCertificateConfig;
  47. @Autowired
  48. private IOrderMasterService iOrderMasterService;
  49. @ApiOperation(value = "预支付-委托")
  50. @PostMapping("preparePayment")
  51. @ApiImplicitParams({
  52. @ApiImplicitParam(name = "openid", value = "openid"),
  53. @ApiImplicitParam(name = "description", value = "商品描述"),
  54. @ApiImplicitParam(name = "outTradeNo", value = "商户订单号"),
  55. @ApiImplicitParam(name = "total", value = "订单总金额,单位为分")
  56. })
  57. public ServiceResult<?> preparePayment(String openid, String description, String outTradeNo, Integer total) {
  58. // 初始化服务
  59. JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).build();
  60. PrepayRequest request = new PrepayRequest();
  61. // 应用ID
  62. request.setAppid(properties.getConfigs().get(0).getAppid());
  63. // 直连商户号
  64. request.setMchid(properties.getConfigs().get(0).getMchid());
  65. // 商品描述
  66. request.setDescription(description);
  67. // 商户订单号
  68. request.setOutTradeNo(outTradeNo);
  69. // 交易结束时间:2018-06-08T10:34:56+08:00
  70. request.setTimeExpire(timeStampToRfc3339(System.currentTimeMillis() + properties.getConfigs().get(0).getTimeExpire()));
  71. // 附加数据:在查询API和支付通知中原样返回,可作为自定义参数使用
  72. request.setAttach("");
  73. // 回调地址:异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 公网域名必须为https
  74. request.setNotifyUrl(properties.getConfigs().get(0).getPayCallBackUrl());
  75. // 商品标记,代金券或立减优惠功能的参数
  76. request.setGoodsTag("");
  77. // 限制支付类型
  78. // request.setLimitPay(LimitPayEnum.);
  79. // 电子发票入口开放标识:传入true时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效
  80. request.setSupportFapiao(true);
  81. Amount amount = new Amount();
  82. amount.setTotal(total);
  83. amount.setCurrency("CNY");
  84. // 订单金额信息
  85. request.setAmount(amount);
  86. Payer payer = new Payer();
  87. payer.setOpenid(openid);
  88. // 支付者信息
  89. request.setPayer(payer);
  90. // 优惠功能
  91. request.setDetail(null);
  92. // 支付场景描述
  93. request.setSceneInfo(null);
  94. // 结算信息
  95. request.setSettleInfo(null);
  96. PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
  97. //重复支付判断TODO
  98. // 存储预付订单信息 TODO
  99. log.info("发起预支付成功-" + response.toString());
  100. return success(response);
  101. }
  102. @ApiOperation(value = "预支付-回调(或退款)")
  103. @RequestMapping("payCallback")
  104. public synchronized String payCallback(HttpServletRequest request) throws IOException {
  105. log.info("收到支付回调-------------");
  106. // 请求头Wechatpay-nonce
  107. String nonce = request.getHeader(WECHAT_PAY_NONCE);
  108. // 请求头Wechatpay-Timestamp
  109. String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP);
  110. // 请求头Wechatpay-Signature
  111. String signature = request.getHeader(WECHAT_PAY_SIGNATURE);
  112. // 微信支付证书序列号 TODO 这里千万不能搞错,不能是商家证书序列号!!!
  113. String serial = request.getHeader("Wechatpay-Serial");
  114. // 签名方式
  115. String signType = request.getHeader("Wechatpay-Signature-Type");
  116. // 构造 RequestParam
  117. RequestParam requestParam = new RequestParam.Builder()
  118. .serialNumber(serial) // TODO 不能搞错!!!
  119. .nonce(nonce)
  120. .signature(signature)
  121. .timestamp(timestamp)
  122. .signType(signType)
  123. .body(getRequestBody())
  124. .build();
  125. // 初始化 NotificationParser
  126. NotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);
  127. // 以支付通知回调为例,验签、解密并转换成 Transaction
  128. log.info("验签参数:" + requestParam);
  129. Transaction transaction = parser.parse(requestParam, Transaction.class);
  130. log.info("验签成功!-支付回调结果:" + transaction.toString());
  131. // RefundNotification refundNotification = parser.parse(requestParam, RefundNotification.class);
  132. // 修改订单之前,主动去微信支付主动查询订单是否已经支付成功,这一步不能少,防止有人假冒主动post接口。
  133. /**
  134. * 收到支付成功的回调:这里进行处理业务
  135. */
  136. // List<OrderMaster> orderMasters = iOrderMasterService.lambdaQuery().eq(OrderMaster::getOrderNo, transaction.getOutTradeNo()).list();
  137. // Assert.isTrue(orderMasters.size() == 1, "根据订单编号未查到订单OR查到了多个订单!!!");
  138. // if (Transaction.TradeStateEnum.SUCCESS.equals(transaction.getTradeState())) {
  139. // //支付成功 0待付款1待发货2待收货3已完成4已取消
  140. // orderMasters.get(0).setBuyStatus(1);
  141. // // 1待送仓2待打款3已完成4已取消
  142. // orderMasters.get(0).setSaleStatus(1);
  143. // // 1现金,2余额,3网银,4支付宝,5微信
  144. // orderMasters.get(0).setPaymentMethod(5);
  145. // return "{\"code\": \"FAIL\",\"message\": \"失败\"}";
  146. // } else {
  147. // log.info("支付未成功:" + transaction.getTradeState());
  148. // }
  149. // // TODO 存储支付流水
  150. return "{\"code\": \"FAIL\",\"message\": \"失败\"}";
  151. }
  152. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/627898
推荐阅读
相关标签
  

闽ICP备14008679号