第一步、抖音小程序发起支付
前端提交订单数据到后端接口,然后使用 tt.pay发起支付
请求参数
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
order_id | string | 是 | 担保交易服务端订单号 |
order_token | string | 是 | 担保交易订单号 token |
javascript
methods: {
requestPayment() {
tt.showLoading();
getDeviceId().then(deviceId => {
tt.request({
url: 'https://xxx.comm',
method: 'POST',
header: {
'Content-Type': 'application/json',
'token': '75dda91d-cb3d-4126-8f63-decee26e9ada'
},
data: {
amount: 1,
device_id: deviceId ,
sid: 8 ,
uid: 1572 ,
pricebuy: 1 ,
lx: 2 ,
priced: 1 ,
sum: 1 ,
buytype: '抖音' ,
},
success: (res) => {
console.log('orderInfo是:', res.data.data);
console.log('order_id:', res.data.data.order_id);
console.log('order_id:', res.data.data.order_token);
tt.pay({
orderInfo: {
order_id: res.data.data.order_id,
order_token:res.data.data.order_token
},
service: 5,
success(res) {
if (res.code == 0) {
// 支付成功处理逻辑,只有res.code=0时,才表示支付成功
// 但是最终状态要以商户后端结果为准
}
},
fail(res) {
// 调起收银台失败处理逻辑
},
});
tt.hideLoading();
}
});
});
}
}
第二步、后端请求抖音预支付接口
1.使用预下单接口
javascript
//amount金额 subject标题 body详情 out_trade_no订单号 notify_url回调地址
public function pay($amount,$subject,$body,$out_trade_no,$notify_url)
{
$site=config('site');
if($amount<=0){
$this->error(__('金额不对'));
}
$amount=$amount*100;
$url = 'https://developer.toutiao.com/api/apps/ecpay/v1/create_order';
$data = [
"app_id" => $site['douyin']['appid'],
"out_order_no" =>$out_trade_no,
"total_amount" => $amount,
"subject" => $subject,
"body" => $body,
"valid_time" => 180,
"cp_extra" =>$subject,
"notify_url" => $notify_url
];
$data['sign']= dysign($data,$site['douyin']['salt']);
$res= jsonPost($url,$data);
$res=json_decode($res,true);
if(!is_array($res)){
$this->error($res);
}
if($res['err_no']!=0){
$this->error($res['err_tips']);
}
$payData=$res['data'];
$this->success('订单提交成功 正在跳转支付',$payData);
}
2.支付签名
javascript
//支付签名
function sign($map,$salt) {
$rList = [];
foreach($map as $k =>$v) {
if ($k == "other_settle_params" || $k == "app_id" || $k == "sign" || $k == "thirdparty_id")
continue;
$value = trim(strval($v));
if (is_array($v)) {
$value = arrayToStr($v);
}
$len = strlen($value);
if ($len > 1 && substr($value, 0,1)=="\"" && substr($value, $len-1)=="\"")
$value = substr($value,1, $len-1);
$value = trim($value);
if ($value == "" || $value == "null")
continue;
$rList[] = $value;
}
$rList[] =$salt;
sort($rList, SORT_STRING);
return md5(implode('&', $rList));
}
3.http请求
javascript
function jsonPost($url, $postData, $customHeaders = []) {
// 初始化curl
$ch = curl_init($url);
// 设置curl选项
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 注意:不推荐在生产环境中禁用SSL验证
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回结果而不是直接输出
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向
curl_setopt($ch, CURLOPT_POST, true); // 发送POST请求
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData)); // JSON格式数据
// 设置HTTP头
curl_setopt($ch, CURLOPT_HTTPHEADER, $customHeaders);
// 执行请求
$response = curl_exec($ch);
// 检查是否有错误发生
if (curl_errno($ch)) {
$error = 'Curl error: ' . curl_error($ch);
curl_close($ch); // 关闭curl资源
return $error; // 返回错误信息
}
curl_close($ch); // 关闭curl资源
// 直接返回原始响应,不进行json_decode
return $response;
}
第三步回调处理
javascript
public function notify(){
$post = file_get_contents('php://input');
$post=json_decode($post,true);
$token='token';//抖音后台配置的token
$post['token']=$token;
$sign=$this->callbackSign($post);
if($sign!=$post['msg_signature']){
echo "签名失败";
}
$return=json_encode(["err_no"=>0,"err_tips"=>'success']);
echo $return;exit;
}
回调签名
javascript
public function callbackSign(array $params) {
$data = [
$params['timestamp'],
(string) $params['nonce'],
(string) $params['msg'],
(string) $params['token'],
];
sort($data, SORT_STRING);
return hash('sha1', join('', $data));
}