您的位置:首页 > 房产 > 建筑 > 【微信支付】【java】Springboot对接开发微信支付

【微信支付】【java】Springboot对接开发微信支付

2024/10/6 20:37:50 来源:https://blog.csdn.net/qq_23126581/article/details/135472754  浏览:    关键词:【微信支付】【java】Springboot对接开发微信支付

本文章是介绍java对接(微信小程序)微信支付,包括微信预下单、支付、退款等等。 

目录

 一、微信配置申请

1、微信支付配置申请

二、开发环境

1、开发环境

2、maven依赖

3、application.yml文件配置

三、代码开发

1、配置类

2、初始化商户配置

3、JSAPI微信预下单

3.1、先建个WxPayService服务类

3.1、R实体类

3.2、CreateOrderReq类

4、微信支付回调通知 

5、根据商户订单号查询订单(out_trade_no)

5.1  QueryOrderReq类

6、根据支付订单号查询订单 (transaction_id)

7、微信申请退款

8、退款回调通知 

四、mysql表结构

五、controller类


 一、微信配置申请

1、微信支付配置申请

详细操作流程参考官方文档:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml#part-1

配置完成需要以下信息:

  • APPID
  • 商户号(mchid)
  • 商户API私钥(apiclient_key.pem)
  • 商户证书序列号
  • 商户APIv3密钥

二、开发环境

1、开发环境

开发语言:java ,编译工具:idea ,框架:springboot ,仓库:maven

2、maven依赖

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

3、application.yml文件配置

#微信支付配置
wx:pay:#应用id(小程序id)appId: wx6b5xxxxxxxxxxxx#商户号merchantId: 1xxxxxxxxx#商户API私钥privateKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#商户证书序列号merchantSerialNumber: 315DDXXXXXXXXXXXXXXXXXXXXXXXXXXX#商户APIv3密钥apiV3Key: XXXXXXXXXXXXXXXXXXXXXXXXXX#支付通知地址payNotifyUrl: https://xxx.xxxx.xxx.xxx/xx/xxxx/xxxx/openapi/wx/payNotify#退款通知地址refundNotifyUrl: https://xxx.xxx.xxx.xxx/xxxx/xxxx/xxxx/openapi/wx/refundNotify

三、代码开发

1、配置类


import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** @author caozhen* @ClassName WxPayConfig* @description: 微信支付配置类* @date 2024年01月03日* @version: 1.0*/
@Data
@Component
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayConfig {//APPIDprivate String appId;//mchidprivate String merchantId;//商户API私钥private String privateKey;//商户证书序列号private String merchantSerialNumber;//商户APIv3密钥private String apiV3Key;//支付通知地址private String payNotifyUrl;//退款通知地址private String refundNotifyUrl;
}

2、初始化商户配置

import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import javax.annotation.Resource;/*** @author caozhen* @ClassName WxPayAutoCertificateConfig* @description: 微信支付证书自动更新配置* @date 2024年01月03日* @version: 1.0*/
@Configuration
public class WxPayAutoCertificateConfig {@Resourceprivate WxPayConfig wxPayConfig;/*** 初始化商户配置* @return*/@Beanpublic RSAAutoCertificateConfig rsaAutoCertificateConfig() {RSAAutoCertificateConfig config = new RSAAutoCertificateConfig.Builder().merchantId(wxPayConfig.getMerchantId()).privateKey(wxPayConfig.getPrivateKey()).merchantSerialNumber(wxPayConfig.getMerchantSerialNumber()).apiV3Key(wxPayConfig.getApiV3Key()).build();return config;}
}

3、JSAPI微信预下单

3.1、先建个WxPayService服务类

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.hvit.user.exception.DataAccessException;
import com.hvit.user.util.DateUtils;
import com.hvit.user.util.R;
import com.hvit.user.yst.entity.WxOrderEntity;
import com.hvit.user.yst.entity.WxPayLogEntity;
import com.hvit.user.yst.request.CreateOrderReq;
import com.hvit.user.yst.request.QueryOrderReq;
import com.hvit.user.yst.request.WxNotifyReq;
import com.hvit.user.yst.service.WKShoppingMallService;
import com.hvit.user.yst.service.data.WxOrderDataService;
import com.hvit.user.yst.service.data.WxPayLogDataService;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.HttpException;
import com.wechat.pay.java.core.exception.MalformedMessageException;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.*;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.*;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.models.auth.In;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;/*** @author caozhen* @ClassName WxPayService* @description: 微信支付* @date 2024年01月03日* @version: 1.0*/
@Slf4j
@Service
public class WxPayService {@Resourceprivate WxPayConfig wxPayConfig;@Autowiredprivate RSAAutoCertificateConfig rsaAutoCertificateConfig;@Autowiredprivate WxOrderDataService wxOrderDataService;@Autowiredprivate WxPayLogDataService wxPayLogDataService;/**** 预支付订单* @param req* @return*/public R createOrder(CreateOrderReq req) throws Exception {if (req == null) {return R.error("创建订单失败,缺少参数!");}//先解密String orderNo = req.getOutTradeNo();Integer totalFee = req.getTotal();//创建初始化订单//todo,创建订单这边你们自己来(后面我会放出表结构)//请求微信支付相关配置JsapiServiceExtension service =new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).signType("RSA") // 不填默认为RSA.build();PrepayWithRequestPaymentResponse response = new PrepayWithRequestPaymentResponse();try {PrepayRequest request = new PrepayRequest();request.setAppid(wxPayConfig.getAppId());request.setMchid(wxPayConfig.getMerchantId());request.setDescription(description);request.setOutTradeNo(orderNo);request.setNotifyUrl(wxPayConfig.getPayNotifyUrl());Amount amount = new Amount();//amount.setTotal(totalFee.multiply(new BigDecimal("100")).intValue());amount.setTotal(totalFee);request.setAmount(amount);Payer payer = new Payer();payer.setOpenid(req.getWxOpenId());request.setPayer(payer);log.info("请求预支付下单,请求参数:{}", JSONObject.toJSONString(request));// 调用预下单接口response = service.prepayWithRequestPayment(request);log.info("订单【{}】发起预支付成功,返回信息:{}", orderNo, response);} catch (HttpException e) { // 发送HTTP请求失败log.error("微信下单发送HTTP请求失败,错误信息:{}", e.getHttpRequest());return R.error("下单失败");} catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500log.error("微信下单服务状态错误,错误信息:{}", e.getErrorMessage());return R.error("下单失败");} catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败log.error("服务返回成功,返回体类型不合法,或者解析返回体失败,错误信息:{}", e.getMessage());return R.error("下单失败");}return R.ok().put("data", response);}
}

3.1、R实体类

import java.util.HashMap;
import java.util.Map;/**** @author 曹震* @date 2024-1-03*/
public class R extends HashMap<String, Object> {private static final long serialVersionUID = 1L;public R() {put("code", 0);}public R(Integer code) {put("code", code);put("data", new HashMap<String, Object>());}public R(Integer code, String msg) {put("code", code);put("msg", msg);put("data", new HashMap<String, Object>());}public static R error() {return error(500, "未知异常,请联系管理员");}public static R errorDebug(String message) {return error(500, "未知异常 " + message + ",请联系管理员");}public static R error(String msg) {return error(500, msg);}public static R error(int code, String msg) {R r = new R();r.put("code", code);r.put("msg", msg);return r;}public R errorInfo(String msg) {this.put("errorMsg", msg);return this;}public static R ok(String msg) {R r = new R();r.put("msg", msg);r.put("data", new HashMap<String, Object>());return r;}public static R ok(Map<String, Object> map) {R r = new R();r.putAll(map);r.put("data", new HashMap<String, Object>());return r;}public static R ok() {return new R().put("msg", "success").put("data", new HashMap<String, Object>());}public static R ok(Integer size) {return new R().put("data", new HashMap<String, Object>((int)Math.round(size / 0.75)));}@Overridepublic R put(String key, Object value) {super.put(key, value);return this;}/*** 添加返回结果数据** @param key* @param value* @return*/public R putData(String key, Object value) {Map<String, Object> map = (HashMap<String, Object>)this.get("data");map.put(key, value);return this;}}

3.2、CreateOrderReq类

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;/*** @author caozhen* @ClassName CreateOrderReq* @description: TODO* @date 2024年01月03日* @version: 1.0*/
@Data
public class CreateOrderReq {@ApiModelProperty(name = "description", value = "商品描述")private String description;@ApiModelProperty(name = "wxOpenId", value = "用户小程序openid")private String wxOpenId;@ApiModelProperty(name = "outTradeNo", value = "商户订单号")private String outTradeNo;@ApiModelProperty(name = "totalFee", value = "支付金额,单位:分")private Long totalFee;

4、微信支付回调通知 

/**** 微信支付回调通知* @param request* @return* @throws IOException*/@Transactionalpublic synchronized String payNotify(HttpServletRequest request) throws Exception {log.info("------收到支付通知------");// 请求头Wechatpay-SignatureString signature = request.getHeader("Wechatpay-Signature");// 请求头Wechatpay-nonceString nonce = request.getHeader("Wechatpay-Nonce");// 请求头Wechatpay-TimestampString timestamp = request.getHeader("Wechatpay-Timestamp");// 微信支付证书序列号String serial = request.getHeader("Wechatpay-Serial");// 签名方式String signType = request.getHeader("Wechatpay-Signature-Type");// 构造 RequestParamRequestParam requestParam = new RequestParam.Builder().serialNumber(serial).nonce(nonce).signature(signature).timestamp(timestamp).signType(signType).body(HttpServletUtils.getRequestBody(request)).build();// 初始化 NotificationParserNotificationParser parser = new NotificationParser(rsaAutoCertificateConfig);// 以支付通知回调为例,验签、解密并转换成 Transactionlog.info("验签参数:{}", requestParam);Transaction transaction = parser.parse(requestParam, Transaction.class);log.info("验签成功!-支付回调结果:{}", transaction.toString());Map<String, String> returnMap = new HashMap<>(2);returnMap.put("code", "FAIL");returnMap.put("message", "失败");//修改订单前,建议主动请求微信查询订单是否支付成功,防止恶意postWrapper wrapper = new EntityWrapper<WxOrderEntity>();wrapper.eq("out_trade_no", transaction.getOutTradeNo());//wrapper.eq("transaction_id", transaction.getTransactionId());WxOrderEntity wxOrderEntity = wxOrderDataService.selectOne(wrapper);if (wxOrderEntity != null) {if (wxOrderEntity.getPayStatus() == 1) {//此时已经是支付成功,不在处理订单信息returnMap.put("code", "SUCCESS");returnMap.put("message", "成功");return JSONObject.toJSONString(returnMap);}}if (Transaction.TradeStateEnum.SUCCESS != transaction.getTradeState()) {log.info("内部订单号【{}】,微信支付订单号【{}】支付未成功", transaction.getOutTradeNo(), transaction.getTransactionId());if (wxOrderEntity != null) {wxOrderEntity.setUpdateTime(new Date());wxOrderEntity.setPayStatus(2);wxOrderEntity.setPayNonce(nonce);wxOrderEntity.setTransactionId(transaction.getTransactionId());//修改订单信息wxOrderDataService.updateById(wxOrderEntity);}return JSONObject.toJSONString(returnMap);}if (wxOrderEntity != null) {wxOrderEntity.setUpdateTime(new Date());wxOrderEntity.setPayTime(DateUtils.stringToDateTime(transaction.getSuccessTime()));wxOrderEntity.setPayDate(DateUtils.stringToDateTime(transaction.getSuccessTime()));wxOrderEntity.setPayStatus(1);wxOrderEntity.setPayNonce(nonce);wxOrderEntity.setTransactionId(transaction.getTransactionId());//修改订单信息wxOrderDataService.updateById(wxOrderEntity);//同时处理支付记录Wrapper payWrapper = new EntityWrapper<WxPayLogEntity>();wrapper.eq("out_trade_no", transaction.getOutTradeNo());wrapper.eq("pay_status", 1);//支付WxPayLogEntity wxPayLogEntity = wxPayLogDataService.selectOne(payWrapper);if (wxPayLogEntity == null) {wxPayLogEntity = new WxPayLogEntity();wxPayLogEntity.setCreateTime(new Date());wxPayLogEntity.setOutTradeNo(wxOrderEntity.getOutTradeNo());wxPayLogEntity.setPayStatus(1);wxPayLogEntity.setTotalFee(wxOrderEntity.getTotalFee());wxPayLogEntity.setTransactionId(wxOrderEntity.getTransactionId());wxPayLogEntity.setWxOpenId(wxOrderEntity.getWxOpenId());wxPayLogDataService.insert(wxPayLogEntity);}}returnMap.put("code", "SUCCESS");returnMap.put("message", "成功");return JSONObject.toJSONString(returnMap);}

5、根据商户订单号查询订单(out_trade_no)

/**** 根据商户订单号查询订单 outTradeNo* @param req* @return*/@Transactionalpublic R queryOrderByOrderNo(QueryOrderReq req) {QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();queryRequest.setMchid(wxPayConfig.getMerchantId());queryRequest.setOutTradeNo(req.getOrderNo());try {JsapiServiceExtension service =new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).signType("RSA") // 不填默认为RSA.build();Transaction result = service.queryOrderByOutTradeNo(queryRequest);LinkedHashMap retmap = new LinkedHashMap();//支付成功if (Transaction.TradeStateEnum.SUCCESS == result.getTradeState()) {log.info("内部订单号【{}】,微信支付订单号【{}】支付成功", result.getOutTradeNo(), result.getTransactionId());retmap.put("out_trade_no", result.getOutTradeNo());retmap.put("transaction_id", result.getTransactionId());retmap.put("success", true);retmap.put("msg", "支付成功!");retmap.put("success_time", DateUtils.getDateTimeString(DateUtils.stringToDateTime(result.getSuccessTime())));//主动查询Wrapper wrapper = new EntityWrapper<WxOrderEntity>();wrapper.eq("out_trade_no", req.getOrderNo());WxOrderEntity wxOrderEntity = wxOrderDataService.selectOne(wrapper);if (wxOrderEntity != null) {if (wxOrderEntity.getPayStatus() != 1) {wxOrderEntity.setPayStatus(1);wxOrderEntity.setTransactionId(result.getTransactionId());wxOrderEntity.setPayDate(DateUtils.stringToDateTime(result.getSuccessTime()));wxOrderEntity.setPayTime(DateUtils.stringToDateTime(result.getSuccessTime()));wxOrderEntity.setUpdateTime(new Date());wxOrderDataService.updateById(wxOrderEntity);//同时处理支付记录Wrapper payWrapper = new EntityWrapper<WxPayLogEntity>();wrapper.eq("out_trade_no", req.getOrderNo());WxPayLogEntity wxPayLogEntity = wxPayLogDataService.selectOne(payWrapper);if (wxPayLogEntity == null) {wxPayLogEntity = new WxPayLogEntity();wxPayLogEntity.setCreateTime(new Date());wxPayLogEntity.setOutTradeNo(wxOrderEntity.getOutTradeNo());wxPayLogEntity.setPayStatus(1);wxPayLogEntity.setTotalFee(wxOrderEntity.getTotalFee());wxPayLogEntity.setTransactionId(result.getTransactionId());wxPayLogEntity.setWxOpenId(wxOrderEntity.getWxOpenId());wxPayLogDataService.insert(wxPayLogEntity);}}}} else {log.info("内部订单号【{}】,微信支付订单号【{}】支付未成功", result.getOutTradeNo(), result.getTransactionId());retmap.put("out_trade_no", result.getOutTradeNo());retmap.put("transaction_id", result.getTransactionId());retmap.put("success", false);retmap.put("msg", "支付失败!");retmap.put("success_time", null);}return R.ok().put("data", retmap);} catch (ServiceException e) {log.error("订单查询失败,返回码:{},返回信息:{}", e.getErrorCode(), e.getErrorMessage());return R.error("订单查询失败!");}}

5.1  QueryOrderReq类

mport io.swagger.annotations.ApiModelProperty;
import lombok.Data;/*** @author caozhen* @ClassName QueryOrderReq* @description: 支付查询* @date 2024年01月04日* @version: 1.0*/
@Data
public class QueryOrderReq {@ApiModelProperty(name = "paymentNo", value = "微信支付订单号,同:transaction_id")private String paymentNo;@ApiModelProperty(name = "orderNo", value = "商户订单号,同:out_trade_no")private String orderNo;
}

6、根据支付订单号查询订单 (transaction_id)

/**** 根据支付订单号查询订单 paymentNo* @param req* @return*/@Transactionalpublic R queryOrderByPaymentNo(QueryOrderReq req) {QueryOrderByIdRequest queryRequest = new QueryOrderByIdRequest();queryRequest.setMchid(wxPayConfig.getMerchantId());queryRequest.setTransactionId(req.getPaymentNo());try {JsapiServiceExtension service =new JsapiServiceExtension.Builder().config(rsaAutoCertificateConfig).signType("RSA") // 不填默认为RSA.build();Transaction result = service.queryOrderById(queryRequest);LinkedHashMap map = new LinkedHashMap();//支付成功if (Transaction.TradeStateEnum.SUCCESS == result.getTradeState()) {log.info("内部订单号【{}】,微信支付订单号【{}】支付成功", result.getOutTradeNo(), result.getTransactionId());map.put("out_trade_no", result.getOutTradeNo());map.put("transaction_id", result.getTransactionId());map.put("success", true);map.put("msg", "支付成功!");map.put("success_time", DateUtils.getDateTimeString(DateUtils.stringToDateTime(result.getSuccessTime())));//主动查询Wrapper wrapper = new EntityWrapper<WxOrderEntity>();wrapper.eq("transaction_id", req.getPaymentNo());WxOrderEntity wxOrderEntity = wxOrderDataService.selectOne(wrapper);if (wxOrderEntity != null) {if (wxOrderEntity.getPayStatus() != 1) {wxOrderEntity.setPayStatus(1);wxOrderEntity.setPayDate(DateUtils.stringToDateTime(result.getSuccessTime()));wxOrderEntity.setPayTime(DateUtils.stringToDateTime(result.getSuccessTime()));wxOrderEntity.setUpdateTime(new Date());wxOrderDataService.updateById(wxOrderEntity);//同时处理支付记录Wrapper payWrapper = new EntityWrapper<WxPayLogEntity>();wrapper.eq("transaction_id", req.getPaymentNo());WxPayLogEntity wxPayLogEntity = wxPayLogDataService.selectOne(payWrapper);if (wxPayLogEntity == null) {wxPayLogEntity = new WxPayLogEntity();wxPayLogEntity.setCreateTime(new Date());wxPayLogEntity.setOutTradeNo(wxOrderEntity.getOutTradeNo());wxPayLogEntity.setPayStatus(1);wxPayLogEntity.setTotalFee(wxOrderEntity.getTotalFee());wxPayLogEntity.setTransactionId(result.getTransactionId());wxPayLogEntity.setWxOpenId(wxOrderEntity.getWxOpenId());wxPayLogDataService.insert(wxPayLogEntity);}}}} else {log.info("内部订单号【{}】,微信支付订单号【{}】支付未成功", result.getOutTradeNo(), result.getTransactionId());map.put("out_trade_no", result.getOutTradeNo());map.put("transaction_id", result.getTransactionId());map.put("success", false);map.put("msg", "支付失败!");map.put("success_time", null);}return R.ok().put("data", map);} catch (ServiceException e) {log.error("订单查询失败,返回码:{},返回信息:{}", e.getErrorCode(), e.getErrorMessage());return R.error("订单查询失败!");}}

7、微信申请退款

/**** 微信申请退款* @param outTradeNo 商户订单号* @param totalAmount* @return*/public R createRefund(String outTradeNo, Long totalAmount) {//返回参数LinkedHashMap map = new LinkedHashMap();map.put("out_trade_no", outTradeNo);map.put("success", false);map.put("msg", "正在申请退款中!");String outRefundNo = "REFUND_" + outTradeNo;map.put("out_refund_no", outRefundNo);//申请退款订单,需要变更订单记录Wrapper wrapper = new EntityWrapper<WxOrderEntity>();wrapper.eq("out_trade_no", outTradeNo);WxOrderEntity wxOrderEntity = wxOrderDataService.selectOne(wrapper);if (wxOrderEntity == null) {return R.error("订单不存在,申请退款不存在!");}wxOrderEntity.setPayStatus(4);//退款中wxOrderEntity.setUpdateTime(new Date());wxOrderDataService.updateById(wxOrderEntity);try {// 构建退款serviceRefundService service = new RefundService.Builder().config(rsaAutoCertificateConfig).build();CreateRequest request = new CreateRequest();// 调用request.setXxx(val)设置所需参数,具体参数可见Request定义request.setOutTradeNo(outTradeNo);request.setOutRefundNo(outRefundNo);AmountReq amount = new AmountReq();amount.setTotal(totalAmount);amount.setRefund(totalAmount);amount.setCurrency("CNY");request.setAmount(amount);request.setNotifyUrl(wxPayConfig.getRefundNotifyUrl());//接收退款返回参数Refund refund = service.create(request);log.info("退款返回信息:{}", refund);if (refund.getStatus().equals(Status.SUCCESS)) {map.put("success", true);map.put("msg", "退款成功!");//说明退款成功,开始接下来的业务操作//主动查询Wrapper againWrapper = new EntityWrapper<WxOrderEntity>();againWrapper.eq("out_trade_no", outTradeNo);WxOrderEntity orderEntity = wxOrderDataService.selectOne(againWrapper);if (orderEntity != null) {orderEntity.setPayStatus(3);//退款成功orderEntity.setUpdateTime(new Date());wxOrderDataService.updateById(orderEntity);//同时处理退款记录Wrapper payWrapper = new EntityWrapper<WxPayLogEntity>();payWrapper.eq("out_trade_no", outTradeNo);payWrapper.eq("pay_status", 2);//退款WxPayLogEntity wxPayLogEntity = wxPayLogDataService.selectOne(payWrapper);if (wxPayLogEntity == null) {wxPayLogEntity = new WxPayLogEntity();wxPayLogEntity.setCreateTime(new Date());wxPayLogEntity.setOutTradeNo(outTradeNo);wxPayLogEntity.setPayStatus(2);wxPayLogEntity.setTotalFee(totalAmount.intValue());wxPayLogEntity.setTransactionId(wxOrderEntity.getTransactionId());wxPayLogEntity.setOutRefundNo(outRefundNo);wxPayLogEntity.setWxOpenId(wxOrderEntity.getWxOpenId());wxPayLogDataService.insert(wxPayLogEntity);}}}} catch (ServiceException e) {log.error("退款失败!,错误信息:{}", e.getMessage());return R.error("退款失败!");} catch (Exception e) {log.error("服务返回成功,返回体类型不合法,或者解析返回体失败,错误信息:{}", e.getMessage());return R.error("退款失败!");}return R.ok().put("data", map);}

8、退款回调通知 

待续......有需要的再联系我!

四、mysql表结构

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for t_wx_order
-- ----------------------------
DROP TABLE IF EXISTS `t_wx_order`;
CREATE TABLE `t_wx_order`  (`uuid` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,`trade_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '商品名称',`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '订单描述',`out_trade_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '(商户)订单流水号',`transaction_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '微信订单号',`total_fee` int(10) NULL DEFAULT NULL COMMENT '订单金额(单位:分)',`pay_nonce` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '支付成功后的随机32位字符串',`pay_time` datetime NULL DEFAULT NULL COMMENT '支付时间',`pay_date` date NULL DEFAULT NULL COMMENT '支付日期',`pay_status` int(3) NULL DEFAULT 0 COMMENT '0:待支付,1:支付成功,2:支付失败,3:退款成功,4:正在退款中,5:未知',`wx_open_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '微信小程序openid',`status` int(2) NULL DEFAULT 0 COMMENT '0:未删除,1:已删除',`create_time` datetime NULL DEFAULT NULL COMMENT '创建订单时间',`update_time` datetime NULL DEFAULT NULL COMMENT '修改订单时间',PRIMARY KEY (`uuid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '微信商品订单表' ROW_FORMAT = Dynamic;-- ----------------------------
-- Table structure for t_wx_pay_log
-- ----------------------------
DROP TABLE IF EXISTS `t_wx_pay_log`;
CREATE TABLE `t_wx_pay_log`  (`uuid` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,`wx_open_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '微信用户openid',`out_trade_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '(商户)订单流水号',`out_refund_no` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '(商户)退款流水号',`transaction_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '微信订单号',`total_fee` int(10) NULL DEFAULT NULL COMMENT '支付金额',`pay_status` int(2) NULL DEFAULT NULL COMMENT '1:支付,2:退款',`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',PRIMARY KEY (`uuid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin COMMENT = '微信用户支付记录表' ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;

五、controller类

退款回调通知,和controller就不写了,如果需要,联系我即可!

哎呀呀呀,缺少了一个类,代码如下:

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/*** @author caozhen* @ClassName HttpServletUtils* @description: TODO* @date 2024年01月04日* @version: 1.0*/
public class HttpServletUtils {/*** 获取请求体** @param request* @return* @throws IOException*/public static String getRequestBody(HttpServletRequest request) throws IOException {ServletInputStream stream = null;BufferedReader reader = null;StringBuffer sb = new StringBuffer();try {stream = request.getInputStream();// 获取响应reader = new BufferedReader(new InputStreamReader(stream));String line;while ((line = reader.readLine()) != null) {sb.append(line);}} catch (IOException e) {throw new IOException("读取返回支付接口数据流出现异常!");} finally {reader.close();}return sb.toString();}
}

如果你在微信支付回调通知中出现 “签名错误”,并且你是windows服务器,请在HttpServletUtils 类中,将reader = new BufferedReader(new InputStreamReader(stream));   替换成:reader = new BufferedReader(new InputStreamReader(stream,"UTF-8"));

替换完整代码:

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/*** @author caozhen* @ClassName HttpServletUtils* @description: TODO* @date 2024年01月04日* @version: 1.0*/
public class HttpServletUtils {/*** 获取请求体** @param request* @return* @throws IOException*/public static String getRequestBody(HttpServletRequest request) throws IOException {ServletInputStream stream = null;BufferedReader reader = null;StringBuffer sb = new StringBuffer();try {stream = request.getInputStream();// 获取响应reader = new BufferedReader(new InputStreamReader(stream,"UTF-8"));String line;while ((line = reader.readLine()) != null) {sb.append(line);}} catch (IOException e) {throw new IOException("读取返回支付接口数据流出现异常!");} finally {reader.close();}return sb.toString();}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com