赞
踩
看效果
参考文章:SpringBoot + 小程序 整合微信支付和退款 V2版 - 码农教程
本文仅作记录
参考文章: UniApp + SpringBoot 实现微信支付和退款 - 奔跑的砖头 - 博客园
Springboot整合支付宝支付参考: UniApp + SpringBoot 实现支付宝支付和退款 - 奔跑的砖头 - 博客园
官方网站: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <!-- 微信支付坐标 start-->
- <dependency>
- <groupId>com.github.binarywang</groupId>
- <artifactId>weixin-java-pay</artifactId>
- <version>4.2.5.B</version>
- </dependency>
- <!-- 退款用 -->
- <dependency>
- <groupId>org.jodd</groupId>
- <artifactId>jodd-http</artifactId>
- <version>6.0.8</version>
- </dependency>
- <!-- 微信支付坐标 end-->
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-configuration-processor</artifactId>
- <optional>true</optional>
- </dependency>
-
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
回调地址 我这里使用 ngrok内网穿透 官网: ngrok - Online in One Line
- # 服务启动端口
- server:
- port: 8081
-
- # 微信pay相关
- wxpay:
- # appId
- appId: # 自己的appId
- # 商户id
- mchId: # 自己的商户id
- # 商户秘钥
- mchKey: # 商户秘钥
- # p12证书文件的绝对路径或者以classpath:开头的类路径.
- keyPath: classpath:/wxpay_cert/apiclient_cert.p12
- privateKeyPath: classpath:/wxpay_cert/apiclient_key.pem
- privateCertPath: classpath:/wxpay_cert/apiclient_cert.pem
- # 微信支付的异步通知接口
- # 我这里使用的ngrok内网穿透
- notifyUrl: https://bfb3-221-237-148-6.ap.ngrok.io/wechat/pay/notify
- # 退款回调地址
- refundNotifyUrl: https://bfb3-221-237-148-6.ap.ngrok.io/wechat/pay/refund_notify
-
- package com.system.system.config;
-
- import lombok.Data;
- import org.springframework.boot.context.properties.ConfigurationProperties;
-
- @Data
- @ConfigurationProperties(prefix = "wxpay")
- public class WechatPayConfig {
- private String appId;
- private String mchId;
- private String mchKey;
- private String keyPath;
- private String privateKeyPath;
- private String privateCertPath;
- private String notifyUrl;
- }
-
- package com.system.system.service.impl;
-
- import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
- import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
- import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
- import com.github.binarywang.wxpay.config.WxPayConfig;
- import com.github.binarywang.wxpay.constant.WxPayConstants;
- import com.github.binarywang.wxpay.exception.WxPayException;
- import com.github.binarywang.wxpay.service.WxPayService;
- import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
- import lombok.AllArgsConstructor;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
- import org.springframework.boot.context.properties.EnableConfigurationProperties;
- import org.springframework.stereotype.Service;
-
- import java.net.InetAddress;
-
- /**
- * 微信支付
- */
- @Service
- @ConditionalOnClass(WxPayService.class)
- @EnableConfigurationProperties(WechatPayConfig.class)
- @AllArgsConstructor
- public class BizWechatPayService {
-
- private WechatPayConfig wechatPayConfig;
-
- public WxPayService wxPayService() {
- WxPayConfig payConfig = new WxPayConfig();
- payConfig.setAppId(wechatPayConfig.getAppId());
- payConfig.setMchId(wechatPayConfig.getMchId());
- payConfig.setMchKey(wechatPayConfig.getMchKey());
- payConfig.setKeyPath(wechatPayConfig.getKeyPath());
- payConfig.setPrivateKeyPath(wechatPayConfig.getPrivateKeyPath());
- payConfig.setPrivateCertPath(wechatPayConfig.getPrivateCertPath());
- // 可以指定是否使用沙箱环境
- payConfig.setUseSandboxEnv(false);
- payConfig.setSignType("MD5");
-
- WxPayService wxPayService = new WxPayServiceImpl();
- wxPayService.setConfig(payConfig);
- return wxPayService;
- }
-
- /**
- * 创建微信支付订单
- *
- * @param productTitle 商品标题
- * @param outTradeNo 订单号
- * @param totalFee 总价
- * @param openId openId
- * @return
- */
- public Object createOrder(String productTitle, String outTradeNo, Integer totalFee, String openId) {
- try {
- WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
- // 支付描述
- request.setBody(productTitle);
- // 订单号
- request.setOutTradeNo(outTradeNo);
- // 请按照分填写
- request.setTotalFee(totalFee);
- // 小程序需要传入 openid
- request.setOpenid(openId);
- // 回调链接
- request.setNotifyUrl(wechatPayConfig.getNotifyUrl());
- // 终端IP.
- request.setSpbillCreateIp(InetAddress.getLocalHost().getHostAddress());
- // 设置类型为JSAPI
- request.setTradeType(WxPayConstants.TradeType.JSAPI);
- // 一定要用 createOrder 不然得自己做二次校验
- Object order = wxPayService().createOrder(request);
- return order;
- } catch (Exception e) {
- return null;
- }
-
- }
-
- /**
- * 退款
- *
- * @param tradeNo 订单号
- * @param totalFee 总价
- * @return
- */
- public WxPayRefundResult refund(String tradeNo, Integer totalFee) {
- WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
- wxPayRefundRequest.setTransactionId(tradeNo);
- wxPayRefundRequest.setOutRefundNo(String.valueOf(System.currentTimeMillis()));
- wxPayRefundRequest.setTotalFee(totalFee);
- wxPayRefundRequest.setRefundFee(totalFee);
- wxPayRefundRequest.setNotifyUrl(wechatPayConfig.getRefundNotifyUrl());
- try {
- WxPayRefundResult refund = wxPayService().refundV2(wxPayRefundRequest);
- if (refund.getReturnCode().equals("SUCCESS") && refund.getResultCode().equals("SUCCESS")) {
- return refund;
- }
-
- } catch (WxPayException e) {
- e.printStackTrace();
- }
- return null;
- }
- }
-
- package com.runbrick.paytest.controller;
-
- import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
- import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
- import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
- import com.github.binarywang.wxpay.exception.WxPayException;
- import com.runbrick.paytest.util.wxpay.BizWechatPayService;
- import lombok.AllArgsConstructor;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestMethod;
- import org.springframework.web.bind.annotation.RestController;
-
- @RestController
- @RequestMapping("/wechat/pay")
- @AllArgsConstructor
- public class WechatController {
-
- BizWechatPayService wechatPayService;
-
- private static Logger logger = LoggerFactory.getLogger(WechatController.class);
-
- /**
- * 创建微信订单
- *
- * @return
- */
- @RequestMapping(value = "/unified/request", method = RequestMethod.GET)
- public Object appPayUnifiedRequest() {
- // totalFee 必须要以分为单位
- Object createOrderResult = wechatPayService.createOrder("测试支付", String.valueOf(System.currentTimeMillis()), 1, "从前端传入的openIdopendId");
- logger.info("统一下单的生成的参数:{}", createOrderResult);
- return createOrderResult;
- }
-
- @RequestMapping(method = RequestMethod.POST, value = "notify")
- public String notify(@RequestBody String xmlData) {
- try {
- WxPayOrderNotifyResult result = wechatPayService.wxPayService().parseOrderNotifyResult(xmlData);
- // 支付返回信息
- if ("SUCCESS".equals(result.getReturnCode())) {
- // 可以实现自己的业务逻辑
- logger.info("来自微信支付的回调:{}", result);
- }
-
- return WxPayNotifyResponse.success("成功");
- } catch (WxPayException e) {
- logger.error(e.getMessage());
- return WxPayNotifyResponse.fail("失败");
- }
- }
-
- /**
- * 退款
- *
- * @param transaction_id
- */
- @RequestMapping(method = RequestMethod.POST, value = "refund")
- public void refund(String transaction_id) {
- // totalFee 必须要以分为单位,退款的价格可以这里只做的全部退款
- WxPayRefundResult refund = wechatPayService.refund(transaction_id, 1);
- // 实现自己的逻辑
- logger.info("退款本地回调:{}", refund);
- }
-
- /**
- * 退款回调
- *
- * @param xmlData
- * @return
- */
- @RequestMapping(method = RequestMethod.POST, value = "refund_notify")
- public String refundNotify(@RequestBody String xmlData) {
- // 实现自己的逻辑
- logger.info("退款远程回调:{}", xmlData);
- // 必须要返回 SUCCESS 不过有 WxPayNotifyResponse 给整合成了 xml了
- return WxPayNotifyResponse.success("成功");
- }
-
- }
- <template>
- <view class="content">
- <view class="text-area">
- <text class="title">{{title}}</text>
- </view>
- <button type="default" @click="goPay()">点我前去支付</button>
- </view>
- </template>
-
- <script>
- export default {
- data() {
- return {
- title: '跟我去支付'
- }
- },
- onLoad() {
-
- },
- methods: {
- goPay() {
- uni.request({
- url: "https://bfb3-221-237-148-6.ap.ngrok.io/wechat/pay/unified/request",
- success(res) {
- let obj = {
- appid: res.data.appId,
- noncestr: res.data.nonceStr,
- package: res.data.packageValue,
- partnerid: res.data.partnerId,
- prepayid: res.data.prepayId,
- timestamp: parseInt(res.data.timeStamp),
- sign: res.data.sign,
- };
-
- uni.requestPayment({
- provider: "wxpay",
- orderInfo: obj,
- success(res) {
- uni.showModal({
- content: "支付成功",
- showCancel: false
- })
- },
- fail(e) {
- uni.showModal({
- content: "支付失败,原因为: " + e.errMsg,
- showCancel: false
- })
- },
- complete() {
- console.log("啥也没干");
- }
- });
-
- }
- })
-
- }
- }
- }
- </script>
-
- <style>
- page {
- background-color: #ff5500;
- }
-
- .content {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- }
-
- .text-area {
- display: flex;
- justify-content: center;
- }
-
- .title {
- font-size: 36rpx;
- color: #8f8f94;
- }
- </style>
待解决的问题
这段前端是怎么传值的,一直没有解决
- @RequestMapping(method = RequestMethod.POST, value = "notify")
- public String notify(@RequestBody String xmlData) {
- try {
- WxPayOrderNotifyResult result = wechatPayService.wxPayService().parseOrderNotifyResult(xmlData);
- // 支付返回信息
- if ("SUCCESS".equals(result.getReturnCode())) {
- // 可以实现自己的业务逻辑
- logger.info("来自微信支付的回调:{}", result);
- }
-
- return WxPayNotifyResponse.success("成功");
- } catch (WxPayException e) {
- logger.error(e.getMessage());
- return WxPayNotifyResponse.fail("失败");
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。