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 AddonsPayThinkPayPayDriver;<br>
<br>
/**<br>
* 微信支付驅動<br>
*/<br>
class Wxpay extends AddonsPayThinkPayPayPay<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's),<br>
'out_trade_no' => $pay_data['out_trade_no'],<br>
'total_fee' => $pay_data['money'] * 100,<br>=> $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>
$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的值格式為Sign=WXPay<br>
$prepayparams
$prepayparams['appid'] = $result['appid'
$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'] = $
$return['json']
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>
'身體' => $pay_data['body'],<br>
'out_trade_no' =>; $pay_data['out_trade_no'],<br>
'total_fee' => $pay_data['money'] * 100,<br>
'spbil_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>
$結果 = $this->FromXml($this->postXmlCurl($xml_param, $this->gateway));<br>
if ($result['return_code'] === '成功') {<br>
if ($this->CheckSign($result)) {<br>
// 取得JSAPI所需參數<br>
$jsApiParameters = $this->GetJsApiParameters($result);<br>
$pay_page =
<br>
<br>
<meta>
<br>
<meta name="viewport" content="width=device-width,initial-scale=1">
<br>
<title>微信支付</title>
<br>
<br> //使用微函JS
function jsApiCall()<br>
{<br>
地
地
}<br>
<br>
function callpay()<br>
{<br>
se);<br>
地
document.attachEvent('WeixinJSBridgeReady', jsApiCall);<br>
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);<br>
}<br>
}else{<br>
jsApiCall();<br>
}<br>
}<br>
</script><br>
</head><br>
<body><br>
<br/><br>
<font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">{$pay_data['money']}</span>元</b></font><br/><br/><br>
<div align="center"><br>
<button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" onclick="callpay()" >立即支付</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 = $1_FromXquecafid);
if ($this->CheckSign($result)) {<br>
$result['status'] = ($result['result_code'] == 'SUCCESS') true : false'] == 'SUCCESS') true : false;
$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>
公共函數 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>
返回$參數;<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>
私人靜態函數 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>
公用函數 CheckSign($param)<br>
{<br>
$sign = $this->MakeSign($param);<br>
if ($param['sign'] == $sign) {<br>
則回 true;<br>
} 另外 {<br>
E("簽署錯誤!");<br>
}<br>
}<br>
<br>
/**<br>
*<br>
* 拼接簽章字串<br>
* @param array $urlObj<br>
*<br>
* @return 回傳已拼接的字串<br>
*/<br>
公用函數 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=修剪($buff,「&」);<br>
返回 $buff;<br>
}<br>
<br>
/**<br>
* 輸出xml字元<br>
* @throws WxPayException<br>
**/<br>
公用函數 ToXml($param)<br>
{<br>
if (!is_array($param)<br>
|| 計數($param)
E("備份資料異常!");<br>
}<br>
<br>
$xml = 「<xml>」;<br>
foreach($param as $key => $val){<br>
如果(is_numeric($val)){<br>
$xml.=「” 。 $val。 “”。 $鍵。 「>」;<br>
} 另有 {<br>
$xml.=「」。 $鍵。 「>」;<br>
}<br>
}<br>
$xml .= 「</xml>」;<br>
返回 $xml;<br>
}<br>
<br>
/**<br>
* 將xml轉換至array<br>
* @param string $xml<br>
* @throws WxPayException<br>
*/<br>
公用函數FromXml($xml)<br>
{<br>
如果(!$ 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>
回 $openid;<br>
}<br>
<br>
/**<br>
*<br>
* 構造取得code的url連結<br>
* @param string $redirectUrl 微信伺服器回跳的url,需要url編碼<br>
*<br>
* @return 返回構造好的url<br>
*/<br>
私人函數__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>
返回「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>
私人函數__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>
返回「https://api.weixin.qq.com/sns/oauth2/access_token?」 。 $bizString;<br>
}<br>
}