您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)php如何實(shí)現(xiàn)支付寶手機(jī)網(wǎng)頁支付類的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。
具體分析如下:
此處注意:
① 該類是用在Yii框架里面的,沒有去掉一些框架的東西。
② 本類不能不做任何修改而使用。
1. PHP代碼部分如下:
<?php namespace weixin\components; use Yii; /** * 支付寶手機(jī)網(wǎng)頁支付 * * @example * 創(chuàng)建支付請求 * $params = []; //支付寶文檔中所需的全部參數(shù) * $alipay = new Alipay(); * $alipay->key = ''; //交易安全校驗(yàn)碼 * $this->alipay->alipay_config = $params; * $alipay->buildRequest(); * * 驗(yàn)證異步通知 * $this->alipay->key = ''; //交易安全校驗(yàn)碼 * $this->alipay->alipay_config = $data; //支付寶異步通知參數(shù) * $this->alipay->verifyNotify(); * * @package Alipay * @author Dyllen * @since Version 0.2 */ class Alipay { /** * 交易安全校驗(yàn)碼 * * @access public * @var string */ public $key; /** * 請求參數(shù)配置,支付寶接口文檔中所需的參數(shù) * * @access public * @var array */ public $alipay_config=[]; /** * HTTPS證書,用于cURL * 默認(rèn)和本類文件同級目錄的cacert.pem文件 * * @access public * @var string */ public $credential; public $notify_data = null; /** * 支付寶即時(shí)到賬網(wǎng)關(guān)地址 */ const ALIPAY_GATEWAY = 'https://mapi.alipay.com/gateway.do?'; /** * HTTPS形式消息驗(yàn)證地址 */ const HTTPS_VERIFY_URL = 'https://mapi.alipay.com/gateway.do?service=notify_verify&'; /** * HTTP形式消息驗(yàn)證地址 */ const HTTP_VERIFY_URL = 'http://notify.alipay.com/trade/notify_query.do?'; /** * 移動(dòng)網(wǎng)頁支付網(wǎng)關(guān) * @var string */ const ALIPAY_PAGE_GATEWAY = 'http://wappaygw.alipay.com/service/rest.htm?'; /** * 創(chuàng)建支付包即時(shí)到賬請求url * * @access public * @return void */ public function buildRequest() { $this->alipay_config['sign'] = $this->signData(); return self::ALIPAY_GATEWAY . $this->createQueryString('', true); } /** * 創(chuàng)建支付寶手機(jī)網(wǎng)頁支付鏈接 * @return string */ public function buildPageUrl() { $this->alipay_config['sign'] = $this->signData(); $url = self::ALIPAY_PAGE_GATEWAY. $this->createQueryString(''); $response = $this->getHttpResponseGET($url); $res = $this->parseResponse(trim($response)); //重新組合支付請求參數(shù) $this->alipay_config['service'] = 'alipay.wap.auth.authAndExecute'; $this->alipay_config['req_data'] = '<auth_and_execute_req><request_token>'.$res['request_token'].'</request_token></auth_and_execute_req>'; $this->alipay_config['sign'] = $this->signData(); return self::ALIPAY_PAGE_GATEWAY. $this->createQueryString('', true); } /** * 驗(yàn)證支付寶異步通知參數(shù)合法性 * * @access public * @return boolean */ public function verifyNotify() { $param_tmp = $this->filter(); //過濾待簽名數(shù)據(jù) if(!isset($this->alipay_config['notify_data'])) { return false; } $this->notify_data = $this->xmlToArray($this->alipay_config['notify_data']); $this->alipay_config['notify_id'] = $this->notify_data['notify_id']; $responseTxt = 'true'; if( !empty( $this->alipay_config['notify_id'] ) ) { $responseTxt = $this->getResponse(); } unset($this->alipay_config['notify_id']); $txt = 'service='; $txt .= $this->alipay_config['service']; $txt .= '&v='.$this->alipay_config['v']; $txt .= '&sec_id='.$this->alipay_config['sec_id']; $txt .= '¬ify_data='.$this->alipay_config['notify_data']; $txt .= $this->key; $sign = md5($txt); if ( preg_match("/true$/i",$responseTxt) && ($sign == $this->alipay_config['sign']) ) { return true; } else { return false; } } /** * 解析授權(quán)接口返回 * @param string $content 授權(quán)接口返回的文本數(shù)據(jù) * @throws \Exception * @return array */ private function parseResponse($content) { parse_str($content, $arr); $data = isset($arr['res_data']) ? $arr['res_data'] : $arr['res_error']; $res_data = simplexml_load_string($data); if(strlen($res_data->request_token) == 0 || strlen($res_data->msg) > 0) { throw new \Exception('code:'.$res_data->code.','.$res_data->msg); } $arr['request_token'] = $res_data->request_token->__toString(); return $arr; } /** * simpleXML對象轉(zhuǎn)成數(shù)組 * @param string $xml * @return multitype:NULL */ private function xmlToArray($xml) { $xml_obj = simplexml_load_string($xml, 'SimpleXMLIterator'); $arr = []; $xml_obj->rewind(); //指針指向第一個(gè)元素 while (1) { if( ! is_object($xml_obj->current()) ) { break; } $arr[$xml_obj->key()] = $xml_obj->current()->__toString(); $xml_obj->next(); //指向下一個(gè)元素 } return $arr; } /** * 簽名數(shù)據(jù) * 簽名規(guī)則: * sign和sign_type不參加簽名,需要去掉 * 對參數(shù)數(shù)組依據(jù)鍵名按照字母順序升序排序 * 排序完成之后鍵值對用&字符連接,組成URL的查詢字符串形式待簽名字符串,待簽名數(shù)據(jù)不需用url encoding * MD5簽名:私鑰拼接到待簽名字符串的后面,然后用md5對字符串運(yùn)算,得到32位簽名結(jié)果 * * @return string 已簽名數(shù)據(jù) */ private function signData() { $param_tmp = $this->getSignString(); //待簽名字符串 if( !isset($this->key) ) { return FALSE; } $sign = ''; //簽名數(shù)據(jù) switch ($this->alipay_config['sec_id']) { case '001': //rsa $sign = $this->rsaSign($param_tmp); break; case 'DES': break; default: $sign = $this->md5Sign($param_tmp); } return $sign; } /** * MD5加密字符串 * * @access private * @param string $data 待加密字符串 * @return string */ private function md5Sign( $data ) { return md5($data . $this->key); } /** * RSA 加密字符串 * * @param string $data 待加密字符串 * @return string */ private function rsaSign( $data ) { return false; } /** * 獲得待簽名數(shù)據(jù) * * @access private * @return string */ private function getSignString() { $param_tmp = $this->filter(); //過濾待簽名數(shù)據(jù) //排序 ksort($param_tmp); reset($param_tmp); //創(chuàng)建查詢字符串形式的待簽名數(shù)據(jù) return $this->createQueryString($param_tmp); } /** * 過濾待簽名數(shù)據(jù),去掉sing、sing_type及空值 * * @access private * @return array */ private function filter() { $para_filter = array(); foreach($this->alipay_config as $key => $value){ if($key == "sign" || $key == "sign_type" || empty($value)) continue; else $para_filter[$key] = $value; } return $para_filter; } /** * 用&拼接字符串,形成URL查詢字符串 * * @access private * @param array $data * @param boolean $is_encode 是否對值做urlencode * @return string */ private function createQueryString($data=NULL, $is_encode=false ) { $arr = empty($data) ? $this->alipay_config : $data; $arg = ''; foreach( $arr as $key => $value ) { if($is_encode) { $key = urlencode($key); $value = urlencode($value); } $arg .= $key . '=' . $value . '&'; } $arg = substr($arg, 0, strlen($arg)-1); //去掉最后一個(gè)& //如果存在轉(zhuǎn)義字符,那么去掉轉(zhuǎn)義 if(get_magic_quotes_gpc()) {$arg = stripslashes($arg);} return $arg; } /** * 獲取遠(yuǎn)程服務(wù)器ATN結(jié)果,驗(yàn)證返回URL * * 驗(yàn)證結(jié)果集: * invalid命令參數(shù)不對 出現(xiàn)這個(gè)錯(cuò)誤,請檢測返回處理中partner和key是否為空 * true 返回正確信息 * false 請檢查防火墻或者是服務(wù)器阻止端口問題以及驗(yàn)證時(shí)間是否超過一分鐘 * * @access private * @return 服務(wù)器ATN結(jié)果 */ private function getResponse() { //載入支付配置 $config = Yii::$app->params['alipay']; $transport = strtolower(trim($config['transport'])); $partner = trim($config['partner']); $veryfy_url = ''; if($transport == 'https') { $veryfy_url = self::HTTPS_VERIFY_URL; } else { $veryfy_url = self::HTTP_VERIFY_URL; } $veryfy_url = $veryfy_url."partner=" . $partner . "¬ify_id=" . $this->alipay_config['notify_id']; $responseTxt = $this->getHttpResponseGET($veryfy_url); return $responseTxt; } /** * 取證書,用于cURL的請求 * * @access private * @return string 證書路徑 */ private function getCr() { if( ! empty($this->credential) ) { return $this->credential; } return __DIR__ . DIRECTORY_SEPARATOR .'cacert.pem'; } /** * 遠(yuǎn)程獲取數(shù)據(jù),POST模式 * 注意: * 1.使用Crul需要修改服務(wù)器中php.ini文件的設(shè)置,找到php_curl.dll去掉前面的";"就行了 * 2.文件夾中cacert.pem是SSL證書請保證其路徑有效,目前默認(rèn)路徑是:getcwd().'\\cacert.pem' * * @param $url 指定URL完整路徑地址 * @param $cacert_url 指定當(dāng)前工作目錄絕對路徑 * @param $para 請求的數(shù)據(jù) * @param $input_charset 編碼格式。默認(rèn)值:空值 * return 遠(yuǎn)程輸出的數(shù)據(jù) */ private function getHttpResponsePOST($url, $para, $input_charset = '') { if (trim($input_charset) != '') { $url = $url."_input_charset=".$input_charset; } $curl = curl_init($url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL證書認(rèn)證 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//嚴(yán)格認(rèn)證 curl_setopt($curl, CURLOPT_CAINFO,$this->getCr());//證書地址 curl_setopt($curl, CURLOPT_HEADER, 0 ); // 過濾HTTP頭 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 顯示輸出結(jié)果 curl_setopt($curl, CURLOPT_POST,true); // post傳輸數(shù)據(jù) curl_setopt($curl, CURLOPT_POSTFIELDS,$para);// post傳輸數(shù)據(jù) $responseText = curl_exec($curl); //var_dump( curl_error($curl) );//如果執(zhí)行curl過程中出現(xiàn)異常,可打開此開關(guān),以便查看異常內(nèi)容 curl_close($curl); return $responseText; } /** * 遠(yuǎn)程獲取數(shù)據(jù),GET模式 * 注意: * 1.使用Crul需要修改服務(wù)器中php.ini文件的設(shè)置,找到php_curl.dll去掉前面的";"就行了 * 2.文件夾中cacert.pem是SSL證書請保證其路徑有效,目前默認(rèn)路徑是:getcwd().'\\cacert.pem' * * @param $url 指定URL完整路徑地址 * @param $cacert_url 指定當(dāng)前工作目錄絕對路徑 * return 遠(yuǎn)程輸出的數(shù)據(jù) */ private function getHttpResponseGET($url) { $curl = curl_init($url); curl_setopt($curl, CURLOPT_HEADER, 0 ); // 過濾HTTP頭 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 顯示輸出結(jié)果 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL證書認(rèn)證 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//嚴(yán)格認(rèn)證 curl_setopt($curl, CURLOPT_CAINFO,$this->getCr());//證書地址 $responseText = curl_exec($curl); //var_dump( curl_error($curl) );exit;//如果執(zhí)行curl過程中出現(xiàn)異常,可打開此開關(guān),以便查看異常內(nèi)容 curl_close($curl); return $responseText; } }
2. 使用方法:
//授權(quán)接口請求參數(shù) $sum = 0.01; //測試用金額 $req_data = '<direct_trade_create_req><subject>充值</subject>'; $req_data .= '<out_trade_no>'.$orderNo.'</out_trade_no>'; $req_data .= '<total_fee>'.$sum.'</total_fee>'; $req_data .= '<call_back_url>'.Url::toRoute(['payment/return'], true).'</call_back_url>'; $req_data .= '<notify_url>'.Url::toRoute(['payment/notify'], true).'</notify_url>'; $req_data .= '<seller_account_name>'.Yii::$app->params['alipay']['seller_email'].'</seller_account_name>'; $req_data .= '</direct_trade_create_req>'; $params = [ 'service' => 'alipay.wap.trade.create.direct', 'format' => 'xml', 'v' => '2.0', 'partner' => Yii::$app->params['alipay']['partner'], //合作者省份ID 'req_id' => date('Ymdhis'), 'sec_id' => Yii::$app->params['alipay']['sign_type'], 'req_data' => $req_data, ]; $alipay = new Alipay(); $alipay->key = Yii::$app->params['alipay']['key']; $alipay->alipay_config = $params; $url = $alipay->buildPageUrl(); $this->redirect($url);
3. 配置示例:
//支付寶相關(guān)配置 'alipay' => [ 'key' => 'XXXXX', //交易安全校驗(yàn)碼,用于簽名的32位密鑰 'transport' => 'https', //消息驗(yàn)證地址使用訪問方式 'seller_email' => 'XXXX', //賣家支付寶賬號,即收款賬戶 'service' => 'create_direct_pay_by_user', //接口名稱 'partner' => 'XXXX', //合作者省份ID '_input_charset' => 'utf-8', //參數(shù)編碼字符集 'sign_type' => 'MD5', //簽名方式,不參加簽名,目前只能是MD5 //以下兩個(gè)參數(shù)沒用 'notify_url' => '', //服務(wù)器異步通知頁面路徑 'return_url' => '', //頁面跳轉(zhuǎn)通知頁面路徑 ],
感謝各位的閱讀!關(guān)于“php如何實(shí)現(xiàn)支付寶手機(jī)網(wǎng)頁支付類”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。