首页 » SEO优化 » phpcreatelinkstring技巧_支付开拓填坑记之支付宝

phpcreatelinkstring技巧_支付开拓填坑记之支付宝

访客 2024-11-20 0

扫一扫用手机浏览

文章目录 [+]

支付宝在所有支付办法中最好开拓的了,由于文档比较清晰,而且开拓起来也比较大略。
因此,支付宝的坑是相对较少的。

APP支付

APP支付步骤为:

phpcreatelinkstring技巧_支付开拓填坑记之支付宝

获取支付宝的配置信息。
天生商家订单信息。
根据订单信息天生待校验数据。
天生要求给支付宝的加密字符串。
将待校验数据和加密字符串拼接,返回给APP。
APP将得到的数据要求支付宝客户端进行支付。

由于APP支付是由APP去调起支付宝支付,以是做事端须要做的事情便是将要求参数封装好之后返回APP即可。

phpcreatelinkstring技巧_支付开拓填坑记之支付宝
(图片来自网络侵删)
获取支付宝的配置信息。
支付时须要的配置信息有:key: 交易安全校验码。
app_id:支付宝分配给开拓者的运用ID。
天生商家订单信息。
这个步骤由商家自行天生。
支付宝那边只须要知道的订单信息为:subject: 必填。
商品的标题/交易标题/订单标题/订单关键字等。
total_amount: 必填。
订单价格。
out_trade_no: 必填。
商户网站唯一订单号。
body: 非必填。
交易的详细描述信息。
根据订单信息天生待校验数据。
APP支付的详细要求参数: 点击查看

天生要求给支付宝的加密字符串。

$sign = $alipaySubmit->buildRequestParaForApp($para_token);个中, buildRequestParaForApp 的实现为:对待署名参数数组排序

/ 对数组排序 @param $para 排序前的数组 return 排序后的数组 /function argSort($para) { ksort($para); reset($para); return $para;}

天生署名结果(阿里推举的是RSA2的署名办法,这里项目用的是RSA)

/ RSA署名 @param $data 待署名数据 @param $private_key_path 商户私钥文件路径 return 署名结果 /function rsaSign($data, $private_key_path) { $priKey = file_get_contents($private_key_path); $res = openssl_get_privatekey($priKey); openssl_sign($data, $sign, $res); openssl_free_key($res); //base64编码 $sign = base64_encode($sign); return $sign;}

将待校验数据和加密字符串拼接,返回给APP。

$url = \"大众\"大众;foreach ($para_token as $key => $value) { $url .= $key.\"大众=\公众.urlencode($value).\公众&\"大众;}return $url.\"大众sign=\"大众.urlencode($sign);APP将得到的数据要求支付宝客户端进行支付。
APP端将拼接好的字符串拿去要求支付宝客户端即可调起支付宝进行支付。
拼接好的字符串大致如下图所示:网页版支付

网页版支付步骤为:

设置支付宝的配置信息。
向支付宝申请新订单,获取支付token。
携带token进行订单支付。

网页版的支付宝支付相对付APP调起支付宝要繁芜,由于网页支付时,须要多次要求支付宝做事器获取支付的必要参数。

设置支付宝配置信息。

/调用授权接口alipay.wap.trade.create.direct获取授权码token/ //返回格式 private $format = \公众\公众; //必填,不须要修正 //版本 private $v = \"大众\"大众; //必填,不须要修正 //要求号 private $req_id = \公众\"大众; //必填,须担保每次要求都是唯一 //req_data详细信息 //做事器异步关照页面路径 private $notify_url = \公众\"大众; //需http://格式的完全路径,不许可加?id=123这类自定义参数 //页面跳转同步关照页面路径 private $call_back_url = \公众\公众; //需http://格式的完全路径,不许可加?id=123这类自定义参数 //卖家支付宝账户 private $seller_email = \公众\"大众; //必填 //商户订单号 private $out_trade_no = \公众\公众; //商户网站订单系统中唯一订单号,必填 //订单名称 private $subject = \"大众\公众; //必填 //付款金额 private $total_fee = \"大众\"大众; //必填 //要求业务参数详细 private $req_data = \公众\"大众; //必填 //配置 private $alipay_config = array(); //

向支付宝申请新订单,并获取订单的token。

1.要求token的service为: alipay.wap.trade.create.direct。

2.布局参数:

$para_token = array( \"大众service\公众 => \"大众alipay.wap.trade.create.direct\公众, // 互助者身份(partner ID) \公众partner\公众 => trim($this->alipay_config['partner']), // APP利用的是RSA,网页版利用的是MD5 \"大众sec_id\"大众 => trim($this->alipay_config['sign_type']), // 返回的数据格式 \"大众format\"大众 => $this->format, // 版本号? \公众v\"大众 => $this->v, // 唯一的要求号 \"大众req_id\"大众 => $this->req_id, // 要求参数 \"大众req_data\"大众 => $req_data, // 字符集,一样平常为utf8即可。
\"大众_input_charset\"大众 => trim(strtolower($this->alipay_config['input_charset'])));

将布局好的要求参数,进行处理,字典排序,拼接字符串,署名:

$para_filter = paraFilter($para_temp);$para_sort = argSort($para_filter);$mysign = $this->buildRequestMysign($para_sort);//署名结果与署名办法加入要求提交参数组中$para_sort['sign'] = $mysign;return $para_sort;

处理:过滤值为空的数据,过滤署名类型和署名。

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;}

署名:

/ 天生署名结果 @param $para_sort 已排序要署名的数组 return 署名结果字符串 /function buildRequestMysign($para_sort) { //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 $prestr = createLinkstring($para_sort); $mysign = \"大众\"大众; switch (strtoupper(trim($this->alipay_config['sign_type']))) { case \"大众MD5\"大众 : // MD5直接将密钥拼接在字符串后面再进行MD5加密。
$mysign = md5Sign($prestr, $this->alipay_config['key']); break; case \"大众RSA\"大众 : // RSA则是先读取商户的私钥,再用该密钥对字符串进行加密。
$mysign = rsaSign($prestr, $this->alipay_config['private_key_path']); break; case \公众0001\"大众 : $mysign = rsaSign($prestr, $this->alipay_config['private_key_path']); break; default : $mysign = \公众\"大众; } return $mysign;}用布局好的参数要求支付宝后台申请新订单:把稳:要求时,必须带上SSL证书。

$sResult = getHttpResponsePOST($this->alipay_gateway_new, $this->alipay_config['cacert'],$request_data,trim(strtolower($this->alipay_config['input_charset'])));

要求函数的实现:

/ 远程获取数据,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;}

处理支付宝返回的数据,并获取token。

//URLDECODE返回的信息$html_text = urldecode($html_text);//解析远程仿照提交后返回的信息$para_html_text = parseResponse($html_text);//获取request_token$request_token = $para_html_text['request_token'];parseResponse函数的实现:

/ 解析远程仿照提交后返回的信息 @param $str_text 要解析的字符串 @return 解析结果 /function parseResponse($str_text) { //以“&”字符切割字符串 $para_split = explode('&',$str_text); //把切割后的字符串数组变成变量与数值组合的数组 foreach ($para_split as $item) { //得到第一个=字符的位置 $nPos = strpos($item,'='); //得到字符串长度 $nLen = strlen($item); //得到变量名 $key = substr($item,0,$nPos); //得到数值 $value = substr($item,$nPos+1,$nLen-$nPos-1); //放入数组中 $para_text[$key] = $value; } if( ! empty ($para_text['res_data'])) { //解析加密部分字符串 if($this->alipay_config['sign_type'] == '0001') { $para_text['res_data'] = rsaDecrypt($para_text['res_data'], $this->alipay_config['private_key_path']); } //token从res_data中解析出来(也便是说res_data中已经包含token的内容) $doc = new DOMDocument(); $doc->loadXML($para_text['res_data']); $para_text['request_token'] = $doc->getElementsByTagName( \"大众request_token\公众 )->item(0)->nodeValue; } return $para_text;}携带token进行订单支付。
成功要求token回来后,就可以向支付宝发出一次支付要求。
同样布局要求数据:

//业务详细只须要携带步骤2的token即可。
$req_data = '<auth_and_execute_req><request_token>' . $request_token . '</request_token></auth_and_execute_req>';//必填//布局要要求的参数数组,无需改动$parameter = array( \"大众service\"大众 => \公众alipay.wap.auth.authAndExecute\"大众, // 互助者身份(partner ID) \"大众partner\"大众 => trim($this->alipay_config['partner']), // 署名类型 \"大众sec_id\"大众 => trim($this->alipay_config['sign_type']), // 和步骤2同等 \"大众format\公众 => $this->format, \"大众v\公众 => $this->v, \"大众req_id\"大众 => $this->req_id, // 业务详细参数 \"大众req_data\"大众 => $req_data, // 字符集,一样平常为utf8. \"大众_input_charset\"大众 => trim(strtolower($this->alipay_config['input_charset'])));将这些参数,在页面中传送给支付宝即可发起一次支付要求。
在PHP 中的实现便是将这些参数,渲染至HTML中,再将HTML中的表单提交即可。
到此,网页版的支付宝支付完玉成部流程。
支付结果异步关照

在上面,我们看到有两个参数传给了支付宝:

call_back_url: 交易成功后,支付宝页面上“返回到商家页面”的地址(同步回调)notify_url: 交易状态变更后,支付宝关照网站的回调地址(异步关照)

对付手机网站支付产生的交易,支付宝会根据原始支付API中传入的异步关照地址notify_url,通过POST要求的形式将支付结果作为参数关照到商户系统。

对付App支付产生的交易,支付宝会根据原始支付API中传入的异步关照地址notify_url,通过POST要求的形式将支付结果作为参数关照到商户系统。

支付宝异步关照官方文档中写的比较清楚,什么时候出发关照,返回什么参数,把稳事变都有,开拓者可以根据自己的情形查看详细信息。

验签步骤可以移步至这里

这里就大略的用手上的项目举例解释,支付宝关照后,后台是如何进行验签和处理订单。

public function app_notifyOp(){ $payment_api = $this->_get_payment_api(); $payment_config = $this->_get_payment_config(); // 支付宝是用POST办法发送关照信息 $callback_info = $payment_api->getNotifyInfoApp($_POST); if($callback_info) { //验证成功 if ($callback_info['order_state']) { // 如果是支付成功则改变订单状态 $result = $this->_update_order($callback_info['out_trade_no'], $callback_info['trade_no']); }else{ // 如果是退款成功则修正退订的干系状态 $result = $this->_app_refund($callback_info['out_trade_no'], $callback_info['trade_no'], $callback_info['refund_fee']); } if($result['state']) { echo 'success';die; } } //验证失落败 echo \"大众fail\公众;die;}获取支付宝关照数据支付宝异步关照是POST要求,返回的数据构造如下:

{ \"大众total_amount\"大众: \公众31.00\"大众, \公众buyer_id\"大众: \"大众ID\"大众, \"大众trade_no\公众: \公众TRADE_NO\"大众, \"大众body\"大众: \"大众pay_sn:580546601841783375\"大众, \公众notify_time\"大众: \公众2017-04-27 09:50:59\"大众, \"大众subject\"大众: \公众580546601841783375\"大众, \"大众sign_type\公众: \公众RSA\"大众, \公众buyer_logon_id\公众: \"大众ID\"大众, \"大众auth_app_id\"大众: \"大众APPID\公众, \"大众charset\公众: \公众utf-8\公众, \公众notify_type\"大众: \"大众trade_status_sync\"大众, \"大众invoice_amount\"大众: \公众31.00\"大众, \公众out_trade_no\公众: \"大众580546601841783375_r\"大众, \"大众trade_status\"大众: \"大众TRADE_SUCCESS\"大众, \"大众gmt_payment\"大众: \"大众2017-04-27 09:50:58\公众, \公众version\公众: \"大众1.0\"大众, \"大众point_amount\公众: \公众0.00\"大众, \公众sign\"大众: \公众SIGNATURE\"大众, \"大众gmt_create\"大众: \"大众2017-04-27 09:50:58\"大众, \公众buyer_pay_amount\"大众: \"大众31.00\"大众, \"大众receipt_amount\"大众: \"大众31.00\"大众, \公众fund_bill_list\"大众: \"大众[{\公众amount\"大众:\"大众31.00\"大众,\"大众fundChannel\公众:\公众ALIPAYACCOUNT\公众}]\"大众, \公众app_id\公众: \公众APPID\公众, \公众seller_id\"大众: \公众SELLERID\公众, \"大众notify_id\公众: \"大众8414394a1190f25edbbec9ba4b98642mem\"大众, \公众seller_email\公众: \公众YOUR_ALIPAY_ACCOUNT\"大众}验签数据验签须要支付宝的公钥验签和署名的流程是一样的,都是将所有除了 sign 以外的参数,进行字典排序,并以 key=value 的形式以 & 符号拼成字符串,再利用密钥进行署名,将得到的署名与支付宝返回的署名进行比拟,完成验签过程。

function getSignVeryfy($para_temp, $sign) { //撤除待署名参数数组中的空值和署名参数 $para = paraFilter($para_temp); //对待署名参数数组排序 $para = argSort($para); //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串 $prestr = createLinkstring($para); $prestr = htmlspecialchars_decode($prestr); $isSgin = false; switch (strtoupper(trim($this->alipay_config['sign_type']))) { case \"大众MD5\"大众 : $isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']); break; case \公众RSA\公众 : $isSgin = rsaVerify($prestr, trim($this->alipay_config['ali_public_key_path']), $sign); break; case \公众0001\公众 : $isSgin = rsaVerify($prestr, trim($this->alipay_config['ali_public_key_path']), $sign); break; default : $isSgin = false; } logResult($log); return $isSgin;}但是这里有个坑,便是返回数据中的 fund_bill_list 是经由html转义的(如例子中的数据: [{\"大众amount\公众:\公众31.00\"大众,\公众fundChannel\"大众:\"大众ALIPAYACCOUNT\"大众}]),如果直策应用该参数进行署名,则会导致署名失落败。
这里就须要将字符串转义了: [{\"大众amount\"大众:\公众31.00\公众,\公众fundChannel\"大众:\"大众ALIPAYACCOUNT\"大众}] ,用转义后的参数值进行署名,通过校验。
变动订单状态验签完毕后,后台就可以根据实际情形进行订单状态的变动。
希望本文能帮助到您!

点赞+转发,让更多的人也能看到这篇内容(收藏不点赞,都是耍泼皮-_-)

关注 {我},享受文章首发体验!

每周重点占领一个前端技能难点。
更多精彩前端内容私信 我 回答“教程”

标签:

相关文章

介绍百度网盘,云端存储时代的创新先锋

随着互联网技术的飞速发展,云计算已经成为现代生活不可或缺的一部分。而在这其中,百度网盘作为国内领先的云存储服务提供商,以其卓越的性...

SEO优化 2025-01-03 阅读1 评论0

介绍监控屏蔽技术,守护个人隐私的利器

随着科技的发展,监控设备已经深入到我们生活的方方面面。在享受便利的隐私安全问题也日益凸显。如何有效屏蔽监控,保护个人隐私,成为人们...

SEO优化 2025-01-03 阅读1 评论0

介绍番号观看方法,轻松驾驭影视世界

随着互联网的普及,网络影视资源日益丰富,番号作为影视作品的标识码,已经成为广大观众了解、搜索和观看影视作品的重要途径。如何正确地使...

SEO优化 2025-01-03 阅读1 评论0

介绍盗微信号黑幕,网络安全的严峻挑战

在数字化时代,微信已成为人们生活中不可或缺的通讯工具。随着微信用户数量的激增,盗微信号的事件也日益增多。本文将深入剖析盗微信号的方...

SEO优化 2025-01-03 阅读1 评论0