天天看点

***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/