-──────
代码文件结构
───────
create_direct_pay_by_user-php-UTF-8
│
├lib┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈类文件夹
│ │
│ ├alipay_core.function.php ┈┈┈┈┈┈支付宝接口公用函数文件
│ │
│ ├alipay_notify.class.php┈┈┈┈┈┈┈支付宝通知处理类文件
│ │
│ ├alipay_submit.class.php┈┈┈┈┈┈┈支付宝各接口请求提交类文件
│ │
│ └alipay_md5.function.php┈┈┈┈┈┈┈支付宝接口MD5函数文件
│
├log.txt┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈日志文件
│
├alipay.config.php┈┈┈┈┈┈┈┈┈┈┈┈基础配置类文件
│
├alipayapi.php┈┈┈┈┈┈┈┈┈┈┈┈┈┈支付宝接口入口文件
│
├notify_url.php ┈┈┈┈┈┈┈┈┈┈┈┈┈服务器异步通知页面文件
│
├return_url.php ┈┈┈┈┈┈┈┈┈┈┈┈┈页面跳转同步通知文件
│
├cacert.pem ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈用于CURL中校验SSL的CA证书文件
│
└readme.txt ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈使用说明文本php
※注意※
一、必须开启curl服务
(1)使用Crul须要修改服务器中php.ini文件的设置,找到php_curl.dll去掉前面的";"便可
(2)文件夹中cacert.pem文件请务必放置到商户网站平台中(如:服务器上),而且保证其路径有效,提供的代码demo中的默认路径是当前文件夹下——getcwd().'\\cacert.pem'
二、须要配置的文件是:
alipay.config.php
alipayapi.phphtml
1:from表单数据提交 node
<!-- 支付宝支付页面 --> <form name=alipayment action="<?php echo Yii::app()->request->baseUrl ?>/index.php/Payment/alipayapi" method=post target="_blank"> <div style="display: none;"><input size="30" name="WIDseller_email" value="XXXXX.com" /> <input size="30" name="WIDout_trade_no" value="<?php echo @$OrderInfo['PayNumber']?>" /> <input size="30" name="WIDsubject" value="<?php echo @XUtils::cutstr($OrderInfo['OrderName'],30)?>" /> <input size="30" name="WIDtotal_fee" value="<?php echo @$OrderInfo['TotalMoney']?>" /> <input size="30" name="WIDbody" /> <input size="30" name="WIDshow_url" /></div> <li> <div class="pay_boxin pay_curr"> <span class="left"><img src="<?php echo Yii::app()->request->baseUrl ?>/assets/default/images/alipay.png" height="30px"></span> <span class="pay_money right"> <p>支付<strong><?php echo @sprintf('%0.2f',$OrderInfo['TotalMoney'])?></strong>元</p> </span> <span class="pay_liji pay_disno"><img src="<?php echo Yii::app()->request->baseUrl ?>/assets/default/images/pay_liji.png"></span> </div> <input type="submit" style="width:220px; height:50px; border:0px; margin:30px 0 0 500px; background: url(<?php echo Yii::app()->request->baseUrl ?>/assets/default/images/pay_quite.png) center no-repeat; cursor:pointer;" value="" > </li> </form>
2:控制器页面跳转数据库
3:alipayapi.php 接口文件 构造请求参api
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>支付宝即时到帐交易接口</title> </head> <?php /* * * 功能:即时到帐交易接口接入页 * 版本:3.3 * 修改日期:2012-07-23 * 说明: * 如下代码只是为了方便商户测试而提供的样例代码,商户能够根据本身网站的须要,按照技术文档编写,并不是必定要使用该代码。 * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 *************************注意************************* * 若是您在接口集成过程当中遇到问题,能够按照下面的途径来解决 * 一、商户服务中心(https://b.alipay.com/support/helperApply.htm?action=consultationApply),提交申请集成协助,咱们会有专业的技术工程师主动联系您协助解决 * 二、商户帮助中心(http://help.alipay.com/support/232511-16307/0-16307.htm?sh=Y&info_type=9) * 三、支付宝论坛(http://club.alipay.com/read-htm-tid-8681712.html) * 若是不想使用扩展功能请把扩展功能参数赋空值。 */ require_once("alipay.config.php"); require_once("lib/alipay_submit.class.php"); /**************************请求参数**************************/ //支付类型 $payment_type = "1"; //必填,不能修改 //服务器异步通知页面路径 $notify_url = "http://www.XXX.com".$this->createUrl('Payment/Notify'); //需http://格式的完整路径,不能加?id=123这类自定义参数 //页面跳转同步通知页面路径 $return_url = "http://www.XXX.com".$this->createUrl('Payment/Return'); //需http://格式的完整路径,不能加?id=123这类自定义参数,不能写成http://localhost/ //卖家支付宝账户 $seller_email = 'XXXX@XXXX.com';//$_POST['WIDseller_email']; //必填 //商户订单号 $out_trade_no = $_POST['WIDout_trade_no']; //商户网站订单系统中惟一订单号,必填 //订单名称 $subject = $_POST['WIDsubject']; //必填 //付款金额 $total_fee = $_POST['WIDtotal_fee']; //必填 //订单描述 $body = $_POST['WIDbody']; //商品展现地址 $show_url = $_POST['WIDshow_url']; //需以http://开头的完整路径,例如:http://www.商户网址.com/myorder.html //防钓鱼时间戳 $anti_phishing_key = ""; //若要使用请调用类文件submit中的query_timestamp函数 //客户端的IP地址 $exter_invoke_ip = ""; //非局域网的外网IP地址,如:221.0.0.1 /************************************************************/ //构造要请求的参数数组,无需改动 $parameter = array( "service" => "create_direct_pay_by_user", "partner" => trim($alipay_config['partner']), "payment_type" => $payment_type, "notify_url" => $notify_url, "return_url" => $return_url, "seller_email" => $seller_email, "out_trade_no" => $out_trade_no, "subject" => $subject, "total_fee" => $total_fee, "body" => '',//$body, "show_url" => $show_url, "anti_phishing_key" => $anti_phishing_key, "exter_invoke_ip" => $exter_invoke_ip, "_input_charset" => trim(strtolower($alipay_config['input_charset'])) ); //创建请求 $alipaySubmit = new AlipaySubmit($alipay_config); $html_text = $alipaySubmit->buildRequestForm($parameter,"get", "确认"); echo $html_text; ?> </body> </html>
4:notify_url.php 服务器异步通知页面文件数组
<?php /* * * 功能:支付宝服务器异步通知页面 * 版本:3.3 * 日期:2012-07-23 * 说明: * 如下代码只是为了方便商户测试而提供的样例代码,商户能够根据本身网站的须要,按照技术文档编写,并不是必定要使用该代码。 * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 *************************页面功能说明************************* * 建立该页面文件时,请留心该页面文件中无任何HTML代码及空格。 * 该页面不能在本机电脑测试,请到服务器上作测试。请确保外部能够访问该页面。 * 该页面调试工具请使用写文本函数logResult,该函数已被默认关闭,见alipay_notify_class.php中的函数verifyNotify * 若是没有收到该页面返回的 success 信息,支付宝会在24小时内按必定的时间策略重发通知 */ require_once("alipay.config.php"); require_once("lib/alipay_notify.class.php"); //计算得出通知验证结果 $alipayNotify = new AlipayNotify($alipay_config); $verify_result = $alipayNotify->verifyNotify(); if($verify_result) {//验证成功 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //请在这里加上商户的业务逻辑程序代 //——请根据您的业务逻辑来编写程序(如下代码仅做参考)—— //获取支付宝的通知返回参数,可参考技术文档中服务器异步通知参数列表 //商户订单号 $out_trade_no = $_POST['out_trade_no']; //支付宝交易号 $trade_no = $_POST['trade_no']; //交易状态 $trade_status = $_POST['trade_status']; if($_POST['trade_status'] == 'TRADE_FINISHED') { //判断该笔订单是否在商户网站中已经作过处理 //若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //若是有作过处理,不执行商户的业务程序 //注意: //该种交易状态只在两种状况下出现 //一、开通了普通即时到帐,买家付款成功后。 //二、开通了高级即时到帐,从该笔交易成功时间算起,过了签约时的可退款时限(如:三个月之内可退款、一年之内可退款等)后。 //调试用,写文本函数记录程序运行状况是否正常 //logResult("这里写入想要调试的代码变量值,或其余运行的结果记录"); } else if ($_POST['trade_status'] == 'TRADE_SUCCESS') { //判断该笔订单是否在商户网站中已经作过处理 //若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //若是有作过处理,不执行商户的业务程序 //注意: //该种交易状态只在一种状况下出现——开通了高级即时到帐,买家付款成功后。 //调试用,写文本函数记录程序运行状况是否正常 //logResult("这里写入想要调试的代码变量值,或其余运行的结果记录"); } //——请根据您的业务逻辑来编写程序(以上代码仅做参考)—— echo "success"; //请不要修改或删除 $this->actionSetPayN($out_trade_no,1); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } else { //验证失败 echo "fail"; //调试用,写文本函数记录程序运行状况是否正常 //logResult("这里写入想要调试的代码变量值,或其余运行的结果记录"); } ?>
5:return_url.php 支付宝跳转会商户通知信息安全
<?php /* * * 功能:支付宝页面跳转同步通知页面 * 版本:3.3 * 日期:2012-07-23 * 说明: * 如下代码只是为了方便商户测试而提供的样例代码,商户能够根据本身网站的须要,按照技术文档编写,并不是必定要使用该代码。 * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 *************************页面功能说明************************* * 该页面可在本机电脑测试 * 可放入HTML等美化页面的代码、商户业务逻辑程序代码 * 该页面能够使用PHP开发工具调试,也能够使用写文本函数logResult,该函数已被默认关闭,见alipay_notify_class.php中的函数verifyReturn */ require_once("alipay.config.php"); require_once("lib/alipay_notify.class.php"); ?> <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <?php //计算得出通知验证结果 $alipayNotify = new AlipayNotify($alipay_config); $verify_result = $alipayNotify->verifyReturn(); if($verify_result) {//验证成功 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //请在这里加上商户的业务逻辑程序代码 //——请根据您的业务逻辑来编写程序(如下代码仅做参考)—— //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表 //商户订单号 $out_trade_no = $_GET['out_trade_no']; //支付宝交易号 $trade_no = $_GET['trade_no']; //交易状态 $trade_status = $_GET['trade_status']; if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') { //判断该笔订单是否在商户网站中已经作过处理 //若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 //若是有作过处理,不执行商户的业务程序 } else { echo "trade_status=".$_GET['trade_status']; } $this->actionSetPayN($out_trade_no,1); $this->redirect(array('/UserCenter')); //——请根据您的业务逻辑来编写程序(以上代码仅做参考)—— ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// } else { //验证失败 //如要调试,请看alipay_notify.php页面的verifyReturn函数 echo "验证失败"; } ?> <title>支付宝即时到帐交易接口</title> </head> <body> </body> </html>
6:config基础配置文件服务器
<?PHP //↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //合做身份者id,以2088开头的16位纯数字 $alipay_config['partner'] = ''; //安全检验码,以数字和字母组成的32位字符 $alipay_config['key'] = ''; //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ //签名方式 不需修改 $alipay_config['sign_type'] = strtoupper('MD5'); //字符编码格式 目前支持 gbk 或 utf-8 $alipay_config['input_charset']= strtolower('utf-8'); //ca证书路径地址,用于curl中ssl校验 //请保证cacert.pem文件在当前文件夹目录中 $alipay_config['cacert'] = getcwd().'\\cacert.pem'; //访问模式,根据本身的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http $alipay_config['transport'] = 'http'; ?>
7:─────────
lib 类文件函数结构
─────────
alipay_core.function.php
function createLinkstring($para)
功能:把数组全部元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
输入:Array $para 须要拼接的数组
输出:String 拼接完成之后的字符串
function createLinkstringUrlencode($para)
功能:把数组全部元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对参数值urlencode
输入:Array $para 须要拼接的数组
输出:String 拼接完成之后的字符串
function paraFilter($para)
功能:除去数组中的空值和签名参数
输入:Array $para 签名参数组
输出:Array 去掉空值与签名参数后的新签名参数组
function argSort($para)
功能:对数组排序
输入:Array $para 排序前的数组
输出:Array 排序后的数组
function logResult($word='')
功能:写日志,方便测试(看网站需求,也能够改为存入数据库)
输入:String $word 要写入日志里的文本内容 默认值:空值
function getHttpResponsePOST($url, $cacert_url, $para, $input_charset = '')
功能:远程获取数据,POST模式
输入:String $url 指定URL完整路径地址
String $cacert_url 指定当前工做目录绝对路径
Array $para 请求的数据
String $input_charset 编码格式。默认值:空值
输出:String 远程输出的数据
function getHttpResponseGET($url, $cacert_url)
功能:远程获取数据,GET模式
输入:String $url 指定URL完整路径地址
String $cacert_url 指定当前工做目录绝对路径
输出:String 远程输出的数据
function charsetEncode($input,$_output_charset ,$_input_charset)
功能:实现多种字符编码方式
输入:String $input 须要编码的字符串
String $_output_charset 输出的编码格式
String $_input_charset 输入的编码格式
输出:String 编码后的字符串
function charsetDecode($input,$_input_charset ,$_output_charset)
功能:实现多种字符解码方式
输入:String $input 须要解码的字符串
String $_output_charset 输出的解码格式
String $_input_charset 输入的解码格式
输出:String 解码后的字符串app
<?php /* * * 支付宝接口公用函数 * 详细:该类是请求、通知返回两个文件所调用的公用函数核心处理文件 * 版本:3.3 * 日期:2012-07-19 * 说明: * 如下代码只是为了方便商户测试而提供的样例代码,商户能够根据本身网站的须要,按照技术文档编写,并不是必定要使用该代码。 * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 */ /** * 把数组全部元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 * @param $para 须要拼接的数组 * return 拼接完成之后的字符串 */ function createLinkstring($para) { $arg = ""; while (list ($key, $val) = each ($para)) { $arg.=$key."=".$val."&"; } //去掉最后一个&字符 $arg = substr($arg,0,count($arg)-2); //若是存在转义字符,那么去掉转义 if(get_magic_quotes_gpc()){$arg = stripslashes($arg);} return $arg; } /** * 把数组全部元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串作urlencode编码 * @param $para 须要拼接的数组 * return 拼接完成之后的字符串 */ function createLinkstringUrlencode($para) { $arg = ""; while (list ($key, $val) = each ($para)) { $arg.=$key."=".urlencode($val)."&"; } //去掉最后一个&字符 $arg = substr($arg,0,count($arg)-2); //若是存在转义字符,那么去掉转义 if(get_magic_quotes_gpc()){$arg = stripslashes($arg);} return $arg; } /** * 除去数组中的空值和签名参数 * @param $para 签名参数组 * return 去掉空值与签名参数后的新签名参数组 */ function paraFilter($para) { $para_filter = array(); while (list ($key, $val) = each ($para)) { if($key == "sign" || $key == "sign_type" || $val == "")continue; else $para_filter[$key] = $para[$key]; } return $para_filter; } /** * 对数组排序 * @param $para 排序前的数组 * return 排序后的数组 */ function argSort($para) { ksort($para); reset($para); return $para; } /** * 写日志,方便测试(看网站需求,也能够改为把记录存入数据库) * 注意:服务器须要开通fopen配置 * @param $word 要写入日志里的文本内容 默认值:空值 */ function logResult($word='') { $fp = fopen("log.txt","a"); flock($fp, LOCK_EX) ; fwrite($fp,"执行日期:".strftime("%Y%m%d%H%M%S",time())."\n".$word."\n"); flock($fp, LOCK_UN); fclose($fp); } /** * 远程获取数据,POST模式 * 注意: * 1.使用Crul须要修改服务器中php.ini文件的设置,找到php_curl.dll去掉前面的";"就好了 * 2.文件夹中cacert.pem是SSL证书请保证其路径有效,目前默认路径是:getcwd().'\\cacert.pem' * @param $url 指定URL完整路径地址 * @param $cacert_url 指定当前工做目录绝对路径 * @param $para 请求的数据 * @param $input_charset 编码格式。默认值:空值 * return 远程输出的数据 */ function getHttpResponsePOST($url, $cacert_url, $para, $input_charset = '') { if (trim($input_charset) != '') { $url = $url."_input_charset=".$input_charset; } $curl = curl_init($url); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);//SSL证书认证 curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证 curl_setopt($curl, CURLOPT_CAINFO,$cacert_url);//证书地址 curl_setopt($curl, CURLOPT_HEADER, 0 ); // 过滤HTTP头 curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);// 显示输出结果 curl_setopt($curl,CURLOPT_POST,true); // post传输数据 curl_setopt($curl,CURLOPT_POSTFIELDS,$para);// post传输数据 $responseText = curl_exec($curl); //var_dump( curl_error($curl) );//若是执行curl过程当中出现异常,可打开此开关,以便查看异常内容 curl_close($curl); return $responseText; } /** * 远程获取数据,GET模式 * 注意: * 1.使用Crul须要修改服务器中php.ini文件的设置,找到php_curl.dll去掉前面的";"就好了 * 2.文件夹中cacert.pem是SSL证书请保证其路径有效,目前默认路径是:getcwd().'\\cacert.pem' * @param $url 指定URL完整路径地址 * @param $cacert_url 指定当前工做目录绝对路径 * return 远程输出的数据 */ function getHttpResponseGET($url,$cacert_url) { $curl = curl_init($url); 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,$cacert_url);//证书地址 $responseText = curl_exec($curl); //var_dump( curl_error($curl) );//若是执行curl过程当中出现异常,可打开此开关,以便查看异常内容 curl_close($curl); return $responseText; } /** * 实现多种字符编码方式 * @param $input 须要编码的字符串 * @param $_output_charset 输出的编码格式 * @param $_input_charset 输入的编码格式 * return 编码后的字符串 */ function charsetEncode($input,$_output_charset ,$_input_charset) { $output = ""; if(!isset($_output_charset) )$_output_charset = $_input_charset; if($_input_charset == $_output_charset || $input ==null ) { $output = $input; } elseif (function_exists("mb_convert_encoding")) { $output = mb_convert_encoding($input,$_output_charset,$_input_charset); } elseif(function_exists("iconv")) { $output = iconv($_input_charset,$_output_charset,$input); } else die("sorry, you have no libs support for charset change."); return $output; } /** * 实现多种字符解码方式 * @param $input 须要解码的字符串 * @param $_output_charset 输出的解码格式 * @param $_input_charset 输入的解码格式 * return 解码后的字符串 */ function charsetDecode($input,$_input_charset ,$_output_charset) { $output = ""; if(!isset($_input_charset) )$_input_charset = $_input_charset ; if($_input_charset == $_output_charset || $input ==null ) { $output = $input; } elseif (function_exists("mb_convert_encoding")) { $output = mb_convert_encoding($input,$_output_charset,$_input_charset); } elseif(function_exists("iconv")) { $output = iconv($_input_charset,$_output_charset,$input); } else die("sorry, you have no libs support for charset changes."); return $output; } ?>
┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉
function md5Sign($prestr, $key)
功能:MD5签名
输入:String $prestr 待签名数据
String $key 私钥
输出:String 签名结果
function md5Verify($prestr, $sign, $key)
功能:MD5验签
输入:String $data 待签名数据
String $sign 签名结果
String $key 私钥
输出:bool 验证结果curl
<?php /* * * MD5 * 详细:MD5加密 * 版本:3.3 * 日期:2012-07-19 * 说明: * 如下代码只是为了方便商户测试而提供的样例代码,商户能够根据本身网站的须要,按照技术文档编写,并不是必定要使用该代码。 * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 */ /** * 签名字符串 * @param $prestr 须要签名的字符串 * @param $key 私钥 * return 签名结果 */ function md5Sign($prestr, $key) { $prestr = $prestr . $key; return md5($prestr); } /** * 验证签名 * @param $prestr 须要签名的字符串 * @param $sign 签名结果 * @param $key 私钥 * return 签名结果 */ function md5Verify($prestr, $sign, $key) { $prestr = $prestr . $key; $mysgin = md5($prestr); if($mysgin == $sign) { return true; } else { return false; } } ?>
┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉
alipay_notify.class.php
function verifyNotify()
功能:对notify_url的认证
输出:Bool 验证结果:true/false
function verifyReturn()
功能:对return_url的认证
输出:Bool 验证结果:true/false
function getSignVeryfy($para_temp, $sign)
功能:获取返回时的签名验证结果
输入:Array $para_temp 通知返回来的参数数组
String $sign 支付宝返回的签名结果
输出:Bool 得到签名验证结果
function getResponse($notify_id)
功能:获取远程服务器ATN结果,验证返回URL
输入:String $notify_id 通知校验ID
输出:String 服务器ATN结果
<?php /* * * 类名:AlipayNotify * 功能:支付宝通知处理类 * 详细:处理支付宝各接口通知返回 * 版本:3.2 * 日期:2011-03-25 * 说明: * 如下代码只是为了方便商户测试而提供的样例代码,商户能够根据本身网站的须要,按照技术文档编写,并不是必定要使用该代码。 * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考 *************************注意************************* * 调试通知返回时,可查看或改写log日志的写入TXT里的数据,来检查通知返回是否正常 */ require_once("alipay_core.function.php"); require_once("alipay_md5.function.php"); class AlipayNotify { /** * HTTPS形式消息验证地址 */ var $https_verify_url = 'https://mapi.alipay.com/gateway.do?service=notify_verify&'; /** * HTTP形式消息验证地址 */ var $http_verify_url = 'http://notify.alipay.com/trade/notify_query.do?'; var $alipay_config; function __construct($alipay_config){ $this->alipay_config = $alipay_config; } function AlipayNotify($alipay_config) { $this->__construct($alipay_config); } /** * 针对notify_url验证消息是不是支付宝发出的合法消息 * @return 验证结果 */ function verifyNotify(){ if(empty($_POST)) {//判断POST来的数组是否为空 return false; } else { //生成签名结果 $isSign = $this->getSignVeryfy($_POST, $_POST["sign"]); //获取支付宝远程服务器ATN结果(验证是不是支付宝发来的消息) $responseTxt = 'true'; if (! empty($_POST["notify_id"])) {$responseTxt = $this->getResponse($_POST["notify_id"]);} //写日志记录 //if ($isSign) { // $isSignStr = 'true'; //} //else { // $isSignStr = 'false'; //} //$log_text = "responseTxt=".$responseTxt."\n notify_url_log:isSign=".$isSignStr.","; //$log_text = $log_text.createLinkString($_POST); //logResult($log_text); //验证 //$responsetTxt的结果不是true,与服务器设置问题、合做身份者ID、notify_id一分钟失效有关 //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 if (preg_match("/true$/i",$responseTxt) && $isSign) { return true; } else { return false; } } } /** * 针对return_url验证消息是不是支付宝发出的合法消息 * @return 验证结果 */ function verifyReturn(){ if(empty($_GET)) {//判断POST来的数组是否为空 return false; } else { //生成签名结果 $isSign = $this->getSignVeryfy($_GET, $_GET["sign"]); //获取支付宝远程服务器ATN结果(验证是不是支付宝发来的消息) $responseTxt = 'true'; if (! empty($_GET["notify_id"])) {$responseTxt = $this->getResponse($_GET["notify_id"]);} //写日志记录 //if ($isSign) { // $isSignStr = 'true'; //} //else { // $isSignStr = 'false'; //} //$log_text = "responseTxt=".$responseTxt."\n return_url_log:isSign=".$isSignStr.","; //$log_text = $log_text.createLinkString($_GET); //logResult($log_text); //验证 //$responsetTxt的结果不是true,与服务器设置问题、合做身份者ID、notify_id一分钟失效有关 //isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 if (preg_match("/true$/i",$responseTxt) && $isSign) { return true; } else { return false; } } } /** * 获取返回时的签名验证结果 * @param $para_temp 通知返回来的参数数组 * @param $sign 返回的签名结果 * @return 签名验证结果 */ function getSignVeryfy($para_temp, $sign) { //除去待签名参数数组中的空值和签名参数 $para_filter = paraFilter($para_temp); //对待签名参数数组排序 $para_sort = argSort($para_filter); //把数组全部元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 $prestr = createLinkstring($para_sort); $isSgin = false; switch (strtoupper(trim($this->alipay_config['sign_type']))) { case "MD5" : $isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']); break; default : $isSgin = false; } return $isSgin; } /** * 获取远程服务器ATN结果,验证返回URL * @param $notify_id 通知校验ID * @return 服务器ATN结果 * 验证结果集: * invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空 * true 返回正确信息 * false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟 */ function getResponse($notify_id) { $transport = strtolower(trim($this->alipay_config['transport'])); $partner = trim($this->alipay_config['partner']); $veryfy_url = ''; if($transport == 'https') { $veryfy_url = $this->https_verify_url; } else { $veryfy_url = $this->http_verify_url; } $veryfy_url = $veryfy_url."partner=" . $partner . "¬ify_id=" . $notify_id; $responseTxt = getHttpResponseGET($veryfy_url, $this->alipay_config['cacert']); return $responseTxt; } } ?>
┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉┉
alipay_submit.class.php
function buildRequestMysign($para_sort)
功能:生成要请求给支付宝的参数数组
输入:Array $para_sort 已排序要签名的数组
输出:String 签名结果
function buildRequestPara($para_temp)
功能:根据反馈回来的信息,生成签名结果
输入:Array $para_temp 请求前的参数数组
输出:String 要请求的参数数组
function buildRequestParaToString($para_temp)
功能:根据反馈回来的信息,生成签名结果
输入:Array $para_temp 请求前的参数数组
输出:String 要请求的参数数组字符串
function buildRequestForm($para_temp, $method, $button_name)
功能:创建请求,以表单HTML形式构造(默认)
输入:Array $para_temp 请求前的参数数组
String $method 提交方式。两个值可选:post、get
String $button_name 确认按钮显示文字
输出:String 提交表单HTML文本
function buildRequestHttp($para_temp)
功能:创建请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果
输入:Array $para_temp 请求前的参数数组
输出:String 支付宝处理结果
function buildRequestHttpInFile($para_temp, $file_para_name, $file_name)
功能:创建请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果,带文件上传功能
输入:Array $para_temp 请求参数数组
String $file_para_name 文件类型的参数名
String $file_name 文件完整绝对路径
输出:String 支付宝返回处理结果
function query_timestamp()
功能:用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数
输出:String 时间戳字符串
<?php /* * * 类名:AlipaySubmit * 功能:支付宝各接口请求提交类 * 详细:构造支付宝各接口表单HTML文本,获取远程HTTP数据 * 版本:3.3 * 日期:2012-07-23 * 说明: * 如下代码只是为了方便商户测试而提供的样例代码,商户能够根据本身网站的须要,按照技术文档编写,并不是必定要使用该代码。 * 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 */ require_once("alipay_core.function.php"); require_once("alipay_md5.function.php"); class AlipaySubmit { var $alipay_config; /** *支付宝网关地址(新) */ var $alipay_gateway_new = 'https://mapi.alipay.com/gateway.do?'; function __construct($alipay_config){ $this->alipay_config = $alipay_config; } function AlipaySubmit($alipay_config) { $this->__construct($alipay_config); } /** * 生成签名结果 * @param $para_sort 已排序要签名的数组 * return 签名结果字符串 */ function buildRequestMysign($para_sort) { //把数组全部元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 $prestr = createLinkstring($para_sort); $mysign = ""; switch (strtoupper(trim($this->alipay_config['sign_type']))) { case "MD5" : $mysign = md5Sign($prestr, $this->alipay_config['key']); break; default : $mysign = ""; } return $mysign; } /** * 生成要请求给支付宝的参数数组 * @param $para_temp 请求前的参数数组 * @return 要请求的参数数组 */ function buildRequestPara($para_temp) { //除去待签名参数数组中的空值和签名参数 $para_filter = paraFilter($para_temp); //对待签名参数数组排序 $para_sort = argSort($para_filter); //生成签名结果 $mysign = $this->buildRequestMysign($para_sort); //签名结果与签名方式加入请求提交参数组中 $para_sort['sign'] = $mysign; $para_sort['sign_type'] = strtoupper(trim($this->alipay_config['sign_type'])); return $para_sort; } /** * 生成要请求给支付宝的参数数组 * @param $para_temp 请求前的参数数组 * @return 要请求的参数数组字符串 */ function buildRequestParaToString($para_temp) { //待请求参数数组 $para = $this->buildRequestPara($para_temp); //把参数组中全部元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串作urlencode编码 $request_data = createLinkstringUrlencode($para); return $request_data; } /** * 创建请求,以表单HTML形式构造(默认) * @param $para_temp 请求参数数组 * @param $method 提交方式。两个值可选:post、get * @param $button_name 确认按钮显示文字 * @return 提交表单HTML文本 */ function buildRequestForm($para_temp, $method, $button_name) { //待请求参数数组 $para = $this->buildRequestPara($para_temp); $sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='".$this->alipay_gateway_new."_input_charset=".trim(strtolower($this->alipay_config['input_charset']))."' method='".$method."'>"; while (list ($key, $val) = each ($para)) { $sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>"; } //submit按钮控件请不要含有name属性 //$sHtml = $sHtml."<input type='submit' value='".$button_name."'></form>"; $sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>"; return $sHtml; } /** * 创建请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果 * @param $para_temp 请求参数数组 * @return 支付宝处理结果 */ function buildRequestHttp($para_temp) { $sResult = ''; //待请求参数数组字符串 $request_data = $this->buildRequestPara($para_temp); //远程获取数据 $sResult = getHttpResponsePOST($this->alipay_gateway_new, $this->alipay_config['cacert'],$request_data,trim(strtolower($this->alipay_config['input_charset']))); return $sResult; } /** * 创建请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果,带文件上传功能 * @param $para_temp 请求参数数组 * @param $file_para_name 文件类型的参数名 * @param $file_name 文件完整绝对路径 * @return 支付宝返回处理结果 */ function buildRequestHttpInFile($para_temp, $file_para_name, $file_name) { //待请求参数数组 $para = $this->buildRequestPara($para_temp); $para[$file_para_name] = "@".$file_name; //远程获取数据 $sResult = getHttpResponsePOST($this->alipay_gateway_new, $this->alipay_config['cacert'],$para,trim(strtolower($this->alipay_config['input_charset']))); return $sResult; } /** * 用于防钓鱼,调用接口query_timestamp来获取时间戳的处理函数 * 注意:该功能PHP5环境及以上支持,所以必须服务器、本地电脑中装有支持DOMDocument、SSL的PHP配置环境。建议本地调试时使用PHP开发软件 * return 时间戳字符串 */ function query_timestamp() { $url = $this->alipay_gateway_new."service=query_timestamp&partner=".trim(strtolower($this->alipay_config['partner']))."&_input_charset=".trim(strtolower($this->alipay_config['input_charset'])); $encrypt_key = ""; $doc = new DOMDocument(); $doc->load($url); $itemEncrypt_key = $doc->getElementsByTagName( "encrypt_key" ); $encrypt_key = $itemEncrypt_key->item(0)->nodeValue; return $encrypt_key; } } ?>