165 lines
5.4 KiB
PHP
165 lines
5.4 KiB
PHP
<?php
|
||
/* *
|
||
* 类名:AlipayNotify
|
||
* 功能:支付宝通知处理类
|
||
* 详细:处理支付宝各接口通知返回
|
||
* 版本:3.2
|
||
* 日期:2011-03-25
|
||
* 说明:
|
||
* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
|
||
* 该代码仅供学习和研究支付宝接口使用,只是提供一个参考
|
||
|
||
*************************注意*************************
|
||
* 调试通知返回时,可查看或改写log日志的写入TXT里的数据,来检查通知返回是否正常
|
||
*/
|
||
|
||
require_once __DIR__ . '/alipay_core.function.php';
|
||
require_once __DIR__ . '/alipay_rsa.function.php';
|
||
|
||
class AlipayNotify
|
||
{
|
||
public $partner = ''; ///
|
||
public $sign_type = ''; /// 签名方式(md5或rsa)
|
||
public $md5_key = ''; /// md5签名key
|
||
public $rsa_private_key_path; /// rsa私钥文件全名
|
||
public $rsa_public_key_path; /// rsa公钥文件全名
|
||
public $alipay_public_key; /// alipay公钥文件全名
|
||
public $input_charset = 'UTF-8'; /// 字符集
|
||
public $cacert_file_path = __DIR__ . '/cacert.pem'; /// ca证书路径地址,用于curl中ssl校验
|
||
public $transport = 'https'; /// 访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http
|
||
|
||
function __construct($config)
|
||
{
|
||
$class_name = get_class($this);
|
||
$Reflect = new ReflectionClass($this);
|
||
foreach ($config as $key => $value)
|
||
{
|
||
if ($Property = $Reflect->GetProperty($key))
|
||
{
|
||
if ($Property->IsPublic())
|
||
$Property->SetValue($this, $value);
|
||
elseif ($Property->IsPrivate())
|
||
throw new Exception('can not access private property: ' . $class_name . '::' . $key . ' in ' . __FILE__ . ' on line ' . __LINE__);
|
||
elseif ($Property->IsProtected())
|
||
throw new Exception('can not access protected property: ' . $class_name . '::' . $key . ' in ' . __FILE__ . ' on line ' . __LINE__);
|
||
else
|
||
throw new Exception('can not access unknown property: ' . $class_name . '::' . $key . ' in ' . __FILE__ . ' on line ' . __LINE__);
|
||
|
||
$Property = null;
|
||
} else
|
||
throw new Exception('undefined property: ' . $class_name . '::' . $key . ' in ' . __FILE__ . ' on line ' . __LINE__);
|
||
}
|
||
}
|
||
|
||
function AlipayNotify($config)
|
||
{
|
||
$this->__construct($config);
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @return 验证结果
|
||
*/
|
||
function verifyNotify()
|
||
{
|
||
if (empty($_POST)) /// 判断POST来的数组是否为空
|
||
return false;
|
||
|
||
/// 生成签名结果
|
||
$isSign = $this->getSignVeryfy($_POST, $_POST["sign"]);
|
||
/// isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
|
||
return $isSign ? true : false;
|
||
}
|
||
|
||
/**
|
||
* 针对return_url验证消息是否是支付宝发出的合法消息
|
||
* @return 验证结果
|
||
*/
|
||
function verifyReturn()
|
||
{
|
||
if (empty($_GET)) //判断POST来的数组是否为空
|
||
return false;
|
||
|
||
//生成签名结果
|
||
$isSign = $this->getSignVeryfy($_GET, $_GET["sign"]);
|
||
//获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息)
|
||
$responseTxt = 'false';
|
||
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,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
|
||
return (preg_match("/true$/i", $responseTxt) && $isSign) ? true : false;
|
||
}
|
||
|
||
/**
|
||
* 获取返回时的签名验证结果
|
||
* @param array $para_temp 通知返回来的参数数组
|
||
* @param string $sign 返回的签名结果
|
||
* @return 签名验证结果
|
||
*/
|
||
function getSignVeryfy($para_temp, $sign)
|
||
{
|
||
//除去待签名参数数组中的空值和签名参数
|
||
$para_filter = paraFilter($para_temp);
|
||
|
||
//对待签名参数数组排序
|
||
$para_sort = argSort($para_filter);
|
||
|
||
//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
|
||
$prestr = createLinkstring($para_sort);
|
||
|
||
switch (strtoupper(trim($this->sign_type)))
|
||
{
|
||
case 'RSA':
|
||
$isSgin = rsaVerify($prestr, trim($this->alipay_public_key), $sign);
|
||
break;
|
||
case 'MD5':
|
||
$isSgin = md5Verify($prestr, $sign, $this->md5_key);
|
||
break;
|
||
default :
|
||
$isSgin = false;
|
||
}
|
||
|
||
return $isSgin;
|
||
}
|
||
|
||
/**
|
||
* 获取远程服务器ATN结果,验证返回URL
|
||
* @param string $notify_id 通知校验ID
|
||
* @return 服务器ATN结果
|
||
* 验证结果集:
|
||
* invalid命令参数不对 出现这个错误,请检测返回处理中partner和key是否为空
|
||
* true 返回正确信息
|
||
* false 请检查防火墙或者是服务器阻止端口问题以及验证时间是否超过一分钟
|
||
*/
|
||
function getResponse($notify_id)
|
||
{
|
||
$transport = strtolower(trim($this->transport));
|
||
$partner = trim($this->partner);
|
||
|
||
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->cacert_file_path);
|
||
|
||
return $responseTxt;
|
||
}
|
||
}
|
||
|