当前位置:   article > 正文

springboot 小程序微信支付_springboot微信小程序支付

springboot微信小程序支付

看效果

 

参考文章:SpringBoot + 小程序 整合微信支付和退款 V2版 - 码农教程

本文仅作记录

参考文章: UniApp + SpringBoot 实现微信支付和退款 - 奔跑的砖头 - 博客园

Springboot整合支付宝支付参考: UniApp + SpringBoot 实现支付宝支付和退款 - 奔跑的砖头 - 博客园

一、开发前提

  • 微信支付商户号接入微信支付
  • 商户号绑定对应的小程序
  • 获取对应的 信息
    • 开放平台: appId
    • 商户号: mchId
    • 商户秘钥: mchKey
    • p12证书:
    • apiclient_key.pem证书文件

官方网站: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

二、Springboot整合微信支付

2.1 导入基本的pom依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. </dependency>
  5. <!-- 微信支付坐标 start-->
  6. <dependency>
  7. <groupId>com.github.binarywang</groupId>
  8. <artifactId>weixin-java-pay</artifactId>
  9. <version>4.2.5.B</version>
  10. </dependency>
  11. <!-- 退款用 -->
  12. <dependency>
  13. <groupId>org.jodd</groupId>
  14. <artifactId>jodd-http</artifactId>
  15. <version>6.0.8</version>
  16. </dependency>
  17. <!-- 微信支付坐标 end-->
  18. <dependency>
  19. <groupId>org.springframework.boot</groupId>
  20. <artifactId>spring-boot-configuration-processor</artifactId>
  21. <optional>true</optional>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.projectlombok</groupId>
  25. <artifactId>lombok</artifactId>
  26. <optional>true</optional>
  27. </dependency>

2.2 在 application.yml 中添加配置

回调地址 我这里使用 ngrok内网穿透 官网: ngrok - Online in One Line

  1. # 服务启动端口
  2. server:
  3. port: 8081
  4. # 微信pay相关
  5. wxpay:
  6. # appId
  7. appId: # 自己的appId
  8. # 商户id
  9. mchId: # 自己的商户id
  10. # 商户秘钥
  11. mchKey: # 商户秘钥
  12. # p12证书文件的绝对路径或者以classpath:开头的类路径.
  13. keyPath: classpath:/wxpay_cert/apiclient_cert.p12
  14. privateKeyPath: classpath:/wxpay_cert/apiclient_key.pem
  15. privateCertPath: classpath:/wxpay_cert/apiclient_cert.pem
  16. # 微信支付的异步通知接口
  17. # 我这里使用的ngrok内网穿透
  18. notifyUrl: https://bfb3-221-237-148-6.ap.ngrok.io/wechat/pay/notify
  19. # 退款回调地址
  20. refundNotifyUrl: https://bfb3-221-237-148-6.ap.ngrok.io/wechat/pay/refund_notify

2.3 创建配置文件对应的 配置类

  1. package com.system.system.config;
  2. import lombok.Data;
  3. import org.springframework.boot.context.properties.ConfigurationProperties;
  4. @Data
  5. @ConfigurationProperties(prefix = "wxpay")
  6. public class WechatPayConfig {
  7. private String appId;
  8. private String mchId;
  9. private String mchKey;
  10. private String keyPath;
  11. private String privateKeyPath;
  12. private String privateCertPath;
  13. private String notifyUrl;
  14. }

2.4 在service层 创建 BizWechatPayService类

  1. package com.system.system.service.impl;
  2. import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
  3. import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
  4. import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
  5. import com.github.binarywang.wxpay.config.WxPayConfig;
  6. import com.github.binarywang.wxpay.constant.WxPayConstants;
  7. import com.github.binarywang.wxpay.exception.WxPayException;
  8. import com.github.binarywang.wxpay.service.WxPayService;
  9. import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
  10. import lombok.AllArgsConstructor;
  11. import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
  12. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  13. import org.springframework.stereotype.Service;
  14. import java.net.InetAddress;
  15. /**
  16. * 微信支付
  17. */
  18. @Service
  19. @ConditionalOnClass(WxPayService.class)
  20. @EnableConfigurationProperties(WechatPayConfig.class)
  21. @AllArgsConstructor
  22. public class BizWechatPayService {
  23. private WechatPayConfig wechatPayConfig;
  24. public WxPayService wxPayService() {
  25. WxPayConfig payConfig = new WxPayConfig();
  26. payConfig.setAppId(wechatPayConfig.getAppId());
  27. payConfig.setMchId(wechatPayConfig.getMchId());
  28. payConfig.setMchKey(wechatPayConfig.getMchKey());
  29. payConfig.setKeyPath(wechatPayConfig.getKeyPath());
  30. payConfig.setPrivateKeyPath(wechatPayConfig.getPrivateKeyPath());
  31. payConfig.setPrivateCertPath(wechatPayConfig.getPrivateCertPath());
  32. // 可以指定是否使用沙箱环境
  33. payConfig.setUseSandboxEnv(false);
  34. payConfig.setSignType("MD5");
  35. WxPayService wxPayService = new WxPayServiceImpl();
  36. wxPayService.setConfig(payConfig);
  37. return wxPayService;
  38. }
  39. /**
  40. * 创建微信支付订单
  41. *
  42. * @param productTitle 商品标题
  43. * @param outTradeNo 订单号
  44. * @param totalFee 总价
  45. * @param openId openId
  46. * @return
  47. */
  48. public Object createOrder(String productTitle, String outTradeNo, Integer totalFee, String openId) {
  49. try {
  50. WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
  51. // 支付描述
  52. request.setBody(productTitle);
  53. // 订单号
  54. request.setOutTradeNo(outTradeNo);
  55. // 请按照分填写
  56. request.setTotalFee(totalFee);
  57. // 小程序需要传入 openid
  58. request.setOpenid(openId);
  59. // 回调链接
  60. request.setNotifyUrl(wechatPayConfig.getNotifyUrl());
  61. // 终端IP.
  62. request.setSpbillCreateIp(InetAddress.getLocalHost().getHostAddress());
  63. // 设置类型为JSAPI
  64. request.setTradeType(WxPayConstants.TradeType.JSAPI);
  65. // 一定要用 createOrder 不然得自己做二次校验
  66. Object order = wxPayService().createOrder(request);
  67. return order;
  68. } catch (Exception e) {
  69. return null;
  70. }
  71. }
  72. /**
  73. * 退款
  74. *
  75. * @param tradeNo 订单号
  76. * @param totalFee 总价
  77. * @return
  78. */
  79. public WxPayRefundResult refund(String tradeNo, Integer totalFee) {
  80. WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
  81. wxPayRefundRequest.setTransactionId(tradeNo);
  82. wxPayRefundRequest.setOutRefundNo(String.valueOf(System.currentTimeMillis()));
  83. wxPayRefundRequest.setTotalFee(totalFee);
  84. wxPayRefundRequest.setRefundFee(totalFee);
  85. wxPayRefundRequest.setNotifyUrl(wechatPayConfig.getRefundNotifyUrl());
  86. try {
  87. WxPayRefundResult refund = wxPayService().refundV2(wxPayRefundRequest);
  88. if (refund.getReturnCode().equals("SUCCESS") && refund.getResultCode().equals("SUCCESS")) {
  89. return refund;
  90. }
  91. } catch (WxPayException e) {
  92. e.printStackTrace();
  93. }
  94. return null;
  95. }
  96. }

2.5 创建Controller测试

  1. package com.runbrick.paytest.controller;
  2. import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
  3. import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
  4. import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
  5. import com.github.binarywang.wxpay.exception.WxPayException;
  6. import com.runbrick.paytest.util.wxpay.BizWechatPayService;
  7. import lombok.AllArgsConstructor;
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;
  10. import org.springframework.web.bind.annotation.RequestBody;
  11. import org.springframework.web.bind.annotation.RequestMapping;
  12. import org.springframework.web.bind.annotation.RequestMethod;
  13. import org.springframework.web.bind.annotation.RestController;
  14. @RestController
  15. @RequestMapping("/wechat/pay")
  16. @AllArgsConstructor
  17. public class WechatController {
  18. BizWechatPayService wechatPayService;
  19. private static Logger logger = LoggerFactory.getLogger(WechatController.class);
  20. /**
  21. * 创建微信订单
  22. *
  23. * @return
  24. */
  25. @RequestMapping(value = "/unified/request", method = RequestMethod.GET)
  26. public Object appPayUnifiedRequest() {
  27. // totalFee 必须要以分为单位
  28. Object createOrderResult = wechatPayService.createOrder("测试支付", String.valueOf(System.currentTimeMillis()), 1, "从前端传入的openIdopendId");
  29. logger.info("统一下单的生成的参数:{}", createOrderResult);
  30. return createOrderResult;
  31. }
  32. @RequestMapping(method = RequestMethod.POST, value = "notify")
  33. public String notify(@RequestBody String xmlData) {
  34. try {
  35. WxPayOrderNotifyResult result = wechatPayService.wxPayService().parseOrderNotifyResult(xmlData);
  36. // 支付返回信息
  37. if ("SUCCESS".equals(result.getReturnCode())) {
  38. // 可以实现自己的业务逻辑
  39. logger.info("来自微信支付的回调:{}", result);
  40. }
  41. return WxPayNotifyResponse.success("成功");
  42. } catch (WxPayException e) {
  43. logger.error(e.getMessage());
  44. return WxPayNotifyResponse.fail("失败");
  45. }
  46. }
  47. /**
  48. * 退款
  49. *
  50. * @param transaction_id
  51. */
  52. @RequestMapping(method = RequestMethod.POST, value = "refund")
  53. public void refund(String transaction_id) {
  54. // totalFee 必须要以分为单位,退款的价格可以这里只做的全部退款
  55. WxPayRefundResult refund = wechatPayService.refund(transaction_id, 1);
  56. // 实现自己的逻辑
  57. logger.info("退款本地回调:{}", refund);
  58. }
  59. /**
  60. * 退款回调
  61. *
  62. * @param xmlData
  63. * @return
  64. */
  65. @RequestMapping(method = RequestMethod.POST, value = "refund_notify")
  66. public String refundNotify(@RequestBody String xmlData) {
  67. // 实现自己的逻辑
  68. logger.info("退款远程回调:{}", xmlData);
  69. // 必须要返回 SUCCESS 不过有 WxPayNotifyResponse 给整合成了 xml了
  70. return WxPayNotifyResponse.success("成功");
  71. }
  72. }

三、前端代码

  1. <template>
  2. <view class="content">
  3. <view class="text-area">
  4. <text class="title">{{title}}</text>
  5. </view>
  6. <button type="default" @click="goPay()">点我前去支付</button>
  7. </view>
  8. </template>
  9. <script>
  10. export default {
  11. data() {
  12. return {
  13. title: '跟我去支付'
  14. }
  15. },
  16. onLoad() {
  17. },
  18. methods: {
  19. goPay() {
  20. uni.request({
  21. url: "https://bfb3-221-237-148-6.ap.ngrok.io/wechat/pay/unified/request",
  22. success(res) {
  23. let obj = {
  24. appid: res.data.appId,
  25. noncestr: res.data.nonceStr,
  26. package: res.data.packageValue,
  27. partnerid: res.data.partnerId,
  28. prepayid: res.data.prepayId,
  29. timestamp: parseInt(res.data.timeStamp),
  30. sign: res.data.sign,
  31. };
  32. uni.requestPayment({
  33. provider: "wxpay",
  34. orderInfo: obj,
  35. success(res) {
  36. uni.showModal({
  37. content: "支付成功",
  38. showCancel: false
  39. })
  40. },
  41. fail(e) {
  42. uni.showModal({
  43. content: "支付失败,原因为: " + e.errMsg,
  44. showCancel: false
  45. })
  46. },
  47. complete() {
  48. console.log("啥也没干");
  49. }
  50. });
  51. }
  52. })
  53. }
  54. }
  55. }
  56. </script>
  57. <style>
  58. page {
  59. background-color: #ff5500;
  60. }
  61. .content {
  62. display: flex;
  63. flex-direction: column;
  64. align-items: center;
  65. justify-content: center;
  66. }
  67. .text-area {
  68. display: flex;
  69. justify-content: center;
  70. }
  71. .title {
  72. font-size: 36rpx;
  73. color: #8f8f94;
  74. }
  75. </style>

待解决的问题

 这段前端是怎么传值的,一直没有解决

  1. @RequestMapping(method = RequestMethod.POST, value = "notify")
  2. public String notify(@RequestBody String xmlData) {
  3. try {
  4. WxPayOrderNotifyResult result = wechatPayService.wxPayService().parseOrderNotifyResult(xmlData);
  5. // 支付返回信息
  6. if ("SUCCESS".equals(result.getReturnCode())) {
  7. // 可以实现自己的业务逻辑
  8. logger.info("来自微信支付的回调:{}", result);
  9. }
  10. return WxPayNotifyResponse.success("成功");
  11. } catch (WxPayException e) {
  12. logger.error(e.getMessage());
  13. return WxPayNotifyResponse.fail("失败");
  14. }
  15. }

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

闽ICP备14008679号