微信公众号支付(统一下单、支付结果通知、查询订单)

最近做的项目涉及到微信公众号的支付,翻遍文档和查阅众多资料后,记一下自己整的过程:

1.先看的官方文档,把DEMO下载下来,发现都是要证书的,继续看文档,API列表

2.还是看文档,参数,坑最多的地方,这里需要在工具类里边先配置几个东西,需要在公众号的账号和商户号里面预先设置好

公众号AppId 微信支付商户号 微信支付API秘钥

微信支付通知URL 我用的是内网穿透工具 nat300 映射的已备案域名

3.调用微信统一下单的接口,微信只接收XML格式的字符串,返回的也是XML格式的字符串,主要代码如下:

/**
     * 微信公众号支付统一下单
     * @param req
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public ServiceResult<Object> unifiedorder(WxOrderReq req, HttpServletRequest request, String openId) {

        Map<String, String> paraMap = new HashMap<String, String>();
        paraMap.put("appid", WXPayConfig.APP_ID);
        paraMap.put("mch_id", WXPayConfig.MCH_ID);
        paraMap.put("nonce_str", WXPayUtil.generateNonceStr());   //随机字符串,长度要求在32位以内。
        paraMap.put("body", req.getIntroduce());
        paraMap.put("out_trade_no", orderNumber);
        paraMap.put("total_fee", req.getSum().multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString());  //订单总金额,单位为分
        paraMap.put("spbill_create_ip", IpUtil.getIpAddr(request));
        paraMap.put("notify_url", WXPayConfig.NOTIFY_URL);
        paraMap.put("trade_type", WXPayConfig.TRADE_TYPE_JSAPI);
        paraMap.put("openid", openId);
        Map<String, String> payMap = new HashMap<String, String>();
        try {
            String sign = WXPayUtil.generateSignature(paraMap, WXPayConfig.KEY);//签名,将所有的请求参数按照ASCII字典排序后,按照规定格式拼接成字符串,再使用MD5加密后生成
            paraMap.put("sign", sign);

            // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
            String url = WXPayConfig.UNIFIED_ORDER_URL;
            String xml = WXPayUtil.mapToXml(paraMap);//将map转成xml格式的 字符串(微信只接受xml格式的字符串)

            String xmlStr = HttpKit.post(url, xml); //请求微信统一下单接口(微信只返回xml格式的字符串)

            Map<String, String> map = WXPayUtil.xmlToMap(xmlStr); //将xml格式的字符串转成 map

            //xmlStr.indexOf("SUCCESS") != -1
            if (!map.get("return_code").equals("SUCCESS")) {
                return ServiceResult.newFailure(new CodeMsg(-1,"调用接口失败!!!!!!"));
            }

            // 微信生成的预支付会话标识,该值有效期为2小时
            String prepay_id = map.get("prepay_id");

            payMap.put("appId", WXPayConfig.APP_ID);
            payMap.put("timeStamp", String.valueOf(WXPayUtil.getCurrentTimestamp()));
            payMap.put("nonceStr", WXPayUtil.generateNonceStr());
            payMap.put("signType", WXPayConfig.SIGNTYPE);
            payMap.put("package", "prepay_id=" + prepay_id);

            String paySign = WXPayUtil.generateSignature(payMap, WXPayConfig.KEY);
            payMap.put("paySign", paySign);
            payMap.put("outTradeNo",orderNumber);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //新增订单业务
        
        return ServiceResult.newSuccess(payMap);
    }

 

4.支付结果通知,这个接口是在工具类中配置好的 微信支付通知url

/**
     * 支付结果通知
     * @param request
     * @param response
     */
    public ServiceResult<Object> getWeChatPayReturn(HttpServletRequest request,  HttpServletResponse response){
        String resSuccessXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
        String resFailXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";
        String resXml = "";
        try {
            InputStream inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }

            WXPayUtil.getLogger().info("wxnotify:微信支付----start----");

            // 获取微信调用我们notify_url的返回信息
            String result = new String(outSteam.toByteArray(), "utf-8");
            WXPayUtil.getLogger().info("wxnotify:微信支付----result----=" + result);

            // 关闭流
            outSteam.close();
            inStream.close();

            // xml转换为map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
            boolean isSuccess = false;
            if (WXPayConstants.SUCCESS.equalsIgnoreCase(resultMap.get("return_code"))){

                WXPayUtil.getLogger().info("wxnotify:微信支付----返回成功");

                if (WXPayUtil.isSignatureValid(resultMap,WXPayConfig.KEY)){

                    // 订单处理 操作 orderconroller 的回写操作?
                    WXPayUtil.getLogger().info("wxnotify:微信支付----验证签名成功");

                    // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                    resXml = resSuccessXml;
                    isSuccess = true;
                } else {
                    WXPayUtil.getLogger().error("wxnotify:微信支付----判断签名错误");
                }
            } else {
                WXPayUtil.getLogger().error("wxnotify:支付失败,错误信息:" + resultMap.get("return_msg"));
                resXml = resFailXml;
            }

            // 回调方法,处理业务 - 修改订单支付状态
            WXPayUtil.getLogger().info("wxnotify:微信支付回调:修改的订单===>" + resultMap.get("out_trade_no"));
//            logger.info("resultMap::::::",resultMap);
            ServiceResult<Object> updateResult = orderService.updateOrderState(resultMap.get("out_trade_no"));
            if (updateResult.success()){
                WXPayUtil.getLogger().info("wxnotify:微信支付回调:修改订单支付状态成功");
            } else {
                WXPayUtil.getLogger().error("wxnotify:微信支付回调:修改订单支付状态失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                // 处理业务完毕
                BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
                out.close();
            } catch (IOException e) {
                WXPayUtil.getLogger().error("wxnotify:支付回调发布异常:out:", e);
            }
        }
        return ServiceResult.newSuccess(resXml);
    }

 

5.查询订单  根据订单号向微信发起请求 得知该订单的状态

/**
     * 查询订单
     * @param req
     * @return
     * @throws Exception
     */
    @Override
    public ServiceResult<Object> orderQuery(OrderQueryReq req) {
        String trade_state = null;
        String accessToken = req.getAccessToken();
        ObjectResult<User> userByToken = authFeignService.getUserByToken(accessToken);
        User data = userByToken.getData();
        if (data == null) {
            return ServiceResult.newFailure(CodeMsg.ERROR_ACCESS_TOKEN);
        }
        Map<String, String> paraMap = new HashMap<String, String>();
        paraMap.put("appid",WXPayConfig.APP_ID);
        paraMap.put("mch_id",WXPayConfig.MCH_ID);
        paraMap.put("nonce_str",WXPayUtil.generateNonceStr());   //随机字符串,长度要求在32位以内。
        paraMap.put("out_trade_no",req.getOutTradeNo());
        try {
            String sign = WXPayUtil.generateSignature(paraMap, WXPayConfig.KEY);//签名,将所有的请求参数按照ASCII字典排序后,按照规定格式拼接成字符串,再使用MD5加密后生成
            paraMap.put("sign", sign);

            // 查询订单 https://api.mch.weixin.qq.com/pay/orderquery
            String url = WXPayConfig.ORDER_QUERY;
            String xml = WXPayUtil.mapToXml(paraMap);//将map转成xml格式的 字符串(微信只接受xml格式的字符串)

            String xmlStr = HttpKit.post(url, xml); //请求微信查询订单接口(微信只返回xml格式的字符串)

            Map<String, String> map = WXPayUtil.xmlToMap(xmlStr); //将xml格式的字符串转成 map
            System.err.println(map);
            trade_state = map.get("trade_state");
        }catch (Exception e){
            e.printStackTrace();
        }

        //SUCCESS—支付成功 REFUND—转入退款 NOTPAY—未支付 CLOSED—已关闭 REVOKED—已撤销(付款码支付)
        // USERPAYING--用户支付中(付款码支付) PAYERROR--支付失败(其他原因,如银行返回失败)
        if ("SUCCESS".equals(trade_state)){
            return ServiceResult.newSuccess(0);
        }
        if ("REFUND".equals(trade_state)){
            return ServiceResult.newSuccess("转入退款");
        }
        if ("NOTPAY".equals(trade_state)){
            return ServiceResult.newSuccess("未支付");
        }
        if ("CLOSED".equals(trade_state)){
            return ServiceResult.newSuccess("已关闭");
        }
        if ("REVOKED".equals(trade_state)){
            return ServiceResult.newSuccess("已撤销(付款码支付)");
        }
        if ("USERPAYING".equals(trade_state)){
            return ServiceResult.newSuccess("用户支付中(付款码支付)");
        }
        if ("PAYERROR".equals(trade_state)){
            return ServiceResult.newSuccess("支付失败");
        }
        return ServiceResult.newSuccess(trade_state);
    }

 

比较懒,所以就直接放的代码了,欢迎大家交流指正 tansky1995@gmail.com

评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值