微信支付踩坑血泪史(JAVA -V3版本)
背景介绍
项目中使用的接入方式是JSAPI(参考 ),当然也可以使用其他接入方式,根据需求来。
项目中我们选择的非官方SDK binarywang,没什么别的原因,主要是更方便。
官网:;
GitHub:
一、接入前准备
接入前需要创建账号等步骤,可以参考官方文档:
二、引入依赖
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
</dependency>
三、编写配置文件
开发环境下可以把秘钥存到本地,线上建议放到服务器。
因为支付会有回调和退款等操作,本地接口不能被访问。建议使用内网穿透工具进行测试()
四、数据库设计
订单表
退款表 支付单表
订单与支付单和退款单关系为一对多 不同用户扫码会产生多个支付记录,同样退款有多个退款记录。业务代码需要做支付幂等,同一笔不允许重复支付,重复支付需要调用退款接口。
五、业务代码
1.控制层
@Api(tags = "订单管理")
@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@Operation(summary = "提交订单")
@PostMapping("/order/create")
public BizResult<String> createOrder(@Valid @RequestBody OrderCreateReq req) {
String orderNO = orderService.createOrder(req);
return BizResult.create(orderNO);
}
@Operation(summary = "订单详情")
@GetMapping("/order/detail")
public BizResult<OrderRsp> orderDetail(@RequestParam String orderNo) {
OrderRsp orderRsp = orderService.orderDetail(orderNo);
return BizResult.create(orderRsp);
}
@Operation(summary = "轮询订单")
@GetMapping("/order/polling")
public BizResult<Boolean> pollingOrder(@RequestParam String orderNo) {
Boolean result = orderService.pollingOrder(orderNo);
return BizResult.create(result);
}
@Operation(summary = "订单列表")
@PostMapping("/order/list")
public BizResult<PageData<OrderListRsp>> queryOrderList(@RequestBody OrderListReq req) {
req.check();
PageData<OrderListRsp> pageData = orderService.queryOrderList(req);
return BizResult.create(pageData);
}
}
2.业务层
3.manager
@Slf4j
@Component
public class WxManager {
@Autowired
WxPayProperties wxPayProperties;
@Resource
private RedissonClient redissonClient;
@Autowired
private WxMpProperties wxMpProperties;
public WxMpService getWxMpService() {
WxMpRedissonConfigImpl config = new WxMpRedissonConfigImpl(redissonClient, CommonConstants.NAMESPACE);
config.setAppId(wxMpProperties.getAppId());
config.setSecret(wxMpProperties.getSecret());
WxMpService service = new WxMpServiceImpl();
service.setWxMpConfigStorage(config);
return service;
}
public WxPayService getWxPayService() {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(wxPayProperties.getAppid());
payConfig.setMchId(wxPayProperties.getMchId());
payConfig.setPrivateKeyPath(wxPayProperties.getPrivateKeyPath());
payConfig.setNotifyUrl(wxPayProperties.getNotifyUrl());
payConfig.setApiV3Key(wxPayProperties.getApiV3key());
payConfig.setPrivateCertPath(wxPayProperties.getPrivateCertPath());
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
public WxPayService getWxPayRefundService() {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(wxPayProperties.getAppid());
payConfig.setMchId(wxPayProperties.getMchId());
payConfig.setPrivateKeyPath(wxPayProperties.getPrivateKeyPath());
payConfig.setNotifyUrl(wxPayProperties.getRefundNotifyUrl());
payConfig.setApiV3Key(wxPayProperties.getApiV3key());
payConfig.setPrivateCertPath(wxPayProperties.getPrivateCertPath());
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}
4.Properties
@Data
@Component
@Configuration
@ConfigurationProperties(prefix = "wechat-pay")
public class WxPayProperties {
/**
* 商户号
*/
private String mchId;
/**
* 证书解密的密钥
*/
private String apiV3key;
/**
* 商户私钥文件
*/
private String privateKeyPath;
/**
* apiclient_cert.pem证书文件
*/
private String privateCertPath;
/**
* 商户证书序列号
*/
private String serialNo;
/**
* 赋选供应链 服务号appid
*/
private String appid;
/**
* 支付回调通知地址
*/
private String notifyUrl;
/**
* 退款回调通知地址
*/
private String refundNotifyUrl;
}
总结
以上就是核心业务代码,涉及到具体业务mapper没有放上来,但是核心的处理步骤已经体现出来了。主要是对订单状态需要仔细判断,不同操作会引起状态的变更。业务中,当多个人扫同一个码,后续扫码成功会调用退款接口。
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
基础篇-ArrayList的扩容机制
