網站添加微信支付功能(小白填坑)


本周的工作安排就是在網站添加支付功能,包括支付寶、微信、財付通等,今天這篇文章先說一下微信支付吧,支付寶的太容易了基本看一下都會了

1、首先准備工作,開通了支付功能的賬號,具體怎么開通的我也不熟悉因為我做的時候都是使用開通好的賬號(目前微信支付好像只支持商家不支持個人吧?)

2、按照我的性格當然是百度一下啦,但是微信支付的文檔說明事例實在是太坑了,完全不是我這種小白可以一下看懂的,在這誇獎一下支付寶,支付寶的事例文檔做的太好了基本做的時候沒什么坑

准備工作結束開工:

我的開發環境是java,所以去官方找代碼不得不說太TM坑了 java版本的好像是維護的最不好的,人家其他的那么多

你看java的 不說了,沒有掃碼支付的,但是我這次使用的肯定是掃碼啊 ,只好繼續百度了。

找到了這個項目,是git上一個人維護的,我看了一下基本符合我的需求,就按照這個改吧

 

WxPayDto.java是微信發送消息的實體類

WxPayResult.java是接收到回調消息的實體類

具體的操作看下面:

具體的操作之前需要先得到幾個必須的參數

	//微信支付商戶開通后 微信會提供appid和appsecret和商戶號partner
	private static String appid = "";
	private static String appsecret = "";
	private static String partner = "";
	//這個參數partnerkey是在商戶后台配置的一個32位的key,微信商戶平台-賬戶設置-安全設置-api安全
	private static String partnerkey = "";
	//openId 是微信用戶針對公眾號的標識,授權的部分這里不解釋
	private static String openId = "";
	//微信支付成功后通知地址 必須要求80端口並且地址不能帶參數
	private static String notifyurl = "";		

 參數什么的都是直接客戶提供給我的,你們如果是自己開發獲取這些參數的時候可能不知道具體位置,我建議你百度一下因為如果參數都不知道怎么獲取還談什么開發接口啊

   這里有幾點需要說明一下的

   openid我沒設置 不知道是干什么 隨便填了成了客戶商戶ID反正也沒報錯。

notifyurl 是交易成功后回調的地址,需要在公眾賬號的后台設置一下,否則即使交易成功返回信息也是錯誤的。

微信支付的步驟是 獲取交易的二維碼,這個二維碼是通過你傳入的商品ID 價格等信息 微信生成的,用戶掃碼后啟動微信的支付客戶端,支付成功后回調你設置的回調地址
那第一步獲取微信支付的二維碼看代碼:
   //掃碼支付
        WxPayDto tpWxPay1 = new WxPayDto();
        tpWxPay1.setBody(gp.getPackname());
        tpWxPay1.setOrderId(of.getOrder_id());
        tpWxPay1.setSpbillCreateIp(request.getRemoteAddr());
        tpWxPay1.setTotalFee(gp.getFee());
        mv.addObject("txcode", getCodeurl(tpWxPay1));


 

       public String getCodeurl(WxPayDto tpWxPayDto){
            
            // 1 參數
            // 訂單號
            String orderId = tpWxPayDto.getOrderId(); // 附加數據 原樣返回 String attach = ""; // 總金額以分為單位,不帶小數點 String totalFee = getMoney(tpWxPayDto.getTotalFee()); // 訂單生成的機器 IP String spbill_create_ip = tpWxPayDto.getSpbillCreateIp(); // 這里notify_url是 支付完成后微信發給該鏈接信息,可以判斷會員是否支付成功,改變訂單狀態等。 String notify_url = notifyurl; String trade_type = "NATIVE"; // 商戶號 String mch_id = partner; // 隨機字符串 String nonce_str = getNonceStr(); // 商品描述根據情況修改 String body = tpWxPayDto.getBody(); // 商戶訂單號 String out_trade_no = orderId; SortedMap<String, String> packageParams = new TreeMap<String, String>(); packageParams.put("appid", appid); packageParams.put("mch_id", mch_id); packageParams.put("nonce_str", nonce_str); packageParams.put("body", body); packageParams.put("attach", attach); packageParams.put("out_trade_no", out_trade_no); // 這里寫的金額為1 分到時修改 packageParams.put("total_fee", totalFee); packageParams.put("spbill_create_ip", spbill_create_ip); packageParams.put("notify_url", notify_url); packageParams.put("trade_type", trade_type); RequestHandler reqHandler = new RequestHandler(null, null); reqHandler.init(appid, appsecret, partnerkey); String sign = reqHandler.createSign(packageParams); String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>" + mch_id + "</mch_id>" + "<nonce_str>" + nonce_str + "</nonce_str>" + "<sign>" + sign + "</sign>" + "<body><![CDATA[" + body + "]]></body>" + "<out_trade_no>" + out_trade_no + "</out_trade_no>" + "<attach>" + attach + "</attach>" + "<total_fee>" + totalFee + "</total_fee>" + "<spbill_create_ip>" + spbill_create_ip + "</spbill_create_ip>" + "<notify_url>" + notify_url + "</notify_url>" + "<trade_type>" + trade_type + "</trade_type>" + "</xml>"; String code_url = ""; String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; code_url = new GetWxOrderno().getCodeUrl(createOrderURL, xml); System.out.println("code_url----------------"+code_url); return code_url; }

 

設置好參數后直接調用getCodeurl()函數就能獲取到微信的二維碼了,如果返回的信息錯誤,可以斷點跟蹤一下看看
 code_url = new GetWxOrderno().getCodeUrl(createOrderURL, xml); 這句返回的具體錯誤信息。

如果這部成功的話,你應該會得到一個類似這樣的地址:weixin://wxpay/bizpayurl?pr=eYaNVZF

在前台直接使用qrcode.js將這個地址生成二維碼顯示在頁面上,我的前台頁面代碼是這樣的
<!doctype html>
<html>
 <head>
  <title>掃碼支付前台demo</title>
  <meta name="keywords" content="關鍵字">
  <meta name="description" content="描述">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <script src=""></script>
  <script src="http://localhost:8080/shopping/resources/newstyle/js/qrcode.js"></script>
 </head>

 <body>
    
    <div align="center" id="qrcode">
        <p >
        掃碼商品二維碼付款
        <br><br>
        </p>
    </div>
 </body>

 <script>
     //這個地址是Demo.java生成的code_url,這個很關鍵
    var url = "weixin://wxpay/bizpayurl?pr=eYaNVZF"; //參數1表示圖像大小,取值范圍1-10;參數2表示質量,取值范圍'L','M','Q','H' var qr = qrcode(10, 'M'); qr.addData(url); qr.make(); var dom=document.createElement('DIV'); dom.innerHTML = qr.createImgTag(); var element=document.getElementById("qrcode"); element.appendChild(dom); </script> </html>

 

接下來到了一個小技巧的提供時間了 ,由於微信的回調地址要求必須是80端口還必須是是外網的,咱們開發都是局域網而且也沒有域名啊 ,怎么辦?當然有辦法了神器登場 ngrok
如果你用的是原版的ngrok 他每次自動生成的二級域名都是隨機生成的 ,這樣會很麻煩因為每次都要修改微信的后台,后來又找到了一個國內的,不但不用翻牆了還可以定制指定的二級域名
http://natapp.cn/ 去這網址,絕對比原版的好用
這是我本機的參數配置,zy是二級域名,8080端口是我的resin的啟動地址,這樣我就可以使用http://zy.ngrok.natapp.cn這樣的域名來訪問我的本機網站了
ngrok -config ngrok.cfg -subdomain  zy 8080
回調地址直接配置成:http://zy.ngrok.natapp.cn/你的處理回調頁面.jsp
這樣就可以實現在本機的調試,這東西我是找了好幾個小時才發現的 ,真心的好用啊
以后微信的相關接口開發都可以使用這個啊

接下來就是接受微信的回調頁面了可以說的不多直接上代碼
       @RequestMapping({"/notifyurl.htm"})
       public void notifyurl(HttpServletRequest request, HttpServletResponse response) throws IOException { //把如下代碼貼到的你的處理回調的servlet 或者.do 中即可明白回調操作 System.out.print("微信支付回調數據開始"); //示例報文 //String xml = "<xml><appid><![CDATA[wxb4dc385f953b356e]]></appid><bank_type><![CDATA[CCB_CREDIT]]></bank_type><cash_fee><![CDATA[1]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[Y]]></is_subscribe><mch_id><![CDATA[1228442802]]></mch_id><nonce_str><![CDATA[1002477130]]></nonce_str><openid><![CDATA[o-HREuJzRr3moMvv990VdfnQ8x4k]]></openid><out_trade_no><![CDATA[jdg_16042915230001]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[1269E03E43F2B8C388A414EDAE185CEE]]></sign><time_end><![CDATA[20150324100405]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[JSAPI]]></trade_type><transaction_id><![CDATA[1009530574201503240036299496]]></transaction_id></xml>";  String inputLine; String notityXml="" ; String resXml = ""; try { while ((inputLine = request.getReader().readLine()) != null) { notityXml += inputLine; } request.getReader().close(); } catch (Exception e) { e.printStackTrace(); } System.out.println("接收到的報文:" + notityXml); Map m = parseXmlToList2(notityXml); WxPayResult wpr = new WxPayResult(); wpr.setAppid(m.get("appid").toString()); wpr.setBankType(m.get("bank_type").toString()); wpr.setCashFee(m.get("cash_fee").toString()); wpr.setFeeType(m.get("fee_type").toString()); wpr.setIsSubscribe(m.get("is_subscribe").toString()); wpr.setMchId(m.get("mch_id").toString()); wpr.setNonceStr(m.get("nonce_str").toString()); wpr.setOpenid(m.get("openid").toString()); wpr.setOutTradeNo(m.get("out_trade_no").toString()); wpr.setResultCode(m.get("result_code").toString()); wpr.setReturnCode(m.get("return_code").toString()); wpr.setSign(m.get("sign").toString()); wpr.setTimeEnd(m.get("time_end").toString()); wpr.setTotalFee(m.get("total_fee").toString()); wpr.setTradeType(m.get("trade_type").toString()); wpr.setTransactionId(m.get("transaction_id").toString()); if("SUCCESS".equals(wpr.getResultCode())){ //支付成功 //加入支付成功業務邏輯 if(this.isczok(wpr.getOutTradeNo()))//判斷該筆訂單是否在商戶網站中已經做過處理  { if(this.addusergoldandlog(wpr.getOutTradeNo()))//增加用戶金幣寫入訂單記錄  { if(setorderstate(wpr.getOutTradeNo(),1)) { resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; } } else { resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[增加金幣失敗]]></return_msg>" + "</xml> "; } }else{ resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[訂單已經處理過了]]></return_msg>" + "</xml> "; } } else { resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[微信返回結果錯誤]]></return_msg>" + "</xml> "; setorderstate(wpr.getOutTradeNo(),2);//講訂單狀態更改成支付失敗  } System.out.println("微信支付回調數據結束"); BufferedOutputStream out = new BufferedOutputStream( response.getOutputStream()); out.write(resXml.getBytes()); out.flush(); out.close(); } /** * description: 解析微信通知xml * * @param xml * @return * @author ex_yangxiaoyi * @see */ @SuppressWarnings({ "unused", "rawtypes", "unchecked" }) private static Map parseXmlToList2(String xml) { Map retMap = new HashMap(); try { StringReader read = new StringReader(xml); // 創建新的輸入源SAX 解析器將使用 InputSource 對象來確定如何讀取 XML 輸入 InputSource source = new InputSource(read); // 創建一個新的SAXBuilder SAXBuilder sb = new SAXBuilder(); // 通過輸入源構造一個Document Document doc = (Document) sb.build(source); Element root = doc.getRootElement();// 指向根節點 List<Element> es = root.getChildren(); if (es != null && es.size() != 0) { for (Element element : es) { retMap.put(element.getName(), element.getValue()); } } } catch (Exception e) { e.printStackTrace(); } return retMap; }

注意:接受到的都是xml格式的數據,騰訊的坑爹團隊,都什么年代了還用xml

其中需要注意的是,如果交易成功后要在頁面中直接返回

"<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "
我這個代碼中的好像沒成功,我准備再修改一下,你們誰知道應該怎么寫的可以私信我
想我這么寫雖然交易成功,但是微信一直沒收到你的反饋會一直異步請求你的頁面,具體會請求多久我沒看到文檔里寫,不過一般其他支付的也就是請求幾次

這篇文章寫的非常倉促,很多細節都沒說到,等接下來有時間一定將文章好好整理一下
 




 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM