支付宝手机网站即时交易 自己封装的类
2015-06-18 15:20
537 查看
<?php /* 支付宝封装类 采用 rsa 生成签名模式 */ class Alipay { private $_config = array(); private $_alipay_gateway_new = 'https://mapi.alipay.com/gateway.do?'; //支付宝网关地址(新) private $_https_verify_url = 'https://mapi.alipay.com/gateway.do?service=notify_verify&'; //校验用到 private $_fix_config = array(); public function __construct() { $this->_makeFixconfig(); } //读取固定参数 private function _makeFixconfig() { $this->_fix_config = array( 'service' => 'alipay.wap.create.direct.pay.by.user', '_input_charset' => 'utf-8', 'sign_type' => 'RSA', 'seller_id' => '', 'private_key_path' => VENDOR_PATH . '/Alipay/rsa_private_key.pem',//私密key 'ali_public_key_path' => VENDOR_PATH . '/Alipay/alipay_public_key.pem',//公开key 'cacert' => VENDOR_PATH . '/Alipay/cacert.pem',//https请求用到验证 'transport' => 'http', 'payment_type' => 1,//固定参数 ); } /* config 需要参数 partner //合作身份者id,以2088开头的16位纯数字 notify_url //阿里处理后,异步处理url地址,http开头 return_url //阿里处理后,同步处理url地址 out_trade_no //订单号 subject //商品名称 total_fee //商品金额 */ //生成配置文件,并请求 public function run($config) { foreach ($config as $value) { if(empty($value)) exit('缺少必要参数'); } $this->_fix_config['seller_id'] = $config['partner']; $this->_config = array_merge($this->_fix_config,$config); //签名,请求 $this->_makeSign(); } //生成签名信息,并发送请求 private function _makeSign() { //获取签名需要的参数 $param = array( '_input_charset' => trim($this->_config['_input_charset']), 'service' => trim($this->_config['service']), 'partner' => trim($this->_config['partner']), 'seller_id' => trim($this->_config['seller_id']), 'payment_type' => trim($this->_config['payment_type']), 'notify_url' => trim($this->_config['notify_url']), 'return_url' => trim($this->_config['return_url']), 'out_trade_no' => trim($this->_config['out_trade_no']), 'subject' => trim($this->_config['subject']), 'total_fee' => trim($this->_config['total_fee']), ); //对数组进行排序 ksort($param); reset($param); //读取pem信息,生成key if(!file_exists($this->_config['private_key_path']) || !file_exists($this->_config['ali_public_key_path'])) exit('缺少pem必要参数,请检查'); if(!function_exists('openssl_pkey_get_private')) exit('不支持openssl'); $query_string = ''; $query_string = $this->_makeSignString($param); $private_key_info = file_get_contents($this->_config['private_key_path']); $private_key_res = openssl_pkey_get_private($private_key_info); $sign = ''; openssl_sign($query_string, $sign, $private_key_res); openssl_free_key($private_key_res); //base64编码 $param['sign'] = base64_encode($sign); //验证签名 // $this->_checkSign($query_string,$param['sign']); $param['sign_type'] = trim($this->_config['sign_type']); //触发表单请求,使用get模拟请求会失败 $this->_formPush($param,'确认'); } /* --不能用模拟请求 发送get请求 $url 请求url地址 */ private function _makeGetHttp($url) { $curl = curl_init($url); // curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);// 显示输出结果 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL证书认证 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证 curl_setopt($curl, CURLOPT_CAINFO,$this->_fix_config['cacert']);//证书地址 curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); 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)"); $result = curl_exec($curl); $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); $curlErrNo = curl_errno($curl); $curlErr = curl_error($curl); curl_close($curl); if ($httpCode == "0") die("Curl error number:" . $curlErrNo . " , Curl error details:" . $curlErr . "\r\n"); else if ($httpCode != "200") die("Http code:" . $httpCode . " details:" . $result . "\r\n"); return $result; } /* 采用表单提交 */ private function _formPush($para_temp,$button_name) { $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>'; $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>'; $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'>"; while (list ($key, $val) = each ($para_temp)) { $sHtml .= "<input type='hidden' name='".$key."' value='".$val."'/>"; } //submit按钮控件请不要含有name属性 $sHtml = $sHtml."<input type='submit' value='".$button_name."'></form></div></body></html>"; $sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>"; echo $sHtml; } /* 构造签名字符串 */ private function _makeSignString($arr,$type=false) { $tmp_str = ''; foreach ($arr as $key => $value) { if($key == 'sign' || $key == 'sign_type') continue; $tmp_str .= $key . '=' . $value . '&'; } return trim($tmp_str,'&'); } /* 验证rsa签名 @param $data 返回的get或者post的总数组, $sign get['sign'] 或者 post['sign'] @return bool */ public function checkSign($data,$sign) { //处理数据 $new_data = array(); foreach ($data as $key => $value) { if($key == 'sign' || $key == 'sign_type' || $key == '_URL_' || $value == '') continue; $new_data[$key] = $value; } ksort($new_data); reset($new_data); $new_data_str = ''; $new_data_str = $this->_makeSignString($new_data); $ali_public_key_info = file_get_contents($this->_fix_config['ali_public_key_path']); $ali_public_key_res = openssl_pkey_get_public($ali_public_key_info); $ali_public_key_verify = openssl_verify($new_data_str, base64_decode($sign), $ali_public_key_res); openssl_free_key($ali_public_key_res); if(!$ali_public_key_verify) return false; return true; } /* 验证url来源是否为支付宝 @param partner 合作账号 notify_id get|post返回的 */ public function checkUrlFrom($partner,$notify_id) { $url = $this->_https_verify_url . 'partner=' . $partner . '¬ify_id=' . $notify_id; return $this->_makeGetHttp($url); } }
调用案例:
通知页面不能有阻拦,比如说要登录才能进入之类的
/* 测试支付宝 */ public function test_alipay() { //引入 Vendor('Alipay.Alipay'); //生成参数 $param = array( 'partner' => C('PARTENR'),//2088开头的支付宝信息 'notify_url' => 'http://' . $_SERVER['HTTP_HOST'] . U('Leasegoods/alipay_notify_url'),//异步通知页面 'return_url' => 'http://' . $_SERVER['HTTP_HOST'] . U('Leasegoods/alipay_return_url'),//同步通知页面 'out_trade_no' => $this->_dealOrderNum(),//订单号 'subject' => 'lxd',//商品名称 'total_fee' => '0.01',//商品价格 ); $alipay_obj = new Alipay(); $alipay_obj->run($param); }
通知页面验证:
同步异步都类似,第一 校验签名;第二 校验来源;其余的就是业务之类的东西了
public function alipay_return_url() { $info = serialize($_GET); $data = array(); //判断状态 if(isset($_GET) && $_GET['is_success'] == 'T') { $order_index = $_GET['out_trade_no']; //校验签名 Vendor('Alipay.Alipay'); $alipay_obj = new Alipay(); $res = $alipay_obj->checkSign($_GET,$_GET['sign']); if(!$res){ $data['type'] = 'error'; $data['info'] = '警告:服务器校验数据失败'; $this->assign('data',$data); $this->display('info');die; } //校验来源 $res = null; $res = $alipay_obj->checkUrlFrom(C('PARTENR'),$_GET['notify_id']); if($res == 'false'){ $data['type'] = 'error'; $data['info'] = '错误:服务器校验来源错误'; $this->assign('data',$data); $this->display('info');die; } //记录流水 $alipay_log_model = M('alipay_log'); $insert_res = $alipay_log_model->add(array('order_index' => $order_index,'type' => 'return','info' => $info)); if(!$insert_res){ $data['type'] = 'error'; $data['info'] = '警告:用户支付成功,服务器流水记录失败'; $this->assign('data',$data); $this->display('info');die; } //接口请求成功 if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') { //交易成功 $data['type'] = 'success'; $data['info'] = '成功:交易成功,请返回'; }else { //交易失败 $data['type'] = 'error'; $data['info'] = '失败:支付失败,请重试'; } }else { //接口请求失败 $data['type'] = 'error'; $data['info'] = '失败:服务器调用支付宝失败'; } $this->assign('data',$data); $this->display('info'); }
相关文章推荐
- 织梦DEDECMS网站安全攻略之修改data目录名称方法步骤
- HAProxy+Keepalived实现负载均衡高可用
- 轻开商贸企业入门级电子商务 B2C网站公共版
- ZOJ 3819 Average Score(数学 牡丹江游戏网站)
- Haskell之Yesod开发–简单网站开发(四)
- 大型网站架构方案系列文章
- Openstack Nova Security Group——安全组之架构篇
- visual studio设置为使用IIS运行网站时加载项目遇到权限问题的解决方法
- 《Android移动网站开发详解》
- 经管爱好者 初创企业网站如何在3天内获得10万浏览量
- 初创企业网站如何在3天内获得10万浏览量
- 网站如何接入支付宝(转)
- 高性能服务器架构
- CDH cm节点高可用方案
- 什么是灰度发布?灰度发布方式 系统的割接 灰度部署典型的框架架构
- Haskell之Yesod开发–简单网站开发(三)
- 大型网站架构改进历程:存储的瓶颈
- 影响网站打开速度的常见因素
- “集群和负载均衡”等的通俗解释
- 案例:修改网站标题对排名有什么影响?