微信支付一 :公众号支付1

微信公众号支付H5调用支付详解

最近项目需要微信支付,然后看了下微信公众号支付,,虽然不难,但是细节还是需要注意的,用了大半天时间写了个demo,并且完整的测试了一下支付流程,下面分享一下微信公众号支付的经验。


一、配置公众号微信支付  

   需要我们配置微信公众号支付地址和测试白名单。

  微信支付一 :公众号支付1_第1张图片

     比如:支付JS页面的地址为 http://www.xxx.com/shop/pay/

            那此处配置www.xxx.com/shop/pay/


  二、开发流程

     借用微信公众号支付api(地址 http://pay.weixin.qq.com/wiki/doc/api/index.PHP?chapter=7_4),我们需要开发的为红色标记出的。如下:

    微信支付一 :公众号支付1_第2张图片

 

三、向微信服务器端下订单

             调用统一下单接口,这样就能获取微信支付的prepay_id(http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1)。

     在调用该接口前有几个字段是H5支付必须填写的openid

    3.1 获取openid

         可以通过网页授权形式(http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html)

       在微信中发送如下链接

      

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=要跳转的下订单的url&response_type=code&scope=snsapi_base&state=123#wechat_redirect


   3.2 下订单获取prepay_id

    代码如下,实际上是通过post发送一个xml 文件,获取微信服务器端发送过来的prepay_id。

   

[java]  view plain  copy
 
  1. import java.io.ByteArrayInputStream;  
  2. import java.io.IOException;  
  3. import java.io.InputStream;  
  4. import java.io.UnsupportedEncodingException;  
  5. import java.util.Date;  
  6. import java.util.HashMap;  
  7. import java.util.Iterator;  
  8. import java.util.Map;  
  9. import java.util.Map.Entry;  
  10. import java.util.Random;  
  11.   
  12. import javax.servlet.http.HttpServletRequest;  
  13. import javax.servlet.http.HttpServletResponse;  
  14.   
  15. import org.apache.commons.codec.digest.DigestUtils;  
  16. import org.springframework.stereotype.Controller;  
  17. import org.springframework.web.bind.annotation.RequestMapping;  
  18. import org.xmlpull.v1.XmlPullParser;  
  19. import org.xmlpull.v1.XmlPullParserException;  
  20. import org.xmlpull.v1.XmlPullParserFactory;  
  21.   
  22. import com.fasterxml.jackson.databind.JsonNode;  
  23. import com.gson.oauth.Oauth;  
  24. import com.gson.oauth.Pay;  
  25. import com.gson.util.HttpKit;  
  26. import com.sy.util.DatetimeUtil;  
  27. import com.sy.util.JsonUtil;  
  28.   
  29. @Controller  
  30. @RequestMapping("/pay")  
  31. public class WXPayController {  
  32.   
  33.     @RequestMapping(value = "wxprepay.do")  
  34.     public void jspay(HttpServletRequest request, HttpServletResponse response, String callback) throws Exception {  
  35.         // 获取openid  
  36.         String openId = SessionUtil.getAtt(request, "openId");  
  37.         if (openId == null) {  
  38.             openId = getUserOpenId(request);  
  39.         }  
  40.   
  41.         String appid = "wx16691fcb0523c1a4";  
  42.         String paternerKey = "ININGFENG1234567fdfwfdfd1ss234567";  
  43.           
  44.         String out_trade_no = getTradeNo();  
  45.         Map paraMap = new HashMap();  
  46.         paraMap.put("appid", appid);  
  47.         paraMap.put("attach""测试");  
  48.         paraMap.put("body""测试购买支付");  
  49.         paraMap.put("mch_id""10283271");  
  50.         paraMap.put("nonce_str", create_nonce_str());  
  51.         paraMap.put("openid", openId);  
  52.         paraMap.put("out_trade_no", out_trade_no);  
  53.         paraMap.put("spbill_create_ip", getAddrIp(request));  
  54.         paraMap.put("total_fee""1");  
  55.         paraMap.put("trade_type""JSAPI");  
  56.         paraMap.put("notify_url""http://www.xxx.co/bank/page/wxnotify");  
  57.         String sign = getSign(paraMap, paternerKey);  
  58.         paraMap.put("sign", sign);  
  59.   
  60.         // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder  
  61.         String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";  
  62.   
  63.         String xml = ArrayToXml(paraMap);  
  64.   
  65.         String xmlStr = HttpKit.post(url, xml);  
  66.   
  67.         // 预付商品id  
  68.         String prepay_id = "";  
  69.   
  70.         if (xmlStr.indexOf("SUCCESS") != -1) {  
  71.             Map map = doXMLParse(xmlStr);  
  72.             prepay_id = (String) map.get("prepay_id");  
  73.         }  
  74.   
  75.         Map payMap = new HashMap();  
  76.         payMap.put("appId", appid);  
  77.         payMap.put("timeStamp", create_timestamp());  
  78.         payMap.put("nonceStr", create_nonce_str());  
  79.         payMap.put("signType""MD5");  
  80.         payMap.put("package""prepay_id=" + prepay_id);  
  81.         String paySign = getSign(payMap, paternerKey);  
  82.           
  83.         payMap.put("pg", prepay_id);  
  84.         payMap.put("paySign", paySign);  
  85.           
  86.           
  87.         WebUtil.response(response, WebUtil.packJsonp(callback, JsonUtil.warpJsonNodeResponse(JsonUtil.objectToJsonNode(payMap)).toString()));  
  88.     }  
  89.   
  90.     /** 
  91.      * map转成xml 
  92.      *  
  93.      * @param arr 
  94.      * @return 
  95.      */  
  96.     public String ArrayToXml(Map arr) {  
  97.         String xml = "";  
  98.   
  99.         Iterator> iter = arr.entrySet().iterator();  
  100.         while (iter.hasNext()) {  
  101.             Entry entry = iter.next();  
  102.             String key = entry.getKey();  
  103.             String val = entry.getValue();  
  104.             xml += "<" + key + ">" + val + " + key + ">";  
  105.         }  
  106.   
  107.         xml += "";  
  108.         return xml;  
  109.     }  
  110.   
  111.     // 获取openId  
  112.     private String getUserOpenId(HttpServletRequest request) throws Exception {  
  113.         String code = request.getParameter("code");  
  114.         if (code == null) {  
  115.             String openId = request.getParameter("openId");  
  116.             return openId;  
  117.         }  
  118.         Oauth o = new Oauth();  
  119.         String token = o.getToken(code);  
  120.         JsonNode node = JsonUtil.StringToJsonNode(token);  
  121.         String openId = node.get("openid").asText();  
  122.         return openId;  
  123.     }  
  124.   
  125.     private String create_nonce_str() {  
  126.             String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";  
  127.             String res = "";  
  128.             for (int i = 0; i < 16; i++) {  
  129.                 Random rd = new Random();  
  130.                 res += chars.charAt(rd.nextInt(chars.length() - 1));  
  131.             }  
  132.             return res;  
  133.     }  
  134.       
  135.     private String getAddrIp(HttpServletRequest request){  
  136.         return request.getRemoteAddr();  
  137.     }  
  138.   
  139.     private String create_timestamp() {  
  140.         return Long.toString(System.currentTimeMillis() / 1000);  
  141.     }  
  142.       
  143.     private String getTradeNo(){  
  144.         String timestamp = DatetimeUtil.formatDate(new Date(), DatetimeUtil.DATETIME_PATTERN);  
  145.         return "HZNO" + timestamp;  
  146.     }  
  147.       
  148.     private String getSign(Map params, String paternerKey )  
  149.             throws UnsupportedEncodingException {  
  150.         String string1 = Pay.createSign(params, false);  
  151.         String stringSignTemp = string1 + "&key=" + paternerKey;  
  152.         String signValue = DigestUtils.md5Hex(stringSignTemp).toUpperCase();  
  153.         return  signValue;  
  154.     }  
  155.   
  156.     private Map doXMLParse(String xml)  
  157.             throws XmlPullParserException, IOException {  
  158.   
  159.         InputStream inputStream = new ByteArrayInputStream(xml.getBytes());  
  160.   
  161.         Map map = null;  
  162.   
  163.         XmlPullParser pullParser = XmlPullParserFactory.newInstance()  
  164.                 .newPullParser();  
  165.   
  166.         pullParser.setInput(inputStream, "UTF-8"); // 为xml设置要解析的xml数据  
  167.   
  168.         int eventType = pullParser.getEventType();  
  169.   
  170.         while (eventType != XmlPullParser.END_DOCUMENT) {  
  171.             switch (eventType) {  
  172.             case XmlPullParser.START_DOCUMENT:  
  173.                 map = new HashMap();  
  174.                 break;  
  175.   
  176.             case XmlPullParser.START_TAG:  
  177.                 String key = pullParser.getName();  
  178.                 if (key.equals("xml"))  
  179.                     break;  
  180.   
  181.                 String value = pullParser.nextText();  
  182.                 map.put(key, value);  
  183.   
  184.                 break;  
  185.   
  186.             case XmlPullParser.END_TAG:  
  187.                 break;  
  188.   
  189.             }  
  190.   
  191.             eventType = pullParser.next();  
  192.   
  193.         }  
  194.   
  195.         return map;  
  196.     }  
  197.   
  198. }  

四、H5支付

      H5支付其实很简单,只需要调用微信内嵌浏览器的js方法就行(http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=7_7)

   

[plain]  view plain  copy
 
  1. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>  
  2. <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>  
  3. <%  
  4.     String path = request.getContextPath();  
  5.     String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/";  
  6. %>  
  7.   
  8.   
  9.   
  10.   
  11.   
  12.   
  13.   
  14.   
  15. 测试支付  
  16.   
  17.   
  18.   
  19.   
  20.       
  21.         微信js支付测试
  
  •           
  •           
  •           
  •             
        
    •                 
    • 测试支付信息
    •   
    •             
      
  •             立即支付

      
  •         
  •   
  •     
  •   
  •   
  •       
  •       
  •       
  •        
  •     var appId = urlparameter("appId");  
  •     var timeStamp = urlparameter("timeStamp");  
  •     var nonceStr = urlparameter("nonceStr");  
  •     var pg = urlparameter("pg");  
  •     var signType = urlparameter("signType");  
  •     var paySign = urlparameter("paySign");  
  •       
  •       
  •       function onBridgeReady(){  
  •            
  •            WeixinJSBridge.invoke(  
  •                'getBrandWCPayRequest', {  
  •                    "appId" : appId,     //公众号名称,由商户传入       
  •                    "timeStamp": timeStamp,         //时间戳,自1970年以来的秒数       
  •                    "nonceStr" : nonceStr, //随机串       
  •                    "package" : "prepay_id=" + pg,       
  •                    "signType" : signType,         //微信签名方式:       
  •                    "paySign" : paySign    //微信签名   
  •                },  
  •                  
  •                function(res){       
  •                    if(res.err_msg == "get_brand_wcpay_request:ok" ) {  
  •                          
  •                        alert("支付成功");  
  •                    }     // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。   
  •                }  
  •            );   
  •         }  
  •         
  •         
  •         function pay(){  
  •               
  •             if (typeof WeixinJSBridge == "undefined"){  
  •                if( document.addEventListener ){  
  •                    document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);  
  •                }else if (document.attachEvent){  
  •                    document.attachEvent('WeixinJSBridgeReady', onBridgeReady);   
  •                    document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);  
  •                }  
  •             }else{  
  •                onBridgeReady();  
  •             }   
  •               
  •         }  
  •       
  •   
  •   

  • 效果如下

    微信支付一 :公众号支付1_第3张图片


    转载于:http://blog.csdn.net/u014351782/article/details/52186932

    你可能感兴趣的:(微信开发-JAVA)