支付宝手机网站即时交易 自己封装的类
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 . '¬ify_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
支付宝手机网站即时交易 自己封装的类相关推荐
- 支付宝手机网页即时到账接口(3)之交易接口请求
前言 这篇文章主要讲诉系统调用支付宝手机网页即时到账交易接口跳转到支付宝收银台. 上篇文章地址:支付宝手机网页即时到账接口(2)之授权接口请求. 这是第一篇文章结尾调用交易接口的图解. 交易接口请求参 ...
- PHP接入支付宝手机网站支付、移动支付接口
payment 项目2.0版本 前面已经说完了 PHP接入支付宝 即时到帐接口 回调接口也已经完成.这篇主要讲 手机网站支付 . 移动支付 接口的调用.调用方式与即时到帐 基本一样. 关于代码部分的详 ...
- 支付--支付宝手机网站支付(WAP)
介绍: 这是放在微信供公众号内的一个项目,支付模块设计到微信公众号支付和支付宝手机网站支付,这次把支付宝手机网站支付整理下来. 文档: 支付宝手机网站支付的开发文档: https://docs.ope ...
- 4.PHP接入支付宝手机网站支付、移动支付接口
Payment项目地址github地址 前面已经说完了 PHP接入支付宝 即时到帐接口 回调接口也已经完成.这篇主要讲 手机网站支付 . 移动支付 接口的调用.调用方式与即时到帐 基本一样. 关于代码 ...
- Laravel 集成支付宝手机网站支付
前期准备: 1.下载SDK,里面还有Demo,可以参照Demo里面的内容快速接入 支付宝 手机网站支付SDK&Demo 2.把下载的zip文件解压,放到项目目录里,这里作者放在app文件夹里, ...
- 支付宝wap端支付php对接_PHP接入支付宝手机网站支付、移动支付接口
前面已经说完了 PHP接入支付宝 即时到帐接口 回调接口也已经完成.这篇主要讲 手机网站支付 . 移动支付 接口的调用.调用方式与即时到帐 基本一样. 关于代码部分的详细解释,请 参看 PHP接入支付 ...
- 支付宝手机网站支付实战踩坑
准备 需求 需求就是最简单的对接支付宝支付接口 方案心路历程 简单用http对接一下,不过想了一下觉得第三方提供的SDK总是不用,所以打算尝试一下 支付宝新版SDK,从文档到git再安装到使用,然后放 ...
- 4 支付宝手机网站支付demo讲解
目录 1 引言 2 业务流程 3 用户下单 4 商户系统处理订单信息 5 支付宝向用户展示支付信息 6 用户付款 7 同步通知与异步通知 1 引言 前面三小节我们已经学过如何使用支付宝手机网站支付的功 ...
- 【支付宝支付】Java实现支付宝手机网站支付流程
前言 微信登录网页授权与APP授权 微信JSAPI支付 微信APP支付 微信APP和JSAPI退款 支付宝手机网站支付 支付宝APP支付 支付宝退款 以上我都放到个人公众号,搜一搜:JAVA大贼船,文 ...
最新文章
- 有关Nodejs的一些插件介绍
- gdb调试多进程和多线程命令 .
- Enterprise Architecture 13 将顺序图自动转化为协作图
- [机器学习]梯度提升决策树--GBDT
- 网站导航颜色停留_做好这几点是建设营销型网站的关键
- CF1497E1 Square-free division (easy version)
- 插件原理[转自CSDN]
- Docker 基础与实战,看这一篇就够了
- 揭秘Facebook官方底层C++函数Folly
- UITransitionView and UILayoutContainerView
- 【转】C# SqlServer操作辅助类(SqlServerHelper.cs)
- linux下安装共享软件,Linux 系统下各种包的安装方法分享
- java项目三——图书馆管理系统(数据库mysql版本)
- 约瑟夫问题 pku1012(转自奋斗青春(亚伟)blog)
- ​为什么用Go编写机器学习的基础架构,而不是Python?
- 人工智能和人类智能的本质区别是什么(五)
- Thread详解一(interrupt)
- https://blog.csdn.net/wutianxu123/article/details/82597337
- 自然数学-对数性质证明
- 软件测试工程师岗位职责
热门文章
- java action提交表单数据,form表单action提交详解
- 难得一见的DIY针孔相机
- 简书留言频率限制机制
- 深入理解Unity刚体(Rigidbody)、碰撞器(Collider)、触发器(Trigger)
- C#控制网页并自动输入
- Android 获取唯一机器码的代码
- Hive和hdfs的关系与区别
- Sqoop导入hive中null是空字符串还是‘null‘的问题(关注)
- MySQL中Join算法实现原理通俗易懂
- jqGrid中时间控件input的值赋给点开后的laydate控件