微信支付APIv2介绍

先看文章

微信支付介绍和接入指引(在线实战!!!!微信直连!!)_微信支付接入-CSDN博客

之前看的都是APIv3的版本

微信支付开发者文档

打开v2

pay.weixin.qq.com/wiki/doc/api/index.html

1、V2和V3的比较

2、引入依赖和工具

2.1、引入依赖

2.2、复制工具类

2.3、添加商户APIv2 key 

然后

2.4、添加枚举

3、统一下单

v2:

v3: 

注意,有些参数都不一样

3.1、创建WxPayV2Controller

3.2、WxPayService

/**
     * v2统一下单
     * @param productId
     * @param remoteAddress
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> nativePayV2(Long productId, String remoteAddress) throws Exception {
        log.info("生成订单");
        //生成订单
        OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId);

        String codeUrl=orderInfo.getCodeUrl();
        if(orderInfo!=null&&!StringUtils.isEmpty(codeUrl)){
            log.info("订单已存在,二维码已保存");
            //返回二维码
            Map<String,Object> map = new HashMap<>();
            map.put("codeUrl",codeUrl);
            map.put("orderNo",orderInfo.getOrderNo());
            return map;
        }

        log.info("调用统一下单API");
        //调用统一下单API
        HttpClientUtils client=new HttpClientUtils(wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY_V2.getType()));
        //请求body参数
        Map<String,String> paramsMap = new HashMap();
        paramsMap.put("appid",wxPayConfig.getAppid());//关联的公众号appid
        paramsMap.put("mch_id",wxPayConfig.getMchId());//商户号
        paramsMap.put("nonce_str", WXPayUtil.generateNonceStr());//生成随机字符串
        paramsMap.put("body",orderInfo.getTitle());//商品描述
        //paramsMap.put("description",orderInfo.getTitle());
        paramsMap.put("out_trade_no",orderInfo.getOrderNo());
        paramsMap.put("trade_type","NATIVE");

        paramsMap.put("notify_url",wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY_V2.getType()));
        //注意,这里必须使用字符串类型的参数(分)
        String totalFee=orderInfo.getTotalFee()+"";
        paramsMap.put("total_fee",totalFee);

        paramsMap.put("spbill_create_ip",remoteAddress);
        //将参数转化为xml字符串格式:生成带有签名的xml格式字符串
        String xmlParams = WXPayUtil.generateSignedXml(paramsMap,wxPayConfig.getPartnerKey());
        log.info("请求参数:"+xmlParams);
        client.setXmlParam(xmlParams);//将参数放入请求对象的方法体
        client.setHttps(true);//使用https请求
        client.post();//发送请求

        String resultXml=client.getContent();//得到响应结果
        log.info("响应结果:"+resultXml);

        //将xml响应结果转换成map对象
        Map<String,String> resultMap = WXPayUtil.xmlToMap(resultXml);

        //错误处理
        if("FATL".equals(resultMap.get("return_code"))||"FAIL".equals(resultMap.get("result_code"))){
            log.error("微信支付统一下单错误====》",resultXml);
            throw new RuntimeException("微信支付统一下单错误");
        }

        //二维码
        codeUrl = resultMap.get("code_url");

        //保存二维码
        String orderNo = orderInfo.getOrderNo();
        orderInfoService.saveCodeUrl(orderNo, codeUrl);
        //返回二维码

        Map<String, Object> map = new HashMap<>();
        map.put("codeUrl",codeUrl);
        map.put("orderNo",orderInfo.getOrderNo());
        return map;

    }

4、支付回调

v2的回调与v3的回调最大的区别就是v2的回调参数没有经过加密,所以可以直接进行解析

 /**
     //处理通知参数
     String body = HttpUtils.readData(request);
     * 支付通知
     * 微信支付通过支付通知接口将用户支付成功消息通知给商户
     */
    @PostMapping("/native/notify")
    public String wxNotify(HttpServletRequest request) throws Exception {
        System.out.println("微信发送的回调");
        Map<String, String> returnMap = new HashMap<>();//应答对象
        //处理通知参数
        String body = HttpUtils.readData(request);
        //验签
        if(!WXPayUtil.isSignatureValid(body, wxPayConfig.getPartnerKey())){
            log.error("通知验签失败");
            //失败应答
            returnMap.put("return_code", "FAIL");
            returnMap.put("return_msg", "验签失败");
            String returnXml=WXPayUtil.mapToXml(returnMap);
            return returnXml;

        }
        //解析xml数据
        Map<String, String> notifyMap = WXPayUtil.xmlToMap(body);
        //判断通信和业务是否成功
        if(!"SUCCESS".equals(notifyMap.get("return_code")) || !"SUCCESS".equals(notifyMap.get("result_code"))){
            log.error("通知业务失败");
            //失败应答
            returnMap.put("return_code", "FAIL");
            returnMap.put("return_msg", "业务失败");
            String returnXml=WXPayUtil.mapToXml(returnMap);
            return returnXml;
        }
        //获取商户订单号
        String orderNo = notifyMap.get("out_trade_no");
        OrderInfo orderInfo = orderInfoService.getOrderByOrderNo(orderNo);
        //并校验返回的订单金额是否与商户侧的订单金额一致
        //也是v2的要求
        if(orderInfo != null && orderInfo.getTotalFee()!=Long.parseLong(notifyMap.get("total_fee"))){
            log.error("通知金额与订单金额不一致");
            //失败应答
            returnMap.put("return_code", "FAIL");
            returnMap.put("return_msg", "金额校验失败");
            String returnXml=WXPayUtil.mapToXml(returnMap);
            return returnXml;
        }
        //处理订单
        if(lock.tryLock()){
            try {
                //处理重复的通知
                //接口调用的幂等性:无论接口被调用多少次,产生的结果是一致的。
                String orderStatus = orderInfoService.getOrderStatus(orderNo);
                if(OrderStatus.NOTPAY.getType().equals(orderStatus)){
                    //更新订单状态
                    orderInfoService.updateStatusByOrderNo(orderNo,
                            OrderStatus.SUCCESS);
                    //记录支付日志
                    paymentInfoService.createPaymentInfo(body);
                }
            } finally {
                //要主动释放锁
                lock.unlock();
            }
        }
        returnMap.put("return_code", "SUCCESS");
        returnMap.put("return_msg", "OK");
        String returnXml = WXPayUtil.mapToXml(returnMap);
        log.info("支付成功,已应答");
        return returnXml;
    }

记录日志的时候注意,可能要做一下数据转换:

可以用swagger测试

或者前端做一个小修改启动程序:

然后

修改

启动程序

支付并通知成功

注意关于记录日志到t_payment_info中:

因为v2通知请求参数和v3有点区别,所以记录的时候会报错,这里可以注释掉关于金额的字段

然后日志 也记录了,不过少了一个字段

到次v2的下单也完成了,不过因为只是介绍一下v2,只写了两个接口。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值