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 . "\r\n");
139             else if ($httpCode != "200")
140                    die("Http code:" . $httpCode .  " details:" . $result . "\r\n");
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         }

转载于:https://www.cnblogs.com/lxdd/p/4585968.html

支付宝手机网站即时交易 自己封装的类相关推荐

  1. 支付宝手机网页即时到账接口(3)之交易接口请求

    前言 这篇文章主要讲诉系统调用支付宝手机网页即时到账交易接口跳转到支付宝收银台. 上篇文章地址:支付宝手机网页即时到账接口(2)之授权接口请求. 这是第一篇文章结尾调用交易接口的图解. 交易接口请求参 ...

  2. PHP接入支付宝手机网站支付、移动支付接口

    payment 项目2.0版本 前面已经说完了 PHP接入支付宝 即时到帐接口 回调接口也已经完成.这篇主要讲 手机网站支付 . 移动支付 接口的调用.调用方式与即时到帐 基本一样. 关于代码部分的详 ...

  3. 支付--支付宝手机网站支付(WAP)

    介绍: 这是放在微信供公众号内的一个项目,支付模块设计到微信公众号支付和支付宝手机网站支付,这次把支付宝手机网站支付整理下来. 文档: 支付宝手机网站支付的开发文档: https://docs.ope ...

  4. 4.PHP接入支付宝手机网站支付、移动支付接口

    Payment项目地址github地址 前面已经说完了 PHP接入支付宝 即时到帐接口 回调接口也已经完成.这篇主要讲 手机网站支付 . 移动支付 接口的调用.调用方式与即时到帐 基本一样. 关于代码 ...

  5. Laravel 集成支付宝手机网站支付

    前期准备: 1.下载SDK,里面还有Demo,可以参照Demo里面的内容快速接入 支付宝 手机网站支付SDK&Demo 2.把下载的zip文件解压,放到项目目录里,这里作者放在app文件夹里, ...

  6. 支付宝wap端支付php对接_PHP接入支付宝手机网站支付、移动支付接口

    前面已经说完了 PHP接入支付宝 即时到帐接口 回调接口也已经完成.这篇主要讲 手机网站支付 . 移动支付 接口的调用.调用方式与即时到帐 基本一样. 关于代码部分的详细解释,请 参看 PHP接入支付 ...

  7. 支付宝手机网站支付实战踩坑

    准备 需求 需求就是最简单的对接支付宝支付接口 方案心路历程 简单用http对接一下,不过想了一下觉得第三方提供的SDK总是不用,所以打算尝试一下 支付宝新版SDK,从文档到git再安装到使用,然后放 ...

  8. 4 支付宝手机网站支付demo讲解

    目录 1 引言 2 业务流程 3 用户下单 4 商户系统处理订单信息 5 支付宝向用户展示支付信息 6 用户付款 7 同步通知与异步通知 1 引言 前面三小节我们已经学过如何使用支付宝手机网站支付的功 ...

  9. 【支付宝支付】Java实现支付宝手机网站支付流程

    前言 微信登录网页授权与APP授权 微信JSAPI支付 微信APP支付 微信APP和JSAPI退款 支付宝手机网站支付 支付宝APP支付 支付宝退款 以上我都放到个人公众号,搜一搜:JAVA大贼船,文 ...

最新文章

  1. 有关Nodejs的一些插件介绍
  2. gdb调试多进程和多线程命令 .
  3. Enterprise Architecture 13 将顺序图自动转化为协作图
  4. [机器学习]梯度提升决策树--GBDT
  5. 网站导航颜色停留_做好这几点是建设营销型网站的关键
  6. CF1497E1 Square-free division (easy version)
  7. 插件原理[转自CSDN]
  8. Docker 基础与实战,看这一篇就够了
  9. 揭秘Facebook官方底层C++函数Folly
  10. UITransitionView and UILayoutContainerView
  11. 【转】C# SqlServer操作辅助类(SqlServerHelper.cs)
  12. linux下安装共享软件,Linux 系统下各种包的安装方法分享
  13. java项目三——图书馆管理系统(数据库mysql版本)
  14. 约瑟夫问题 pku1012(转自奋斗青春(亚伟)blog)
  15. ​为什么用Go编写机器学习的基础架构,而不是Python?
  16. 人工智能和人类智能的本质区别是什么(五)
  17. Thread详解一(interrupt)
  18. https://blog.csdn.net/wutianxu123/article/details/82597337
  19. 自然数学-对数性质证明
  20. 软件测试工程师岗位职责

热门文章

  1. java action提交表单数据,form表单action提交详解
  2. 难得一见的DIY针孔相机
  3. 简书留言频率限制机制
  4. 深入理解Unity刚体(Rigidbody)、碰撞器(Collider)、触发器(Trigger)
  5. C#控制网页并自动输入
  6. Android 获取唯一机器码的代码
  7. Hive和hdfs的关系与区别
  8. Sqoop导入hive中null是空字符串还是‘null‘的问题(关注)
  9. MySQL中Join算法实现原理通俗易懂
  10. jqGrid中时间控件input的值赋给点开后的laydate控件