微信開發 3 微信支付
微信開發(3)微信支付
一、 微信後臺設定
1.新增測試授權目錄和測試白名單:
在微信後臺,設定測試授權目錄,如http://xxx.sinaapp.com/example/,測試白名單中新增你的微訊號。 注意,這裡的“個人微訊號”既不是qq號也不是個人暱稱。而是登入微信後在“我”介面中的“微訊號”欄位的字串。 支付授權目錄設不設無所謂,因為我們只是測試。
2.列表內容
設定網頁授權域名: 在“開發者中心/介面許可權表/網頁賬號/網頁授權獲取使用者基本資訊”中進行設定。網頁授權域名設定為測試伺服器的域名,如:xxx.sinaapp.com,不需要http://。
二、商戶平臺設定
1.下載證書
在“賬戶設定/API安全/API證書”中下載。需要用到管理員的手機驗證碼。下載後的進行解壓縮,我們需要用到的是apiclient_key.pem和apiclient_cert.pem。
2.生成支付key
在“賬戶設定/API安全/API金鑰”中進行設定。支付key將在支付時用到,這個值就是原始碼配置檔案中的KEY常量。
三、使用官方V3.7的示例程式碼
1、在Wxpay.pub.config.php修改配置,主要是:
const APPID //公眾號中“開發者中心”看到的AppID const MCHID //微信支付商戶資料稽核成功郵件中的商戶號 const KEY //你在商戶平臺中設定的支付key const APPSECRET //公眾號中“開發者中心”看到的AppSecret const JS_API_CALL_URL //設定這個url,可在此頁面中獲得使用者的openid。 //證書路徑,注意應該填寫絕對路徑 const SSLCERT_PATH // apiclient_cert.pem檔案url const SSLKEY_PATH // apiclient_key.pem檔案url,如’/cert/ apiclient_key.pem’ const NOTIFY_URL //非同步通知url,可使用demo中的notify_url.php
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
2、修改官方程式碼中的bug: 如果出現“curl_setopt() expects parameter 2 to be long”錯誤,是因為WxPayPubHelper.php中有幾個地方將“curl_setopt”拼錯了,拼成“curl_setop”,將其修改後即可。如果出現“curl_close(): 11 is not a valid”,則是因為錯誤地關閉了一個已經關閉的curl session,可以將curl_close()程式碼加上如下判斷:
if(gettype($ch) == 'resource') curl_close($ch);
- 1
3、官方demo直接跑不通,我們需要自己搞定它。首先中index.php中增加一個連結:
<a href="pay.php"> 獲取openid</a></h4>
- 1
3、 然後寫一個pay.php頁面,用於獲取使用者openid併發起支付:
<?php/** * JS_API支付demo * ==================================================== * 在微信瀏覽器裡面開啟H5網頁中執行JS調起支付。介面輸入輸出資料格式為JSON。 * 成功調起支付需要三個步驟: * 步驟1:網頁授權獲取使用者openid * 步驟2:使用統一支付介面,獲取prepay_id * 步驟3:使用jsapi調起支付 */include_once ("WxPayPubHelper.php");$jsApi = new JsApi_pub();// =========步驟1:網頁授權獲取使用者openid============// 通過code獲得openidif (! isset($_GET['code'])) { // 觸發微信返回code碼 $url = $jsApi->createOauthUrlForCode(WxPayConf_pub::JS_API_CALL_URL); Header("Location: $url");} else { // 獲取code碼,以獲取openid $code = $_GET['code']; $jsApi->setCode($code); $openid = $jsApi->getOpenId();}$goods = "test";// 使用統一支付介面$unifiedOrder = new UnifiedOrder_pub();$unifiedOrder->setParameter("openid", "$openid"); // 使用者openid$unifiedOrder->setParameter("body", "$goods"); // 商品描述 // 自定義訂單號,此處僅作舉例$timeStamp = time();$out_trade_no = WxPayConf_pub::APPID . "$timeStamp"; // 商戶訂單號$unifiedOrder->setParameter("out_trade_no", "$out_trade_no");$price = "1";$unifiedOrder->setParameter("total_fee", "$price"); // 總金額$unifiedOrder->setParameter("notify_url", WxPayConf_pub::NOTIFY_URL); // 通知地址$unifiedOrder->setParameter("trade_type", "JSAPI"); // 交易型別$prepay_id = $unifiedOrder->getPrepayId();// =========步驟3:使用jsapi調起支付============$jsApi->setPrepayId($prepay_id);$jsApiParameters = $jsApi->getParameters();echo $jsApiParameters;?><html><head><meta http-equiv="content-type" content="text/html;charset=utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1.0" /><title>微信安全支付</title><script type="text/javascript"> //呼叫微信JS api 支付 function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', <?php echo $jsApiParameters; ?>, function(res){ WeixinJSBridge.log(res.err_msg); //alert(res.err_code+res.err_desc+res.err_msg); } ); } function callpay() { if (typeof WeixinJSBridge == "undefined"){ if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } }else{ jsApiCall(); } } </script></head><body> <p> </p> <p> </p> <div align="center"> <table border="1"> <tr> <td>openID</td> <td><?php echo $openid;?></td> </tr> <tr> <td>商品名稱</td> <td><?php echo $goods;?></td> </tr> <tr> <td>訂單號</td> <td><?php echo $out_trade_no;?></td> </tr> <tr> <td>prepay_id</td> <td><?php echo $prepay_id;?></td> </tr> <tr> <td>價格</td> <td><?php echo $price;?></td> </tr> </table> <button data-theme="b" type="button" onclick="callpay()">貢獻一下</button> </div></body></html>
- 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
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
四、使用官方V3的示例程式碼
2、將demo解壓縮放到你的web根目錄下。比如,壓縮包解開後的目錄是WxpayAPI_php_v3,你要進入這個目錄後將所有檔案選中,然後複製到你的專案目錄中去。在這個目錄中有一個index.php,那麼到測試時候需要訪問 http://xxx.sinaapp.com/index.php。
4、在你的微信中,隨便開啟一個對話視窗,輸入index.php地址,如http://xxx.sinaapp.com/index.php,然後在對話視窗中點選這個連結。會出現幾個按鈕,點“JSAPI支付”的按鈕,即可彈出支付金額為1分錢的視窗,輸入收貨人,支付。即會彈出支付成功介面。 到這一步,說明官方的支付程式碼是基本可用的,接下來,我們可以在它的基礎上修改成自己的程式碼。
5、替換cert目錄下的apiclient_key.pem和apiclient_cert.pem成你自己的證書。
6、修改WxPay.Config.php中的以下幾項成你自己的:
const APPID //公眾號中“開發者中心”看到的AppIDconst MCHID //微信支付商戶資料稽核成功郵件中的商戶號const KEY //你在商戶平臺中設定的支付keyconst APPSECRET //公眾號中“開發者中心”看到的AppSecret
- 1
- 2
- 3
- 4
7、因為我們使用了sina的sae作為測試伺服器,sae不允許直接寫檔案io,因此可以將官網程式碼中的檔案操作進行相應的修改(使用SaeStorage)。也就是需要修改log.php中的CLogFileHandler類:
class CLogFileHandler implements ILogHandler{ private $fn=null; private $ss=null; public function __construct($file = '') { $this->fn=str_replace("../logs/", "", $file); $this->ss=new SaeStorage(); } public function write($msg) { $bytes = $this->ss->read('log', $this->fn); $str = $bytes; $this->ss->write('log', $this->fn, "$str\n$msg"); } public function __destruct() { $fn=null; $ss=null; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
8、如果出現簽名失敗的錯誤,我們可以使用微信的支付介面除錯工具來進行測試:https://pay.weixin.qq.com/wiki/tools/signverify/。 這個工具是雖然是用於驗證“被掃支付”的,但通過它的“增加引數”按鈕和“刪除引數”按鈕,我們也可以用它來測試“公眾號支付”。例如,如果你提交的xml內容如下(可利用Log函式儲存提交的xml內容到sae storage,然後下載日誌檔案):
<xml><openid><![CDATA[om8888LTHBj99992Qgl_eUAOFgxs]]></openid><body><![CDATA[test]]></body><out_trade_no><![CDATA[wx111196222243ffa1143858aaaa]]></out_trade_no><total_fee>1</total_fee><notify_url><![CDATA[http://xxx.sinaapp.com/wxpay/demo/notify_url.php]]></notify_url><trade_type><![CDATA[JSAPI]]></trade_type><appid><![CDATA[wx000096104a431111]]></appid><mch_id>6666833333</mch_id><spbill_create_ip><![CDATA[10.211.76.107]]></spbill_create_ip><nonce_str><![CDATA[1agieoxyi8hc7e817rsnjlyn9lxmsnxj]]></nonce_str><sign><![CDATA[817034E4DE8E6067EB85CDF7318EF0A1]]></sign></xml>
- 1
則你可以中測試工具中這樣填寫表單: 點選“生成簽名”。將得到的簽名和日誌檔案中的簽名進行比較,看是否一致,即可排除簽名演算法的問題。 如果2個簽名一致,則可以肯定是支付key的問題。要麼是產品MM搞錯了,要麼是AppSecret和支付key搞反了(有一次產品MM告訴了為一個錯誤的支付key,浪費了我3天的時間!我反覆確認了每一處程式碼、每一次後臺引數設定之後,最終用“支付介面除錯工具”確認簽名無誤,問題就出在支付key上。於是登入商戶平臺,因為不是管理員,又跟產品MM要了手機驗證碼,重新設定了支付key,程式碼一下就通了)