微信公众号开发03----微信支付

1、微信支付之Native支付

关于如何开通微信支付大家可以直接去【微信支付】官网查阅。这里我们直接进入正题。

1.1 Native支付场景(以电商网站为例)

设置商品价格
支付成功
支付失败
用户购买商品
支付界面生成付款二维码
用户扫码付款
生成支付订单
付款失败界面

1.2 支付场景示例图

微信公众号开发03----微信支付_第1张图片

1.3 核心代码

1.3.1 统一下单封装后的方法
public static WeixinPayResult createNative(String callbackUrl, String app_id, String mch_id, String api_key, String out_trade_no, Integer total_fee, String body) {
     
        //1.参数封装
        Map param = new HashMap();
        param.put("appid", app_id);//公众账号ID
        param.put("mch_id", mch_id);//商户
        param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
        param.put("body", body);
        param.put("out_trade_no", out_trade_no);//交易订单号(是由系统内部来生成)
        param.put("total_fee", total_fee.toString());//金额(分)
        param.put("spbill_create_ip", "127.0.0.1");//支付客户端的IP地址(这里没做记录)
        param.put("notify_url", callbackUrl);
        param.put("trade_type", "NATIVE");//交易类型
        try {
     
            //根据appkey来生成签名,并同时将参数进行转换为xml格式
            String xmlParam = WXPayUtil.generateSignedXml(param, api_key);
            //2.发送请求(按照官方接口要求,将数据以post请求方式发送)
            HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            httpClient.setHttps(true);//以https的协议发送请求
            httpClient.setXmlParam(xmlParam);//设置post请求的参数列表
            httpClient.post();
            //3.获取结果
            String xmlResult = httpClient.getContent();
            Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
            //将返回的结果转换为对象
            WeixinPayResult weixinPayResult = new WeixinPayResult();
            //防止进行bean复制时,日期为null时报错
            ConvertUtils.register(new DateConverter(null), Date.class);
            BeanUtils.copyProperties(weixinPayResult, mapResult);
            //注意:付款订单编号是后台动态生成,必须要手动添加到返回结果中  勿忘,切记!!!
            weixinPayResult.setOut_trade_no(out_trade_no);
            return weixinPayResult;
        } catch (Exception e) {
     
            e.printStackTrace();
            return null;
        }
    }
  • 封装统一下单涉及到的工具类WXPayUtil.java代码需要导入微信支付开发的pom坐标

        <dependency>
            <groupId>com.github.wxpaygroupId>
            <artifactId>wxpay-sdkartifactId>
            <version>0.0.3version>
        dependency>
        <dependency>
            <groupId>com.thoughtworks.xstreamgroupId>
            <artifactId>xstreamartifactId>
            <version>1.4.10version>
        dependency>
1.3.2 根据订单号查询订单状态
public static WeixinPayResult queryPayStatus(String app_id, String mch_id, String api_key, String out_trade_no) {
     
        Map resultMap = new HashMap();
        //1.封装参数
        Map param = new HashMap();
        param.put("appid", app_id);//appid
        param.put("mch_id", mch_id);//商户ID
        param.put("out_trade_no", out_trade_no);//要查询的订单号(自己系统所生成订单号)
        param.put("nonce_str", WXPayUtil.generateNonceStr());
        try {
     
            String xmlParam = WXPayUtil.generateSignedXml(param, api_key);
            //2.发送请求
            HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            httpClient.setHttps(true);
            httpClient.setXmlParam(xmlParam);
            httpClient.post();
            //3.获取结果
            String xmlResult = httpClient.getContent();
            Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
            //封装结果数据
            WeixinPayResult weixinPayResult = new WeixinPayResult();
            //防止进行bean复制时,日期为null时报错
            ConvertUtils.register(new DateConverter(null), Date.class);
            BeanUtils.copyProperties(weixinPayResult, mapResult);
            return weixinPayResult;
        } catch (Exception e) {
     
            e.printStackTrace();
            return null;
        }
    }
1.3.3 关于生成付款码时的回调方法应用(重点!重点!重点!)

相信很多新手在使用【微信支付】接口时,都会选择在前端设置定时器来间隔查询,如果查询到订单状态为【支付成功】再走生成订单的流程。如这种方法的操作是非常错误的,而且还有非常多的安全隐患。

  • 正确处理查看支付成功并处理后续业务的流程如下:
设置回调参数callback
支付成功
支付失败
创建统一下单接口
界面展示付款码
用户扫码支付
触发回调参数callback的请求
调用查询订单状态接口确定付款成功
触发回调参数callback的请求,并返回失败的结果
失败结果返回给前端

你没看错,流程图也没画错。其实正确的付款支付接口时,生成的付款码和查询订单支付状态是两个完全独立的操作。

  • 前端在调用[统一下单]接口并生成【付款码】后,这步操作就结束
  • 当用户扫码后,无论付款成功还是失败,只要完成这个扫码操作,就会调用【统一下单】接口中所配置的callback回调url。
  • 这种实现方式优点:
    1. 支持离线支付(复制付款码后,可以关闭当前付款页面,只要扫码成功支付,购买成功业务都会执行)
    2. 支持代付(用户可以把付款码截图发给其他人代付)
    3. 安全性高

1.3.4 附加回调的方法

防止有些朋友不知道回调方法怎么写,这里也贴出回调方法的实现

  • 如果你在调用【统一下单】封装方法,传入的callback参数值为
    callbackUrl: http://你服务器的回调方法根路径/callbackpay
    那么就应该在你当前工程的方法中,添加一个回调方法的实现
/**
     * 微信支付成功后的回调函数
     */
    @RequestMapping("/callbackpay")
    public Result callbackPay(HttpServletRequest request) {
     
        StringBuffer sb = new StringBuffer();
        try {
     
            List<String> readLines = IOUtils.readLines(request.getInputStream(), "utf-8");
            for (String readLine : readLines) {
     
                sb.append(readLine);
            }
            Map<String, String> mapResult = WXPayUtil.xmlToMap(sb.toString());
            //防止进行bean复制时,日期为null时报错
            ConvertUtils.register(new DateConverter(null), Date.class);
            WeixinPayResult weixinPayResult = new WeixinPayResult();
            BeanUtils.copyProperties(weixinPayResult, mapResult);
            return weixinPayService.callbackPay(weixinPayResult);//这行代码是调用业务层的付款成功后的处理逻辑
        } catch (Exception e) {
     
            e.printStackTrace();
            return new Result(false, "服务器异常");
        }
    }

注意:最后提醒一下,上面这个回调方法的url,一定要记得在你的权限框架中放行

下一章会介绍【微信支付----- 微信红包和企业付款到微信用户零钱】

你可能感兴趣的:(微信公众号开发)