当前位置:首页 > PHP教程 > php高级应用 > 列表

php支付宝手机网页支付类实例

发布:smiling 来源: PHP粉丝网  添加日期:2021-05-15 15:35:49 浏览: 评论:0 

这篇文章主要介绍了php支付宝手机网页支付类实例,是基于Yii框架使用的支付宝接口类文件,非常具有实用价值,需要的朋友可以参考下

本文实例讲述了php支付宝手机网页支付类,分享给大家供大家参考,具体分析如下:

此处注意:

① 该类是用在Yii框架里面的,没有去掉一些框架的东西。

② 本类不能不做任何修改而使用。

1. PHP代码部分如下:

  1. <?php 
  2. namespace weixin\components; 
  3. use Yii; 
  4. /** 
  5.  * 支付宝手机网页支付 
  6.  * 
  7.  * @example 
  8.  *     创建支付请求 
  9.  *     $params = []; //支付宝文档中所需的全部参数 
  10.  *     $alipay = new Alipay(); 
  11.  *     $alipay->key = ''; //交易安全校验码 
  12.  *     $this->alipay->alipay_config = $params; 
  13.  *     $alipay->buildRequest(); 
  14.  *     
  15.  *     验证异步通知 
  16.  *     $this->alipay->key = ''; //交易安全校验码 
  17.  *     $this->alipay->alipay_config = $data; //支付宝异步通知参数 
  18.  *     $this->alipay->verifyNotify(); 
  19.  * 
  20.  * @package Alipay 
  21.  * @author Dyllen 
  22.  * @since Version 0.2 
  23.  */ 
  24. class Alipay { 
  25.     /** 
  26.      * 交易安全校验码 
  27.      * 
  28.      * @access public 
  29.      * @var string 
  30.      */ 
  31.     public $key
  32.      
  33.     /** 
  34.      * 请求参数配置,支付宝接口文档中所需的参数 
  35.      * 
  36.      * @access public 
  37.      * @var array 
  38.      */ 
  39.     public $alipay_config=[]; 
  40.      
  41.     /** 
  42.      * HTTPS证书,用于cURL 
  43.      * 默认和本类文件同级目录的cacert.pem文件 
  44.      * 
  45.      * @access public 
  46.      * @var string 
  47.      */ 
  48.     public $credential
  49.      
  50.     public $notify_data = null; 
  51.      
  52.     /** 
  53.      * 支付宝即时到账网关地址 
  54.      */ 
  55.     const ALIPAY_GATEWAY = 'https://mapi.alipay.com/gateway.do?'
  56.      
  57.     /** 
  58.      * HTTPS形式消息验证地址 
  59.      */ 
  60.     const HTTPS_VERIFY_URL = 'https://mapi.alipay.com/gateway.do?service=notify_verify&'
  61.      
  62.     /** 
  63.      * HTTP形式消息验证地址 
  64.      */ 
  65.     const HTTP_VERIFY_URL = 'http://notify.alipay.com/trade/notify_query.do?'
  66.      
  67.     /** 
  68.      * 移动网页支付网关 
  69.      * @var string 
  70.      */ 
  71.     const ALIPAY_PAGE_GATEWAY = 'http://wappaygw.alipay.com/service/rest.htm?'
  72.      
  73.      
  74.     /** 
  75.      * 创建支付包即时到账请求url 
  76.      * 
  77.      * @access public 
  78.      * @return void 
  79.      */ 
  80.     public function buildRequest() { 
  81.         $this->alipay_config['sign'] = $this->signData(); 
  82.         return self::ALIPAY_GATEWAY . $this->createQueryString('', true);        
  83.     } 
  84.      
  85.     /** 
  86.      * 创建支付宝手机网页支付链接 
  87.      * @return string 
  88.      */ 
  89.     public function buildPageUrl() 
  90.     { 
  91.         $this->alipay_config['sign'] = $this->signData(); 
  92.         $url = self::ALIPAY_PAGE_GATEWAY. $this->createQueryString(''); 
  93.         $response = $this->getHttpResponseGET($url); 
  94.         $res = $this->parseResponse(trim($response)); 
  95.         //重新组合支付请求参数 
  96.         $this->alipay_config['service'] = 'alipay.wap.auth.authAndExecute'
  97.         $this->alipay_config['req_data'] = '<auth_and_execute_req><request_token>'.$res['request_token'].'</request_token></auth_and_execute_req>'
  98.          
  99.         $this->alipay_config['sign'] = $this->signData(); 
  100.         return self::ALIPAY_PAGE_GATEWAY. $this->createQueryString('', true); 
  101.     } 
  102.      
  103.     /** 
  104.      * 验证支付宝异步通知参数合法性 
  105.      * 
  106.      * @access public 
  107.      * @return boolean 
  108.      */ 
  109.     public function verifyNotify() { 
  110.         $param_tmp = $this->filter(); //过滤待签名数据 
  111.         if(!isset($this->alipay_config['notify_data'])) { 
  112.             return false; 
  113.         } 
  114.         $this->notify_data = $this->xmlToArray($this->alipay_config['notify_data']); 
  115.         $this->alipay_config['notify_id'] = $this->notify_data['notify_id']; 
  116.         $responseTxt = 'true'
  117.         if( !emptyempty$this->alipay_config['notify_id'] ) ) { 
  118.             $responseTxt = $this->getResponse(); 
  119.         } 
  120.         unset($this->alipay_config['notify_id']); 
  121.         $txt = 'service='
  122.         $txt .= $this->alipay_config['service']; 
  123.         $txt .= '&v='.$this->alipay_config['v']; 
  124.         $txt .= '&sec_id='.$this->alipay_config['sec_id']; 
  125.         $txt .= '&notify_data='.$this->alipay_config['notify_data']; 
  126.         $txt .= $this->key;      
  127.         $sign = md5($txt); 
  128.  
  129.         if ( preg_match("/true$/i",$responseTxt) && ($sign == $this->alipay_config['sign']) ) { 
  130.             return true; 
  131.         } else { 
  132.             return false; 
  133.         } 
  134.     } 
  135.      
  136.     /** 
  137.      * 解析授权接口返回 
  138.      * @param string $content 授权接口返回的文本数据 
  139.      * @throws \Exception 
  140.      * @return array 
  141.      */ 
  142.     private function parseResponse($content) { 
  143.         parse_str($content$arr); 
  144.         $data = isset($arr['res_data']) ? $arr['res_data'] : $arr['res_error']; 
  145.         $res_data = simplexml_load_string($data); 
  146.         if(strlen($res_data->request_token) == 0 || strlen($res_data->msg) > 0) { 
  147.             throw new \Exception('code:'.$res_data->code.','.$res_data->msg); 
  148.         } 
  149.         $arr['request_token'] = $res_data->request_token->__toString(); 
  150.         return $arr
  151.     } 
  152.      
  153.     /** 
  154.      * simpleXML对象转成数组 
  155.      * @param string $xml 
  156.      * @return multitype:NULL 
  157.      */ 
  158.     private function xmlToArray($xml
  159.     { 
  160.         $xml_obj = simplexml_load_string($xml'SimpleXMLIterator'); 
  161.         $arr = []; 
  162.         $xml_obj->rewind(); //指针指向第一个元素 
  163.         while (1) { 
  164.             if( ! is_object($xml_obj->current()) ) 
  165.             { 
  166.                 break
  167.             } 
  168.             $arr[$xml_obj->key()] = $xml_obj->current()->__toString(); 
  169.             $xml_obj->next(); //指向下一个元素 
  170.         } 
  171.         return $arr
  172.     } 
  173.      
  174.     /** 
  175.      * 签名数据 
  176.      * 签名规则: 
  177.      *     sign和sign_type不参加签名,需要去掉 
  178.      *     对参数数组依据键名按照字母顺序升序排序 
  179.      *     排序完成之后键值对用&字符连接,组成URL的查询字符串形式待签名字符串,待签名数据不需用url encoding 
  180.      *     MD5签名:私钥拼接到待签名字符串的后面,然后用md5对字符串运算,得到32位签名结果 
  181.      *     
  182.      * @return string 已签名数据 
  183.      */ 
  184.     private function signData() { 
  185.         $param_tmp = $this->getSignString(); //待签名字符串 
  186.          
  187.         if( !isset($this->key) ) { 
  188.             return FALSE; 
  189.         } 
  190.          
  191.         $sign = ''
  192.          
  193.         //签名数据 
  194.         switch ($this->alipay_config['sec_id']) { 
  195.             case '001'//rsa 
  196.                 $sign = $this->rsaSign($param_tmp); 
  197.                 break
  198.             case 'DES'
  199.                 break
  200.             default
  201.                 $sign = $this->md5Sign($param_tmp); 
  202.         } 
  203.          
  204.         return $sign
  205.     } 
  206.      
  207.     /** 
  208.      * MD5加密字符串 
  209.      * 
  210.      * @access private 
  211.      * @param string $data 待加密字符串 
  212.      * @return string 
  213.      */ 
  214.     private function md5Sign( $data ) { 
  215.         return md5($data . $this->key); 
  216.     } 
  217.      
  218.     /** 
  219.      * RSA 加密字符串 
  220.      * 
  221.      * @param string $data 待加密字符串 
  222.      * @return string 
  223.      */ 
  224.     private function rsaSign( $data ) { 
  225.         return false; 
  226.     } 
  227.      
  228.     /** 
  229.      * 获得待签名数据 
  230.      * 
  231.      * @access private 
  232.      * @return string 
  233.      */ 
  234.     private function getSignString() { 
  235.         $param_tmp = $this->filter(); //过滤待签名数据 
  236.          
  237.         //排序 
  238.         ksort($param_tmp); 
  239.         reset($param_tmp); 
  240.          
  241.         //创建查询字符串形式的待签名数据 
  242.         return $this->createQueryString($param_tmp); 
  243.     } 
  244.      
  245.     /** 
  246.      * 过滤待签名数据,去掉sing、sing_type及空值 
  247.      * 
  248.      * @access private 
  249.      * @return array 
  250.      */ 
  251.     private function filter() { 
  252.         $para_filter = array(); 
  253.         foreach($this->alipay_config as $key => $value){ 
  254.             if($key == "sign" || $key == "sign_type" || emptyempty($value)) continue
  255.             else $para_filter[$key] = $value
  256.         } 
  257.         return $para_filter
  258.     } 
  259.      
  260.     /** 
  261.      * 用&拼接字符串,形成URL查询字符串 
  262.      * 
  263.      * @access private 
  264.      * @param array $data 
  265.      * @param boolean $is_encode 是否对值做urlencode 
  266.      * @return string 
  267.      */ 
  268.     private function createQueryString($data=NULL, $is_encode=false ) { 
  269.         $arr = emptyempty($data) ? $this->alipay_config : $data
  270.         $arg = ''
  271.         foreach$arr as $key => $value ) { 
  272.             if($is_encode) { 
  273.                 $key = urlencode($key); 
  274.                 $value = urlencode($value); 
  275.             } 
  276.             $arg .= $key . '=' . $value . '&'
  277.         } 
  278.         $arg = substr($arg, 0, strlen($arg)-1); //去掉最后一个& 
  279.         //如果存在转义字符,那么去掉转义 
  280.         if(get_magic_quotes_gpc()) {$arg = stripslashes($arg);} 
  281.          
  282.         return $arg
  283.     } 
  284.      
  285.     /** 
  286.      * 获取远程服务器ATN结果,验证返回URL 
  287.      * 
  288.      * 验证结果集: 
  289.      * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空 
  290.      * true 返回正确信息 
  291.      * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟 
  292.      * 
  293.      * @access private 
  294.      * @return 服务器ATN结果 
  295.      */ 
  296.     private function getResponse() { 
  297.         //载入支付配置 
  298.         $config = Yii::$app->params['alipay']; 
  299.          
  300.         $transport = strtolower(trim($config['transport'])); 
  301.         $partner = trim($config['partner']); 
  302.         $veryfy_url = ''
  303.         if($transport == 'https') { 
  304.             $veryfy_url = self::HTTPS_VERIFY_URL; 
  305.         } 
  306.         else { 
  307.             $veryfy_url = self::HTTP_VERIFY_URL; 
  308.         } 
  309.         $veryfy_url = $veryfy_url."partner=" . $partner . "&notify_id=" . $this->alipay_config['notify_id']; 
  310.         $responseTxt = $this->getHttpResponseGET($veryfy_url); 
  311.      
  312.         return $responseTxt
  313.     } 
  314.      
  315.     /** 
  316.      * 取证书,用于cURL的请求 
  317.      * 
  318.      * @access private 
  319.      * @return string 证书路径 
  320.      */ 
  321.     private function getCr() { 
  322.         if( ! emptyempty($this->credential) ) { 
  323.             return $this->credential; 
  324.         } 
  325.         return __DIR__ . DIRECTORY_SEPARATOR .'cacert.pem'
  326.     } 
  327.      
  328.     /** 
  329.      * 远程获取数据,POST模式 
  330.      * 注意: 
  331.      * 1.使用Crul需要修改服务器中php.ini文件的设置,找到php_curl.dll去掉前面的";"就行了 
  332.      * 2.文件夹中cacert.pem是SSL证书请保证其路径有效,目前默认路径是:getcwd().'\\cacert.pem' 
  333.      * 
  334.      * @param $url 指定URL完整路径地址 
  335.      * @param $cacert_url 指定当前工作目录绝对路径 
  336.      * @param $para 请求的数据 
  337.      * @param $input_charset 编码格式。默认值:空值 
  338.      * return 远程输出的数据 
  339.      */ 
  340.     private function getHttpResponsePOST($url$para$input_charset = '') { 
  341.      
  342.         if (trim($input_charset) != '') { 
  343.             $url = $url."_input_charset=".$input_charset
  344.         } 
  345.         $curl = curl_init($url); 
  346.         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL证书认证 
  347.         curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证 
  348.         curl_setopt($curl, CURLOPT_CAINFO,$this->getCr());//证书地址 
  349.         curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头 
  350.         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 显示输出结果 
  351.         curl_setopt($curl, CURLOPT_POST,true); // post传输数据 
  352.         curl_setopt($curl, CURLOPT_POSTFIELDS,$para);// post传输数据 
  353.         $responseText = curl_exec($curl); 
  354.         //var_dump( curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容 
  355.         curl_close($curl); 
  356.      
  357.         return $responseText
  358.     } 
  359.      
  360.     /** 
  361.      * 远程获取数据,GET模式 
  362.      * 注意: 
  363.      * 1.使用Crul需要修改服务器中php.ini文件的设置,找到php_curl.dll去掉前面的";"就行了 
  364.      * 2.文件夹中cacert.pem是SSL证书请保证其路径有效,目前默认路径是:getcwd().'\\cacert.pem' 
  365.      * 
  366.      * @param $url 指定URL完整路径地址 
  367.      * @param $cacert_url 指定当前工作目录绝对路径 
  368.      * return 远程输出的数据 
  369.      */ 
  370.     private function getHttpResponseGET($url) { 
  371.         $curl = curl_init($url); 
  372.         curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头 
  373.         curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 显示输出结果 
  374.         curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL证书认证 
  375.         curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证 
  376.         curl_setopt($curl, CURLOPT_CAINFO,$this->getCr());//证书地址 
  377.         $responseText = curl_exec($curl); 
  378.         //var_dump( curl_error($curl) );exit;//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容 
  379.         curl_close($curl); 
  380.      
  381.         return $responseText
  382.     } 

2. 使用方法:

  1. //授权接口请求参数 
  2. $sum = 0.01; //测试用金额 
  3. $req_data = '<direct_trade_create_req><subject>充值</subject>'
  4. $req_data .= '<out_trade_no>'.$orderNo.'</out_trade_no>'
  5. $req_data .= '<total_fee>'.$sum.'</total_fee>'
  6. $req_data .= '<call_back_url>'.Url::toRoute(['payment/return'], true).'</call_back_url>'
  7. $req_data .= '<notify_url>'.Url::toRoute(['payment/notify'], true).'</notify_url>'
  8. $req_data .= '<seller_account_name>'.Yii::$app->params['alipay']['seller_email'].'</seller_account_name>'
  9. $req_data .= '</direct_trade_create_req>'
  10. $params = [ 
  11.     'service' => 'alipay.wap.trade.create.direct'
  12.     'format' => 'xml'
  13.     'v' => '2.0'
  14.     'partner' => Yii::$app->params['alipay']['partner'], //合作者省份ID 
  15.     'req_id' => date('Ymdhis'), 
  16.     'sec_id' => Yii::$app->params['alipay']['sign_type'], 
  17.     'req_data' => $req_data
  18. ]; 
  19.  
  20. $alipay = new Alipay(); 
  21. $alipay->key = Yii::$app->params['alipay']['key']; 
  22. $alipay->alipay_config = $params
  23. $url = $alipay->buildPageUrl(); 
  24. $this->redirect($url); 

3. 配置示例:

  1. //支付宝相关配置 
  2. 'alipay' => [ 
  3.         'key' => 'XXXXX',  //交易安全校验码,用于签名的32位密钥 
  4.         'transport' => 'https',         //消息验证地址使用访问方式 
  5.         'seller_email' => 'XXXX'//卖家支付宝账号,即收款账户 
  6.         'service' => 'create_direct_pay_by_user'//接口名称 
  7.         'partner' => 'XXXX'//合作者省份ID 
  8.         '_input_charset' => 'utf-8'//参数编码字符集 
  9.         'sign_type' => 'MD5'//签名方式,不参加签名,目前只能是MD5 
  10.         //以下两个参数没用 
  11.         'notify_url' => ''//服务器异步通知页面路径 
  12.         'return_url' => ''//页面跳转通知页面路径 
  13. ],

Tags: php支付宝手机网页支付类

分享到: