http://www.cnblogs.com/24la/p/wxpay-native-qrcode-codeigniter.html
CI:3.0.5
微信支付API類庫來自:https://github.com/zhangv/wechat-pay
請先看一眼官方場景及支付時序圖:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
官方API清單:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
二維碼生成類庫:phpqrcode
走了幾天的彎路,直到遇到Lamtin指點(熱心網友),他說你既然是內建到CI為何不自己寫,我想了想是啊,為什麼我一直陷入官方sdk的漩渦裡不能跳出來去看這件事,官方提供了API接口,你隻需要去調用這些接口啊,post參數啊,是吧,後悔浪費了3天時間。為了不讓你們和我一樣我把我的思路及代碼釋出出來,有什麼問題可以留言。
我們為什麼使用三方支付類庫?
縱觀微信支付的sdk或者其他的微信支付demo,或多或少的都是圍繞官方API接口來寫,增加些自己用的方法友善調用之類的,而如果我自己再去寫這樣的一個東西,第一可能組織不好,基礎弱啊,第二可能需要花費大量時間,鑒于此我去尋找比較好用的别人封裝的API類庫好了,終于不負所望,真有,隻可以這個類庫幾乎沒有人用,不過真不錯
<code>class</code> <code>WechatPay {</code>
<code> </code><code>const</code> <code>TRADETYPE_JSAPI = </code><code>'JSAPI'</code><code>,TRADETYPE_NATIVE = </code><code>'NATIVE'</code><code>,TRADETYPE_APP = </code><code>'APP'</code><code>;</code>
<code> </code><code>const</code> <code>URL_UNIFIEDORDER = </code><code>"https://api.mch.weixin.qq.com/pay/unifiedorder"</code><code>;</code>
<code> </code><code>const</code> <code>URL_ORDERQUERY = </code><code>"https://api.mch.weixin.qq.com/pay/orderquery"</code><code>;</code>
<code> </code><code>const</code> <code>URL_CLOSEORDER = </code><code>'https://api.mch.weixin.qq.com/pay/closeorder'</code><code>;</code>
<code> </code><code>const</code> <code>URL_REFUND = </code><code>'https://api.mch.weixin.qq.com/secapi/pay/refund'</code><code>;</code>
<code> </code><code>const</code> <code>URL_REFUNDQUERY = </code><code>'https://api.mch.weixin.qq.com/pay/refundquery'</code><code>;</code>
<code> </code><code>const</code> <code>URL_DOWNLOADBILL = </code><code>'https://api.mch.weixin.qq.com/pay/downloadbill'</code><code>;</code>
<code> </code><code>const</code> <code>URL_REPORT = </code><code>'https://api.mch.weixin.qq.com/payitil/report'</code><code>;</code>
<code> </code><code>const</code> <code>URL_SHORTURL = </code><code>'https://api.mch.weixin.qq.com/tools/shorturl'</code><code>;</code>
<code> </code><code>const</code> <code>URL_MICROPAY = </code><code>'https://api.mch.weixin.qq.com/pay/micropay'</code><code>;</code>
<code> </code><code>/**</code>
<code> </code><code>* 錯誤資訊</code>
<code> </code><code>*/</code>
<code> </code><code>public</code> <code>$error</code> <code>= null;</code>
<code> </code><code>* 錯誤資訊XML</code>
<code> </code><code>public</code> <code>$errorXML</code> <code>= null;</code>
<code> </code><code>* 微信支付配置數組</code>
<code> </code><code>* appid 公衆賬号appid</code>
<code> </code><code>* mch_id 商戶号</code>
<code> </code><code>* apikey 加密key</code>
<code> </code><code>* appsecret 公衆号appsecret</code>
<code> </code><code>* sslcertPath 證書路徑(apiclient_cert.pem)</code>
<code> </code><code>* sslkeyPath 密鑰路徑(apiclient_key.pem)</code>
<code> </code><code>private</code> <code>$_config</code><code>;</code>
<code> </code><code>* @param $config 微信支付配置數組</code>
<code> </code><code>public</code> <code>function</code> <code>__construct(</code><code>$config</code><code>) {</code>
<code> </code><code>$this</code><code>->_config = </code><code>$config</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>* JSAPI擷取prepay_id</code>
<code> </code><code>* @param $body</code>
<code> </code><code>* @param $out_trade_no</code>
<code> </code><code>* @param $total_fee</code>
<code> </code><code>* @param $notify_url</code>
<code> </code><code>* @param $openid</code>
<code> </code><code>* @return null</code>
<code> </code><code>public</code> <code>function</code> <code>getPrepayId(</code><code>$body</code><code>,</code><code>$out_trade_no</code><code>,</code><code>$total_fee</code><code>,</code><code>$notify_url</code><code>,</code><code>$openid</code><code>) {</code>
<code> </code><code>$data</code> <code>= </code><code>array</code><code>();</code>
<code> </code><code>$data</code><code>[</code><code>"nonce_str"</code><code>] = </code><code>$this</code><code>->get_nonce_string();</code>
<code> </code><code>$data</code><code>[</code><code>"body"</code><code>] = </code><code>$body</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"out_trade_no"</code><code>] = </code><code>$out_trade_no</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"total_fee"</code><code>] = </code><code>$total_fee</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"spbill_create_ip"</code><code>] = </code><code>$_SERVER</code><code>[</code><code>"REMOTE_ADDR"</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"notify_url"</code><code>] = </code><code>$notify_url</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"trade_type"</code><code>] = self::TRADETYPE_JSAPI;</code>
<code> </code><code>$data</code><code>[</code><code>"openid"</code><code>] = </code><code>$openid</code><code>;</code>
<code> </code><code>$result</code> <code>= </code><code>$this</code><code>->unifiedOrder(</code><code>$data</code><code>);</code>
<code> </code><code>if</code> <code>(</code><code>$result</code><code>[</code><code>"return_code"</code><code>] == </code><code>"SUCCESS"</code> <code>&& </code><code>$result</code><code>[</code><code>"result_code"</code><code>] == </code><code>"SUCCESS"</code><code>) {</code>
<code> </code><code>return</code> <code>$result</code><code>[</code><code>"prepay_id"</code><code>];</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
<code> </code><code>$this</code><code>->error = </code><code>$result</code><code>[</code><code>"return_code"</code><code>] == </code><code>"SUCCESS"</code> <code>? </code><code>$result</code><code>[</code><code>"err_code_des"</code><code>] : </code><code>$result</code><code>[</code><code>"return_msg"</code><code>];</code>
<code> </code><code>$this</code><code>->errorXML = </code><code>$this</code><code>->array2xml(</code><code>$result</code><code>);</code>
<code> </code><code>return</code> <code>null;</code>
<code> </code><code>}</code>
<code> </code><code>private</code> <code>function</code> <code>get_nonce_string() {</code>
<code> </code><code>return</code> <code>substr</code><code>(</code><code>str_shuffle</code><code>(</code><code>"abcdefghijklmnopqrstuvwxyz0123456789"</code><code>),0,32);</code>
<code> </code><code>* 統一下單接口</code>
<code> </code><code>public</code> <code>function</code> <code>unifiedOrder(</code><code>$params</code><code>) {</code>
<code> </code><code>$data</code><code>[</code><code>"appid"</code><code>] = </code><code>$this</code><code>->_config[</code><code>"appid"</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"mch_id"</code><code>] = </code><code>$this</code><code>->_config[</code><code>"mch_id"</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"device_info"</code><code>] = (isset(</code><code>$params</code><code>[</code><code>'device_info'</code><code>])&&trim(</code><code>$params</code><code>[</code><code>'device_info'</code><code>])!=</code><code>''</code><code>)?</code><code>$params</code><code>[</code><code>'device_info'</code><code>]:null;</code>
<code> </code><code>$data</code><code>[</code><code>"nonce_str"</code><code>] = </code><code>$this</code><code>->get_nonce_string();</code>
<code> </code><code>$data</code><code>[</code><code>"body"</code><code>] = </code><code>$params</code><code>[</code><code>'body'</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"detail"</code><code>] = isset(</code><code>$params</code><code>[</code><code>'detail'</code><code>])?</code><code>$params</code><code>[</code><code>'detail'</code><code>]:null;</code><code>//optional</code>
<code> </code><code>$data</code><code>[</code><code>"attach"</code><code>] = isset(</code><code>$params</code><code>[</code><code>'attach'</code><code>])?</code><code>$params</code><code>[</code><code>'attach'</code><code>]:null;</code><code>//optional</code>
<code> </code><code>$data</code><code>[</code><code>"out_trade_no"</code><code>] = isset(</code><code>$params</code><code>[</code><code>'out_trade_no'</code><code>])?</code><code>$params</code><code>[</code><code>'out_trade_no'</code><code>]:null;</code>
<code> </code><code>$data</code><code>[</code><code>"fee_type"</code><code>] = isset(</code><code>$params</code><code>[</code><code>'fee_type'</code><code>])?</code><code>$params</code><code>[</code><code>'fee_type'</code><code>]:</code><code>'CNY'</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"total_fee"</code><code>] = </code><code>$params</code><code>[</code><code>'total_fee'</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"spbill_create_ip"</code><code>] = </code><code>$params</code><code>[</code><code>'spbill_create_ip'</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"time_start"</code><code>] = isset(</code><code>$params</code><code>[</code><code>'time_start'</code><code>])?</code><code>$params</code><code>[</code><code>'time_start'</code><code>]:null;</code><code>//optional</code>
<code> </code><code>$data</code><code>[</code><code>"time_expire"</code><code>] = isset(</code><code>$params</code><code>[</code><code>'time_expire'</code><code>])?</code><code>$params</code><code>[</code><code>'time_expire'</code><code>]:null;</code><code>//optional</code>
<code> </code><code>$data</code><code>[</code><code>"goods_tag"</code><code>] = isset(</code><code>$params</code><code>[</code><code>'goods_tag'</code><code>])?</code><code>$params</code><code>[</code><code>'goods_tag'</code><code>]:null;</code>
<code> </code><code>$data</code><code>[</code><code>"notify_url"</code><code>] = </code><code>$params</code><code>[</code><code>'notify_url'</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"trade_type"</code><code>] = </code><code>$params</code><code>[</code><code>'trade_type'</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"product_id"</code><code>] = isset(</code><code>$params</code><code>[</code><code>'product_id'</code><code>])?</code><code>$params</code><code>[</code><code>'product_id'</code><code>]:null;</code><code>//required when trade_type = NATIVE</code>
<code> </code><code>$data</code><code>[</code><code>"openid"</code><code>] = isset(</code><code>$params</code><code>[</code><code>'openid'</code><code>])?</code><code>$params</code><code>[</code><code>'openid'</code><code>]:null;</code><code>//required when trade_type = JSAPI</code>
<code> </code><code>$result</code> <code>= </code><code>$this</code><code>->post(self::URL_UNIFIEDORDER, </code><code>$data</code><code>);</code>
<code> </code><code>return</code> <code>$result</code><code>;</code>
<code> </code><code>private</code> <code>function</code> <code>post(</code><code>$url</code><code>, </code><code>$data</code><code>,</code><code>$cert</code> <code>= false) {</code>
<code> </code><code>$data</code><code>[</code><code>"sign"</code><code>] = </code><code>$this</code><code>->sign(</code><code>$data</code><code>);</code>
<code> </code><code>$xml</code> <code>= </code><code>$this</code><code>->array2xml(</code><code>$data</code><code>);</code>
<code> </code><code>$ch</code> <code>= curl_init();</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>, CURLOPT_SSL_VERIFYPEER, false);</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>, CURLOPT_SSL_VERIFYHOST, false);</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>, CURLOPT_POST, 1);</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>, CURLOPT_POSTFIELDS, </code><code>$xml</code><code>);</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>, CURLOPT_RETURNTRANSFER, true);</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>, CURLOPT_URL, </code><code>$url</code><code>);</code>
<code> </code><code>if</code><code>(</code><code>$cert</code> <code>== true){</code>
<code> </code><code>//使用證書:cert 與 key 分别屬于兩個.pem檔案</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>,CURLOPT_SSLCERTTYPE,</code><code>'PEM'</code><code>);</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>,CURLOPT_SSLCERT, </code><code>$this</code><code>->_config[</code><code>'sslcertPath'</code><code>]);</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>,CURLOPT_SSLKEYTYPE,</code><code>'PEM'</code><code>);</code>
<code> </code><code>curl_setopt(</code><code>$ch</code><code>,CURLOPT_SSLKEY, </code><code>$this</code><code>->_config[</code><code>'sslkeyPath'</code><code>]);</code>
<code> </code><code>$content</code> <code>= curl_exec(</code><code>$ch</code><code>);</code>
<code> </code><code>$array</code> <code>= </code><code>$this</code><code>->xml2array(</code><code>$content</code><code>);</code>
<code> </code><code>return</code> <code>$array</code><code>;</code>
<code> </code><code>* 資料簽名</code>
<code> </code><code>* @param $data</code>
<code> </code><code>* @return string</code>
<code> </code><code>private</code> <code>function</code> <code>sign(</code><code>$data</code><code>) {</code>
<code> </code><code>ksort(</code><code>$data</code><code>);</code>
<code> </code><code>$string1</code> <code>= </code><code>""</code><code>;</code>
<code> </code><code>foreach</code> <code>(</code><code>$data</code> <code>as</code> <code>$k</code> <code>=> </code><code>$v</code><code>) {</code>
<code> </code><code>if</code> <code>(</code><code>$v</code> <code>&& trim(</code><code>$v</code><code>)!=</code><code>''</code><code>) {</code>
<code> </code><code>$string1</code> <code>.= </code><code>"$k=$v&"</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>$stringSignTemp</code> <code>= </code><code>$string1</code> <code>. </code><code>"key="</code> <code>. </code><code>$this</code><code>->_config[</code><code>"apikey"</code><code>];</code>
<code> </code><code>$sign</code> <code>= </code><code>strtoupper</code><code>(md5(</code><code>$stringSignTemp</code><code>));</code>
<code> </code><code>return</code> <code>$sign</code><code>;</code>
<code> </code><code>private</code> <code>function</code> <code>array2xml(</code><code>$array</code><code>) {</code>
<code> </code><code>$xml</code> <code>= </code><code>"<xml>"</code> <code>. PHP_EOL;</code>
<code> </code><code>foreach</code> <code>(</code><code>$array</code> <code>as</code> <code>$k</code> <code>=> </code><code>$v</code><code>) {</code>
<code> </code><code>if</code><code>(</code><code>$v</code> <code>&& trim(</code><code>$v</code><code>)!=</code><code>''</code><code>)</code>
<code> </code><code>$xml</code> <code>.= </code><code>"<$k><![CDATA[$v]]></$k>"</code> <code>. PHP_EOL;</code>
<code> </code><code>$xml</code> <code>.= </code><code>"</xml>"</code><code>;</code>
<code> </code><code>return</code> <code>$xml</code><code>;</code>
<code> </code><code>private</code> <code>function</code> <code>xml2array(</code><code>$xml</code><code>) {</code>
<code> </code><code>$array</code> <code>= </code><code>array</code><code>();</code>
<code> </code><code>$tmp</code> <code>= null;</code>
<code> </code><code>try</code><code>{</code>
<code> </code><code>$tmp</code> <code>= (</code><code>array</code><code>) simplexml_load_string(</code><code>$xml</code><code>);</code>
<code> </code><code>}</code><code>catch</code><code>(Exception </code><code>$e</code><code>){}</code>
<code> </code><code>if</code><code>(</code><code>$tmp</code> <code>&& </code><code>is_array</code><code>(</code><code>$tmp</code><code>)){</code>
<code> </code><code>foreach</code> <code>( </code><code>$tmp</code> <code>as</code> <code>$k</code> <code>=> </code><code>$v</code><code>) {</code>
<code> </code><code>$array</code><code>[</code><code>$k</code><code>] = (string) </code><code>$v</code><code>;</code>
<code> </code><code>* 掃碼支付(模式二)擷取支付二維碼</code>
<code> </code><code>* @param $product_id</code>
<code> </code><code>public</code> <code>function</code> <code>getCodeUrl(</code><code>$body</code><code>,</code><code>$out_trade_no</code><code>,</code><code>$total_fee</code><code>,</code><code>$notify_url</code><code>,</code><code>$product_id</code><code>){</code>
<code> </code><code>$data</code><code>[</code><code>"spbill_create_ip"</code><code>] = </code><code>$_SERVER</code><code>[</code><code>"SERVER_ADDR"</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"trade_type"</code><code>] = self::TRADETYPE_NATIVE;</code>
<code> </code><code>$data</code><code>[</code><code>"product_id"</code><code>] = </code><code>$product_id</code><code>;</code>
<code> </code><code>return</code> <code>$result</code><code>[</code><code>"code_url"</code><code>];</code>
<code> </code><code>* 查詢訂單</code>
<code> </code><code>* @param $transaction_id</code>
<code> </code><code>* @return array</code>
<code> </code><code>public</code> <code>function</code> <code>orderQuery(</code><code>$transaction_id</code><code>,</code><code>$out_trade_no</code><code>){</code>
<code> </code><code>$data</code><code>[</code><code>"transaction_id"</code><code>] = </code><code>$transaction_id</code><code>;</code>
<code> </code><code>$result</code> <code>= </code><code>$this</code><code>->post(self::URL_ORDERQUERY, </code><code>$data</code><code>);</code>
<code> </code><code>* 關閉訂單</code>
<code> </code><code>public</code> <code>function</code> <code>closeOrder(</code><code>$out_trade_no</code><code>){</code>
<code> </code><code>$result</code> <code>= </code><code>$this</code><code>->post(self::URL_CLOSEORDER, </code><code>$data</code><code>);</code>
<code> </code><code>* 申請退款 - 使用商戶訂單号</code>
<code> </code><code>* @param $out_trade_no 商戶訂單号</code>
<code> </code><code>* @param $out_refund_no 退款單号</code>
<code> </code><code>* @param $total_fee 總金額(機關:分)</code>
<code> </code><code>* @param $refund_fee 退款金額(機關:分)</code>
<code> </code><code>* @param $op_user_id 操作員賬号</code>
<code> </code><code>public</code> <code>function</code> <code>refund(</code><code>$out_trade_no</code><code>,</code><code>$out_refund_no</code><code>,</code><code>$total_fee</code><code>,</code><code>$refund_fee</code><code>,</code><code>$op_user_id</code><code>){</code>
<code> </code><code>$data</code><code>[</code><code>"out_refund_no"</code><code>] = </code><code>$out_refund_no</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"total_fee"</code><code>] = </code><code>$total_fee</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"refund_fee"</code><code>] = </code><code>$refund_fee</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"op_user_id"</code><code>] = </code><code>$op_user_id</code><code>;</code>
<code> </code><code>$result</code> <code>= </code><code>$this</code><code>->post(self::URL_REFUND, </code><code>$data</code><code>,true);</code>
<code> </code><code>* 申請退款 - 使用微信訂單号</code>
<code> </code><code>public</code> <code>function</code> <code>refundByTransId(</code><code>$transaction_id</code><code>,</code><code>$out_refund_no</code><code>,</code><code>$total_fee</code><code>,</code><code>$refund_fee</code><code>,</code><code>$op_user_id</code><code>){</code>
<code> </code><code>* 下載下傳對賬單</code>
<code> </code><code>* @param $bill_date 下載下傳對賬單的日期,格式:20140603</code>
<code> </code><code>* @param $bill_type 類型</code>
<code> </code><code>public</code> <code>function</code> <code>downloadBill(</code><code>$bill_date</code><code>,</code><code>$bill_type</code> <code>= </code><code>'ALL'</code><code>){</code>
<code> </code><code>$data</code><code>[</code><code>"bill_date"</code><code>] = </code><code>$bill_date</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"bill_type"</code><code>] = </code><code>$bill_type</code><code>;</code>
<code> </code><code>$result</code> <code>= </code><code>$this</code><code>->post(self::URL_DOWNLOADBILL, </code><code>$data</code><code>);</code>
<code> </code><code>* 擷取js支付使用的第二個參數</code>
<code> </code><code>public</code> <code>function</code> <code>get_package(</code><code>$prepay_id</code><code>) {</code>
<code> </code><code>$data</code><code>[</code><code>"appId"</code><code>] = </code><code>$this</code><code>->_config[</code><code>"appid"</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"timeStamp"</code><code>] = time();</code>
<code> </code><code>$data</code><code>[</code><code>"nonceStr"</code><code>] = </code><code>$this</code><code>->get_nonce_string();</code>
<code> </code><code>$data</code><code>[</code><code>"package"</code><code>] = </code><code>"prepay_id=$prepay_id"</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"signType"</code><code>] = </code><code>"MD5"</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"paySign"</code><code>] = </code><code>$this</code><code>->sign(</code><code>$data</code><code>);</code>
<code> </code><code>return</code> <code>$data</code><code>;</code>
<code> </code><code>* 擷取發送到通知位址的資料(在通知位址内使用)</code>
<code> </code><code>* @return 結果數組,如果不是微信伺服器發送的資料傳回null</code>
<code> </code><code>* appid</code>
<code> </code><code>* bank_type</code>
<code> </code><code>* cash_fee</code>
<code> </code><code>* fee_type</code>
<code> </code><code>* is_subscribe</code>
<code> </code><code>* mch_id</code>
<code> </code><code>* nonce_str</code>
<code> </code><code>* openid</code>
<code> </code><code>* out_trade_no 商戶訂單号</code>
<code> </code><code>* result_code</code>
<code> </code><code>* return_code</code>
<code> </code><code>* sign</code>
<code> </code><code>* time_end</code>
<code> </code><code>* total_fee 總金額</code>
<code> </code><code>* trade_type</code>
<code> </code><code>* transaction_id 微信支付訂單号</code>
<code> </code><code>public</code> <code>function</code> <code>get_back_data() {</code>
<code> </code><code>$xml</code> <code>= </code><code>file_get_contents</code><code>(</code><code>"php://input"</code><code>);</code>
<code> </code><code>$data</code> <code>= </code><code>$this</code><code>->xml2array(</code><code>$xml</code><code>);</code>
<code> </code><code>if</code> <code>(</code><code>$this</code><code>->validate(</code><code>$data</code><code>)) {</code>
<code> </code><code>return</code> <code>$data</code><code>;</code>
<code> </code><code>* 驗證資料簽名</code>
<code> </code><code>* @param $data 資料數組</code>
<code> </code><code>* @return 資料校驗結果</code>
<code> </code><code>public</code> <code>function</code> <code>validate(</code><code>$data</code><code>) {</code>
<code> </code><code>if</code> <code>(!isset(</code><code>$data</code><code>[</code><code>"sign"</code><code>])) {</code>
<code> </code><code>return</code> <code>false;</code>
<code> </code><code>$sign</code> <code>= </code><code>$data</code><code>[</code><code>"sign"</code><code>];</code>
<code> </code><code>unset(</code><code>$data</code><code>[</code><code>"sign"</code><code>]);</code>
<code> </code><code>return</code> <code>$this</code><code>->sign(</code><code>$data</code><code>) == </code><code>$sign</code><code>;</code>
<code> </code><code>* 響應微信支付背景通知</code>
<code> </code><code>* @param $return_code 傳回狀态碼 SUCCESS/FAIL</code>
<code> </code><code>* @param $return_msg 傳回資訊</code>
<code> </code><code>public</code> <code>function</code> <code>response_back(</code><code>$return_code</code><code>=</code><code>"SUCCESS"</code><code>, </code><code>$return_msg</code><code>=null) {</code>
<code> </code><code>$data</code><code>[</code><code>"return_code"</code><code>] = </code><code>$return_code</code><code>;</code>
<code> </code><code>if</code> <code>(</code><code>$return_msg</code><code>) {</code>
<code> </code><code>$data</code><code>[</code><code>"return_msg"</code><code>] = </code><code>$return_msg</code><code>;</code>
<code> </code><code>print</code> <code>$xml</code><code>;</code>
<code>}</code>
一、注意:此類庫內建到ci我們要改名WechatPay改為Wechatpay讓他符ci類庫規範,而且檔案名也要改保持統一性
二、把Wechatpay.php放在application\libraries檔案夾内,将證書之類的,日志檔案之類的放置在和wechatpay.php同級目錄下即可,當然可以随便放
三、将微信配置資訊,商戶号、appid、AppSecret、API key、證書位置等資訊放在wxpay_config.php檔案中,放在application\config目錄中
wxpay_config.php代碼
<code><?php defined(</code><code>'BASEPATH'</code><code>) OR </code><code>exit</code><code>(</code><code>'No direct script access allowed'</code><code>);</code>
<code>/**</code>
<code> </code><code>* Created by PhpStorm.</code>
<code> </code><code>* User: sxq</code>
<code> </code><code>* Date: 2016-04-20</code>
<code> </code><code>* Time: 16:59</code>
<code> </code><code>*/</code>
<code>$config</code><code>[</code><code>'appid'</code><code>] = </code><code>'你的公衆号appid'</code><code>;</code>
<code>$config</code><code>[</code><code>'mch_id'</code><code>] = </code><code>'你的商戶号'</code><code>;</code>
<code>$config</code><code>[</code><code>'apikey'</code><code>] = </code><code>'你的APIkey'</code><code>;</code>
<code>$config</code><code>[</code><code>'appsecret'</code><code>] = </code><code>"你的AppSecret"</code><code>;</code>
<code>$config</code><code>[</code><code>'sslcertPath'</code><code>] = APPPATH.</code><code>'libraries/cert/apiclient_cert.pem'</code><code>;</code>
<code>$config</code><code>[</code><code>'sslkeyPath'</code><code>] = APPPATH.</code><code>'libraries/cert/apiclient_key.pem'</code><code>;</code>
四、phpqrcode檔案,這份檔案在微信官方sdk中,使用檔案有phpqrcode檔案夾和qrcode.php也一同放置在application\libraries檔案夾内
五、日志檔案log.php,這份檔案在微信官方sdk中也一同放置在application\libraries檔案夾内
<code>require_once</code> <code>(APPPATH.</code><code>'libraries/log.php'</code><code>);</code>
<code>//初始化日志</code>
<code>$logHandler</code><code>= </code><code>new</code> <code>CLogFileHandler(APPPATH.</code><code>"logs/"</code><code>.</code><code>date</code><code>(</code><code>'Y-m-d'</code><code>).</code><code>'.log'</code><code>);</code>
<code>Log::Init(</code><code>$logHandler</code><code>, 15);</code>
<code>//我在控制器最頂部加了這個執行個體化,日志檔案放在了application/logs檔案夾</code>
<code>//調用方式:log::debug("輸出資訊");簡單記錄執行資訊友善調試</code>
六、配置資訊寫完後,那麼在控制器裡調用吧(滿滿的全是幹貨)
我們首先按照正常的加載配置資訊代碼一樣去加載微信配置資訊,最後再加載三方類庫wechatpay.php
<code>$this</code><code>->load->config(</code><code>'wxpay_config'</code><code>);</code>
<code>$wxconfig</code><code>[</code><code>'appid'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'appid'</code><code>);</code>
<code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'mch_id'</code><code>);</code>
<code>$wxconfig</code><code>[</code><code>'apikey'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'apikey'</code><code>);</code>
<code>$wxconfig</code><code>[</code><code>'appsecret'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'appsecret'</code><code>);</code>
<code>$wxconfig</code><code>[</code><code>'sslcertPath'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'sslcertPath'</code><code>);</code>
<code>$wxconfig</code><code>[</code><code>'sslkeyPath'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'sslkeyPath'</code><code>);</code>
<code>//由于此類庫構造函數需要傳參,我們初始化類庫就傳參數給他吧</code>
<code>$this</code><code>->load->library(</code><code>'Wechatpay'</code><code>,</code><code>$wxconfig</code><code>);</code>
這步基礎資訊配置完畢,接下來我們需要構造統一下單API接口參數
<code> </code><code>$param</code><code>[</code><code>'body'</code><code>]=</code><code>"商品名稱(自行看文檔具體填什麼)"</code><code>;</code>
<code> </code><code>$param</code><code>[</code><code>'attach'</code><code>]=</code><code>"我有個參數要傳我就穿了個id過來,這裡不要有空格避免出錯"</code><code>;</code>
<code> </code><code>$param</code><code>[</code><code>'detail'</code><code>]=</code><code>"我填了商品名稱加訂單号"</code><code>;</code>
<code> </code><code>$param</code><code>[</code><code>'out_trade_no'</code><code>]=</code><code>"商戶訂單号"</code><code>;</code>
<code> </code><code>$param</code><code>[</code><code>'total_fee'</code><code>]=</code><code>"金額,記得乘以100,微信支付機關預設分"</code><code>;</code><code>//如$total_fee*100</code>
<code> </code><code>$param</code><code>[</code><code>"spbill_create_ip"</code><code>] =</code><code>$_SERVER</code><code>[</code><code>'REMOTE_ADDR'</code><code>];</code><code>//用戶端IP位址</code>
<code> </code><code>$param</code><code>[</code><code>"time_start"</code><code>] = </code><code>date</code><code>(</code><code>"YmdHis"</code><code>);</code><code>//請求開始時間</code>
<code> </code><code>$param</code><code>[</code><code>"time_expire"</code><code>] =</code><code>date</code><code>(</code><code>"YmdHis"</code><code>, time() + 600);</code><code>//請求逾時時間</code>
<code> </code><code>$param</code><code>[</code><code>"goods_tag"</code><code>] = urldecode(</code><code>$productname</code><code>);</code><code>//商品标簽,自行填寫</code>
<code> </code><code>$param</code><code>[</code><code>"notify_url"</code><code>] = base_url().</code><code>"home/wxnotify"</code><code>;</code><code>//自行定義異步通知url</code>
<code> </code><code>$param</code><code>[</code><code>"trade_type"</code><code>] = </code><code>"NATIVE"</code><code>;</code><code>//掃碼支付模式二</code>
<code> </code><code>$param</code><code>[</code><code>"product_id"</code><code>] = </code><code>$order</code><code>->productid;</code><code>//正好有産品id就傳了個,看文檔說自己定義</code>
<code>//調用統一下單API接口</code>
<code> </code><code>$result</code><code>=</code><code>$this</code><code>->wechatpay->unifiedOrder(</code><code>$param</code><code>); </code><code>//這裡可以加日志輸出,log::debug(json_encode($result));</code>
<code>//成功(return_code和result_code都為SUCCESS)就會傳回含有帶支付二維碼連結的資料</code>
<code> </code><code>if</code> <code>(isset(</code><code>$result</code><code>[</code><code>"code_url"</code><code>]) && !</code><code>empty</code><code>(</code><code>$result</code><code>[</code><code>"code_url"</code><code>])) { /> </code><code>//二維碼圖檔連結</code>
<code> </code><code>$data</code><code>[</code><code>'wxurl'</code><code>] = </code><code>$result</code><code>[</code><code>"code_url"</code><code>];</code>
<code>//這裡傳遞商戶訂單号到掃碼視圖,是因為我想做跳轉,根據商戶号去查詢訂單是否支付成功,如果成功了就跳轉,定時輪詢微信伺服器(這個誰有好的方法可以分享給我啊,表示感謝啦)</code>
<code> </code><code>$data</code><code>[</code><code>'orderno'</code><code>] = </code><code>$out_trade_no</code><code>;</code>
<code> </code><code>$this</code><code>->load->view(</code><code>'home/pay'</code><code>, </code><code>$data</code><code>);</code>
<code> </code><code>}</code>

pay.php掃碼視圖頁面代碼如下:這部分代碼來自(https://github.com/Alpha2016/wxpay)
<code><?php </code><code>if</code><code>(isset(</code><code>$wxurl</code><code>)&&!</code><code>empty</code><code>(</code><code>$wxurl</code><code>)){?></code>
<code> </code><code><div </code><code>class</code><code>=</code><code>"bgcolor"</code><code>></code>
<code> </code><code><div </code><code>class</code><code>=</code><code>"container"</code><code>></code>
<code> </code><code><div </code><code>class</code><code>=</code><code>"panel"</code><code>></code>
<code> </code><code><div </code><code>class</code><code>=</code><code>"panel-heading"</code><code>></code>
<code> </code><code><ol </code><code>class</code><code>=</code><code>"breadcrumb"</code><code>></code>
<code> </code><code><li><a href=</code><code>"<?php echo base_url().'home';?>"</code><code>>首頁</a><span </code><code>class</code><code>=</code><code>'divider'</code><code>>></span></li></code>
<code> </code><code><li </code><code>class</code><code>=</code><code>"active active-tab"</code><code>><span><?php </code><code>echo</code> <code>"二維碼支付"</code><code>;?></span></li></code>
<code> </code><code></ol></code>
<code> </code><code></div></code>
<code> </code><code><div </code><code>class</code><code>=</code><code>"panel-body"</code><code>></code>
<code> </code><code><div </code><code>class</code><code>=</code><code>"page-header"</code><code>>二維碼支付</div></code>
<code> </code><code><div </code><code>class</code><code>=</code><code>"text-danger center-block text-center"</code><code>></code>
<code> </code><code><input type=</code><code>"hidden"</code> <code>id=</code><code>"orderno"</code> <code>value=</code><code>"<?php echo $orderno;?>"</code><code>/></code>
<code> </code><code><img alt=</code><code>"掃碼支付"</code> <code>src=</code><code>"<?php echo base_url().'home/qrcode?data='.urlencode($wxurl);?>"</code> <code>style=</code><code>"width:200px;height:200px;"</code><code>/></code>
<code> </code><code></div></code>
<code> </code><code></div></code>
<code> </code><code></div></code>
<code> </code><code></div></code>
<code><?php }?></code>
<code><script></code>
<code> </code><code>// 每半秒請求一次資料,然後判斷,跳轉,增加使用者友好性</code>
<code> </code><code>$(</code><code>function</code><code>(){</code>
<code> </code><code>orderno = $(</code><code>'#orderno'</code><code>).val();</code>
<code> </code><code>start = self.setInterval(</code><code>"checkstatus(orderno)"</code><code>, 500);</code>
<code> </code><code>});</code>
<code> </code><code>function</code> <code>checkstatus(order_no){</code>
<code> </code><code>if</code><code>(order_no == undefined || order_no == </code><code>''</code><code>){</code>
<code> </code><code>window.clearInterval(start);</code>
<code> </code><code>else</code><code>{</code>
<code> </code><code>$.ajax({</code>
<code> </code><code>url:</code><code>"<?php echo base_url().'home/queryorder';?>"</code><code>,</code>
<code> </code><code>type:</code><code>'POST'</code><code>,</code>
<code> </code><code>dataType:</code><code>'json'</code><code>,</code>
<code> </code><code>data:{orderno:orderno},</code>
<code> </code><code>success:</code><code>function</code><code>(msg){</code>
<code> </code><code>if</code><code>(msg.trade_state == </code><code>"SUCCESS"</code><code>) {</code>
<code> </code><code>window.clearInterval(start);</code>
<code> </code><code>alert(</code><code>'支付成功'</code><code>);</code>
<code> </code><code>location.href = </code><code>"<?php echo base_url().'home/myorder';?>"</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
<code> </code><code>});</code>
<code></script></code>
其實核心在二維碼連結如何轉換成二維碼圖檔和如何定時輪詢支付結果
<code><?php </code><code>echo</code> <code>base_url().</code><code>'home/qrcode?data='</code><code>.urlencode(</code><code>$wxurl</code><code>);?>這句是調用phpqrcode類庫<br>輪詢方法代碼:<br>該部分在home控制器下</code>
<code>function</code> <code>queryorder()</code>
<code>{</code>
<code> </code><code>$this</code><code>->load->config(</code><code>'wxpay_config'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'appid'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'appid'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'mch_id'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'apikey'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'apikey'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'appsecret'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'appsecret'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'sslcertPath'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'sslcertPath'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'sslkeyPath'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'sslkeyPath'</code><code>);</code>
<code> </code><code>$this</code><code>->load->library(</code><code>'Wechatpay'</code><code>,</code><code>$wxconfig</code><code>);</code>
<code> </code><code>$out_trade_no</code> <code>= </code><code>$_POST</code><code>[</code><code>'orderno'</code><code>]; </code><code>//調用查詢訂單API接口</code>
<code> </code><code>$array</code> <code>= </code><code>$this</code><code>->wechatpay->orderQuery(</code><code>''</code><code>,</code><code>$out_trade_no</code><code>);</code>
<code> </code><code>echo</code> <code>json_encode(</code><code>$array</code><code>);</code>
那麼二維碼類庫調用在這裡
<code>function</code> <code>qrcode()</code>
<code> </code><code>require_once</code><code>(APPPATH.</code><code>'libraries/phpqrcode/phpqrcode.php'</code><code>);</code>
<code> </code><code>$url</code> <code>= urldecode(</code><code>$_GET</code><code>[</code><code>"data"</code><code>]);</code>
<code> </code><code>QRcode::png(</code><code>$url</code><code>);</code>
那麼二維碼生成支付圖檔完成,支付輪詢也完成了,該如何去處理業務邏輯呢?
先說明下,這部分有個弊端,如果客戶一直不支付那麼他就一直輪詢,可以自行設定個有效期,我沒有設定。如果在輪詢到處理業務邏輯怎麼樣?可以的,但是也有個問題如果客戶直接關掉了,你來不及處理的業務怎麼辦?是以還要確定不掉單,還需要再微信異步通知url那裡處理下業務
<code> </code><code>//微信異步通知</code>
<code> </code><code>function</code> <code>wxnotify()</code>
<code> </code><code>{</code>
<code>//$postStr = file_get_contents("php://input");//因為很多都設定了register_globals禁止,不能用$GLOBALS["HTTP_RAW_POST_DATA'] //這部分困擾了好久用上面這種一直接受不到資料,或者接受了解析不正确,最終用下面的正常了,有哪位願意指點的可以告知一二</code>
<code> </code><code>$xml</code> <code>= </code><code>$GLOBALS</code><code>[</code><code>'HTTP_RAW_POST_DATA'</code><code>];</code><code>//這個需要開啟;always_populate_raw_post_data = On</code>
<code> </code><code>$this</code><code>->load->config(</code><code>'wxpay_config'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'appid'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'appid'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'mch_id'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'apikey'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'apikey'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'appsecret'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'appsecret'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'sslcertPath'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'sslcertPath'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'sslkeyPath'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'sslkeyPath'</code><code>);</code>
<code> </code><code>$this</code><code>->load->library(</code><code>'Wechatpay'</code><code>,</code><code>$wxconfig</code><code>);</code>
<code> </code><code>libxml_disable_entity_loader(true);</code>
<code> </code><code>$array</code><code>= json_decode(json_encode(simplexml_load_string(</code><code>$xml</code><code>, </code><code>'SimpleXMLElement'</code><code>, LIBXML_NOCDATA)), true);</code>
<code> </code><code>log::debug(</code><code>$xml</code><code>);</code>
<code> </code><code>log::debug(json_encode(</code><code>$array</code><code>));</code>
<code> </code><code>if</code><code>(</code><code>$array</code><code>!=null)</code>
<code> </code><code>{</code>
<code> </code><code>$out_trade_no</code> <code>= </code><code>$array</code><code>[</code><code>'out_trade_no'</code><code>];</code>
<code> </code><code>$trade_no</code> <code>= </code><code>$array</code><code>[</code><code>'transaction_id'</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>'orderid'</code><code>]=</code><code>$array</code><code>[</code><code>'attach'</code><code>];</code>
<code> </code><code>$this</code><code>->load->model(</code><code>'payorder'</code><code>);</code>
<code> </code><code>$payinfo</code> <code>= </code><code>$this</code><code>->payorder->GetPayorder(</code><code>array</code><code>(</code><code>'orderno'</code> <code>=> </code><code>$out_trade_no</code><code>));</code>
<code> </code><code>if</code> <code>(!</code><code>$payinfo</code><code>) {</code>
<code> </code><code>$data</code><code>[</code><code>'orderno'</code><code>] = </code><code>$out_trade_no</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>'money'</code><code>] = </code><code>$array</code><code>[</code><code>'total_fee'</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>'tradeno'</code><code>] = </code><code>$trade_no</code><code>;</code>
<code> </code><code>$rs</code><code>=</code><code>$this</code><code>->payorder->AddPayorder(</code><code>$data</code><code>);</code>
<code> </code><code>if</code><code>(</code><code>$rs</code><code>>0)</code>
<code> </code><code>{ </code><code>//告知微信我成功了</code>
<code> </code><code>$this</code><code>->wechatpay->response_back();</code>
<code> </code><code>}</code><code>else</code><code>{ </code><code>//告知微信我失敗了繼續發</code>
<code> </code><code>$this</code><code>->wechatpay->response_back(</code><code>"FAIL"</code><code>);</code>
<code> </code><code>}</code><code>else</code><code>{</code>
<code> </code><code>$this</code><code>->wechatpay->response_back();</code>
花了5天的時間去研究這個類型的微信支付,花了半天的時間去梳理知識點,整體感覺就是如果API接口少,又有成熟類庫自己去內建吧
http://www.cnblogs.com/24la/p/wxpay-jsapi-refund.html
微信支付接口文檔:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1
首先你得知道這個jsapi是不能離開微信進行調用支付的,明白了這個道理我們好下手,頁面是在微信内顯示并通過jsapi調用微信支付元件進行支付。
我們仍然繼續使用wechatpay.php這個支付內建類,簡單友善好了解,不過如果應用jsapi的話這個類有個bug
在我們構造jsapi需要的參數時有個時間戳,我們用time()生成的,會報微信支付調用JSAPI缺少參數:timeStamp
修改如下:
<code> </code><code>* 擷取js支付使用的第二個參數</code>
<code>public</code> <code>function</code> <code>get_package(</code><code>$prepay_id</code><code>) {</code>
<code> </code><code>$data</code> <code>= </code><code>array</code><code>();</code>
<code> </code><code>$data</code><code>[</code><code>"appId"</code><code>] = </code><code>$this</code><code>->_config[</code><code>"appid"</code><code>];</code>
<code> </code><code>//改動地方,把它變成字元串</code>
<code> </code><code>$time</code><code>=time();</code>
<code> </code><code>$data</code><code>[</code><code>"timeStamp"</code><code>] = </code><code>"\""</code><code>.</code><code>$time</code><code>.</code><code>"\""</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"nonceStr"</code><code>] = </code><code>$this</code><code>->get_nonce_string();</code>
<code> </code><code>$data</code><code>[</code><code>"package"</code><code>] = </code><code>"prepay_id=$prepay_id"</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"signType"</code><code>] = </code><code>"MD5"</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"paySign"</code><code>] = </code><code>$this</code><code>->sign(</code><code>$data</code><code>);</code>
<code> </code><code>return</code> <code>$data</code><code>;</code>
其實這個方法就是擷取jsapi的支付參數了
一、微信JSAPI支付
不能忘記配置授權目錄,調用jsapi我是在http://xxx.com/index.php/home下我配置了這個
首先我們還是要調用統一下單接口,擷取我們要的參數(如果此類的配置放置位置等不會的請參考上篇文章),此為pay方法,在調用統一下單接口的時候我們需要知道需要哪些參數
1、要擷取openid,這個我是項目用了一個微信API的類庫,https://github.com/dodgepudding/wechat-php-sdk,主要是用了這裡面的方法
此項目有朋友專門的對接了CodeIgniter架構的擴充類庫,可以直接用,目錄結構,我們直接上代碼吧
<code>public</code> <code>function</code> <code>__construct()</code>
<code> </code><code>parent::__construct();</code>
<code> </code><code>$this</code><code>->load->library(</code><code>'CI_Wechat'</code><code>);</code><code>//由于我的項目是時刻都跟微信綁在一起,是以直接加載在構造函數裡了,不用每個方法都加載了。</code>
<code> </code><code>$this</code><code>->load->library(</code><code>'pagination'</code><code>);</code>
CI_Model内容大家看下上面的類庫源碼,還有裡面如何配置的,下面我們看看如何擷取openid
<code>function</code> <code>oauthurl()</code>
<code> </code><code>$oauth_url</code> <code>= </code><code>$this</code><code>->ci_wechat->getOauthRedirect(base_url() . </code><code>'index.php/home/oauth'</code><code>, 1);</code>
<code> </code><code>header(</code><code>'Location: '</code> <code>. </code><code>$oauth_url</code><code>);</code>
<code> </code><code>exit</code><code>();</code>
<code>function</code> <code>oauth()</code>
<code> </code><code>if</code> <code>(!isset(</code><code>$_GET</code><code>[</code><code>'code'</code><code>])) {</code>
<code> </code><code>//觸發微信傳回code碼</code>
<code> </code><code>$baseUrl</code> <code>= urlencode(</code><code>'http://'</code> <code>. </code><code>$_SERVER</code><code>[</code><code>'HTTP_HOST'</code><code>] . </code><code>$_SERVER</code><code>[</code><code>'PHP_SELF'</code><code>] . </code><code>$_SERVER</code><code>[</code><code>'QUERY_STRING'</code><code>]);</code>
<code> </code><code>$url</code> <code>= </code><code>$this</code><code>->__CreateOauthUrlForCode(</code><code>$baseUrl</code><code>);</code>
<code> </code><code>Header(</code><code>"Location: $url"</code><code>);</code>
<code> </code><code>exit</code><code>();</code>
<code> </code><code>} </code><code>else</code> <code>{</code>
<code> </code><code>$json</code> <code>= </code><code>$this</code><code>->ci_wechat->getOauthAccessToken();</code>
<code> </code><code>$openid</code> <code>= </code><code>$json</code><code>[</code><code>'openid'</code><code>];</code>
<code> </code><code>//注冊使用者,成功後可以搶單</code>
<code> </code><code>//return $this->_isRegistered($_SESSION['user']['openid']);</code>
<code> </code><code>return</code> <code>$openid</code><code>;</code>
以上兩個方法就是擷取openid的,擷取之後我是儲存在session裡的,我每個頁面都判斷是否擷取了openid如果沒有擷取直接
<code>$this</code><code>->session->set_userdata(</code><code>'openid'</code><code>, </code><code>$this</code><code>->oauth());</code>
這樣保證一直能得到openid
2、構造JSAPI支付所需參數(統一下單的參數構造)
<code>$this</code><code>->load->model(</code><code>'publist'</code><code>);</code><code>//擷取訂單資訊</code>
<code>$pub</code> <code>= </code><code>$this</code><code>->publist->GetList(</code><code>array</code><code>(</code><code>'id'</code> <code>=> </code><code>$_SESSION</code><code>[</code><code>'orderid'</code><code>]));</code>
<code>//微信支付配置的參數配置讀取</code>
<code>//商戶交易單号</code>
<code>$out_trade_no</code> <code>= </code><code>$pub</code><code>->listno;</code>
<code>$total_fee</code><code>=</code><code>$pub</code><code>->fee;</code>
<code>$openid</code><code>=</code><code>$_SESSION</code><code>[</code><code>'openid'</code><code>];</code>
<code>$param</code><code>[</code><code>'body'</code><code>]=</code><code>"黑人牙膏"</code><code>;</code>
<code>$param</code><code>[</code><code>'attach'</code><code>]=</code><code>$pub</code><code>->id;</code>
<code>$param</code><code>[</code><code>'detail'</code><code>]=</code><code>"黑人牙膏-"</code><code>.</code><code>$out_trade_no</code><code>;</code>
<code>$param</code><code>[</code><code>'out_trade_no'</code><code>]=</code><code>$out_trade_no</code><code>;</code>
<code>$param</code><code>[</code><code>'total_fee'</code><code>]=</code><code>$total_fee</code><code>*100;</code>
<code>$param</code><code>[</code><code>"spbill_create_ip"</code><code>] =</code><code>$_SERVER</code><code>[</code><code>'REMOTE_ADDR'</code><code>];</code>
<code>$param</code><code>[</code><code>"time_start"</code><code>] = </code><code>date</code><code>(</code><code>"YmdHis"</code><code>);</code>
<code>$param</code><code>[</code><code>"time_expire"</code><code>] =</code><code>date</code><code>(</code><code>"YmdHis"</code><code>, time() + 600);</code>
<code>$param</code><code>[</code><code>"goods_tag"</code><code>] = </code><code>"黑人牙膏"</code><code>;</code>
<code>$param</code><code>[</code><code>"notify_url"</code><code>] = base_url().</code><code>"index.php/home/notify"</code><code>;</code>
<code>$param</code><code>[</code><code>"trade_type"</code><code>] = </code><code>"JSAPI"</code><code>;</code>
<code>$param</code><code>[</code><code>"openid"</code><code>] = </code><code>$openid</code><code>;</code>
<code>//統一下單,擷取結果,結果是為了構造jsapi調用微信支付元件所需參數</code>
<code>$result</code><code>=</code><code>$this</code><code>->wechatpay->unifiedOrder(</code><code>$param</code><code>);</code>
<code>//如果結果是成功的我們才能構造所需參數,首要判斷預支付id</code>
<code>if</code> <code>(isset(</code><code>$result</code><code>[</code><code>"prepay_id"</code><code>]) && !</code><code>empty</code><code>(</code><code>$result</code><code>[</code><code>"prepay_id"</code><code>])) {</code>
<code> </code><code>//調用支付類裡的get_package方法,得到構造的參數</code>
<code> </code><code>$data</code><code>[</code><code>'parameters'</code><code>]=json_encode(</code><code>$this</code><code>->wechatpay->get_package(</code><code>$result</code><code>[</code><code>'prepay_id'</code><code>]));</code>
<code> </code><code>$data</code><code>[</code><code>'notifyurl'</code><code>]=</code><code>$param</code><code>[</code><code>"notify_url"</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>'fee'</code><code>]=</code><code>$total_fee</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>'pubid'</code><code>]=</code><code>$_SESSION</code><code>[</code><code>'orderid'</code><code>];</code>
<code> </code><code>$this</code><code>->load->view(</code><code>'home/header'</code><code>);</code>
<code> </code><code>//要有個頁面将以上資料傳遞過去并展示給使用者</code>
<code> </code><code>$this</code><code>->load->view(</code><code>'home/pay'</code><code>, </code><code>$data</code><code>);</code>
<code> </code><code>$this</code><code>->load->view(</code><code>'home/footer'</code><code>);</code>
<code>} </code>
3、支付頁面,views視圖pay.php
<code><?php</code>
<code>$jsApiParameters</code> <code>= </code><code>$parameters</code><code>;</code><code>//參數指派</code>
<code>?></code>
<code><script type=</code><code>"text/javascript"</code><code>></code>
<code> </code><code>//調用微信JS api 支付</code>
<code> </code><code>function</code> <code>jsApiCall()</code>
<code> </code><code>WeixinJSBridge.invoke(</code>
<code> </code><code>'getBrandWCPayRequest'</code><code>,</code>
<code> </code><code><?php </code><code>echo</code> <code>$jsApiParameters</code><code>; ?>,</code>
<code> </code><code>function</code><code>(res){</code>
<code> </code><code>WeixinJSBridge.log(res.err_msg);</code>
<code> </code><code>if</code><code>(res.err_msg == </code><code>"get_brand_wcpay_request:ok"</code> <code>){</code>
<code> </code><code>$.alert(</code><code>'支付成功'</code><code>);</code>
<code> </code><code>//我在這裡選擇了前台隻要支付成功将單号傳遞更新資料</code>
<code> </code><code>$.ajax({</code>
<code> </code><code>url:</code><code>'<?php echo $notifyurl.'</code><code>/</code><code>'.$pubid;?>'</code><code>,</code>
<code> </code><code>dataType:</code><code>'json'</code><code>,</code>
<code> </code><code>success : </code><code>function</code><code>(ret){</code>
<code> </code><code>if</code><code>(ret==1){</code>
<code> </code><code>//成功後傳回我的訂單頁面</code>
<code> </code><code>location.href=</code><code>"<?php echo base_url().'index.php/home/myorder';?>"</code><code>;</code>
<code> </code><code>}</code>
<code> </code><code>}</code>
<code> </code><code>});</code>
<code> </code><code>}</code><code>else</code>
<code> </code><code>{</code>
<code> </code><code>//$.alert('支付失敗');</code>
<code> </code><code>//alert(res.err_code+res.err_desc+res.err_msg);</code>
<code> </code><code>);</code>
<code> </code><code>function</code> <code>callpay()</code>
<code> </code><code>if</code> <code>(typeof WeixinJSBridge == </code><code>"undefined"</code><code>){</code>
<code> </code><code>if</code><code>( document.addEventListener ){</code>
<code> </code><code>document.addEventListener(</code><code>'WeixinJSBridgeReady'</code><code>, jsApiCall, false);</code>
<code> </code><code>}</code><code>else</code> <code>if</code> <code>(document.attachEvent){</code>
<code> </code><code>document.attachEvent(</code><code>'WeixinJSBridgeReady'</code><code>, jsApiCall);</code>
<code> </code><code>document.attachEvent(</code><code>'onWeixinJSBridgeReady'</code><code>, jsApiCall);</code>
<code> </code><code>}</code><code>else</code><code>{</code>
<code> </code><code>jsApiCall();</code>
<code><div </code><code>class</code><code>=</code><code>"hd"</code><code>></code>
<code> </code><code><h1 </code><code>class</code><code>=</code><code>"page_title"</code><code>>支付傭金</h1></code>
<code> </code><code><p </code><code>class</code><code>=</code><code>"page_desc"</code><code>>請認真核對傭金金額</p></code>
<code></div></code>
<code><div </code><code>class</code><code>=</code><code>"weui_cells"</code><code>></code>
<code> </code><code><div </code><code>class</code><code>=</code><code>"weui_cell"</code><code>></code>
<code> </code><code><div </code><code>class</code><code>=</code><code>"weui_cell_hd weui_cell_primary"</code><code>></code>
<code> </code><code>該筆訂單支付金額為<span style=</code><code>"color:#f00;font-size:50px"</code><code>><?php </code><code>echo</code> <code>$fee</code><code>; ?></span>元錢</code>
<code><button </code><code>class</code><code>=</code><code>"weui_btn weui_btn_primary"</code> <code>type=</code><code>"button"</code> <code>onclick=</code><code>"callpay()"</code> <code>>立即支付</button></code>
4、支付成功跳轉頁面,我們看notify方法
<code>function</code> <code>notify()</code>
<code> </code><code>$id</code> <code>= </code><code>$this</code><code>->uri->segment(3);</code>
<code> </code><code>if</code> <code>(isset(</code><code>$_SESSION</code><code>[</code><code>'openid'</code><code>])) {</code>
<code> </code><code>$this</code><code>->load->model(</code><code>'publist'</code><code>);</code><code>//更新業務邏輯</code>
<code> </code><code>$rs</code> <code>= </code><code>$this</code><code>->publist->UpdateList(</code><code>array</code><code>(</code><code>'id'</code> <code>=> </code><code>$id</code><code>, </code><code>'feestatus'</code> <code>=> 1));</code>
<code> </code><code>if</code> <code>(</code><code>$rs</code> <code>> 0) {</code>
<code> </code><code>echo</code> <code>1;</code>
<code> </code><code>exit</code><code>;</code>
<code> </code><code>echo</code> <code>0;</code>
這樣我們的支付流程就徹底走完了。
二、當我們支付完之後,有些單子可以退單的,如何将款項也退回呢
以上場景要弄明白了
我們申請退款需要參數有哪些?我們看看支付類裡的退款方法
<code> </code><code>* 申請退款 - 使用商戶訂單号</code>
<code> </code><code>* @param $out_trade_no 商戶訂單号</code>
<code> </code><code>* @param $out_refund_no 退款單号</code>
<code> </code><code>* @param $total_fee 總金額(機關:分)</code>
<code> </code><code>* @param $refund_fee 退款金額(機關:分)</code>
<code> </code><code>* @param $op_user_id 操作員賬号</code>
<code> </code><code>* @return array</code>
<code>public</code> <code>function</code> <code>refund(</code><code>$out_trade_no</code><code>,</code><code>$out_refund_no</code><code>,</code><code>$total_fee</code><code>,</code><code>$refund_fee</code><code>,</code><code>$op_user_id</code><code>){</code>
<code> </code><code>$data</code><code>[</code><code>"appid"</code><code>] = </code><code>$this</code><code>->_config[</code><code>"appid"</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"mch_id"</code><code>] = </code><code>$this</code><code>->_config[</code><code>"mch_id"</code><code>];</code>
<code> </code><code>$data</code><code>[</code><code>"nonce_str"</code><code>] = </code><code>$this</code><code>->get_nonce_string();</code>
<code> </code><code>$data</code><code>[</code><code>"out_trade_no"</code><code>] = </code><code>$out_trade_no</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"out_refund_no"</code><code>] = </code><code>$out_refund_no</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"total_fee"</code><code>] = </code><code>$total_fee</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"refund_fee"</code><code>] = </code><code>$refund_fee</code><code>;</code>
<code> </code><code>$data</code><code>[</code><code>"op_user_id"</code><code>] = </code><code>$op_user_id</code><code>;</code>
<code> </code><code>$result</code> <code>= </code><code>$this</code><code>->post(self::URL_REFUND, </code><code>$data</code><code>,true);</code>
<code> </code><code>return</code> <code>$result</code><code>;</code>
商戶訂單号,商戶提供的退單号,付款金額,退款金額(不能退的比實際付款的多),操作員(一般商戶号)
控制器内寫退款方法
<code>//申請退款</code>
<code>function</code> <code>refund(</code><code>$id</code><code>=</code><code>""</code><code>)</code>
<code> </code><code>if</code><code>(</code><code>$id</code><code>==</code><code>""</code><code>){</code>
<code> </code><code>//友善我手動調用退單</code>
<code> </code><code>$id</code> <code>= </code><code>$this</code><code>->uri->segment(3);</code>
<code> </code><code>if</code> <code>(isset(</code><code>$id</code><code>) && </code><code>$id</code> <code>!= </code><code>""</code><code>) {</code>
<code> </code><code>$this</code><code>->load->model(</code><code>'publist'</code><code>);</code>
<code> </code><code>//1、取消訂單可以退款。2、失敗訂單可以退款</code>
<code> </code><code>$pub</code> <code>= </code><code>$this</code><code>->publist->GetList(</code><code>array</code><code>(</code><code>'id'</code> <code>=> </code><code>$id</code><code>));</code>
<code> </code><code>if</code> <code>(</code><code>$pub</code><code>->liststatus == 3 || </code><code>$pub</code><code>->liststatus == 4) {</code>
<code> </code><code>$listno</code> <code>= </code><code>$pub</code><code>->listno;</code>
<code> </code><code>$fee</code> <code>= </code><code>$pub</code><code>->fee * 100;</code>
<code> </code><code>$this</code><code>->load->config(</code><code>'wxpay_config'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'appid'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'appid'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'mch_id'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'apikey'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'apikey'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'appsecret'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'appsecret'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'sslcertPath'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'sslcertPath'</code><code>);</code>
<code> </code><code>$wxconfig</code><code>[</code><code>'sslkeyPath'</code><code>]=</code><code>$this</code><code>->config->item(</code><code>'sslkeyPath'</code><code>);</code>
<code> </code><code>$this</code><code>->load->library(</code><code>'Wechatpay'</code><code>,</code><code>$wxconfig</code><code>);</code>
<code> </code><code>if</code> <code>(isset(</code><code>$listno</code><code>) && </code><code>$listno</code> <code>!= </code><code>""</code><code>) {</code>
<code> </code><code>$out_trade_no</code> <code>= </code><code>$listno</code><code>;</code>
<code> </code><code>$total_fee</code> <code>= </code><code>$fee</code><code>;</code>
<code> </code><code>$refund_fee</code> <code>= </code><code>$fee</code><code>;</code>
<code> </code><code>//自定義商戶退單号</code>
<code> </code><code>$out_refund_no</code><code>=</code><code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>].</code><code>date</code><code>(</code><code>"YmdHis"</code><code>);</code>
<code> </code><code>$result</code><code>=</code><code>$this</code><code>->wechatpay->refund(</code><code>$out_trade_no</code><code>,</code><code>$out_refund_no</code><code>,</code><code>$total_fee</code><code>,</code><code>$refund_fee</code><code>,</code><code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>]);</code>
<code> </code><code>log::DEBUG(json_encode(</code><code>$result</code><code>));</code>
<code> </code><code>if</code> <code>(isset(</code><code>$result</code><code>[</code><code>"return_code"</code><code>]) && </code><code>$result</code><code>[</code><code>"return_code"</code><code>]=</code><code>"SUCCESS"</code><code>&&isset(</code><code>$result</code><code>[</code><code>"result_code"</code><code>]) && </code><code>$result</code><code>[</code><code>"result_code"</code><code>]=</code><code>"SUCCESS"</code><code>) {</code>
<code> </code><code>echo</code> <code>"<script>$.toast('退款成功')</script>"</code><code>;</code>
<code> </code><code>//傭金狀态更改為已退款</code>
<code> </code><code>$this</code><code>->publist->UpdateList(</code><code>array</code><code>(</code><code>'id'</code><code>=></code><code>$id</code><code>,</code><code>'liststatus'</code><code>=>3,</code><code>'listoutno'</code><code>=></code><code>$out_refund_no</code><code>));</code>
<code> </code><code>redirect(</code><code>'home/myorder'</code><code>);</code>
試試就好了,很快就可以接到退款消息
以上是這幾天摸索出來的東西,分享給大家。
其他參考文章:
http://blog.sina.com.cn/s/blog_14955e3b70102wvmj.html
如何聯系我:【萬裡虎】www.bravetiger.cn
【QQ】3396726884 (咨詢問題100元起,幫助解決問題500元起)
【部落格】http://www.cnblogs.com/kenshinobiy/