• 微信app支付


    https://blog.csdn.net/Zhihua_W/article/details/80606089

    出于兴趣写了一个纯支付的模块,有兴趣的同学可以去看看(戳我)

    ———————————分隔线———————————–

    微信APP支付大致的流程和支付宝APP支付有很大不同(想了解支付宝APP支付的同学点这里),其中略坑的一点就是MD5加密的方法需要自己写,好在微信官方给出了测试地址。
    前置准备

    微信的东西比支付宝要复杂一点,要先去注册开发者账号,然后一系列巴拉巴拉……,然后得到下面列出的我们开发需要的参数,下面的参数中TOKEN和CERT_PATH是需要退款和设计到其他功能才需要的,如果只做APP支付功能的同学可以忽略。

        APP_ID : 服务号的应用ID
        APP_SECRET : 服务号的应用密钥
        TOKEN : 服务号的配置token
        MCH_ID : 商户号
        API_KEY : API密钥
        SIGN_TYPE : 签名加密方式
        CERT_PATH : 微信支付证书名称、

    支付流程

    具体的流程大概就是后台拿到(或生成)自己的订单号后,拿着一堆参数按ASCII码(即abc…)排序后用MD5加密后调用微信的服务器地址拿到一个prepayId,再将prepayId和当前的参数再次排序和加密(二次加密)生成sign后返回前端进行支付,支付完成后,微信的后台会回调我们的后台接口。
    Java代码

    maven依赖

    `<!-- 微信支付依赖 -->
    <dependency>
        <groupId>org.xmlpull</groupId>
        <artifactId>xmlpull</artifactId>
        <version>1.1.3.1 </version>
    </dependency>
    <dependency>
        <groupId>net.sf.json-lib</groupId>
        <artifactId>json-lib</artifactId>
        <version>2.3</version>
        <classifier>jdk15</classifier>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
    <dependency>
        <groupId>com.thoughtworks.xstream</groupId>
        <artifactId>xstream</artifactId>
        <version>1.4.5</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.ning/async-http-client -->
    <dependency>
        <groupId>com.ning</groupId>
        <artifactId>async-http-client</artifactId>
        <version>1.8.13</version>
    </dependency>`

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24

    Java代码

    @ResponseBody
    @RequestMapping(value="/wxpaySign",method=RequestMethod.POST)
    public JsonResult getWXPaySign(double totalAmount,String userId,String out_trade_no,String ip)
                throws JDOMException, IOException{
            //预备参数
            WXPayDTO wxPayDTO = new WXPayDTO();
            String subject = "******";
            String body = "******";
            String nonceStr = setNonceStr();
            long timeStamp = (long)CommonUtil.getSecondTimestamp(new Date());
            String packageStr = "Sign=WXPay";
            String total_fee = String.valueOf(CommonUtil.double100ToInt(totalAmount));

            SortedMap<String,String> payMap = genOrderData(PayConstants.WX_APP_ID,body,out_trade_no,
                    nonceStr,packageStr,PayConstants.WX_PARTNER_ID,total_fee,subject,ip);

            //设置WXPayDTO
            wxPayDTO.setAppId(PayConstants.WX_APP_ID);
            //商家id
            wxPayDTO.setPartnerId(PayConstants.WX_PARTNER_ID);  
            wxPayDTO.setPrepayId(out_trade_no);     //订单
            wxPayDTO.setNonceStr(nonceStr); //设置随机串
            wxPayDTO.setTimeStamp(timeStamp);   //设置时间戳
            wxPayDTO.setPackageStr(packageStr);
            wxPayDTO.setSign(payMap.get("sign"));
            wxPayDTO.setPrepayId(payMap.get("prepayid"));
            return new JsonResult(Message.M2000,wxPayDTO);
        }

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28

    private SortedMap<String, String> genOrderData(String appId, String body, String out_trade_no,
                String nonceStr, String packageStr, String partnerId,String total_fee,String subject,String ip)
                        throws JDOMException, IOException {
            SortedMap<String, String> paraMap = new TreeMap<String,String>();
        //按照官方文档的要求,这里参数名ASCII码从小到大排序(字典序);
            paraMap.put("appid", appId);
            paraMap.put("body",body);
            paraMap.put("mch_id",partnerId);        //微信商户账号
            paraMap.put("nonce_str",nonceStr);  //32位不重复的编号
            paraMap.put("notify_url",
            PayConstants.WX_Notify_Url);    //设置一个回调的地址
            paraMap.put("out_trade_no", out_trade_no);  //订单号
            paraMap.put("spbill_create_ip", ip);//前端传回来的ip
            paraMap.put("total_fee",total_fee);     //设置金额
            paraMap.put("trade_type","APP");    //方式为APP支付
            //用上面封装的参数生成sign
            String sign = PayCommonUtil.createSign("UTF-8", paraMap,PayConstants.WX_API_KEY);
            //这里的sign用二次签名生成的sign
            paraMap.put("sign",sign);
            //统一下单地址
            //将上面集合内容转成xml
            String xml = getRequestXML(paraMap);
            String xmlStr = HttpUtil.postData(PayConstants.WX_Notify_Url,xml);
            //将返回的xml转换成map
            Map map = XMLUtil.doXMLParse(xmlStr);
            //预付商品id
            String prepay_id = (String) map.get("prepay_id");

            //这里要对参数进行二次签名
            SortedMap<String, String> secParaMap = new TreeMap<String,String>();
            secParaMap.put("appid", appId);
            secParaMap.put("partnerid",partnerId);
            secParaMap.put("prepayid", prepay_id);
            //这里不确定是不是要重新生成一个随机串,再改
            secParaMap.put("noncestr", nonceStr);
            secParaMap.put("timestamp", CommonUtil.getTimeStamp());
            secParaMap.put("package", "Sign=WXPay");
            String secSign = PayCommonUtil.createSign("UTF-8", secParaMap, PayConstants.WX_API_KEY);
            secParaMap.put("sign", secSign);
            secParaMap.put("prepayid", prepay_id);

            return secParaMap;
        }

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43

    支付回调
    微信的支付回调是用流形式传输的,所以要先对流形式的数据进行解析再得到我们需要的东西。

        @RequestMapping(value = "payNotifyUrl", produces = "application/json;charset=UTF-8")
        @ResponseBody
        public String payNotifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
            //读取参数

            InputStream inputStream ;  
            StringBuffer sb = new StringBuffer();  
            inputStream = request.getInputStream();  
            String s ;  
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));  
            while ((s = in.readLine()) != null){  
                sb.append(s);  
            }  
            in.close();  
            inputStream.close();  

            //解析xml成map  
            Map<String, String> m = new HashMap<String, String>();  
            m = XMLUtil.doXMLParse(sb.toString());  

            //过滤空 设置 TreeMap  
            SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();        
            Iterator it = m.keySet().iterator();  
            while (it.hasNext()) {  
                String parameter = (String) it.next();  
                String parameterValue = m.get(parameter);  

                String v = "";  
                if(null != parameterValue) {  
                    v = parameterValue.trim();  
                }  
                packageParams.put(parameter, v);  
            }  

            //判断签名是否正确  
            if(PayCommonUtil.isTenpaySign("UTF-8", packageParams,PayConstants.WX_API_KEY)) {  
                //------------------------------  
                //处理业务开始  
                //------------------------------  
                String resXml = "";  
                if("SUCCESS".equals((String)packageParams.get("result_code"))){  
                    // 这里是支付成功  
                    //////////执行自己的业务逻辑////////////////  
                    String mch_id = (String)packageParams.get("mch_id");  
                    String openid = (String)packageParams.get("openid");  
                    String is_subscribe = (String)packageParams.get("is_subscribe");  
                    String out_trade_no = (String)packageParams.get("out_trade_no");  

                    String total_fee = (String)packageParams.get("total_fee");  

                    System.out.println("mch_id:"+mch_id);  
                    System.out.println("openid:"+openid);  
                    logger.info("is_subscribe:"+is_subscribe);  
                    logger.info("out_trade_no:"+out_trade_no);  
                    logger.info("total_fee:"+total_fee);  

                    //////////执行自己的业务逻辑////////////////  

                    logger.info("支付成功");  
                    //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.  
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";  

                } else {  
                    logger.info("支付失败,错误信息:" + packageParams.get("err_code"));  
                    resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
                            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  
                }  
                //------------------------------  
                //处理业务完毕  
                //------------------------------  
                BufferedOutputStream out = new BufferedOutputStream(  
                        response.getOutputStream());  
                out.write(resXml.getBytes());  
                out.flush();  
                out.close();  
            } else{  
                logger.info("通知签名验证失败");  
            }  
            return "SUCCESS";
        }

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        65
        66
        67
        68
        69
        70
        71
        72
        73
        74
        75
        76
        77
        78
        79
        80
        81

    代码中包含一些常用的工具类,是从别人的资源来下载来的,觉得很好用。
    ---------------------
    作者:J_Howie
    来源:CSDN
    原文:https://blog.csdn.net/Dream__Snow/article/details/79098630
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    微软API集
    如何在Visual Studio.net中让同一解决方案中包含多个不同类型的项目并共享同一命名空间
    总结:Asp.net页面之间传递参数的几种方法
    Javascript 鼠标滑过显示大图的效果
    HttpContext.Current.Session["key"]取值
    数字金额转大写
    整合多个图片到一个pdf
    .net reflector & disassembler
    yacc grammar for a simple shell
    Windows cmd编码
  • 原文地址:https://www.cnblogs.com/zuoqun/p/9982717.html
Copyright © 2020-2023  润新知