zoukankan      html  css  js  c++  java
  • 支付宝手机网站即时交易 自己封装的类

      1 <?php
      2     /*
      3         支付宝封装类
      4         采用 rsa 生成签名模式
      5     */
      6     class Alipay {
      7         private $_config                     = array();
      8         private $_alipay_gateway_new         = 'https://mapi.alipay.com/gateway.do?'; //支付宝网关地址(新)
      9         private $_https_verify_url             = 'https://mapi.alipay.com/gateway.do?service=notify_verify&'; //校验用到
     10         private $_fix_config                   = array();
     11 
     12 
     13         public function __construct() {
     14             $this->_makeFixconfig();
     15         }
     16 
     17         //读取固定参数
     18         private function _makeFixconfig() {
     19             $this->_fix_config             = array(
     20                 'service'                 => 'alipay.wap.create.direct.pay.by.user',
     21                 '_input_charset'         => 'utf-8',
     22                 'sign_type'             => 'RSA',
     23                 'seller_id'             => '',
     24                 'private_key_path'         => VENDOR_PATH . '/Alipay/rsa_private_key.pem',//私密key
     25                 'ali_public_key_path'     => VENDOR_PATH . '/Alipay/alipay_public_key.pem',//公开key
     26                 'cacert'                 => VENDOR_PATH . '/Alipay/cacert.pem',//https请求用到验证
     27                 'transport'             => 'http',
     28                 'payment_type'             => 1,//固定参数
     29             );
     30         }
     31 
     32         /*
     33             config 需要参数
     34                 partner                         //合作身份者id,以2088开头的16位纯数字
     35                 notify_url                         //阿里处理后,异步处理url地址,http开头
     36                 return_url                         //阿里处理后,同步处理url地址
     37             
     38                 out_trade_no                     //订单号
     39                 subject                         //商品名称
     40                 total_fee                         //商品金额
     41                 
     42 
     43         */
     44         //生成配置文件,并请求
     45         public function run($config) {
     46             foreach ($config as $value) {
     47                 if(empty($value))
     48                     exit('缺少必要参数');
     49             }    
     50 
     51             $this->_fix_config['seller_id']         = $config['partner'];
     52 
     53             $this->_config                             = array_merge($this->_fix_config,$config);
     54 
     55             //签名,请求
     56             $this->_makeSign();
     57         }
     58 
     59 
     60         //生成签名信息,并发送请求
     61         private function _makeSign() {
     62             //获取签名需要的参数
     63             $param                 = array(
     64                     '_input_charset'    => trim($this->_config['_input_charset']),
     65                     'service'             => trim($this->_config['service']),
     66                     'partner'             => trim($this->_config['partner']),
     67                     'seller_id'            => trim($this->_config['seller_id']),
     68                     'payment_type'        => trim($this->_config['payment_type']),
     69                     'notify_url'        => trim($this->_config['notify_url']),
     70                     'return_url'        => trim($this->_config['return_url']),
     71                     'out_trade_no'        => trim($this->_config['out_trade_no']),
     72                     'subject'            => trim($this->_config['subject']),
     73                     'total_fee'            => trim($this->_config['total_fee']),                    
     74             );
     75 
     76             //对数组进行排序
     77             ksort($param);
     78             reset($param);
     79             
     80             //读取pem信息,生成key
     81             if(!file_exists($this->_config['private_key_path']) || !file_exists($this->_config['ali_public_key_path']))
     82                 exit('缺少pem必要参数,请检查');
     83 
     84             if(!function_exists('openssl_pkey_get_private'))
     85                 exit('不支持openssl');
     86 
     87             $query_string         = '';
     88             $query_string         = $this->_makeSignString($param);
     89 
     90             $private_key_info    = file_get_contents($this->_config['private_key_path']);
     91 
     92             $private_key_res     = openssl_pkey_get_private($private_key_info);
     93 
     94             $sign                 = '';
     95             openssl_sign($query_string, $sign, $private_key_res);
     96 
     97             openssl_free_key($private_key_res);
     98 
     99             //base64编码
    100             $param['sign']                 = base64_encode($sign);
    101 
    102             //验证签名
    103             // $this->_checkSign($query_string,$param['sign']);
    104 
    105             $param['sign_type']            = trim($this->_config['sign_type']);
    106 
    107             //触发表单请求,使用get模拟请求会失败
    108             $this->_formPush($param,'确认');
    109         }
    110 
    111         /*
    112             --不能用模拟请求
    113             发送get请求
    114             $url         请求url地址
    115         */
    116         private function _makeGetHttp($url) {
    117             $curl                 = curl_init($url);
    118 
    119             // curl_setopt($curl, CURLOPT_POST, 1);
    120             curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头
    121             curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
    122             curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL证书认证
    123             curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证
    124             curl_setopt($curl, CURLOPT_CAINFO,$this->_fix_config['cacert']);//证书地址
    125             curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
    126             curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
    127             curl_setopt($curl,    CURLOPT_USERAGENT,"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"); 
    128 
    129             $result             = curl_exec($curl);
    130 
    131             $httpCode             = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    132             $curlErrNo             = curl_errno($curl);
    133             $curlErr             = curl_error($curl);
    134 
    135             curl_close($curl);
    136 
    137             if ($httpCode == "0") 
    138                    die("Curl error number:" . $curlErrNo . " , Curl error details:" . $curlErr . "
    ");
    139             else if ($httpCode != "200") 
    140                    die("Http code:" . $httpCode .  " details:" . $result . "
    ");
    141               
    142             return $result;
    143         }
    144 
    145         /*
    146             采用表单提交
    147         */
    148         private function _formPush($para_temp,$button_name) {
    149             $sHtml         = '<!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>支付宝通信中...</title><link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/3.3.4/css/bootstrap.min.css"></head><body>';
    150 
    151             $sHtml         .= '<div class="container-fluid"><div class="row" style="margin-top:200px;"><div class="col-xs-10 col-md-10 col-xs-offset-1 col-md-offset-1"><span class="btn btn-success btn-block">请稍后,连接支付宝...</span></div></div></div>';
    152 
    153             $sHtml         .= "<div style='display:none;'><form id='alipaysubmit' name='alipaysubmit' action='".$this->_alipay_gateway_new."_input_charset=".trim(strtolower($this->_config['_input_charset']))."' method='get'>";
    154             while (list ($key, $val) = each ($para_temp)) {
    155                 $sHtml    .= "<input type='hidden' name='".$key."' value='".$val."'/>";
    156             }
    157 
    158             //submit按钮控件请不要含有name属性
    159             $sHtml         = $sHtml."<input type='submit' value='".$button_name."'></form></div></body></html>";
    160             
    161             $sHtml         = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>";
    162             
    163 
    164             echo $sHtml;
    165         }
    166 
    167 
    168         /*
    169             构造签名字符串
    170         */
    171         private function _makeSignString($arr,$type=false) {
    172             $tmp_str             = '';
    173             foreach ($arr as $key => $value) {
    174                 if($key == 'sign' || $key == 'sign_type') 
    175                     continue;
    176                 $tmp_str         .= $key . '=' . $value . '&';
    177             }
    178 
    179             return trim($tmp_str,'&');
    180         }
    181 
    182         /*
    183             验证rsa签名
    184             @param         $data 返回的get或者post的总数组,
    185                         $sign get['sign'] 或者 post['sign']
    186             @return     bool
    187         */
    188         public function checkSign($data,$sign) {
    189 
    190             //处理数据
    191             $new_data                     = array();
    192             foreach ($data as $key => $value) {
    193                 if($key == 'sign' || $key == 'sign_type' || $key == '_URL_' || $value == '')
    194                     continue;
    195                 $new_data[$key]             = $value;
    196             }
    197 
    198             ksort($new_data);
    199             reset($new_data);
    200 
    201             $new_data_str                 = '';
    202             $new_data_str                 = $this->_makeSignString($new_data);
    203 
    204             $ali_public_key_info         = file_get_contents($this->_fix_config['ali_public_key_path']);
    205             $ali_public_key_res         = openssl_pkey_get_public($ali_public_key_info);
    206             
    207             $ali_public_key_verify        = openssl_verify($new_data_str, base64_decode($sign), $ali_public_key_res);
    208             openssl_free_key($ali_public_key_res);
    209 
    210                if(!$ali_public_key_verify)
    211                    return false;
    212                return true;
    213         }
    214 
    215 
    216         /*
    217             验证url来源是否为支付宝
    218             @param             partner 合作账号
    219                             notify_id get|post返回的
    220         */
    221         public function checkUrlFrom($partner,$notify_id) {
    222             $url             = $this->_https_verify_url . 'partner=' . $partner . '&notify_id=' . $notify_id;
    223             return $this->_makeGetHttp($url);
    224         }
    225 
    226 
    227 
    228 
    229 
    230 
    231 
    232 
    233 
    234 
    235 
    236     }

    调用案例:

      通知页面不能有阻拦,比如说要登录才能进入之类的

     1         /*
     2             测试支付宝
     3         */
     4         public function test_alipay() {
     5             //引入
     6             Vendor('Alipay.Alipay');
     7 
     8             //生成参数
     9             $param                 = array(
    10                 'partner'         => C('PARTENR'),//2088开头的支付宝信息
    11                 'notify_url'     => 'http://' . $_SERVER['HTTP_HOST'] . U('Leasegoods/alipay_notify_url'),//异步通知页面
    12                 'return_url'     => 'http://' . $_SERVER['HTTP_HOST'] . U('Leasegoods/alipay_return_url'),//同步通知页面
    13                 'out_trade_no'     => $this->_dealOrderNum(),//订单号
    14                 'subject'         => 'lxd',//商品名称
    15                 'total_fee'     => '0.01',//商品价格
    16 
    17             );
    18 
    19             $alipay_obj         = new Alipay();
    20             $alipay_obj->run($param);
    21         }

     通知页面验证:

      同步异步都类似,第一 校验签名;第二 校验来源;其余的就是业务之类的东西了

     1 public function alipay_return_url() {
     2             $info                 = serialize($_GET);
     3             
     4             $data                 = array();
     5             //判断状态
     6             if(isset($_GET) && $_GET['is_success'] == 'T') {
     7                 $order_index         = $_GET['out_trade_no'];
     8 
     9                 //校验签名
    10                 Vendor('Alipay.Alipay');
    11                 $alipay_obj         = new Alipay();
    12                 $res                 = $alipay_obj->checkSign($_GET,$_GET['sign']);
    13 
    14                 if(!$res){
    15                     $data['type']     = 'error';
    16                     $data['info']   = '警告:服务器校验数据失败';
    17                     $this->assign('data',$data);
    18                     $this->display('info');die;
    19                 }
    20 
    21                 //校验来源
    22                 $res                 = null;
    23                 $res                 = $alipay_obj->checkUrlFrom(C('PARTENR'),$_GET['notify_id']);
    24                 if($res == 'false'){
    25                     $data['type']     = 'error';
    26                     $data['info']   = '错误:服务器校验来源错误';
    27                     $this->assign('data',$data);
    28                     $this->display('info');die;
    29                 }
    30 
    31                 //记录流水
    32                 $alipay_log_model     = M('alipay_log');
    33                 $insert_res         = $alipay_log_model->add(array('order_index' => $order_index,'type' => 'return','info' => $info));
    34                 if(!$insert_res){
    35                     $data['type']     = 'error';
    36                     $data['info']   = '警告:用户支付成功,服务器流水记录失败';
    37                     $this->assign('data',$data);
    38                     $this->display('info');die;
    39                 }
    40 
    41 
    42                 //接口请求成功
    43                 if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') {
    44 
    45                     //交易成功
    46                     $data['type']     = 'success';
    47                     $data['info']   = '成功:交易成功,请返回';
    48                 }else {
    49 
    50                    
    59                     //交易失败
    60                     $data['type']     = 'error';
    61                     $data['info']   = '失败:支付失败,请重试';
    62                 }
    63             }else {
    64                 //接口请求失败
    65                 $data['type']     = 'error';
    66                 $data['info']   = '失败:服务器调用支付宝失败';
    67             }
    68             $this->assign('data',$data);
    69             $this->display('info');
    70         }
  • 相关阅读:
    接口的使用
    web service 实现无刷新返回一个表
    webservice 实现动态刷新
    js 实现子树选中时父目录全被选中
    相册的简单实现
    基于角色的身份验证3
    一个购物车的简单实现(多层开发)
    asp2.0 中实现 msdn 左边导航栏
    xsl 中 xsl:copy 的使用
    企业库中使用transaction(企业库中的列子)
  • 原文地址:https://www.cnblogs.com/lxdd/p/4585968.html
Copyright © 2011-2022 走看看