支付宝安全云检测alipay.security.risk.detect的简易的类API
- 9575
- PHP
- 7
- super_dodo
- 2014/09/13
客户的支付宝接口最近升级,支付宝方面要求进行安全云检测,发来了两个文档,但是没有demo.甚是捉急.看了文档一遍一遍,差点连接口的地址都确定不了。参数真是一大串,手忙脚乱,差点就要进入失眠的状态了。眼看实在拖不下去了,不得不进行硬着头皮上。
自己按照步骤去尝试,组装相应的参数,参数排序,排序后组装拼接成为url,都不知道怎么去请求,管它了,生成之后先跳转或者复制到url地址去请求。未果,一直报各种错误。不得不承认自己的技不如人,结果按照菜鸟的本能。开始了寻求之路。
1.跟支付宝的技术,也就是邮件发来的人,回复他的邮件,很诚恳的说明自己是怎么操作的,什么步骤,写了个方法,各种标注,期待对方能回应。
2.次日(周五)上午,再次邮件请求协助。尚无结果(或许他太忙了,我也太焦急了)。
3.眼看周末了,不能再沉默了,不然周末心里不踏实。果断电话一下客服,客服给了个地址:https://b.alipay.com/support/helperApply.htm?action=supportHome 结果要登录,登陆进去没什么东西,要点击在线客服,这样进入了排队的大军,预计三个小时,还好差不多一个小时的时候轮到我了。一听是安全云的,直接告诉我用旺旺联系"末宇"
4.虽然有些周折,但是能找到人能及时沟通还是挺美的。我马不停蹄的下载了旺旺,结果登不进去,一检查下成了商家版本的旺旺了。涨知识了。再下载买家版的旺旺。登录之后查找。查找到了,可惜对方一直离线。(目测淘宝是不是不能用QQ)
5.沮丧之际,QQ邮件来了,仔细一看发邮件的就是"末宇",我这是有多笨呐。转了一大个圈。
6.邮件里面有 “这是自己测试的PHP的demo,请参考!”,看到demo这个单词的时候,差点没泪崩。而且还是PHP版本的,灰常灰常的感激.(此处不得不BS一下有些服务商。寻求帮助,他们居然说不会PHP,不会JAVA,问啥不会啥,这不明显的坑人吗?你作为一个技术,你的存在感何在,对于这种无良的技术支持,下次果断规避.同时表扬一下银联和支付宝)
7.看到demo的时候其实也是很多文件。也是无从下手,但是心里有底了。按照步骤去一个一个方法的去寻找。尝试之后直接上代码(我废话说的实在太多了)。
调用的接口的方法
//云安全检测
public function actionCheckYun() {
// Yii::import('application.extensions.AlipayRisk.*'); //引入AlipayRisk
// $request = Yii::app()->request;
$buyer_account_no='155****3485'; //买家支付宝账号
$buyer_reg_date='2014-05-05'; //买家注册时间
$timestamp = '2014-09-08 01:27:08'; //请求时间
$order_no='20140908_2554'; //订单号
$order_credate_time='2014-09-08 01:26:50'; //下单时间
$order_category='虚拟^话费充值^移动'; //订单商品所在类目( 必填,虚拟^彩票^双色球;虚拟^游戏^魔兽;虚拟^话费充值^移动;服装^女装^裤子)
$order_item_name='话费充值活动'; //订单商品名称
$order_amount='500'; //价格(总价)
//组装参数提交---参数提交的越多,越准确
$post_param = array(
"timestamp" => $timestamp, //请求时间
"order_no" => $order_no,
"order_credate_time" => $order_credate_time,
"order_category" => $order_category,
"order_item_name" => $order_item_name,
"order_item_city" => '昆明',
"buyer_scene_mobile" => '155****3485',
"buyer_reg_mobile" => '155****3485',
"buyer_grade" => 'VIP',
"buyer_identity_type" => 'IDENTITY_CARD',
"buyer_identity_no" => '4509****01312813',
"seller_account_no" => '1001',
"seller_reg_date" => '2014-05-05',
"order_amount"=>$order_amount,
"buyer_account_no"=>$buyer_account_no,
"buyer_reg_date"=>$buyer_reg_date,
);
$riskDetect = new RiskDemo();
$risk_text = $riskDetect->detect($post_param); //得到检测的结果
print_r($risk_text);
}
//类文件的配置文件【RiskConfig.php】
<?php
/* *
* 配置文件
* 版本:3.3
* 日期:2012-07-19
* 说明:
* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
* 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
* 提示:如何获取安全校验码和合作身份者id
* 1.用您的签约支付宝账号登录支付宝网站(www.alipay.com)
* 2.点击“商家服务”(https://b.alipay.com/order/myorder.htm)
* 3.点击“查询合作者身份(pid)”、“查询安全校验码(key)”
* 安全校验码查看时,输入支付密码后,页面呈灰色的现象,怎么办?
* 解决方法:
* 1、检查浏览器配置,不让浏览器做弹框屏蔽设置
* 2、更换浏览器或电脑,重新登录查询。
*/
class RiskConfig
{
//合作身份者id,以2088开头的16位纯数字
static $partner = '2088*****342649';
//安全检验码,以数字和字母组成的32位字符
static $key = 'ezz6x3*********ff5hwhfeh15e6';
//签名方式 不需修改
static $sign_type = 'MD5';
//字符编码格式 目前支持 gbk 或 utf-8
static $input_charset = 'utf-8';
//ca证书路径地址,用于curl中ssl校验
//请保证cacert.pem文件在当前文件夹目录中
// static $cacert = getcwd().'\\cacert.pem';
//static $cacert = '\\cacert.pem';
//访问模式,根据自己的服务器是否支持ssl访问,若支持请选择https;若不支持请选择http
static $transport = 'http';
//*支付宝网关地址(新)
static $alipay_gateway_new = 'https://mapi.alipay.com/gateway.do?';
//页面跳转同步通知页面路径,需http://格式的完整路径,不能加?id=123这类自定义参数,不能写成http://localhost/
static $return_url = "http://localhost/bank/alipay.security.risk.detect/return_url.php";
static $notify_url = "http://localhost/bank/alipay.security.risk.detect/notify_url.php"; //异步地址
}
[/php]
接口类文件,和配置文件放在同一目录即可【RiskDemo.php】
[php]
<?php
/* *
* 功能:即时到账交易接口接入页
* 版本:3.3
* 修改日期:2012-07-23
* 说明:
* 以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
* 该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*************************注意*************************
* 如果您在接口集成过程中遇到问题,可以按照下面的途径来解决
* 1、商户服务中心(https://b.alipay.com/support/helperApply.htm?action=consultationApply),提交申请集成协助,我们会有专业的技术工程师主动联系您协助解决
* 2、商户帮助中心(http://help.alipay.com/support/232511-16307/0-16307.htm?sh=Y&info_type=9)
* 3、支付宝论坛(http://club.alipay.com/read-htm-tid-8681712.html)
* 如果不想使用扩展功能请把扩展功能参数赋空值。
*/
/**************************安全云请求参数**************************/
/*
//构造要请求的参数数组,无需改动---最终构造成该参数
$parameter = array(
"service" => "alipay.security.risk.detect", //接口的方法
"partner" => trim($alipay_config['partner']), //合作身份者id,以2088开头的16位纯数字
// "payment_type" => $payment_type, //类型(该行请注释)
"notify_url" => $notify_url, //异步地址
"return_url" => $return_url, //页面跳转同步通知页面路径,需http://格式的完整路径,不能加?id=123这类自定义参数
"seller_email" => $seller_email, //卖家支付宝帐户
"timestamp" => $timestamp, //请求时间
"terminal_type" => $terminal_type, //终端类型
"terminal_info" => $terminal_info, //终端详情
"order_no" => $order_no, //订单号
"order_credate_time" => $order_credate_time, //下单时间
"order_category" => $order_category, //订单商品所在类目
"order_item_name" => $order_item_name, //订单商品名称
"order_amount"=>$order_amount, //价格(总价)
"scene_code"=>$scene_code, //场景编码
"buyer_account_no"=>$buyer_account_no, //买家支付宝账号
"buyer_reg_date"=>$buyer_reg_date, //买家注册时间
"_input_charset" => trim(strtolower($alipay_config['input_charset'])),
"order_item_city" => '昆明',
"buyer_scene_mobile" => '155****3485',
"buyer_reg_mobile" => '155****3485',
"buyer_grade" => 'VIP',
"buyer_identity_type" => 'IDENTITY_CARD',
"buyer_identity_no" => '4509*******12813',
"seller_account_no" => '1001',
"seller_reg_date" => '2014-05-05',
"buyer_grade" => 'VIP',
);*/
require_once("RiskConfig.php");
//安全云检测的类
class RiskDemo {
//检测--根据传递过来的参数,合并数组,调用检测方法进行检测.
public function detect($post_param){
//基本配置文件的参数
$config_param = array(
"service" => "alipay.security.risk.detect",
"partner" => trim(RiskConfig::$partner),
// "payment_type" => $payment_type,
// "notify_url" => RiskConfig::$notify_url,
// "return_url" => RiskConfig::$return_url,
"terminal_type" => 'APP', //终端类型(必填,请求终端类型,范围:WEB,WAP,APP)
"terminal_info" => '', //终端详情(可空,请求终端详情,以“操作系统^版本号”为格式。)
"scene_code"=> 'PAYMENT', //场景编码
"_input_charset" => trim(strtolower(RiskConfig::$input_charset)),
//卖家的相关信息,因为该项目都是对应充值到指定的账户,所以该信息是固定的
"seller_email" => '****@******.com', //卖家支付宝帐户
"seller_account_no" => '1002', //卖家账户编号
"seller_reg_moile" => '137********', //卖家注册手机号码
"seller_reg_date" => '2014-05-05', //卖家注册时间
"seller_real_name" => '**', //卖家真实姓名
"seller_identity_type" => 'IDENTITY_CARD', //卖家证件类型
"seller_identity_no" => '532**********', //卖家证件号码
//订单相关基础信息
"timestamp" => date('Y-m-d H:i:s'), //请求时间(2014-09-08 01:27:08)
"order_credate_time" => date('Y-m-d H:i:s'), //下单时间(2014-09-08 01:26:50)
"order_category" => '虚拟^话费充值^移动', //订单商品所在类目( 必填,虚拟^彩票^双色球;虚拟^游戏^魔兽;虚拟^话费充值^移动;服装^女装^裤子)
"order_item_name" => '话费充值活动', //订单商品名称
"order_item_city" => '昆明', //订单商品所在城市
);
//提交来的参数和配置的参数合并
$parameter = array_merge($config_param, $post_param);
//建立请求
$html_text = $this->buildRequestHttp($parameter);
$risk_level = '-1'; //未识别 默认值--接口未响应
$risk_code = '1'; //未识别 默认值--接口未响应
if($html_text){
// return $html_text; //直接返回界面XML格式(调试测试时这个更直观)
$risk = array(); //用于组装新的数组--返回的数组形势
$doc = new DOMDocument();
$doc->loadXML($html_text); //解析XML
$risk['is_success'] = $doc->getElementsByTagName("is_success")->item(0)->nodeValue; //接口响应情况
$risk['risk_level'] = $doc->getElementsByTagName("risk_level")->item(0)->nodeValue; //风险预警值
$risk['risk_code'] = $doc->getElementsByTagName("risk_code")->item(0)->nodeValue; //风险预警值
if(!empty($risk)){
if($risk['is_success'] == 'T'){
$risk_level = $risk['risk_level'];
$risk_code = $risk['risk_code'];
}
}
}
return array('risk_level'=>$risk_level,'risk_code'=>$risk_code);
}
/**
* 建立请求,以模拟远程HTTP的POST请求方式构造并获取支付宝的处理结果
* @param $para_temp 请求参数数组
* @return 支付宝处理结果
*/
public function buildRequestHttp($para_temp) {
$sResult = '';
//待请求参数数组字符串
$request_data = $this->buildRequestPara($para_temp);
//ca证书路径地址,用于curl中ssl校验
//请保证cacert.pem文件在当前文件夹目录中
$cacert = getcwd().'\\cacert.pem';
//远程获取数据
$sResult = $this->getHttpResponsePOST(RiskConfig::$alipay_gateway_new, $cacert,$request_data,trim(strtolower(RiskConfig::$input_charset)));
return $sResult;
}
/**
* 生成要请求给支付宝的参数数组
* @param $para_temp 请求前的参数数组
* @return 要请求的参数数组
*/
public function buildRequestPara($para_temp) {
//除去待签名参数数组中的空值和签名参数
$para_filter = $this->paraFilter($para_temp);
//对待签名参数数组排序
$para_sort = $this->argSort($para_filter);
//生成签名结果
$mysign = $this->buildRequestMysign($para_sort);
//签名结果与签名方式加入请求提交参数组中
$para_sort['sign'] = $mysign;
$para_sort['sign_type'] = strtoupper(trim(RiskConfig::$sign_type));
return $para_sort;
}
/**
* 除去数组中的空值和签名参数
* @param $para 签名参数组
* return 去掉空值与签名参数后的新签名参数组
*/
public 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 排序后的数组
*/
public function argSort($para) {
ksort($para);
reset($para);
return $para;
}
/**
* 生成签名结果
* @param $para_sort 已排序要签名的数组
* return 签名结果字符串
*/
public function buildRequestMysign($para_sort) {
//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
$prestr = $this->createLinkstring($para_sort);
$mysign = "";
switch (strtoupper(trim(RiskConfig::$sign_type))) {
case "MD5" :
$mysign = $this->md5Sign($prestr, RiskConfig::$key);
break;
default :
$mysign = "";
}
return $mysign;
}
/**
* 远程获取数据,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 远程输出的数据
*/
public 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;
}
/* *
* 支付宝接口公用函数
* 详细:该类是请求、通知返回两个文件所调用的公用函数核心处理文件
*/
/**
* 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
* @param $para 需要拼接的数组
* return 拼接完成以后的字符串
*/
public 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 拼接完成以后的字符串
*/
public 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;
}
/**
* 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
* 注意:服务器需要开通fopen配置
* @param $word 要写入日志里的文本内容 默认值:空值
*/
public 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);
}
/**
* 远程获取数据,GET模式
* 注意:
* 1.使用Crul需要修改服务器中php.ini文件的设置,找到php_curl.dll去掉前面的";"就行了
* 2.文件夹中cacert.pem是SSL证书请保证其路径有效,目前默认路径是:getcwd().'\\cacert.pem'
* @param $url 指定URL完整路径地址
* @param $cacert_url 指定当前工作目录绝对路径
* return 远程输出的数据
*/
public 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 编码后的字符串
*/
public 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 解码后的字符串
*/
public 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;
}
/**
* 签名字符串
* @param $prestr 需要签名的字符串
* @param $key 私钥
* return 签名结果
*/
public function md5Sign($prestr, $key) {
$prestr = $prestr . $key;
return md5($prestr);
}
/**
* 验证签名
* @param $prestr 需要签名的字符串
* @param $sign 签名结果
* @param $key 私钥
* return 签名结果
*/
public function md5Verify($prestr, $sign, $key) {
$prestr = $prestr . $key;
$mysgin = md5($prestr);
if($mysgin == $sign) {
return true;
}
else {
return false;
}
}
}

备注,里面的部分方法可以舍弃,根据你自己的需要慢慢的改进优化。
不为物所役,不忘初心,几十年如一日,安于清贫,甘于寂寞,淡泊名利。---《坚守》
相关阅读
- 通过Google API客户端访问Google Play帐户报告PHP库
- PHP执行文件的压缩和解压缩方法
- 消息中间件MQ与RabbitMQ面试题
- 如何搭建一个拖垮公司的技术架构?
- Yii2中ElasticSearch的使用示例
热门文章
- 通过Google API客户端访问Google Play帐户报告PHP库
- PHP执行文件的压缩和解压缩方法
- 消息中间件MQ与RabbitMQ面试题
- 如何搭建一个拖垮公司的技术架构?
- Yii2中ElasticSearch的使用示例
最新文章
- 通过Google API客户端访问Google Play帐户报告PHP库
- PHP执行文件的压缩和解压缩方法
- 消息中间件MQ与RabbitMQ面试题
- 如何搭建一个拖垮公司的技术架构?
- Yii2中ElasticSearch的使用示例

