天天看點

***CodeIgniter內建微信支付(轉)微信支付Native掃碼支付模式二之CodeIgniter內建篇微信支付JSAPI模式及退款CodeIgniter內建篇CI內建JSApi微信支付

 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>-&gt;_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>-&gt;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>-&gt;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>&amp;&amp; </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>-&gt;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>-&gt;errorXML = </code><code>$this</code><code>-&gt;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>-&gt;_config[</code><code>"appid"</code><code>];</code>

<code>        </code><code>$data</code><code>[</code><code>"mch_id"</code><code>] = </code><code>$this</code><code>-&gt;_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>])&amp;&amp;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>-&gt;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>-&gt;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>-&gt;sign(</code><code>$data</code><code>);</code>

<code>        </code><code>$xml</code> <code>= </code><code>$this</code><code>-&gt;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>-&gt;_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>-&gt;_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>-&gt;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>=&gt; </code><code>$v</code><code>) {</code>

<code>            </code><code>if</code> <code>(</code><code>$v</code> <code>&amp;&amp; trim(</code><code>$v</code><code>)!=</code><code>''</code><code>) {</code>

<code>                </code><code>$string1</code> <code>.= </code><code>"$k=$v&amp;"</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>-&gt;_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>"&lt;xml&gt;"</code> <code>. PHP_EOL;</code>

<code>        </code><code>foreach</code> <code>(</code><code>$array</code> <code>as</code> <code>$k</code> <code>=&gt; </code><code>$v</code><code>) {</code>

<code>            </code><code>if</code><code>(</code><code>$v</code> <code>&amp;&amp; trim(</code><code>$v</code><code>)!=</code><code>''</code><code>)</code>

<code>                </code><code>$xml</code> <code>.= </code><code>"&lt;$k&gt;&lt;![CDATA[$v]]&gt;&lt;/$k&gt;"</code> <code>. PHP_EOL;</code>

<code>        </code><code>$xml</code> <code>.= </code><code>"&lt;/xml&gt;"</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>&amp;&amp; </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>=&gt; </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>-&gt;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>-&gt;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>-&gt;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>-&gt;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>-&gt;_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>-&gt;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>-&gt;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>-&gt;xml2array(</code><code>$xml</code><code>);</code>

<code>        </code><code>if</code> <code>(</code><code>$this</code><code>-&gt;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>-&gt;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>&lt;?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>-&gt;load-&gt;config(</code><code>'wxpay_config'</code><code>);</code>

<code>$wxconfig</code><code>[</code><code>'appid'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'appid'</code><code>);</code>

<code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'mch_id'</code><code>);</code>

<code>$wxconfig</code><code>[</code><code>'apikey'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'apikey'</code><code>);</code>

<code>$wxconfig</code><code>[</code><code>'appsecret'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'appsecret'</code><code>);</code>

<code>$wxconfig</code><code>[</code><code>'sslcertPath'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'sslcertPath'</code><code>);</code>

<code>$wxconfig</code><code>[</code><code>'sslkeyPath'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'sslkeyPath'</code><code>);</code>

<code>//由于此類庫構造函數需要傳參,我們初始化類庫就傳參數給他吧</code>

<code>$this</code><code>-&gt;load-&gt;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>-&gt;productid;</code><code>//正好有産品id就傳了個,看文檔說自己定義</code>

<code>//調用統一下單API接口</code>

<code>      </code><code>$result</code><code>=</code><code>$this</code><code>-&gt;wechatpay-&gt;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>]) &amp;&amp; !</code><code>empty</code><code>(</code><code>$result</code><code>[</code><code>"code_url"</code><code>])) { /&gt;            </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>-&gt;load-&gt;view(</code><code>'home/pay'</code><code>, </code><code>$data</code><code>);</code>

<code>      </code><code>}</code>

***CodeIgniter內建微信支付(轉)微信支付Native掃碼支付模式二之CodeIgniter內建篇微信支付JSAPI模式及退款CodeIgniter內建篇CI內建JSApi微信支付

pay.php掃碼視圖頁面代碼如下:這部分代碼來自(https://github.com/Alpha2016/wxpay)

<code>&lt;?php </code><code>if</code><code>(isset(</code><code>$wxurl</code><code>)&amp;&amp;!</code><code>empty</code><code>(</code><code>$wxurl</code><code>)){?&gt;</code>

<code>    </code><code>&lt;div </code><code>class</code><code>=</code><code>"bgcolor"</code><code>&gt;</code>

<code>        </code><code>&lt;div </code><code>class</code><code>=</code><code>"container"</code><code>&gt;</code>

<code>            </code><code>&lt;div </code><code>class</code><code>=</code><code>"panel"</code><code>&gt;</code>

<code>                </code><code>&lt;div </code><code>class</code><code>=</code><code>"panel-heading"</code><code>&gt;</code>

<code>                    </code><code>&lt;ol </code><code>class</code><code>=</code><code>"breadcrumb"</code><code>&gt;</code>

<code>                        </code><code>&lt;li&gt;&lt;a href=</code><code>"&lt;?php echo base_url().'home';?&gt;"</code><code>&gt;首頁&lt;/a&gt;&lt;span </code><code>class</code><code>=</code><code>'divider'</code><code>&gt;&gt;&lt;/span&gt;&lt;/li&gt;</code>

<code>                        </code><code>&lt;li </code><code>class</code><code>=</code><code>"active active-tab"</code><code>&gt;&lt;span&gt;&lt;?php </code><code>echo</code> <code>"二維碼支付"</code><code>;?&gt;&lt;/span&gt;&lt;/li&gt;</code>

<code>                    </code><code>&lt;/ol&gt;</code>

<code>                </code><code>&lt;/div&gt;</code>

<code>                </code><code>&lt;div </code><code>class</code><code>=</code><code>"panel-body"</code><code>&gt;</code>

<code>                    </code><code>&lt;div </code><code>class</code><code>=</code><code>"page-header"</code><code>&gt;二維碼支付&lt;/div&gt;</code>

<code>                    </code><code>&lt;div </code><code>class</code><code>=</code><code>"text-danger center-block text-center"</code><code>&gt;</code>

<code>                        </code><code>&lt;input type=</code><code>"hidden"</code> <code>id=</code><code>"orderno"</code> <code>value=</code><code>"&lt;?php echo $orderno;?&gt;"</code><code>/&gt;</code>

<code>                        </code><code>&lt;img alt=</code><code>"掃碼支付"</code> <code>src=</code><code>"&lt;?php echo base_url().'home/qrcode?data='.urlencode($wxurl);?&gt;"</code> <code>style=</code><code>"width:200px;height:200px;"</code><code>/&gt;</code>

<code>                    </code><code>&lt;/div&gt;</code>

<code>            </code><code>&lt;/div&gt;</code>

<code>        </code><code>&lt;/div&gt;</code>

<code>    </code><code>&lt;/div&gt;</code>

<code>&lt;?php }?&gt;</code>

<code>&lt;script&gt;</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>"&lt;?php echo base_url().'home/queryorder';?&gt;"</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>"&lt;?php echo base_url().'home/myorder';?&gt;"</code><code>;</code>

<code>                    </code><code>}</code>

<code>                </code><code>}</code>

<code>            </code><code>});</code>

<code>&lt;/script&gt;</code>

  其實核心在二維碼連結如何轉換成二維碼圖檔和如何定時輪詢支付結果

<code>&lt;?php </code><code>echo</code> <code>base_url().</code><code>'home/qrcode?data='</code><code>.urlencode(</code><code>$wxurl</code><code>);?&gt;這句是調用phpqrcode類庫&lt;br&gt;輪詢方法代碼:&lt;br&gt;該部分在home控制器下</code>

<code>function</code> <code>queryorder()</code>

<code>{</code>

<code>    </code><code>$this</code><code>-&gt;load-&gt;config(</code><code>'wxpay_config'</code><code>);</code>

<code>    </code><code>$wxconfig</code><code>[</code><code>'appid'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'appid'</code><code>);</code>

<code>    </code><code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'mch_id'</code><code>);</code>

<code>    </code><code>$wxconfig</code><code>[</code><code>'apikey'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'apikey'</code><code>);</code>

<code>    </code><code>$wxconfig</code><code>[</code><code>'appsecret'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'appsecret'</code><code>);</code>

<code>    </code><code>$wxconfig</code><code>[</code><code>'sslcertPath'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'sslcertPath'</code><code>);</code>

<code>    </code><code>$wxconfig</code><code>[</code><code>'sslkeyPath'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'sslkeyPath'</code><code>);</code>

<code>    </code><code>$this</code><code>-&gt;load-&gt;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>-&gt;wechatpay-&gt;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>-&gt;load-&gt;config(</code><code>'wxpay_config'</code><code>);</code>

<code>        </code><code>$wxconfig</code><code>[</code><code>'appid'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'appid'</code><code>);</code>

<code>        </code><code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'mch_id'</code><code>);</code>

<code>        </code><code>$wxconfig</code><code>[</code><code>'apikey'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'apikey'</code><code>);</code>

<code>        </code><code>$wxconfig</code><code>[</code><code>'appsecret'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'appsecret'</code><code>);</code>

<code>        </code><code>$wxconfig</code><code>[</code><code>'sslcertPath'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'sslcertPath'</code><code>);</code>

<code>        </code><code>$wxconfig</code><code>[</code><code>'sslkeyPath'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'sslkeyPath'</code><code>);</code>

<code>        </code><code>$this</code><code>-&gt;load-&gt;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>-&gt;load-&gt;model(</code><code>'payorder'</code><code>);</code>

<code>            </code><code>$payinfo</code> <code>= </code><code>$this</code><code>-&gt;payorder-&gt;GetPayorder(</code><code>array</code><code>(</code><code>'orderno'</code> <code>=&gt; </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>-&gt;payorder-&gt;AddPayorder(</code><code>$data</code><code>);</code>

<code>                </code><code>if</code><code>(</code><code>$rs</code><code>&gt;0)</code>

<code>                </code><code>{            </code><code>//告知微信我成功了</code>

<code>                    </code><code>$this</code><code>-&gt;wechatpay-&gt;response_back();</code>

<code>                </code><code>}</code><code>else</code><code>{            </code><code>//告知微信我失敗了繼續發</code>

<code>                    </code><code>$this</code><code>-&gt;wechatpay-&gt;response_back(</code><code>"FAIL"</code><code>);</code>

<code>            </code><code>}</code><code>else</code><code>{</code>

<code>                </code><code>$this</code><code>-&gt;wechatpay-&gt;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>-&gt;_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>-&gt;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>-&gt;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架構的擴充類庫,可以直接用,目錄結構,我們直接上代碼吧

***CodeIgniter內建微信支付(轉)微信支付Native掃碼支付模式二之CodeIgniter內建篇微信支付JSAPI模式及退款CodeIgniter內建篇CI內建JSApi微信支付

<code>public</code> <code>function</code> <code>__construct()</code>

<code>    </code><code>parent::__construct();</code>

<code>    </code><code>$this</code><code>-&gt;load-&gt;library(</code><code>'CI_Wechat'</code><code>);</code><code>//由于我的項目是時刻都跟微信綁在一起,是以直接加載在構造函數裡了,不用每個方法都加載了。</code>

<code>    </code><code>$this</code><code>-&gt;load-&gt;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>-&gt;ci_wechat-&gt;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>-&gt;__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>-&gt;ci_wechat-&gt;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-&gt;_isRegistered($_SESSION['user']['openid']);</code>

<code>        </code><code>return</code> <code>$openid</code><code>;</code>

 以上兩個方法就是擷取openid的,擷取之後我是儲存在session裡的,我每個頁面都判斷是否擷取了openid如果沒有擷取直接

<code>$this</code><code>-&gt;session-&gt;set_userdata(</code><code>'openid'</code><code>, </code><code>$this</code><code>-&gt;oauth());</code>

 這樣保證一直能得到openid

2、構造JSAPI支付所需參數(統一下單的參數構造)

<code>$this</code><code>-&gt;load-&gt;model(</code><code>'publist'</code><code>);</code><code>//擷取訂單資訊</code>

<code>$pub</code> <code>= </code><code>$this</code><code>-&gt;publist-&gt;GetList(</code><code>array</code><code>(</code><code>'id'</code> <code>=&gt; </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>-&gt;listno;</code>

<code>$total_fee</code><code>=</code><code>$pub</code><code>-&gt;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>-&gt;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>-&gt;wechatpay-&gt;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>]) &amp;&amp; !</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>-&gt;wechatpay-&gt;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>-&gt;load-&gt;view(</code><code>'home/header'</code><code>);</code>

<code>    </code><code>//要有個頁面将以上資料傳遞過去并展示給使用者</code>

<code>    </code><code>$this</code><code>-&gt;load-&gt;view(</code><code>'home/pay'</code><code>, </code><code>$data</code><code>);</code>

<code>    </code><code>$this</code><code>-&gt;load-&gt;view(</code><code>'home/footer'</code><code>);</code>

<code>}       </code>

 3、支付頁面,views視圖pay.php

<code>&lt;?php</code>

<code>$jsApiParameters</code> <code>= </code><code>$parameters</code><code>;</code><code>//參數指派</code>

<code>?&gt;</code>

<code>&lt;script type=</code><code>"text/javascript"</code><code>&gt;</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>&lt;?php </code><code>echo</code> <code>$jsApiParameters</code><code>; ?&gt;,</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>'&lt;?php  echo $notifyurl.'</code><code>/</code><code>'.$pubid;?&gt;'</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>"&lt;?php echo base_url().'index.php/home/myorder';?&gt;"</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>&lt;div </code><code>class</code><code>=</code><code>"hd"</code><code>&gt;</code>

<code>    </code><code>&lt;h1 </code><code>class</code><code>=</code><code>"page_title"</code><code>&gt;支付傭金&lt;/h1&gt;</code>

<code>    </code><code>&lt;p </code><code>class</code><code>=</code><code>"page_desc"</code><code>&gt;請認真核對傭金金額&lt;/p&gt;</code>

<code>&lt;/div&gt;</code>

<code>&lt;div </code><code>class</code><code>=</code><code>"weui_cells"</code><code>&gt;</code>

<code>    </code><code>&lt;div </code><code>class</code><code>=</code><code>"weui_cell"</code><code>&gt;</code>

<code>        </code><code>&lt;div </code><code>class</code><code>=</code><code>"weui_cell_hd weui_cell_primary"</code><code>&gt;</code>

<code>            </code><code>該筆訂單支付金額為&lt;span style=</code><code>"color:#f00;font-size:50px"</code><code>&gt;&lt;?php </code><code>echo</code> <code>$fee</code><code>; ?&gt;&lt;/span&gt;元錢</code>

<code>&lt;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>&gt;立即支付&lt;/button&gt;</code>

4、支付成功跳轉頁面,我們看notify方法

<code>function</code> <code>notify()</code>

<code>    </code><code>$id</code> <code>= </code><code>$this</code><code>-&gt;uri-&gt;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>-&gt;load-&gt;model(</code><code>'publist'</code><code>);</code><code>//更新業務邏輯</code>

<code>        </code><code>$rs</code> <code>= </code><code>$this</code><code>-&gt;publist-&gt;UpdateList(</code><code>array</code><code>(</code><code>'id'</code> <code>=&gt; </code><code>$id</code><code>, </code><code>'feestatus'</code> <code>=&gt; 1));</code>

<code>        </code><code>if</code> <code>(</code><code>$rs</code> <code>&gt; 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>-&gt;_config[</code><code>"appid"</code><code>];</code>

<code>    </code><code>$data</code><code>[</code><code>"mch_id"</code><code>] = </code><code>$this</code><code>-&gt;_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>-&gt;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>-&gt;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>-&gt;uri-&gt;segment(3);</code>

<code>    </code><code>if</code> <code>(isset(</code><code>$id</code><code>) &amp;&amp; </code><code>$id</code> <code>!= </code><code>""</code><code>) {</code>

<code>        </code><code>$this</code><code>-&gt;load-&gt;model(</code><code>'publist'</code><code>);</code>

<code>        </code><code>//1、取消訂單可以退款。2、失敗訂單可以退款</code>

<code>        </code><code>$pub</code> <code>= </code><code>$this</code><code>-&gt;publist-&gt;GetList(</code><code>array</code><code>(</code><code>'id'</code> <code>=&gt; </code><code>$id</code><code>));</code>

<code>        </code><code>if</code> <code>(</code><code>$pub</code><code>-&gt;liststatus == 3 || </code><code>$pub</code><code>-&gt;liststatus == 4) {</code>

<code>            </code><code>$listno</code> <code>= </code><code>$pub</code><code>-&gt;listno;</code>

<code>            </code><code>$fee</code> <code>= </code><code>$pub</code><code>-&gt;fee * 100;</code>

<code>            </code><code>$this</code><code>-&gt;load-&gt;config(</code><code>'wxpay_config'</code><code>);</code>

<code>            </code><code>$wxconfig</code><code>[</code><code>'appid'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'appid'</code><code>);</code>

<code>            </code><code>$wxconfig</code><code>[</code><code>'mch_id'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'mch_id'</code><code>);</code>

<code>            </code><code>$wxconfig</code><code>[</code><code>'apikey'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'apikey'</code><code>);</code>

<code>            </code><code>$wxconfig</code><code>[</code><code>'appsecret'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'appsecret'</code><code>);</code>

<code>            </code><code>$wxconfig</code><code>[</code><code>'sslcertPath'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'sslcertPath'</code><code>);</code>

<code>            </code><code>$wxconfig</code><code>[</code><code>'sslkeyPath'</code><code>]=</code><code>$this</code><code>-&gt;config-&gt;item(</code><code>'sslkeyPath'</code><code>);</code>

<code>            </code><code>$this</code><code>-&gt;load-&gt;library(</code><code>'Wechatpay'</code><code>,</code><code>$wxconfig</code><code>);</code>

<code>            </code><code>if</code> <code>(isset(</code><code>$listno</code><code>) &amp;&amp; </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>-&gt;wechatpay-&gt;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>]) &amp;&amp; </code><code>$result</code><code>[</code><code>"return_code"</code><code>]=</code><code>"SUCCESS"</code><code>&amp;&amp;isset(</code><code>$result</code><code>[</code><code>"result_code"</code><code>]) &amp;&amp; </code><code>$result</code><code>[</code><code>"result_code"</code><code>]=</code><code>"SUCCESS"</code><code>) {</code>

<code>                    </code><code>echo</code> <code>"&lt;script&gt;$.toast('退款成功')&lt;/script&gt;"</code><code>;</code>

<code>                </code><code>//傭金狀态更改為已退款</code>

<code>                </code><code>$this</code><code>-&gt;publist-&gt;UpdateList(</code><code>array</code><code>(</code><code>'id'</code><code>=&gt;</code><code>$id</code><code>,</code><code>'liststatus'</code><code>=&gt;3,</code><code>'listoutno'</code><code>=&gt;</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/