支付宝安全云检测alipay.security.risk.detect的简易的类API
- 9043
- 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的使用示例