因为项目需求,接触过几个国家第三方支付,所以说一下各个三方支付的类型及支付的流程【仅代表个人观点】。
下面以这四个国家个人接触的第三方支付为例:
- 国内的彩虹易支付
- 墨西哥的STP支付
- 美国的原子支付
- 印尼的TopPay支付
一:支付接入的大概流程:
- 用户选择套餐下单
- 本地生成订单
- 生成签名及参数
- 调用支付接口
- 回调
- 验签
- 验证订单
- 更改订单状态
- 用户支付成功相关操作
上述流程中,我认为最重要的两个环节就是签名和回调,下面单独说下这两个环节
二:调起支付-生成签名
签名成功的话,差不多能代表完成调起支付这个操作,对于不同的支付来说,签名规则各不相同不同。
上述四种支付大概是两种签名规则,都先是使用参数名ASCII 码从小到大排序,然后再使用MD5或者rsa加密**【如果你在接入支付的过程中遇到签名失败或者其它问题一定要及时的联系支付方】**
下面是分别是PHP的MD5签名加密处理和rsa签名加密
/**
* MD5-生产数据签名
* @param array $args 参数值
* @param string $key 加密秘钥
* @return string
*/
private function _makeOrderSign($args, $key) {
// 去除带有的签名字段
unset($args['sign']);
// ASCII 码排序
ksort($args);
// 待加密参数
$str = '';
foreach ($args as $key => $value) {
if(!$value) {
continue;
}
$str .= $key . '=' . $value;
$str .= '&';
}
return strtoupper(md5($str . 'key=' . $key));
}
/**
* ras-生产数据签名
* @param $args array 参数值
* @param $mchPrivateKey string rsa私钥
*
* @return string
*/
private function _makeOrderSign($args, $mchPrivateKey = '') {
// 去除带有的签名字段
unset($args['platSign']);
// ASCII 码排序
ksort($args);
$params_str = '';
foreach ($args as $key => $val) {
$params_str = $params_str . $val;
}
return $this->privateKeyEncrypt($params_str, $mchPrivateKey);
}
/**
* 使用商户私钥对拼接字符串 stringA 进行RSA加密
* @param $data string 待加密参数
* @param $mchPrivateKey string rsa私钥
*
* @return string
*/
public function privateKeyEncrypt($data, $mchPrivateKey)
{
$pivate_key = '-----BEGIN PRIVATE KEY-----'."\n".$mchPrivateKey."\n".'-----END PRIVATE KEY-----';
$pi_key = openssl_pkey_get_private($pivate_key);
$crypto = '';
foreach (str_split($data, 117) as $chunk) {
openssl_private_encrypt($chunk, $encryptData, $pi_key);
$crypto .= $encryptData;
}
return base64_encode($crypto);
}
三:支付回调:
支付方回调我们的接口时,一般会回传价格、内部订单号、外部订单号、支付状态等信息,这里我们会进一步对回传的参数进行验证,主要是下面三步:
- 回调验签 :这里的处理逻辑和上面生成签名一致,只不过要把回传的参数签名值去除后再生成签名验签
- 订单信息校验 :这里根据回传的内部订单号,去数据库里面查询此订单是否存在,及订单状态是否支付成功,如果订单不存在或订单状态为支付成功,这里我们就不继续向下处理。
- 检测回调订单状态,如果返回状态为支付失败,也不往下进行处理
三、各个支付的区别
- 国内的彩虹易支付:可能因为国内支付发展的比较快,就我个人而言,上面四个支付该支付的接入是最轻松的。按照文档参数要求,组装参数,以form表单的方式提交参数,然后就跳转到第三方支付的支付页面,用户进行支付,就完成了支付。
/**
* form表单提交参数
* @param $arr array 支付相关参数
* @param $actionUrl string 跳转支付接口
*
* @return string
*/
public function pay($arr, $actionUrl)
{
//循环拼接表单项
$formItemString = '' ;
foreach ( $arr as $key => $value ){
$formItemString .= "<input name='{$key}' type='text' value='{$value}' />";
}
//构建表单并跳转
$content = <<<EOF
<form style="display: none" name="submit_form" id="submit_form" action="{$actionUrl}"method="post">
{$formItemString}
</form>
<script type="text/javascript">
document.submit_form.submit();
</script>
EOF;
return $content;
}
- 美国的原子支付:原子支付的话稍微麻烦些,此支付的支付环境是,只要用户输入信用卡号 持卡人姓名MM/YY 和CVV 都是正确的 就不需要输入卡号密码,所以对于参数的要求比较严格,每次都需要填写十几个参数才能进行支付。用户输入参数这个页面需要自己开发,用户在这个页面输入完信息,直接调用支付接口,此处并不是调起支付, 上述信息输入正确就代表付款成功。
- 墨西哥的STP支付:这个支付和国内的支付有很大的区别,这个支付没有订单的概念,用户购买商品,跳转到我们自己开发的一个web页,这个页面再调用支付方的支付接口,获取接口返回的是一个code码,这个页面展示用户购买商品的金额和code码。用户复制code码,然后打开三方银行的APP,就会弹出支付页面,然后输入购买的商品金额,进行支付。这个就是支付的流程,在回调的是时候,我们再创建订单,然后通过code码和金额来确认订单,进行回调流程的处理。
- 印尼的TopPay支付:这个其实和彩虹易支付有些相似,这个是调用支付方的支付接口,如果成功的话,接口里面会返回一个支付链接,我们拿到这个链接之后再手动的向这个链接里面进行跳转。