逆风的snail 发表于 2017-7-24 10:44

【分享】微信APP支付Java版的一个小demo

本帖最后由 wushaominkk 于 2018-5-2 13:54 编辑

前一段时间公司搞微信的APP支付,看过微信的官方文档之后只能感叹自己果然还是太嫩,只有思想,连个demo都没有,上网到处查找资料之后找了一个博主分享的看着相对靠谱的下载下来配置好了,改了一些回调方面的错误,终于能正常运行,分享一下,给需要的人!{:1_906:}
个人觉得核心部分的代码:
签名:

//参数:开始生成签名
      SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
      parameters.put("appid", appid);
      parameters.put("mch_id", mch_id);
      parameters.put("nonce_str", nonce_str);
      parameters.put("body", body);
      parameters.put("nonce_str", nonce_str);
      parameters.put("detail", detail);
      parameters.put("attach", attach);
      parameters.put("out_trade_no", out_trade_no);
      parameters.put("total_fee", total_fee);
      parameters.put("time_start", time_start);
      parameters.put("time_expire", time_expire);
      parameters.put("notify_url", notify_url);
      parameters.put("trade_type", trade_type);
      parameters.put("spbill_create_ip", spbill_create_ip);





/**
   * 微信支付签名算法sign
   * @param characterEncoding
   * @param parameters
   * @Return
   */
    @SuppressWarnings("rawtypes")
    public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){
      StringBuffer sb = new StringBuffer();
      Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
      Iterator it = es.iterator();
      while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            Object v = entry.getValue();
            if(null != v && !"".equals(v)   
                  && !"sign".equals(k) && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
      }
      sb.append("key=" + Key);
      System.out.println("字符串拼接后是:"+sb.toString());
      String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
      return sign;
    }

将一坨参数包装成XML格式丢给微信:

/**
   * 构造xml参数
   * @param xml
   * @return
   */
    public static String xmlInfo(Unifiedorder unifiedorder){
      //构造xml参数的时候,至少有10个必传参数
      /*
         * <xml>
               <appid>wx2421b1c4370ec43b</appid>
               <attach>支付测试</attach>
               <body>JSAPI支付测试</body>
               <mch_id>10000100</mch_id>
               <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
               <notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>
               <openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
               <out_trade_no>1415659990</out_trade_no>
               <spbill_create_ip>14.23.150.211</spbill_create_ip>
               <total_fee>1</total_fee>
               <trade_type>JSAPI</trade_type>
               <sign>0CB01533B8C1EF103065174F50BCA001</sign>
            </xml>
         */

       if(unifiedorder!=null){
            StringBuffer bf = new StringBuffer();
            bf.append("<xml>");

            bf.append("<appid><![CDATA[");
            bf.append(unifiedorder.getAppid());
            bf.append("]]></appid>");

            bf.append("<mch_id><![CDATA[");
            bf.append(unifiedorder.getMch_id());
            bf.append("]]></mch_id>");

            bf.append("<nonce_str><![CDATA[");
            bf.append(unifiedorder.getNonce_str());
            bf.append("]]></nonce_str>");

            bf.append("<sign><![CDATA[");
            bf.append(unifiedorder.getSign());
            bf.append("]]></sign>");

            bf.append("<body><![CDATA[");
            bf.append(unifiedorder.getBody());
            bf.append("]]></body>");

            bf.append("<detail><![CDATA[");
            bf.append(unifiedorder.getDetail());
            bf.append("]]></detail>");

            bf.append("<attach><![CDATA[");
            bf.append(unifiedorder.getAttach());
            bf.append("]]></attach>");

            bf.append("<out_trade_no><![CDATA[");
            bf.append(unifiedorder.getOut_trade_no());
            bf.append("]]></out_trade_no>");

            bf.append("<total_fee><![CDATA[");
            bf.append(unifiedorder.getTotal_fee());
            bf.append("]]></total_fee>");

            bf.append("<spbill_create_ip><![CDATA[");
            bf.append(unifiedorder.getSpbill_create_ip());
            bf.append("]]></spbill_create_ip>");

            bf.append("<time_start><![CDATA[");
            bf.append(unifiedorder.getTime_start());
            bf.append("]]></time_start>");

            bf.append("<time_expire><![CDATA[");
            bf.append(unifiedorder.getTime_expire());
            bf.append("]]></time_expire>");

            bf.append("<notify_url><![CDATA[");
            bf.append(unifiedorder.getNotify_url());
            bf.append("]]></notify_url>");

            bf.append("<trade_type><![CDATA[");
            bf.append(unifiedorder.getTrade_type());
            bf.append("]]></trade_type>");


            bf.append("</xml>");
            return bf.toString();
      }

      return "";
    }



//构造xml参数
      String xmlInfo = HttpXmlUtils.xmlInfo(unifiedorder);
         
      String wxUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
         
      String method = "POST";
         
      String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
因为body部分是商品的名称什么的,设计到中文,这个过程可能毁在统一下单的时候提醒:body不是UTF-8编码(我擦,我就在这里折腾了半天的http://blog.csdn.net/xb12369/article/details/50512633)

然后开始统一下单得到预支付ID,包装好给app端,app端处理好后再由微信开始回调,回调就会跳转到你的回调地址上,微信说建议校验下签名,照做就是的!


/**
   * 微信支付回调
   * @param request
   * @param resposne
   */
    @RequestMapping(value="/notifyUrlWeixin")
    public void notifyWeixinPayment(HttpServletRequest request,HttpServletResponse response){
      try{
            BufferedReader reader = request.getReader();

            String line = "";
            StringBuffer inputString = new StringBuffer();

            try{
                PrintWriter writer = response.getWriter();

                while ((line = reader.readLine()) != null) {
                  inputString.append(line);
                }

                if(reader!=null){
                  reader.close();
                }

                System.out.println("----[微信回调]接收到的报文---"+inputString.toString());

                if(!StringUtils.isEmpty(inputString.toString())){
                  WXPayResult wxPayResult = JdomParseXmlUtils.getWXPayResult(inputString.toString());

                  if("SUCCESS".equalsIgnoreCase(wxPayResult.getReturn_code())){
                        SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
                        parameters.put("appid", wxPayResult.getAppid());
                        parameters.put("attach", wxPayResult.getAttach());
                        parameters.put("bank_type", wxPayResult.getBank_type());
                        parameters.put("cash_fee", wxPayResult.getCash_fee());
                        parameters.put("fee_type", wxPayResult.getFee_type());
                        parameters.put("is_subscribe", wxPayResult.getIs_subscribe());
                        parameters.put("mch_id", wxPayResult.getMch_id());
                        parameters.put("nonce_str", wxPayResult.getNonce_str());
                        parameters.put("openid", wxPayResult.getOpenid());
                        parameters.put("out_trade_no", wxPayResult.getOut_trade_no());
                        parameters.put("result_code", wxPayResult.getResult_code());
                        parameters.put("return_code", wxPayResult.getReturn_code());
                        parameters.put("time_end", wxPayResult.getTime_end());
                        parameters.put("total_fee", wxPayResult.getTotal_fee());
                        parameters.put("trade_type", wxPayResult.getTrade_type());
                        parameters.put("transaction_id", wxPayResult.getTransaction_id());

                        //反校验签名
                        String sign = WXSignUtils.createSign("UTF-8", parameters);

                        if(sign.equals(wxPayResult.getSign())){
                            //修改订单的状态
                            orderService.alipayNotifyPayment(wxPayResult.getOut_trade_no(), wxPayResult.getTransaction_id(),2);
                              
                            writer.write(HttpXmlUtils.backWeixin("SUCCESS","OK"));
                        }else{
                            writer.write(HttpXmlUtils.backWeixin("FAIL","签名失败"));
                        }
                  }else{
                        writer.write(HttpXmlUtils.backWeixin("FAIL",wxPayResult.getReturn_msg()));
                        
                        System.out.println("---------微信支付返回Fail----------"+wxPayResult.getReturn_msg());
                  }

                  if(writer!=null){
                        writer.close();
                  }
                }else{
                  writer.write(HttpXmlUtils.backWeixin("FAIL","未获取到微信返回的结果"));
                }
            }catch(Exception e){
                e.printStackTrace();
            }
      }catch(Exception ex){
            ex.printStackTrace();
      }
    }



到这里差不多这个流程就算完了!!!!

http://img.blog.csdn.net/20160114102409341?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

觉得有用的欢迎评分!!!{:1_1:}

lqy144032 发表于 2018-11-2 09:07

在拼接xml请求支付时,微信没给你们公司发邮件么(说存在XXE漏洞),其实我认为是微信自己的问题,后来看了官方文档,建议是由微信自己封装的方法将map2xml和xml2map,不要循环拼接,这样微信就不会给警告了.可以参考一下 https://www.cnblogs.com/future/p/9266387.html

verybest2012 发表于 2017-7-24 10:46

谢谢楼主分享

lkjlkjhong 发表于 2017-7-24 10:55

谢谢楼主分享

87266381 发表于 2017-7-24 10:55

下载试验下怎么样

逆风的snail 发表于 2017-7-24 10:57

87266381 发表于 2017-7-24 10:55
下载试验下怎么样

有问题可以探讨沟通:handshake

luojizhihen 发表于 2017-7-24 10:58

谢谢楼主分享。

黑山走天涯 发表于 2017-7-24 11:01

支持下!谢谢分享!!!

落枫BJ 发表于 2017-7-24 11:06

牛的一批!

星落秋枫 发表于 2017-7-24 11:07

还没试过用java搞这个

白笙 发表于 2017-7-24 11:09

谢谢分享!可能以后用得到也说不定。
页: [1] 2 3 4 5
查看完整版本: 【分享】微信APP支付Java版的一个小demo