微信小程序支付实现(java)
2022年12月24日约 781 字大约 3 分钟
微信小程序支付实现(java)
1. 实现流程
2. 实现细节
2.1 微信支付配置
/**
* 微信支付Configuration
* @author www.joolun.com
*
*/
@Slf4j
@Configuration
public class WxPayConfiguration {
private static WxMaProperties wxMaProperties;
@Autowired
public WxPayConfiguration(WxMaProperties wxMaProperties) {
this.wxMaProperties = wxMaProperties;
}
/**
* 获取WxMpService
* @return
*/
public static WxPayService getPayService() {
WxPayService wxPayService = null;
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(wxMaProperties.getConfigs().get(0).getAppId());
payConfig.setMchId(wxMaProperties.getConfigs().get(0).getMchId());
payConfig.setMchKey(wxMaProperties.getConfigs().get(0).getMchKey());
payConfig.setKeyPath(wxMaProperties.getConfigs().get(0).getKeyPath());
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(false);
wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}
配置信息
wx:
# 小程序配置
ma:
configs:
- appId: xxx
secret: xxx
# 微信支付商户号,请去微信支付平台申请
mchId: xxx
# 微信支付商户密钥,请去微信支付平台申请
mchKey: xxx
mall:
# 支付、物流回调地址,即后台服务7500端口的外网访问域名,要保证外网能访问
notify-host: http://xx.xxxx.com
2.2 统一下单接口
- 获取登录的微信用户信息
- 获取订单信息
- 将订单信息封装成WxPayUnifiedOrderRequest(wxjava 提供的订单请求类)
- setOutTradeNo:设置订单
- setTotalFee:设置支付金额
- setNotifyUrl:设置回调地址
- 调用wxPayService 创建订单
/**
* 调用统一下单接口,并组装生成支付所需参数对象.
*
* @param orderInfo 统一下单请求参数
* @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的类对象
*/
@ApiOperation(value = "调用统一下单接口")
@PostMapping("/unifiedOrder")
public AjaxResult unifiedOrder(HttpServletRequest request, @RequestBody OrderInfo orderInfo) throws WxPayException {
//检验用户session登录
WxUser wxUser = new WxUser();
wxUser.setId(ThirdSessionHolder.getThirdSession().getWxUserId());
wxUser.setSessionKey(ThirdSessionHolder.getThirdSession().getSessionKey());
wxUser.setOpenId(ThirdSessionHolder.getThirdSession().getOpenId());
orderInfo = orderInfoService.getById(orderInfo.getId());
if(orderInfo == null){
return AjaxResult.error(MyReturnCode.ERR_70005.getCode(), MyReturnCode.ERR_70005.getMsg());
}
if(!CommonConstants.NO.equals(orderInfo.getIsPay())){//只有未支付的详单能发起支付
return AjaxResult.error(MyReturnCode.ERR_70004.getCode(), MyReturnCode.ERR_70004.getMsg());
}
if(orderInfo.getPaymentPrice().compareTo(BigDecimal.ZERO)==0){//0元购买不调支付
orderInfo.setPaymentTime(LocalDateTime.now());
orderInfoService.notifyOrder(orderInfo);
return AjaxResult.success();
}
String appId = WxMaUtil.getAppId(request);
WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
wxPayUnifiedOrderRequest.setAppid(appId);
String body = orderInfo.getName();
body = body.length() > 40 ? body.substring(0,39) : body;
wxPayUnifiedOrderRequest.setBody(body);
wxPayUnifiedOrderRequest.setOutTradeNo(orderInfo.getOrderNo());
wxPayUnifiedOrderRequest.setTotalFee(orderInfo.getPaymentPrice().multiply(new BigDecimal(100)).intValue());
wxPayUnifiedOrderRequest.setTradeType("JSAPI");
wxPayUnifiedOrderRequest.setNotifyUrl(mallConfigProperties.getNotifyHost()+"/weixin/api/ma/orderinfo/notify-order");
wxPayUnifiedOrderRequest.setSpbillCreateIp("127.0.0.1");
wxPayUnifiedOrderRequest.setOpenid(wxUser.getOpenId());
WxPayService wxPayService = WxPayConfiguration.getPayService();
return AjaxResult.success(JSONUtil.parse(wxPayService.createOrder(wxPayUnifiedOrderRequest)));
}
2.3 唤起微信支付
2.4 支付完成回调
- 获取支付回调结果
- 查找支付订单id的订单信息
- 设置交易时间和交易id
/**
* 支付回调
* @param xmlData
* @return
* @throws WxPayException
*/
@ApiOperation(value = "支付回调")
@PostMapping("/notify-order")
public String notifyOrder(@RequestBody String xmlData) throws WxPayException {
log.info("支付回调:"+xmlData);
WxPayService wxPayService = WxPayConfiguration.getPayService();
WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
OrderInfo orderInfo = orderInfoService.getOne(Wrappers.<OrderInfo>lambdaQuery()
.eq(OrderInfo::getOrderNo,notifyResult.getOutTradeNo()));
if(orderInfo != null){
if(orderInfo.getPaymentPrice().multiply(new BigDecimal(100)).intValue() == notifyResult.getTotalFee()){
String timeEnd = notifyResult.getTimeEnd();
LocalDateTime paymentTime = LocalDateTimeUtils.parse(timeEnd);
orderInfo.setPaymentTime(paymentTime);
orderInfo.setTransactionId(notifyResult.getTransactionId());
orderInfoService.notifyOrder(orderInfo);
return WxPayNotifyResponse.success("成功");
}else{
return WxPayNotifyResponse.fail("付款金额与订单金额不等");
}
}else{
return WxPayNotifyResponse.fail("无此订单");
}
}
2.5 通知订单信息
@Override
@Transactional(rollbackFor = Exception.class)
public void notifyOrder(OrderInfo orderInfo) {
if(CommonConstants.NO.equals(orderInfo.getIsPay())){//只有未支付订单能操作
orderInfo.setIsPay(CommonConstants.YES);
orderInfo.setStatus(OrderInfoEnum.STATUS_1.getValue());
List<OrderItem> listOrderItem = orderItemService.list(Wrappers.<OrderItem>lambdaQuery()
.eq(OrderItem::getOrderId,orderInfo.getId()));
Map<String, List<OrderItem>> resultList = listOrderItem.stream().collect(Collectors.groupingBy(OrderItem::getSpuId));
List<GoodsSpu> listGoodsSpu = goodsSpuService.listByIds(resultList.keySet());
listGoodsSpu.forEach(goodsSpu -> {
resultList.get(goodsSpu.getId()).forEach(orderItem -> {
//更新销量
goodsSpu.setSaleNum(goodsSpu.getSaleNum()+orderItem.getQuantity());
});
goodsSpuService.updateById(goodsSpu);
baseMapper.updateById(orderInfo);//更新订单
});
}
}
3. 问题点
3.1 没有接收到微信回调
从以下几个地方排查
接口是不是有权限控制了?
例如校验token,但是此时是微信过来的,肯定不包含token
3.2 微信不停发回调
可能是没按要求返回指定格式数据
微信格式
WxPayNotifyResponse.success("成功");
json形式返回
@ResponseBody
Powered by Waline v2.9.1