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

本文详细解析了微信APP支付的实现流程,从签名生成、XML参数构造到统一下单及回调处理,分享了一套完整的解决方案,特别强调了中文编码问题及签名验证的重要性。

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

//参数:开始生成签名  

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>[url]http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>[/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.youkuaiyun.com/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();  
        }  
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值