├── LICENSE ├── README.md ├── composer.json └── src └── Lxu └── Alipay ├── AlipayServiceProvider.php ├── config ├── cacert.pem ├── key │ ├── rsa_private_key.pem │ └── rsa_public_key.pem └── lxu-alipay.php ├── mobile ├── HelperFunction.php └── MobileSdk.php └── pc ├── HelperFunction.php └── PcSdk.php /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 gaoxuxu123 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ##安装 4 | ``` 5 | composer require laravel-alipay/alipay dev-master 6 | 7 | 或者在composer.json中加入 8 | 9 | "require": { 10 | 11 | "laravel-alipay/alipay": "dev-master" 12 | } 13 | 14 | ``` 15 | 更新依赖 ``` composer update ``` 16 | 17 | ##使用说明 18 | 19 | 找到 `config/app.php` 文件 20 | ``` 21 | 'providers' => [ 22 | 23 | Lxu\Alipay\AlipayServiceProvider::class, 24 | ] 25 | ``` 26 | 27 | 运行 `php artisan vendor:publish` 命令 28 | 29 | 配置文件 `config/lxu-alipay.php` 已经生成,按照要求配置即可 30 | 31 | ##DEMO 32 | 33 | ###PC网页支付 34 | 35 | ``` 36 | public function getPay(Request $request) 37 | { 38 | //唯一的订单号 39 | $out_trade_no = '20160122'; 40 | //订单名称 41 | $subject = 'xxxxxxxxxxx'; 42 | //付款金额 43 | $total_fee = '0.01'; 44 | //订单描述 45 | $body = 'xxxxxxxxxxx'; 46 | $show_url = ''; 47 | $anti_phishing_key = ''; 48 | $exter_invoke_ip = $request->getClientIp(); 49 | $parameter = [ 50 | "service" => config('lxu-alipay.pcconfig.service'), 51 | "partner" => trim(config('lxu-alipay.pcconfig.partner')), 52 | "seller_id" => trim(config('lxu-alipay.pcconfig.seller_id')), 53 | "payment_type" => config('lxu-alipay.pcconfig.payment_type'), 54 | "notify_url" => config('lxu-alipay.pcconfig.notify_url'), 55 | "return_url" => config('lxu-alipay.pcconfig.return_url'), 56 | "seller_email" => config('lxu-alipay.pcconfig.seller_email'), 57 | "out_trade_no" => $out_trade_no, 58 | "subject" => $subject, 59 | "total_fee" => $total_fee, 60 | "body" => $body, 61 | "show_url" => $show_url, 62 | "anti_phishing_key" => $anti_phishing_key, 63 | "exter_invoke_ip" => $exter_invoke_ip, 64 | "_input_charset" => trim(strtolower(config('lxu-alipay.pcconfig.input_charset'))) 65 | ]; 66 | $pc = app('PcAlipay'); 67 | $html_text = $pc->buildRequestForm($parameter,"post", "确认"); 68 | echo $html_text; 69 | 70 | } 71 | /** 72 | * 支付宝服务器异步通知 73 | * @param $request 74 | * @return mixed 75 | */ 76 | public function getNotifyurl(Request $request) 77 | { 78 | $alipayNotify = app('PcAlipay'); 79 | $verify_result = $alipayNotify->verifyNotify(); 80 | if($verify_result){ 81 | //验证成功 82 | //获取支付宝的通知返回参数 83 | $parameter = [ 84 | "out_trade_no" => $request->out_trade_no, //商户订单编号; 85 | "trade_no" => $request->trade_no, //支付宝交易号; 86 | "total_fee" => $request->total_fee, //交易金额; 87 | "trade_status" => $request->trade_status, //交易状态 88 | "notify_id" => $request->notify_id, //通知校验ID。 89 | "notify_time" => $request->notify_time, //通知的发送时间。格式为yyyy-MM-dd HH:mm:ss。 90 | "buyer_email" => $request->buyer_email, //买家支付宝帐号; 91 | ]; 92 | if($request->trade_status == 'TRADE_FINISHED') { 93 | // 94 | 95 | }else if ($request->trade_status == 'TRADE_SUCCESS') { 96 | 97 | //进行订单处理,并传送从支付宝返回的参数; 98 | //检查是否已经支付 99 | //checkorderstatus($request->out_trade_no); 100 | //修改支付状态 101 | //orderHandle($parameter); 102 | } 103 | //请不要修改或删除 104 | echo "success"; 105 | }else { 106 | //验证失败 107 | echo "fail"; 108 | } 109 | } 110 | /** 111 | * 支付宝页面跳转同步通知 112 | * @param $request 113 | * @return mixed 114 | */ 115 | public function getReturnurl(Request $request) 116 | { 117 | $alipayNotify = app('PcAlipay'); 118 | $verify_result = $alipayNotify->verifyReturn(); 119 | if($verify_result){ 120 | 121 | $parameter = [ 122 | "out_trade_no" => $request->out_trade_no, //商户订单编号; 123 | "trade_no" => $request->trade_no, //支付宝交易号; 124 | "total_fee" => $request->total_fee, //交易金额; 125 | "trade_status" => $request->trade_status, //交易状态 126 | "notify_id" => $request->notify_id, //通知校验ID。 127 | "notify_time" => $request->notify_time, //通知的发送时间。格式为yyyy-MM-dd HH:mm:ss。 128 | "buyer_email" => $request->buyer_email, //买家支付宝帐号; 129 | ]; 130 | if($request->trade_status == 'TRADE_FINISHED' || $request->trade_status == 'TRADE_SUCCESS') { 131 | //支付成功 132 | //处理订单状态,记录支付记录 133 | //检查是否已经支付 134 | //checkorderstatus($request->out_trade_no); 135 | //修改支付状态 136 | //orderHandle($parameter); 137 | //跳转支付成功界面 138 | return view(''); 139 | }else{ 140 | 141 | //跳转支付失败界面 142 | return view(''); 143 | } 144 | }else{ 145 | //echo '支付失败!'; 146 | return view(''); 147 | } 148 | } 149 | 150 | ``` 151 | 152 | ###手机网页支付 153 | 154 | ``` 155 | 首先下载 Openssl工具,windows开发者下载链接: http://download.csdn.net/detail/gaoxuaiguoyi/9443275 156 | 157 | Linux开发者直接去官网下载openssl.org 158 | 159 | 解压之后按照: 160 | 161 | https://doc.open.alipay.com/doc2/detail.htm?spm=0.0.0.0.y0P2mJ&treeId=58&articleId=103242&docType=1 162 | 163 | 教程即可生成 rsa_private_key.pem和rsa_public_key.pem 2个文件覆盖项目中的key文件夹下载文件即可。 164 | 165 | ``` 166 | 167 | 168 | ##待续 169 | 170 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel-alipay/alipay", 3 | "type": "library", 4 | "description": "支付宝SDK在Laravel5封装包。", 5 | "keywords": ["Laravel 5", "Laravel", "Alipay", "Alipay SDK"], 6 | "homepage": "https://github.com/gaoxuxu123/laravel-alipay", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "gaoxuxu", 11 | "email": "394703554@qq.com" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=5.4.0", 16 | "illuminate/support": "~5.0", 17 | "illuminate/events": "~5.0", 18 | "illuminate/config": "~5.0" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Lxu\\Alipay\\": "src/Lxu/Alipay" 23 | } 24 | }, 25 | "minimum-stability": "stable" 26 | } 27 | -------------------------------------------------------------------------------- /src/Lxu/Alipay/AlipayServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 22 | 23 | __DIR__.'/config/lxu-alipay.php' => config_path('lxu-alipay.php'), 24 | ]); 25 | } 26 | 27 | /** 28 | * Register the service provider. 29 | * 30 | * @return void 31 | */ 32 | public function register() 33 | { 34 | $this->mergeConfigFrom(__DIR__ . '/config/lxu-alipay.php', 'lxu-alipay'); 35 | //PC支付对象绑定 36 | $this->app->bind('PcAlipay', function () { 37 | 38 | $pcAlipay = new PcSdk(); 39 | $pcAlipay->partner = config('lxu-alipay.pcconfig.partner'); 40 | $pcAlipay->cacert = __DIR__.'\\config\\cacert.pem'; 41 | $pcAlipay->key = config('lxu-alipay.pcconfig.key'); 42 | $pcAlipay->sign_type = config('lxu-alipay.pcconfig.sign_type'); 43 | $pcAlipay->input_charset = config('lxu-alipay.pcconfig.input_charset'); 44 | $pcAlipay->transport = config('lxu-alipay.pcconfig.transport'); 45 | return $pcAlipay; 46 | }); 47 | //手机支付对象绑定 48 | $this->app->bind('MobileAlipay', function () { 49 | 50 | $mobileAlipay = new MobileSdk(); 51 | $mobileAlipay->partner = config('lxu-alipay.mobileconfig.partner'); 52 | $mobileAlipay->cacert = __DIR__.'\\config\\cacert.pem'; 53 | $mobileAlipay->key = config('lxu-alipay.mobileconfig.key'); 54 | $mobileAlipay->sign_type = config('lxu-alipay.mobileconfig.sign_type'); 55 | $mobileAlipay->input_charset = config('lxu-alipay.mobileconfig.input_charset'); 56 | $mobileAlipay->ali_public_key_path = __DIR__.'\\config\\key\\rsa_public_key.pem'; 57 | $mobileAlipay->private_key_path = __DIR__.'\\config\\key\\rsa_private_key.pem'; 58 | $mobileAlipay->transport = config('lxu-alipay.mobileconfig.transport'); 59 | return $mobileAlipay; 60 | }); 61 | } 62 | } -------------------------------------------------------------------------------- /src/Lxu/Alipay/config/cacert.pem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gaoxuxu123/laravel-alipay/0a7d06dad3984445958cd8c3e1d7e21268ce7707/src/Lxu/Alipay/config/cacert.pem -------------------------------------------------------------------------------- /src/Lxu/Alipay/config/key/rsa_private_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXgIBAAKBgQDKV+yMv6gT+cW3gDfV4KXOl+uG4sXnrMTqghpL8JsxQhL/SjDD 3 | FiitXME5NyMvh3N0AIQ1KPAXK6x2fVwRjCaiv6hDv5NAzt8i1tZCm/ptEuMwggHX 4 | O94yS+ntEL0g9qKyProKeHFzPbbKLCQlwZDl6/dyyyHVd2uYT92zsUkrRwIDAQAB 5 | AoGAQwXUqNpjBhrZzup9lC6RPVk8/rTm8NJdd4AYzcao4SwNttoQRM52MtZiel01 6 | Hm0zZN027ZTd0g75VVY4xOczdGZVYhun2RinkhdKVHqfTVBc6p+gKOu7uSjDqcdI 7 | usQ8tTcDr9ud+umfA3Nln3w5xUxdQHsqgZB9Y7qzngiRuaECQQDml7fXNaQOvz+T 8 | 3lV5aVy+IV5tqrZvqxJxit5W7rwdIunngiRJM16Akv5bXSuKvb2d8d8HDePnqgte 9 | T25ZjD1zAkEA4KNi50H1/j3bQYBNTnxnRa7enuXEuFU4C9g2FEyBqPdAQQl+4xYA 10 | pgDIP85xlWOUKTKpykTyO9mnE1aZiq+l3QJBAJcMt16AQtFuMgV41ODNRfU+Ao8w 11 | DoWjuFcsMm0bwZoMbtA6De7teXAb2gabR5SAqh82e3QxgyMT3pKO0ahTF0UCQQCr 12 | O2AUr673kecj0s0a2rFN6LJBpRuC91K1lKYEax0a0v3jlX1nVEpCP65lFNR372Ps 13 | 03WhfVS4UnyMvSJlGObxAkEAr0cLZQYICUk9xmWrVGp9xjFnGkDQ7d4w+kWf4WkU 14 | h9S65Lu1ItQlmywDADKsIej82EBYgDpum6IPEqmTFGARqQ== 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /src/Lxu/Alipay/config/key/rsa_public_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDKV+yMv6gT+cW3gDfV4KXOl+uG 3 | 4sXnrMTqghpL8JsxQhL/SjDDFiitXME5NyMvh3N0AIQ1KPAXK6x2fVwRjCaiv6hD 4 | v5NAzt8i1tZCm/ptEuMwggHXO94yS+ntEL0g9qKyProKeHFzPbbKLCQlwZDl6/dy 5 | yyHVd2uYT92zsUkrRwIDAQAB 6 | -----END PUBLIC KEY----- 7 | -------------------------------------------------------------------------------- /src/Lxu/Alipay/config/lxu-alipay.php: -------------------------------------------------------------------------------- 1 | 13 | [ 14 | 'partner' =>'xxxxxxxxxxxxxxxxxx', //这里是你在成功申请支付宝接口后获取到的PID; 15 | 'key' =>'xxxxxxxxxxxxxxxxxx', //这里是你在成功申请支付宝接口后获取到的Key 16 | 'seller_id' =>'xxxxxxxxxxxxxxxxxx', //就是partner 17 | 'sign_type' =>strtoupper('MD5'), //不需修改 18 | 'input_charset' =>strtolower('utf-8'), //不需修改 19 | 'transport' =>'http', 20 | 'notify_url' =>'http://自己的域名/自己的路由/方法',//异步通知 21 | 'return_url' =>'http://自己的域名/自己的路由/方法',//同步通知 22 | 'refund_notify_url' => 'http://自己的域名/自己的路由/方法',//不做退款无需配置 23 | 'service' =>'create_direct_pay_by_user', //不需修改,支付service 24 | 'refundservice' =>'refund_fastpay_by_platform_pwd',//退款service 25 | 'payment_type' =>'1', //不需修改 26 | //卖家账户信息 27 | 'seller_email' =>'xxxxxxxxxxxx@xxx.com', //卖家邮箱 28 | 29 | ], 30 | //手机配置 31 | 'mobileconfig'=> 32 | [ 33 | 'partner' =>'xxxxxxxxxxxxxxxxxxxxxx', 34 | 'seller_id' =>'xxxxxxxxxxxxxxxxxxxxxx', 35 | 'key' =>'xxxxxxxxxxxxxxxxxxxxxx', 36 | 'sign_type' =>strtoupper('RSA'), //不需修改 37 | 'input_charset' =>strtolower('utf-8'), //不需修改 38 | 'notify_url' =>'http://自己的域名/自己的路由/方法', //异步通知 39 | 'return_url' =>'http://自己的域名/自己的路由/方法', //同步通知 40 | 'refund_notify_url' => 'http://自己的域名/自己的路由/方法',//不做退款无需配置 41 | 'transport' =>'http', 42 | 'service' =>'alipay.wap.create.direct.pay.by.user',//不需修改 43 | 'refundservice' =>'refund_fastpay_by_platform_pwd',//退款service 44 | 'payment_type' =>'1', 45 | 'seller_email' =>'xxxxxxxxxxxx@xxx.com', 46 | ] 47 | 48 | ]; -------------------------------------------------------------------------------- /src/Lxu/Alipay/mobile/HelperFunction.php: -------------------------------------------------------------------------------- 1 | sign_type))) { 47 | case "MD5" : 48 | $mysign = HelperFunction::md5Sign($prestr, $this->key); 49 | break; 50 | case "RSA" : 51 | $mysign = HelperFunction::rsaSign($prestr, $this->private_key_path); 52 | break; 53 | default : 54 | $mysign = ""; 55 | } 56 | 57 | return $mysign; 58 | } 59 | 60 | /** 61 | * 生成要请求给支付宝的参数数组 62 | * @param $para_temp 请求前的参数数组 63 | * @return 要请求的参数数组 64 | */ 65 | public function buildRequestPara($para_temp) { 66 | //除去待签名参数数组中的空值和签名参数 67 | $para_filter = HelperFunction::paraFilter($para_temp); 68 | 69 | //对待签名参数数组排序 70 | $para_sort = HelperFunction::argSort($para_filter); 71 | 72 | //生成签名结果 73 | $mysign = $this->buildRequestMysign($para_sort); 74 | 75 | //签名结果与签名方式加入请求提交参数组中 76 | $para_sort['sign'] = $mysign; 77 | $para_sort['sign_type'] = strtoupper(trim($this->sign_type)); 78 | 79 | return $para_sort; 80 | } 81 | 82 | /** 83 | * 生成要请求给支付宝的参数数组 84 | * @param $para_temp 请求前的参数数组 85 | * @return 要请求的参数数组字符串 86 | */ 87 | public function buildRequestParaToString($para_temp) { 88 | //待请求参数数组 89 | $para = $this->buildRequestPara($para_temp); 90 | 91 | //把参数组中所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码 92 | $request_data = HelperFunction::createLinkstringUrlencode($para); 93 | 94 | return $request_data; 95 | } 96 | 97 | /** 98 | * 建立请求,以表单HTML形式构造(默认) 99 | * @param $para_temp 请求参数数组 100 | * @param $method 提交方式。两个值可选:post、get 101 | * @param $button_name 确认按钮显示文字 102 | * @return 提交表单HTML文本 103 | */ 104 | public function buildRequestForm($para_temp, $method, $button_name) { 105 | //待请求参数数组 106 | $para = $this->buildRequestPara($para_temp); 107 | 108 | $sHtml = "
"; 116 | $sHtml = $sHtml.""; 117 | 118 | return $sHtml; 119 | } 120 | 121 | /** 122 | * 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果 123 | * @param $para_temp 请求参数数组 124 | * @return 支付宝处理结果 125 | */ 126 | public function buildRequestHttp($para_temp) { 127 | $sResult = ''; 128 | 129 | //待请求参数数组字符串 130 | $request_data = $this->buildRequestPara($para_temp); 131 | 132 | //远程获取数据 133 | $sResult = HelperFunction::getHttpResponsePOST($this->alipay_gateway_new, $this->cacert,$request_data,trim(strtolower($this->input_charset))); 134 | 135 | return $sResult; 136 | } 137 | 138 | /** 139 | * 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果,带文件上传功能 140 | * @param $para_temp 请求参数数组 141 | * @param $file_para_name 文件类型的参数名 142 | * @param $file_name 文件完整绝对路径 143 | * @return 支付宝返回处理结果 144 | */ 145 | public function buildRequestHttpInFile($para_temp, $file_para_name, $file_name) { 146 | 147 | //待请求参数数组 148 | $para = $this->buildRequestPara($para_temp); 149 | $para[$file_para_name] = "@".$file_name; 150 | 151 | //远程获取数据 152 | $sResult = HelperFunction::getHttpResponsePOST($this->alipay_gateway_new, $this->cacert,$para,trim(strtolower($this->input_charset))); 153 | 154 | return $sResult; 155 | } 156 | 157 | /** 158 | * 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数 159 | * 注意:该功能PHP5环境及以上支持,因此必须服务器、本地电脑中装有支持DOMDocument、SSL的PHP配置环境。建议本地调试时使用PHP开发软件 160 | * return 时间戳字符串 161 | */ 162 | public function query_timestamp() { 163 | $url = $this->alipay_gateway_new."service=query_timestamp&partner=".trim(strtolower($this->partner))."&_input_charset=".trim(strtolower($this->input_charset)); 164 | $encrypt_key = ""; 165 | 166 | $doc = new DOMDocument(); 167 | $doc->load($url); 168 | $itemEncrypt_key = $doc->getElementsByTagName( "encrypt_key" ); 169 | $encrypt_key = $itemEncrypt_key->item(0)->nodeValue; 170 | 171 | return $encrypt_key; 172 | } 173 | /** 174 | * 针对notify_url验证消息是否是支付宝发出的合法消息 175 | * @return 验证结果 176 | */ 177 | public function verifyNotify(){ 178 | if(empty($_POST)) {//判断POST来的数组是否为空 179 | return false; 180 | } 181 | else { 182 | //生成签名结果 183 | $isSign = $this->getSignVeryfy($_POST, $_POST["sign"]); 184 | //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) 185 | $responseTxt = 'true'; 186 | if (! empty($_POST["notify_id"])) {$responseTxt = $this->getResponse($_POST["notify_id"]);} 187 | 188 | //写日志记录 189 | //if ($isSign) { 190 | // $isSignStr = 'true'; 191 | //} 192 | //else { 193 | // $isSignStr = 'false'; 194 | //} 195 | //$log_text = "responseTxt=".$responseTxt."\n notify_url_log:isSign=".$isSignStr.","; 196 | //$log_text = $log_text.createLinkString($_POST); 197 | //logResult($log_text); 198 | 199 | //验证 200 | //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 201 | //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 202 | if (preg_match("/true$/i",$responseTxt) && $isSign) { 203 | return true; 204 | } else { 205 | return false; 206 | } 207 | } 208 | } 209 | 210 | /** 211 | * 针对return_url验证消息是否是支付宝发出的合法消息 212 | * @return 验证结果 213 | */ 214 | public function verifyReturn(){ 215 | if(empty($_GET)) {//判断POST来的数组是否为空 216 | return false; 217 | } 218 | else { 219 | //生成签名结果 220 | $isSign = $this->getSignVeryfy($_GET, $_GET["sign"]); 221 | //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) 222 | $responseTxt = 'true'; 223 | if (! empty($_GET["notify_id"])) {$responseTxt = $this->getResponse($_GET["notify_id"]);} 224 | 225 | //写日志记录 226 | /* if ($isSign) { 227 | $isSignStr = 'true'; 228 | } 229 | else { 230 | $isSignStr = 'false'; 231 | } 232 | $log_text = "responseTxt=".$responseTxt."\n return_url_log:isSign=".$isSignStr.","; 233 | $log_text = $log_text.createLinkString($_GET); 234 | logResult($log_text);*/ 235 | 236 | //验证 237 | //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 238 | //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 239 | if (preg_match("/true$/i",$responseTxt) && $isSign) { 240 | return true; 241 | } else { 242 | return false; 243 | } 244 | } 245 | } 246 | 247 | /** 248 | * 获取返回时的签名验证结果 249 | * @param $para_temp 通知返回来的参数数组 250 | * @param $sign 返回的签名结果 251 | * @return 签名验证结果 252 | */ 253 | public function getSignVeryfy($para_temp, $sign) { 254 | //除去待签名参数数组中的空值和签名参数 255 | $para_filter = HelperFunction::paraFilter($para_temp); 256 | 257 | //对待签名参数数组排序 258 | $para_sort = HelperFunction::argSort($para_filter); 259 | 260 | //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 261 | $prestr = HelperFunction::createLinkstring($para_sort); 262 | 263 | $isSgin = false; 264 | switch (strtoupper(trim($this->sign_type))) { 265 | case "MD5" : 266 | $isSgin = HelperFunction::md5Verify($prestr, $sign, $this->key); 267 | break; 268 | case "RSA" : 269 | $isSgin = HelperFunction::rsaVerify($prestr, trim($this->ali_public_key_path), $sign); 270 | break; 271 | default : 272 | $isSgin = false; 273 | } 274 | 275 | return $isSgin; 276 | } 277 | 278 | /** 279 | * 获取远程服务器ATN结果,验证返回URL 280 | * @param $notify_id 通知校验ID 281 | * @return 服务器ATN结果 282 | * 验证结果集: 283 | * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空 284 | * true 返回正确信息 285 | * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟 286 | */ 287 | public function getResponse($notify_id) { 288 | $transport = strtolower(trim($this->transport)); 289 | $partner = trim($this->partner); 290 | $veryfy_url = ''; 291 | if($transport == 'https') { 292 | $veryfy_url = $this->https_verify_url; 293 | } 294 | else { 295 | $veryfy_url = $this->http_verify_url; 296 | } 297 | $veryfy_url = $veryfy_url."partner=" . $partner . "¬ify_id=" . $notify_id; 298 | $responseTxt = HelperFunction::getHttpResponseGET($veryfy_url, $this->cacert); 299 | 300 | return $responseTxt; 301 | } 302 | 303 | 304 | } 305 | -------------------------------------------------------------------------------- /src/Lxu/Alipay/pc/HelperFunction.php: -------------------------------------------------------------------------------- 1 | cacert);exit; 39 | } 40 | /** 41 | * 生成签名结果 42 | * @param $para_sort 已排序要签名的数组 43 | * return 签名结果字符串 44 | */ 45 | public function buildRequestMysign($para_sort) { 46 | //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 47 | $prestr = HelperFunction::createLinkstring($para_sort); 48 | 49 | $mysign = ""; 50 | switch (strtoupper(trim($this->sign_type))) { 51 | case "MD5" : 52 | $mysign = HelperFunction::md5Sign($prestr, $this->key); 53 | break; 54 | default : 55 | $mysign = ""; 56 | } 57 | 58 | return $mysign; 59 | } 60 | 61 | /** 62 | * 生成要请求给支付宝的参数数组 63 | * @param $para_temp 请求前的参数数组 64 | * @return 要请求的参数数组 65 | */ 66 | public function buildRequestPara($para_temp) { 67 | //除去待签名参数数组中的空值和签名参数 68 | $para_filter = HelperFunction::paraFilter($para_temp); 69 | 70 | //对待签名参数数组排序 71 | $para_sort = HelperFunction::argSort($para_filter); 72 | 73 | //生成签名结果 74 | $mysign = $this->buildRequestMysign($para_sort); 75 | 76 | //签名结果与签名方式加入请求提交参数组中 77 | $para_sort['sign'] = $mysign; 78 | $para_sort['sign_type'] = strtoupper(trim($this->sign_type)); 79 | 80 | return $para_sort; 81 | } 82 | 83 | /** 84 | * 生成要请求给支付宝的参数数组 85 | * @param $para_temp 请求前的参数数组 86 | * @return 要请求的参数数组字符串 87 | */ 88 | public function buildRequestParaToString($para_temp) { 89 | //待请求参数数组 90 | $para = $this->buildRequestPara($para_temp); 91 | 92 | //把参数组中所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码 93 | $request_data = HelperFunction::createLinkstringUrlencode($para); 94 | 95 | return $request_data; 96 | } 97 | 98 | /** 99 | * 建立请求,以表单HTML形式构造(默认) 100 | * @param $para_temp 请求参数数组 101 | * @param $method 提交方式。两个值可选:post、get 102 | * @param $button_name 确认按钮显示文字 103 | * @return $sHtml 提交的html文本 104 | */ 105 | public function buildRequestForm($para_temp, $method, $button_name) { 106 | //待请求参数数组 107 | $para = $this->buildRequestPara($para_temp); 108 | 109 | $sHtml = ""; 117 | $sHtml = $sHtml.""; 118 | 119 | return $sHtml; 120 | } 121 | 122 | /** 123 | * 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果 124 | * @param $para_temp 请求参数数组 125 | * @return 支付宝处理结果 126 | */ 127 | public function buildRequestHttp($para_temp) { 128 | $sResult = ''; 129 | 130 | //待请求参数数组字符串 131 | $request_data = $this->buildRequestPara($para_temp); 132 | 133 | //远程获取数据 134 | $sResult = HelperFunction::getHttpResponsePOST($this->alipay_gateway_new, $this->cacert,$request_data,trim(strtolower($this->input_charset))); 135 | 136 | return $sResult; 137 | } 138 | 139 | /** 140 | * 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果,带文件上传功能 141 | * @param $para_temp 请求参数数组 142 | * @param $file_para_name 文件类型的参数名 143 | * @param $file_name 文件完整绝对路径 144 | * @return 支付宝返回处理结果 145 | */ 146 | public function buildRequestHttpInFile($para_temp, $file_para_name, $file_name) { 147 | 148 | //待请求参数数组 149 | $para = $this->buildRequestPara($para_temp); 150 | $para[$file_para_name] = "@".$file_name; 151 | 152 | //远程获取数据 153 | $sResult = HelperFunction::getHttpResponsePOST($this->alipay_gateway_new, $this->cacert,$para,trim(strtolower($this->input_charset))); 154 | 155 | return $sResult; 156 | } 157 | 158 | /** 159 | * 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数 160 | * 注意:该功能PHP5环境及以上支持,因此必须服务器、本地电脑中装有支持DOMDocument、SSL的PHP配置环境。建议本地调试时使用PHP开发软件 161 | * return 时间戳字符串 162 | */ 163 | public function query_timestamp() { 164 | $url = $this->alipay_gateway_new."service=query_timestamp&partner=".trim(strtolower($this->partner))."&_input_charset=".trim(strtolower($this->input_charset)); 165 | $encrypt_key = ""; 166 | 167 | $doc = new DOMDocument(); 168 | $doc->load($url); 169 | $itemEncrypt_key = $doc->getElementsByTagName( "encrypt_key" ); 170 | $encrypt_key = $itemEncrypt_key->item(0)->nodeValue; 171 | 172 | return $encrypt_key; 173 | } 174 | /** 175 | * 针对notify_url验证消息是否是支付宝发出的合法消息 176 | * @return 验证结果 177 | */ 178 | public function verifyNotify(){ 179 | if(empty($_POST)) {//判断POST来的数组是否为空 180 | return false; 181 | } 182 | else { 183 | //生成签名结果 184 | $isSign = $this->getSignVeryfy($_POST, $_POST["sign"]); 185 | //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) 186 | $responseTxt = 'true'; 187 | if (! empty($_POST["notify_id"])) {$responseTxt = $this->getResponse($_POST["notify_id"]);} 188 | 189 | //写日志记录 190 | //if ($isSign) { 191 | // $isSignStr = 'true'; 192 | //} 193 | //else { 194 | // $isSignStr = 'false'; 195 | //} 196 | //$log_text = "responseTxt=".$responseTxt."\n notify_url_log:isSign=".$isSignStr.","; 197 | //$log_text = $log_text.createLinkString($_POST); 198 | //logResult($log_text); 199 | 200 | //验证 201 | //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 202 | //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 203 | if (preg_match("/true$/i",$responseTxt) && $isSign) { 204 | return true; 205 | } else { 206 | return false; 207 | } 208 | } 209 | } 210 | 211 | /** 212 | * 针对return_url验证消息是否是支付宝发出的合法消息 213 | * @return 验证结果 214 | */ 215 | public function verifyReturn(){ 216 | if(empty($_GET)) {//判断POST来的数组是否为空 217 | return false; 218 | } 219 | else { 220 | //生成签名结果 221 | $isSign = $this->getSignVeryfy($_GET, $_GET["sign"]); 222 | //获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息) 223 | $responseTxt = 'true'; 224 | if (! empty($_GET["notify_id"])) {$responseTxt = $this->getResponse($_GET["notify_id"]);} 225 | 226 | //写日志记录 227 | //if ($isSign) { 228 | // $isSignStr = 'true'; 229 | //} 230 | //else { 231 | // $isSignStr = 'false'; 232 | //} 233 | //$log_text = "responseTxt=".$responseTxt."\n return_url_log:isSign=".$isSignStr.","; 234 | //$log_text = $log_text.createLinkString($_GET); 235 | //logResult($log_text); 236 | 237 | //验证 238 | //$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关 239 | //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 240 | if (preg_match("/true$/i",$responseTxt) && $isSign) { 241 | return true; 242 | } else { 243 | return false; 244 | } 245 | } 246 | } 247 | 248 | /** 249 | * 获取返回时的签名验证结果 250 | * @param $para_temp 通知返回来的参数数组 251 | * @param $sign 返回的签名结果 252 | * @return 签名验证结果 253 | */ 254 | public function getSignVeryfy($para_temp, $sign) { 255 | //除去待签名参数数组中的空值和签名参数 256 | $para_filter = HelperFunction::paraFilter($para_temp); 257 | 258 | //对待签名参数数组排序 259 | $para_sort = HelperFunction::argSort($para_filter); 260 | 261 | //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 262 | $prestr = HelperFunction::createLinkstring($para_sort); 263 | 264 | $isSgin = false; 265 | switch (strtoupper(trim($this->sign_type))) { 266 | case "MD5" : 267 | $isSgin = HelperFunction::md5Verify($prestr, $sign, $this->key); 268 | break; 269 | default : 270 | $isSgin = false; 271 | } 272 | 273 | return $isSgin; 274 | } 275 | 276 | /** 277 | * 获取远程服务器ATN结果,验证返回URL 278 | * @param $notify_id 通知校验ID 279 | * @return 服务器ATN结果 280 | * 验证结果集: 281 | * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空 282 | * true 返回正确信息 283 | * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟 284 | */ 285 | public function getResponse($notify_id) { 286 | $transport = strtolower(trim($this->transport)); 287 | $partner = trim($this->partner); 288 | $veryfy_url = ''; 289 | if($transport == 'https') { 290 | $veryfy_url = $this->https_verify_url; 291 | } 292 | else { 293 | $veryfy_url = $this->http_verify_url; 294 | } 295 | $veryfy_url = $veryfy_url."partner=" . $partner . "¬ify_id=" . $notify_id; 296 | $responseTxt = HelperFunction::getHttpResponseGET($veryfy_url, $this->cacert); 297 | 298 | return $responseTxt; 299 | } 300 | 301 | } --------------------------------------------------------------------------------