微信支付-H5支付-第三章

前言

微信支付-H5支付-第二章

这一章开始代码分析 下单相关的接口,需要查询接口的可以进入下一章。

微信支付-H5支付-第四章

正言

前端发起下单请求

后台统一下单

控制层

    /**
     * 统一下单 应用场景
     * H5支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认使用微信支付时,商户发起本服务呼起微信客户端进行支付。
     * 主要用于触屏版的手机浏览器请求微信支付的场景。可以方便的从外部浏览器唤起微信支付。
     * 参考博客:https://blog.csdn.net/qq_41490913/article/details/104957525?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161127802816780269838022%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=161127802816780269838022&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-104957525.first_rank_v2_pc_rank_v29&utm_term=SpringBoot%E6%95%B4%E5%90%88%E5%BE%AE%E4%BF%A1H5%E6%94%AF%E4%BB%98%20&spm=1018.2226.3001.4187
     * 参考博客代码排了一些坑。
     */
    @PostMapping("/order")
    public AjaxResult order(@RequestBody ZlsPaymentlog zlsPaymentlog){
        AjaxResult result = wXH5PayService.order(zlsPaymentlog);
        return result;
    }

业务层

    @Override
    @Transactional
    public AjaxResult order(ZlsPaymentlog zlsPaymentlog) {
        AjaxResult result = AjaxResult.success();

        MyWXPayConfig config = new MyWXPayConfig();//配置类

        Map<String, String> data = new HashMap<String, String>();
        String outRradeNo = IdUtils.fastSimpleUUID();
        data.put("device_info", "WEB"); //设备号 PC网页或公众号内支付可以传"WEB"
        data.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
        data.put("body", WXPayConstants.BODY); //商品描述
        data.put("out_trade_no", outRradeNo); //商户订单号
        data.put("total_fee", String.valueOf(zlsPaymentlog.getAmount().intValue())); //标价金额 单位是分
        data.put("spbill_create_ip", IpUtils.getHostIp()); //用户的客户端IP
        data.put("notify_url", defultUrl+"prod-api/wxpay/h5pay/orderNotify"); //通知地址
        data.put("trade_type", "MWEB");  // 交易类型  JSAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付
        logger.info("data="+ JSONUtils.toJSONString(data));
        try {
            WXPay wxpay = new WXPay(config);

            //统一下单接口
            Map<String, String> resp = wxpay.unifiedOrder(data);
            logger.info("统一下单:resp="+JSONUtils.toJSONString(resp));
            logger.info("需要请求的地址:"+resp.get("mweb_url"));
            String returnCode = resp.get("return_code");
            if(WXPayConstants.SUCCESS.equals(returnCode)){
                //跳转URL  //redirect_url则为支付后返回的指定页面
                String url = resp.get("mweb_url");
                //不添加redirect_url参数,则默认返回原路径。
                //url = url+"&redirect_url="+defultUrl+"xswk/mobiles/searchPayInfo"

                // TODO 自己的一些逻辑 例如日志 或者记录订单状态 
                result = AjaxResult.success("统一下单接口成功",url);
            }else {
                throw new RuntimeException(resp.get("err_code_des"));
            }

        } catch (Exception e) {
            result = AjaxResult.error("统一下单接口失败",e.getMessage());
        }
        logger.info("统一下单接口result:"+JSONUtils.toJSONString(result));
        return result;
    }

后台支付结果通知

控制层

    /**
     * 支付结果通知 应用场景
     * 当商户申请的退款有结果后(退款状态为:退款成功、退款关闭、退款异常),微信会把相关结果发送给商户,商户需要接收处理,并返回应答。
     * 对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功(通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m)。
     * 注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
     * 推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
     * 特别说明:退款结果对重要的数据进行了加密,商户需要用商户秘钥进行解密后才能获得结果通知的内容
     * 注意点(坑):商户系统收到支付结果通知,需要在 5 秒内返回应答报文,否则微信支付认为通知失败,后续会重复发送通知。。
     */
    @ResponseBody
    @RequestMapping("/orderNotify")
    public String orderNotify(HttpServletRequest request, HttpServletResponse response) {
        String result = wXH5PayService.orderNotify(request,response);
        return result;
    }

业务层

    @Override
    @Transactional
    public String orderNotify(HttpServletRequest request, HttpServletResponse response) {
        logger.info("支付结果通知回调中");

        //默认返回给微信的数据 标志成功, SUCCESS表示商户接收通知成功并校验成功
        Map<String, String> map = new HashMap<String, String>(){{put("return_code", WXPayConstants.SUCCESS);put("return_msg", WXPayConstants.OK);}};
        String result = WXPayUtil.mapToXml(map);

        try {
            InputStream inputStream = request.getInputStream();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[2048];
            int len = 0;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }

            String notifyData = new String(outputStream.toByteArray(), "utf-8");// 支付结果通知的xml格式数据

            //关闭流
            outputStream.close();
            inputStream.close();
            logger.info("获取xml格式数据成功:\n" + notifyData);

            Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map
            logger.info("notifyMap = " + notifyMap);

            String returnCode = notifyMap.get("return_code");
            if(WXPayConstants.SUCCESS.equals(returnCode)&&WXPayConstants.SUCCESS.equals(notifyMap.get("result_code"))){
                String outTradeNo = notifyMap.get("out_trade_no");//获取商户订单号
                logger.info("outTradeNo = " + outTradeNo);
                String transactionId = notifyMap.get("transaction_id");//微信支付订单号
                logger.info("transactionId = " + transactionId);

                // TODO 微信回调函数5秒没有返回给微信后台,则认为失败,为防止各种原因导致多次回调,需要加校验判断,防止多次扣费。
                
                
                // TODO 自己的业务逻辑,例如 更改订单状态 记录日志
                
            }

            //以XML格式发送给微信后台,不然可能会发生多次回调。
            response.setContentType("text/xml");
            response.getWriter().write(result);
            response.flushBuffer();
        } catch (Exception e) {
            //发生异常,微信后台不会自动退费.
            logger.info("支付信息回调发生异常:"+e.getMessage());
            map.put("return_code", WXPayConstants.FAIL);
            map.put("return_msg", e.getMessage());
            result = WXPayUtil.mapToXml(map);
        }
        logger.info("支付结果通知接口result:" + result);
        return result;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值