zoukankan      html  css  js  c++  java
  • app端微信支付(二)

    ​前一篇文章的时序图中说了,app端调用微信支付必须先由后台调用微信后台生成预付单,再构建参数给手机端,而数据的构建要以xml形式,那么看看代码具体实现吧,代码已经精简过了,自己的业务已经除去,精简的代码附上注释是可以直接调用微信后台的

    这个是微信所要接受的参数,咱们可以把它构建成一个entity

    public class WXPrepay {
        private static String unifiedorder = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        private static String orderquery = "https://api.mch.weixin.qq.com/pay/orderquery";
        private String appid;                // 应用ID            微信开放平台审核通过的应用APPID
        private String mch_id;                // 商户号            微信支付分配的商户号
        private String nonce_str = OrderUtil.CreateNoncestr();        // 随机字符串        随机字符串,不长于32位
        private String sign;                // 签名        
        private String body;                // 商品描述        商品描述交易字段格式根据不同的应用场景按照以下格式:APP——需传入应用市场上的APP名字-实际商品名称,天天爱消除-游戏充值。
        private String out_trade_no;        // 商户订单号        商户系统内部的订单号,32个字符内、可包含字母
        private String total_fee;            // 总金额            订单总金额,单位为分
        private String spbill_create_ip;    // 终端IP            用户端实际ip
        private String notify_url;            // 通知地址        接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。    
        private String trade_type;            // 交易类型        支付类型
        private String partnerKey;
        private String attach;                // 附加数据        附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
        
        private String prepay_id;            // 预支付订单号

    controller作为一个restful接口供手机端调用,这个接口可以被ios,安卓等调用,只要微信提供了相应手机端的sdk,那就没有问题

    @RequestMapping("/wxpay")
        @ResponseBody
        public LeeJSONResult wxpay(HttpServletRequest request, Model model) {
            try {
                // TODO 根据你的业务逻辑计算你需要支付的订单总额
                double totalFee = 1;
                // 生成交易流水,流水id需要传给微信,这个流水ID可以作为你的订单ID,由于我们的业务是多订单的,流水ID仅仅只是作为表关联
                // 需要保存货源id,需要的车辆数,订单id在通知成功后保存
                String payFlowId = sid.nextShort();
                SpPayFlowCargoSource payFlowCargoSource = new SpPayFlowCargoSource();
                payFlowCargoSource.setId(payFlowId);
                payFlowCargoSource.setFee(new BigDecimal(totalFee));
                payFlowCargoSource.setPayStatus(PayStatusEnum.NOT_PAID.value);    // 支付状态:未支付
                
                // 构建微信参数
                String spbill_create_ip = request.getRemoteAddr();        // 用户IP
                WXPrepay prePay = new WXPrepay();
                prePay.setAppid(WXPayContants.appId);                    
                prePay.setMch_id(WXPayContants.partnerId);
                prePay.setBody("demo - 微信支付");                    
                prePay.setOut_trade_no(payFlowId);                        
                // 这里要注意,微信支付是以分为单位,而系统是以元为单位,所以需要金额转换。题外话:曾经看到过京东和苏宁都有类似的bug,就是一个台手机和耳机都是要十几元,估计是金额转换出的问题
                prePay.setTotal_fee(String.valueOf(new BigDecimal(totalFee).multiply(new BigDecimal(100)).intValue()));     
    //            prePay.setTotal_fee("1");
                prePay.setSpbill_create_ip(spbill_create_ip);
                prePay.setNotify_url(notifyUrl);                    // 异步通知,这个下篇文章讲
                prePay.setTrade_type("APP");
                prePay.setAttach(payFlowId);                        // 存入交易流水id
                    
                prePay.setPartnerKey(WXPayContants.partnerKey);
                
                // 获取预支付订单号
                String prepayId = prePay.submitXmlGetPrepayId();
                logger.info("获取的预支付订单是:" + prepayId);
                if (prepayId != null && prepayId.length() > 10) {
                    // 生成微信支付参数,此处拼接为完整的JSON格式,符合支付调起传入格式
                    String jsParam = WXPay.createPackageValue(WXPayContants.appId, WXPayContants.partnerKey, prepayId);
                    System.out.println("jsParam=" + jsParam);
                    // 此处可以添加订单的处理逻辑
                    model.addAttribute("jsParam", jsParam);
                    logger.info("生成的微信调起JS参数为:" + jsParam);
                    
                    payFlowCargoSource.setPrepayId(prepayId);                            
                    spPayFlowCargoSourceService.savePayFlow(payFlowCargoSource);
                    
                    return LeeJSONResult.ok();
                } else {
                    return LeeJSONResult.errorMsg("微信支付接口调用失败");
                }
            } catch (Exception e) {
                e.printStackTrace();
                return LeeJSONResult.errorException(e.getMessage());
            }
        }

    需要注意的是,微信后台接受的参数都是xml格式的,所以咱们的bean需要转换为xml再传给微信,最后调用成功,微信会封装一个xml传过来,咱们同样再解析一下获取预付单号就OK了

    public String submitXmlGetPrepayId() {
            // 创建HttpClientBuilder
            HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
            // HttpClient
            CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
            HttpPost httpPost = new HttpPost(unifiedorder);
            String xml = getPackage();
            StringEntity entity;
            try {
                entity = new StringEntity(xml, "utf-8");
                httpPost.setEntity(entity);
                HttpResponse httpResponse;
                // post请求
                httpResponse = closeableHttpClient.execute(httpPost);
                HttpEntity httpEntity = httpResponse.getEntity();
                if (httpEntity != null) {
                    // 打印响应内容
                    String result = EntityUtils.toString(httpEntity, "UTF-8");
                    System.out.println(result);
                    // 过滤
                    result = result.replaceAll("<![CDATA[|]]>", "");
                    String prepay_id = Jsoup.parse(result).select("prepay_id").html();
                    this.prepay_id = prepay_id;
                    if (prepay_id != null) {
                        return prepay_id;
                    }
                }
                // 释放资源
                closeableHttpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return prepay_id;
        }

    其实不用这样的方式也行,把bean通过json的方式封装,最后让它自动转为xml,也是没有问题的,或者直接使用 restful webservice标准协议来接受xml和发送xml

  • 相关阅读:
    图片上传 多张
    ES6的新特性
    css超出一行添加省略号属性:text-overflow和white-space
    JQuery 中 is(':visible') 解析及用法
    Git详解之Git分支
    jQuery选择器和选取方法
    git命令之git remote的用法
    运算符中的一些小技巧
    Git 忽略一些文件不加入版本控制
    git 查看远程分支、本地分支、创建分支、把分支推到远程repository、删除本地分支
  • 原文地址:https://www.cnblogs.com/leechenxiang/p/6169888.html
Copyright © 2011-2022 走看看