此方式与普通的托管集成方式付款的主要区别:
(1)请求的url不同
(2)提交form时,需要增加参数:payment_method (取值:card / echeck / paypal)
一、准备信息
1.merchantID:商家ID,商户号,组织ID
2.Profile ID:Profile文件的ID
3.Profile Access Key:Profile 的访问密钥
4.Profile Secret Key:Profile的密钥
5.url:
(1)沙盒(测试)环境url:
https://testsecureacceptance.cybersource.com/silent/embedded/pay
或者
https://testsecureacceptance.cybersource.com/silent/pay
(2)正式环境url:
https://secureacceptance.cybersource.com/silent/embedded/pay
或者
https://secureacceptance.cybersource.com/silent/pay
silent/embedded/pay:Iframe Transaction Endpoints (不跳转到第三方页面,成功/失败,没有取消)。
silent/pay:Process Transaction Endpoints(不跳转到第三方页面,成功/失败,没有取消)。
二、获取需要提交给CyberSource的表单参数 --- 动态form所需要的参数
public function getCheckoutUrl()
{
// 卡信息
$card_type =!empty($this->customParams['paymentParams']['card_type']) ?$this->customParams['paymentParams']['card_type'] : '';
$card_number =!empty($this->customParams['paymentParams']['card_number']) ?$this->customParams['paymentParams']['card_number'] : '';
$card_expiry_date =!empty($this->customParams['paymentParams']['card_expiry_date']) ?$this->customParams['paymentParams']['card_expiry_date'] : '';
$card_cvn =!empty($this->customParams['paymentParams']['card_cvn']) ?$this->customParams['paymentParams']['card_cvn'] : '';
//需要签名的字段(用','隔开)
$signed_field_names = 'access_key,profile_id,transaction_uuid,signed_field_names,unsigned_field_names,'.
'signed_date_time,locale,transaction_type,reference_number,amount,'.
'currency,bill_to_forename,bill_to_surname,bill_to_address_line1,'.//bill_to_address_line2,'.
'bill_to_address_city,bill_to_address_country,bill_to_address_postal_code,bill_to_email,'.
'bill_to_phone,'.//ship_to_forename,ship_to_surname,ship_to_address_line1,ship_to_address_line2,'.
//'ship_to_address_city,ship_to_address_country,ship_to_address_state,ship_to_address_postal_code,ship_to_phone,'.
'override_custom_cancel_page,override_custom_receipt_page,'.
'card_type,card_number,card_expiry_date,card_cvn,payment_method'; // payment_method:silent/pay,silent/embedded/pay追加字段
//第三方支付页面的语言:en-us,zh-hk,zh-cn。英文,香港繁体中文,简体中文
$locale = ‘’;
//签名的时间,要用比北京时间小8小时的时间
$signed_date_time = gmdate("Y-m-d\TH:i:s\Z");
//$signed_date_time = date('Y-m-d') . 'T' . date('H:i:s') . 'Z';
//$signed_date_time = gmdate("Y-m-d\TH:i:s\Z", mktime() + 8 *3600);
//$signed_date_time = date("Y-m-d\TH:i:s\Z", time() - 8 *3600);
// 参数数组
$params = [
'access_key' => ‘’, // Profile的访问密钥,Profile Access Key
'profile_id' => ‘’, //Profile文件的ID,Profile ID
//唯一的商人生成的标识符。为每个事务包含access_key字段。此标识符对于每个事务都必须是唯一的。此字段用于检查重复记录索引尝试。
'transaction_uuid' => uniqid(), //先使用 uniqid() 生成,进行请求;回调时,保存 返回值(交易ID)
//由服务器签名的以逗号分隔的响应数据列表。此列表中的所有字段都应该用于生成一个签名,然后可以将其与要进行ve的响应签名进行比较 释放响应。
'signed_field_names' => $signed_field_names,
'unsigned_field_names' => '',
//由服务器生成签名的日期和时间。格式: yyyy-MM-DDThh: mm: ssZ例子22日Z等于2020年8月11日22:47:57(下午10:47:57)。
// T的分离 具体的日期和时间。Z表示UTC。(小8小时)
'signed_date_time' => $signed_date_time,
//表示对于面向客户的内容所要使用的语言。
'locale' => $locale,
//事务处理的类型。可能值:
// authorization
// authorization,create_payment_token
// authorization,update_payment_token
// sale
// sale,create_payment_token
// sale,update_payment_token
// create_payment_token
// update_payment_token
// 只有一个是 支持签证点击支付交易 的授权和销售。
'transaction_type' => 'authorization', // sale
//每个交易的唯一的商家生成的订单参考或跟踪编号。(自己平台的订单编号)
'reference_number' => ‘’,
//该订单的总额。必须大于或等于零,并且必须等于包括税额在内的每个行项目的总额。
'amount' => ‘’, //付款金额
//货币类型(要注意类型!!!)
'currency' => ‘USD’ //测试环境,用USD;正式环境,可以换成动态的货币类型,
//客户的名字。此名称必须与板卡上的名称相同。
'bill_to_forename' => ‘’,
//客户姓氏。此名称必须与板卡上的名称相同。*
'bill_to_surname' => ‘’,
//账单地址的第一行。*
//在JCN网关上,当授权或销售请求包括创建_支付_令牌或决策管理器时,则需要此字段。
//这个字段是可选的,当重新选择 在不创建支付凭证或决策经理的情况下请求授权或销售。
'bill_to_address_line1' => ‘’,
// 'bill_to_address_line2' => '',
//账单地址中的城市。*
'bill_to_address_city' => ‘’,
//账单地址的国家代码 *(要用代码!!!)
'bill_to_address_country' => ‘’,
//在账单地址中的州或省。包含两个字符的ISO州代码和省代码。这个字段将返回给美国和加拿大。
// 'bill_to_address_state' =>'address state',
//帐单地址的邮政编码。
'bill_to_address_postal_code' => '', //默认可以用000000
//客户的电子邮件地址,包括完整的域名。*
'bill_to_email' => ‘’,
//客户电话号码。网络源建议您,如果订单来自美国以外的地区,则包括国家代码。
//请参见配置计费信息字段。此字段对于信用卡支付是可选的。
//对于电子邮件检查支付,如果需要此字段 你的处理器是网络源ACH服务或远程检查
'bill_to_phone' => ‘’,
//客户的公司名称。(暂时不用)
//'bill_to_company_name' => '',
//客户的名字。此名称必须与板卡上的名称相同。
// 'ship_to_forename' => ‘’,
//客户姓氏。此名称必须与板卡上的名称相同。
// 'ship_to_surname' => ‘’,
//接收该产品的公司的名称。(暂时不用)
//'ship_to_company_name' => '',
//第一行的航运地址。
// 'ship_to_address_line1' => '', //默认可以用'default'
//第二行航运地址。
// 'ship_to_address_line2' => '', //默认可以用'default'
//城市的运输地址
// 'ship_to_address_city' => '',
//运输地址的国家代码
// 'ship_to_address_country' => ‘’,
//运输地址的州或省。对于美国和加拿大,请使用标准的州、省和地区代码。如果运输地址是美国或加拿大,则需要此字段。
// 'ship_to_address_state' =>'default',
//运输地址的邮政编码。如果账单地址国家为美国或加拿大,则需要此字段。
// 'ship_to_address_postal_code' =>'default', //默认可以用000000
//送货地址的电话号码。
// 'ship_to_phone' => ‘’,
//运输目的地。例如:商业、住宅、商店
//'ship_to_type' => '', //留空/不传/给个默认值
//该产品的运输方法。可能值:
// sameday:快递或当日服务
// oneday:次日或通宵服务
// twoday:为期两天的服务
// threeday:三天服务
// lowcost:最低成本服务
// pickup:商店皮卡
// other:其他运输方式
// none:无运输方式
//'shipping_method' => '', //留空/不传/给个默认值
//取消url(取消后,可以重新付款)
'override_custom_cancel_page' => ‘’,
//支付回调url(同步回调)
'override_custom_receipt_page' => ‘’,
//预授权(钱没有真正到商家中,退款时,会灵活一些):0: Preauthorization
//最终授权:1: Final authorization
// 'auth_indicator' => '1',
// AUTOCAPTURE:自动捕获,是不是不用再请求 rest api 的 /v1/payments/{id}/captures接口??????
// STANDARDCAPTURE:标准捕获
// verbal:强制捕获
// 'auth_type' => 'AUTOCAPTURE'
// 卡信息
'card_type' => $card_type,
'card_number' => $card_number,
'card_expiry_date' =>$card_expiry_date,
'card_cvn' => $card_cvn,
// card, echeck, paypal
'payment_method' => 'card', // payment_method:silent/pay,silent/embedded/pay 追加字段
];
//参数签名
$params['signature'] = $this->sign($params);
//保存请求的参数
……
//返回form参数数组(k=v,kv形式)
return $params;
}
三、将返回的form参数数组,渲染到 隐藏的动态表单中,表单自动提交给CyberSource --- 动态form。也可以通过静态form,填写信息,然后手动点击提交。
//$p:返回的form参数数组
//action中,填写请求的CyberSource的url
public function buildOnlinePaymentSubmitForm($p) {
$params = $p;
$html = '<form id="cybersource-payment-form" action="url的地址(测试/正式)" method="post" style="display:none;">';
foreach ($params as $key => $value) {
$html .= '<div class="form-group">
<label>' . $key . '</label>
<input class="form-control" type="text" name="' . $key . '" value="' . $value . '" />
</div>
';
}
$html .= '
<button type="submit">GO!</button>
</form>
';
return $html;
}
// 表单自动提交给CyberSource
$('#cybersource-payment-form')[0].submit();
四、第二步中,涉及到的签名方法
//根据 Profile Secret Key,对参数字符串进行签名(加密)-托管集成方式
//$params:form表单的参数(主要是提交给支付那边的参数)
function sign($params) {
return $this->signData($this->buildDataToSign($params), 'Profile Secret Key的值');
}
//根据 Profile Secret Key,对数据进行加密-托管集成方式
//$data:form表单的参数(主要是提交给支付那边的参数)
//$profileSecretKey:profile secret key密钥
function signData($data, $profileSecretKey) {
return base64_encode(hash_hmac(‘sha256’, $data, $profileSecretKey, true));
}
// 构建需要加密的字符串-托管集成方式
// $params:form表单的参数(主要是提交给支付那边的参数)
function buildDataToSign($params) {
$signedFieldNames =explode(",", $params["signed_field_names"]);
foreach ($signedFieldNames as $field) {
$dataToSign[] = $field ."=" . $params[$field];
}
return$this->commaSeparate($dataToSign);
}
// 用',',将kv数组,连接成字符串-托管集成方式
// $dataToSign:k=v形式的字符串数组
function commaSeparate($dataToSign) {
return implode(",", $dataToSign);
}
五、第二步中,涉及到的 支付回调url(CyberSource回调请求,并传递参数)
publicfunction verifyReturn()
{
//支付回调 请求的参数
$params = [];
foreach($_REQUEST as $name => $value) {
$params[$name] = $value;
}
$params['requestId'] = $_REQUEST['transaction_id'];
$responseBody = @json_encode($params);
//支付响应的决策类型:ACCEPT;DECLINE;REVIEW;ERROR;CANCEL
//$type = 'CYBERSOURCE_' . $params['decision'] . '_NOTIFY';
//记录请求日志
……
//验证返回的 签名 和 状态码
if (strcmp($params["signature"], $this->sign($params)) == 0 && $params['reason_code'] == '100') {
//付款成功,处理逻辑
……
return true;
}
//付款失败,处理逻辑
return false;
}
六、第二步中,涉及到的 取消url
自定义方法,实现处理逻辑即可,一般是展示付款失败的页面。