(132)Part35-微信支付-04-支付回调

一、准备

1、配置ngrok

将ngrok映射到本地8170端口,并启动

2、添加工具类

在common-util中添加工具类

StreamUtils.java

二、支付回调

1、回调方法

该链接是通过【统一下单API】中提交的参数notify_url设置,如果链接无法访问,商户将无法接收到微信通知。

参考文档:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_7&index=8

ApiWeixinPayController

@Autowired
private WeixinPayProperties weixinPayProperties;

@Autowired
private OrderService orderService;

/**
     * 支付回调:注意这里是【post】方式
     */
@PostMapping("callback/notify")
public String wxNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {

    System.out.println("callback/notify 被调用");

    // 获得通知结果
    ServletInputStream inputStream = request.getInputStream();
    String notifyXml = StreamUtils.inputStream2String(inputStream, "utf-8");
    System.out.println("xmlString = " + notifyXml);

    // 定义响应对象
    HashMap<String, String> returnMap = new HashMap<>();

    // 签名验证:防止伪造回调
    if (WXPayUtil.isSignatureValid(notifyXml, weixinPayProperties.getPartnerKey())) {

        // 解析返回结果
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyXml);

        //判断支付是否成功
        if("SUCCESS".equals(notifyMap.get("result_code"))){

            // 校验订单金额是否一致
            String totalFee = notifyMap.get("total_fee");
            String outTradeNo = notifyMap.get("out_trade_no");
            Order order = orderService.getOrderByOrderNo(outTradeNo);
            if(order != null && order.getTotalFee().intValue() == Integer.parseInt(totalFee)){

                // 判断订单状态:保证接口调用的幂等性,如果订单状态已更新直接返回成功响应
                // 幂等性:无论调用多少次结果都是一样的
                if(order.getStatus() == 1){
                    returnMap.put("return_code", "SUCCESS");
                    returnMap.put("return_msg", "OK");
                    String returnXml = WXPayUtil.mapToXml(returnMap);
                    response.setContentType("text/xml");
                    log.warn("通知已处理");
                    return returnXml;
                }else{
                    // 更新订单支付状态,并返回成功响应
                    orderService.updateOrderStatus(notifyMap);
                    returnMap.put("return_code", "SUCCESS");
                    returnMap.put("return_msg", "OK");
                    String returnXml = WXPayUtil.mapToXml(returnMap);
                    response.setContentType("text/xml");
                    log.info("支付成功,通知已处理");
                    return returnXml;
                }
            }
        }
    }

    // 校验失败,返回失败应答
    returnMap.put("return_code", "FAIL");
    returnMap.put("return_msg", "");
    String returnXml = WXPayUtil.mapToXml(returnMap);
    response.setContentType("text/xml");
    log.warn("校验失败");
    return returnXml;
}

2、更新订单状态

更新订单支付状态并记录支付日志,将微信返回的支付结果全部记录进数据库的json字段中
接口:OrderService

void updateOrderStatus(Map<String, String> map);

实现:OrderServiceImpl

@Autowired
private PayLogMapper payLogMapper;

@Transactional(rollbackFor = Exception.class)
@Override
public void updateOrderStatus(Map<String, String> map) {

    //更新订单状态
    String orderNo = map.get("out_trade_no");
    Order order = this.getOrderByOrderNo(orderNo);
    order.setStatus(1);//支付成功
    baseMapper.updateById(order);

    //记录支付日志
    PayLog payLog = new PayLog();
    payLog.setOrderNo(orderNo);
    payLog.setPayTime(new Date());
    payLog.setPayType(1);//支付类型
    payLog.setTotalFee(Long.parseLong(map.get("total_fee")));//总金额(分)
    payLog.setTradeState(map.get("result_code"));//支付状态
    payLog.setTransactionId(map.get("transaction_id"));
    payLog.setAttr(new Gson().toJson(map));
    payLogMapper.insert(payLog);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

destiny- freedom

感觉怎么样呐?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值