Maison >php教程 >php手册 >ThinkPay最新微信支付公众号支付驱动分享

ThinkPay最新微信支付公众号支付驱动分享

WBOY
WBOYoriginal
2016-12-01 00:00:171436parcourir

ThinkPay最新微信支付公众号支付驱动分享
下面分享个ThinkPay的微信支付驱动,便于大家使用,如有疑问加QQ群讨论105108204<?php <br /> // +----------------------------------------------------------------------<br> // | 零云 [ 简单 高效 卓越 ]<br> // +----------------------------------------------------------------------<br> // | Copyright (c) 2016 http://www.lingyun.net All rights reserved.<br> // +----------------------------------------------------------------------<br> // | Author: jry <br> // +----------------------------------------------------------------------<br> namespace Addons\Pay\ThinkPay\Pay\Driver;<br> <br> /**<br>  * 微信支付驱动<br>  */<br> class Wxpay extends \Addons\Pay\ThinkPay\Pay\Pay<br> {<br>     protected $gateway    = 'https://api.mch.weixin.qq.com/pay/unifiedorder';<br>     protected $orderquery = 'https://api.mch.weixin.qq.com/pay/orderquery';<br>     protected $config     = array(<br>         'appid'     => '',<br>         'appsecret' => '',<br>         'mchid'     => '',<br>         'key'       => '',<br>     );<br> <br>     public function check()<br>     {<br>         if (!$this->config['appid'] || !$this->config['appsecret'] || !$this->config['mchid'] || !$this->config['key']) {<br>             E("微信支付设置有误!");<br>         }<br>         return true;<br>     }<br> <br>     public function buildRequestForm($pay_data)<br>     {<br>         // APP支付<br>         if (C('IS_API')) {<br>             $param = array(<br>                 'appid'            => $this->config['appid'],<br>                 'mch_id'           => $this->config['mchid'],<br>                 'nonce_str'        => $this->getNonceStr(),<br>                 'body'             => $pay_data['body'],<br>                 'out_trade_no'     => $pay_data['out_trade_no'],<br>                 'total_fee'        => $pay_data['money'] * 100,<br>                 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],<br>                 'notify_url'       => $this->config['notify_url'],<br>                 'trade_type'       => 'APP',<br>             );<br> <br>             // 签名<br>             $param['sign'] = $this->MakeSign($param);<br>             $xml_param     = $this->ToXml($param);<br>             $result        = $this->FromXml($this->postXmlCurl($xml_param, $this->gateway));<br>             if ($result['return_code'] === 'SUCCESS') {<br>                 if ($this->CheckSign($result)) {<br>                     // 统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。<br>                     // 参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay<br>                     $prepayparams              = array();<br>                     $prepayparams['appid']     = $result['appid'];<br>                     $prepayparams['partnerid'] = $result['mch_id'];<br>                     $prepayparams['prepayid']  = $result['prepay_id'];<br>                     $prepayparams['noncestr']  = $result['nonce_str'];<br>                     $prepayparams['package']   = 'Sign=WXPay';<br>                     $prepayparams['timestamp'] = time();<br>                     $prepayparams['sign']      = $this->MakeSign($prepayparams); // 签名<br>                     $return['json']            = json_encode($prepayparams);<br>                     return $return;<br>                 }<br>             }<br>         } else {<br>             // 获取用户openId,微信公众号JSAPI支付必须<br>             $openId = $this->GetOpenid();<br>             $param  = array(<br>                 'appid'            => $this->config['appid'],<br>                 'mch_id'           => $this->config['mchid'],<br>                 'nonce_str'        => $this->getNonceStr(),<br>                 'body'             => $pay_data['body'],<br>                 'out_trade_no'     => $pay_data['out_trade_no'],<br>                 'total_fee'        => $pay_data['money'] * 100,<br>                 'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],<br>                 'notify_url'       => $this->config['notify_url'],<br>                 'trade_type'       => 'JSAPI',<br>                 'openid'           => $openId,<br>             );<br> <br>             // 签名<br>             $param['sign'] = $this->MakeSign($param);<br>             $xml_param     = $this->ToXml($param);<br>             $result        = $this->FromXml($this->postXmlCurl($xml_param, $this->gateway));<br>             if ($result['return_code'] === 'SUCCESS') {<br>                 if ($this->CheckSign($result)) {<br>                     // 获取JSAPI所需参数<br>                     $jsApiParameters = $this->GetJsApiParameters($result);<br>                     $pay_page        =                          <br>                             <br>                                 <meta> <br>                                 <meta> <br>                                 <title>微信支付</title> <br>                                 <script><br /> //调用微信JS api 支付<br /> function jsApiCall()<br /> {<br /> WeixinJSBridge.invoke(<br /> &#039;getBrandWCPayRequest&#039;,<br /> {$jsApiParameters},<br /> function(res){<br /> WeixinJSBridge.log(res.err_msg);<br /> //alert(res.err_code+res.err_desc+res.err_msg);<br /> }<br /> );<br /> }<br /> <br /> function callpay()<br /> {<br /> if (typeof WeixinJSBridge == "undefined"){<br /> if( document.addEventListener ){<br /> document.addEventListener(&#039;WeixinJSBridgeReady&#039;, jsApiCall, false);<br /> }else if (document.attachEvent){<br /> document.attachEvent(&#039;WeixinJSBridgeReady&#039;, jsApiCall);<br /> document.attachEvent(&#039;onWeixinJSBridgeReady&#039;, jsApiCall);<br /> }<br /> }else{<br /> jsApiCall();<br /> }<br /> }<br /> </script><br>                             <br>                             <br>                                 <br><br>                                 <font><b>该笔订单支付金额为<span>{$pay_data['money']}</span>元</b></font><br><br><br>                                 <div> <br>                                     <button>立即支付</button><br>                                 </div> <br>                             <br>                             <br> EOF;<br>                     return $pay_page;<br>                 }<br>             } else {<br>                 E("微信订单错误!" . $result['return_msg']);<br>             }<br>         }<br>     }<br> <br>     /**<br>      * 异步通知验证<br>      */<br>     public function verifyNotify($notify)<br>     {<br>         //获取通知的数据<br>         if ($notify['return_code'] === 'SUCCESS') {<br>             if (!array_key_exists("transaction_id", $notify)) {<br>                 E("输入参数不正确!");<br>             }<br>             $param['transaction_id'] = $notify["transaction_id"];<br>             $param['appid']          = $this->config['appid'];<br>             $param['mch_id']         = $this->config['mchid'];<br>             $param['nonce_str']      = $this->getNonceStr();<br>             $param['sign']           = $this->MakeSign($param);<br>             $xml_param               = $this->ToXml($param);<br>             $result                  = $this->FromXml($this->postXmlCurl($xml_param, $this->orderquery));<br>             if ($this->CheckSign($result)) {<br>                 $result['status'] = ($result['result_code'] == 'SUCCESS') ? true : false;<br>                 $result['money']  = $result['total_fee'] / 100;<br>                 $this->info       = $result;<br>                 return true;<br>             }<br>         } else {<br>             E('通知错误');<br>         }<br>     }<br> <br>     /**<br>      *<br>      * 获取jsapi支付的参数<br>      * @param array $UnifiedOrderResult 统一支付接口返回的数据<br>      * @throws WxPayException<br>      *<br>      * @return json数据,可直接填入js函数作为参数<br>      */<br>     public function GetJsApiParameters($UnifiedOrderResult)<br>     {<br>         if (!array_key_exists("appid", $UnifiedOrderResult)<br>             || !array_key_exists("prepay_id", $UnifiedOrderResult)<br>             || $UnifiedOrderResult['prepay_id'] == "") {<br>             E("参数错误");<br>         }<br>         $jsapi['appId']     = $UnifiedOrderResult["appid"];<br>         $jsapi['timeStamp'] = (string) time();<br>         $jsapi['nonceStr']  = $this->getNonceStr();<br>         $jsapi['appId']     = $UnifiedOrderResult["appid"];<br>         $jsapi['package']   = "prepay_id=" . $UnifiedOrderResult['prepay_id'];<br>         $jsapi['signType']  = 'MD5';<br>         $jsapi['paySign']   = $this->MakeSign($jsapi);<br>         $parameters         = json_encode($jsapi);<br>         return $parameters;<br>     }<br> <br>     /**<br>      * 以post方式提交xml到对应的接口url<br>      *<br>      * @param string $xml  需要post的xml数据<br>      * @param string $url  url<br>      * @param bool $useCert 是否需要证书,默认不需要<br>      * @param int $second   url执行超时时间,默认30s<br>      * @throws WxPayException<br>      */<br>     private static function postXmlCurl($xml, $url, $useCert = false, $second = 30)<br>     {<br>         $ch = curl_init();<br>         //设置超时<br>         curl_setopt($ch, CURLOPT_TIMEOUT, $second);<br> <br>         //如果有配置代理这里就设置代理<br>         // if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"<br>         //             && WxPayConfig::CURL_PROXY_PORT != 0){<br>         //             curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);<br>         //             curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);<br>         //         }<br>         curl_setopt($ch, CURLOPT_URL, $url);<br>         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);<br>         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); //严格校验<br>         //设置header<br>         curl_setopt($ch, CURLOPT_HEADER, false);<br>         //要求结果为字符串且输出到屏幕上<br>         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br> <br>         if ($useCert == true) {<br>             //设置证书<br>             //使用证书:cert 与 key 分别属于两个.pem文件<br>             curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');<br>             curl_setopt($ch, CURLOPT_SSLCERT, WxPayConfig::SSLCERT_PATH);<br>             curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');<br>             curl_setopt($ch, CURLOPT_SSLKEY, WxPayConfig::SSLKEY_PATH);<br>         }<br>         //post提交方式<br>         curl_setopt($ch, CURLOPT_POST, true);<br>         curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);<br>         //运行curl<br>         $data = curl_exec($ch);<br>         //返回结果<br>         if ($data) {<br>             curl_close($ch);<br>             return $data;<br>         } else {<br>             $error = curl_errno($ch);<br>             curl_close($ch);<br>             E("curl出错,错误码:$error");<br>         }<br>     }<br> <br>     /*<br>      * 产生随机字符串,不长于32位<br>      * @param int $length<br>      * @return 产生的随机字符串<br>      */<br>     public static function getNonceStr($length = 32)<br>     {<br>         $chars = "abcdefghijklmnopqrstuvwxyz0123456789";<br>         $str   = "";<br>         for ($i = 0; $i              $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);<br>         }<br>         return $str;<br>     }<br> <br>     /**<br>      * 生成签名<br>      * @return 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值<br>      */<br>     public function MakeSign($param)<br>     {<br>         //签名步骤一:按字典序排序参数<br>         ksort($param);<br>         $string = $this->ToUrlParams($param);<br>         //签名步骤二:在string后加入KEY<br>         $string = $string . "&key=" . $this->config['key'];<br>         //签名步骤三:MD5加密<br>         $string = md5($string);<br>         //签名步骤四:所有字符转为大写<br>         $result = strtoupper($string);<br>         return $result;<br>     }<br> <br>     /**<br>      *<br>      * 检测签名<br>      */<br>     public function CheckSign($param)<br>     {<br>         $sign = $this->MakeSign($param);<br>         if ($param['sign'] == $sign) {<br>             return true;<br>         } else {<br>             E("签名错误!");<br>         }<br>     }<br> <br>     /**<br>      *<br>      * 拼接签名字符串<br>      * @param array $urlObj<br>      *<br>      * @return 返回已经拼接好的字符串<br>      */<br>     public function ToUrlParams($param)<br>     {<br>         $buff = "";<br>         foreach ($param as $k => $v) {<br>             if ($k != "sign" && $v != "" && !is_array($v)) {<br>                 $buff .= $k . "=" . $v . "&";<br>             }<br>         }<br> <br>         $buff = trim($buff, "&");<br>         return $buff;<br>     }<br> <br>     /**<br>      * 输出xml字符<br>      * @throws WxPayException<br>      **/<br>     public function ToXml($param)<br>     {<br>         if (!is_array($param)<br>             || count($param)              E("数组数据异常!");<br>         }<br> <br>         $xml = "<xml>";<br>         foreach ($param as $key => $val) {<br>             if (is_numeric($val)) {<br>                 $xml .= "" . $val . "" . $key . ">";<br>             } else {<br>                 $xml .= "" . $key . ">";<br>             }<br>         }<br>         $xml .= "</xml>";<br>         return $xml;<br>     }<br> <br>     /**<br>      * 将xml转为array<br>      * @param string $xml<br>      * @throws WxPayException<br>      */<br>     public function FromXml($xml)<br>     {<br>         if (!$xml) {<br>             E("xml数据异常!");<br>         }<br>         //将XML转为array<br>         //禁止引用外部xml实体<br>         libxml_disable_entity_loader(true);<br>         $this->values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);<br>         return $this->values;<br>     }<br> <br>     /**<br>      *<br>      * 通过跳转获取用户的openid,跳转流程如下:<br>      * 1、设置自己需要调回的url及其其他参数,跳转到微信服务器https://open.weixin.qq.com/connect/oauth2/authorize<br>      * 2、微信服务处理完成之后会跳转回用户redirect_uri地址,此时会带上一些参数,如:code<br>      *<br>      * @return 用户的openid<br>      */<br>     public function GetOpenid()<br>     {<br>         //通过code获得openid<br>         if (!isset($_GET['code'])) {<br>             //触发微信返回code码<br>             $baseUrl = urlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);<br>             $url     = $this->__CreateOauthUrlForCode($baseUrl);<br>             Header("Location: $url");<br>             exit();<br>         } else {<br>             //获取code码,以获取openid<br>             $code   = $_GET['code'];<br>             $openid = $this->getOpenidFromMp($code);<br>             return $openid;<br>         }<br>     }<br> <br>     /**<br>      *<br>      * 通过code从工作平台获取openid机器access_token<br>      * @param string $code 微信跳转回来带上的code<br>      *<br>      * @return openid<br>      */<br>     public function GetOpenidFromMp($code)<br>     {<br>         $url = $this->__CreateOauthUrlForOpenid($code);<br>         //初始化curl<br>         $ch = curl_init();<br>         //设置超时<br>         curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);<br>         curl_setopt($ch, CURLOPT_URL, $url);<br>         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);<br>         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);<br>         curl_setopt($ch, CURLOPT_HEADER, false);<br>         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);<br>         // if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0"<br>         //             && WxPayConfig::CURL_PROXY_PORT != 0){<br>         //             curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);<br>         //             curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);<br>         //         }<br>         //运行curl,结果以jason形式返回<br>         $res = curl_exec($ch);<br>         curl_close($ch);<br>         //取出openid<br>         $data       = json_decode($res, true);<br>         $this->data = $data;<br>         $openid     = $data['openid'];<br>         return $openid;<br>     }<br> <br>     /**<br>      *<br>      * 构造获取code的url连接<br>      * @param string $redirectUrl 微信服务器回跳的url,需要url编码<br>      *<br>      * @return 返回构造好的url<br>      */<br>     private function __CreateOauthUrlForCode($redirectUrl)<br>     {<br>         $urlObj["appid"]         = $this->config['appid'];<br>         $urlObj["redirect_uri"]  = "$redirectUrl";<br>         $urlObj["response_type"] = "code";<br>         $urlObj["scope"]         = "snsapi_base";<br>         $urlObj["state"]         = "#wechat_redirect";<br>         $bizString               = $this->ToUrlParams($urlObj);<br>         return "https://open.weixin.qq.com/connect/oauth2/authorize?" . $bizString;<br>     }<br> <br>     /**<br>      *<br>      * 构造获取open和access_toke的url地址<br>      * @param string $code,微信跳转带回的code<br>      *<br>      * @return 请求的url<br>      */<br>     private function __CreateOauthUrlForOpenid($code)<br>     {<br>         $urlObj["appid"]      = $this->config['appid'];<br>         $urlObj["secret"]     = $this->config['appsecret'];<br>         $urlObj["code"]       = $code;<br>         $urlObj["grant_type"] = "authorization_code";<br>         $bizString            = $this->ToUrlParams($urlObj);<br>         return "https://api.weixin.qq.com/sns/oauth2/access_token?" . $bizString;<br>     }<br> }

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn