PHP项目如何对接抖音支付接口?

wen PHP项目 17

本文目录导读:

PHP项目如何对接抖音支付接口?

  1. 对接前的必备准备
  2. 核心API对接流程(以小程序为例)
  3. PHP核心代码示例
  4. 常见关键问题
  5. 补充:PC/Web网站对接

在PHP项目中对接抖音支付(现在通常指抖音支付抖音电商的支付能力),主要场景有两种:

  1. 抖音小程序/小游戏:用户在小程序内下单,调用抖音支付。
  2. 抖音开放平台(App/网站):用户通过抖音App授权或扫码,在第三方App或网站完成支付。

由于抖音支付接口文档更新较快,以下提供一套核心的通用对接逻辑和代码示例(基于官方标准API),建议以抖音开放平台的最新文档为准。


对接前的必备准备

  1. 注册开发者:在抖音开放平台注册成为开发者,创建应用(小程序/移动应用/网站应用)。
  2. 申请支付权限:在应用功能中申请“支付能力”,并完成签约(通常需要个体工商户或企业资质)。
  3. 获取关键参数
    • AppID(应用唯一标识)
    • AppSecret(签名密钥)
    • 商户号(抖音支付分配的商户号)
    • 支付密钥(MD5 Key 或 RSA私钥)
    • 回调地址(Notify URL):用于接收支付结果通知。

核心API对接流程(以小程序为例)

典型的支付交互流程如下:

  1. 用户选择商品 -> 前端(小程序)向你的后端PHP服务器发起“统一下单”请求。
  2. PHP后端 调用抖音支付API https://developer.toutiao.com/api/apps/ecpay/v1/create_order 获取预支付ID。
  3. PHP后端 根据返回的 prepay_id 进行二次签名,返回给前端调起支付所需参数(order_id, sign, timestamp等)。
  4. 前端 通过 tt.pay(小程序)或 openURL(网页)调起抖音支付。
  5. 用户支付完成 -> 抖音服务器异步通知你的PHP回调地址(Notify URL)。
  6. PHP后端 验证签名、处理订单状态,并返回成功应答给抖音。

PHP核心代码示例

以下使用 MD5 签名算法(抖音也支持HMAC-SHA256,请根据文档选择)。

统一下单接口 (PHP)

<?php
class DouyinPay
{
    private $appId = '你的AppID';
    private $merchantId = '你的商户号'; // 抖音支付分配的商户号
    private $salt = '你的支付密钥(Token/Salt)'; // 用于签名
    /**
     * 生成统一下单参数并请求抖音
     * @param string $outOrderNo 商户订单号
     * @param int $totalAmount 支付金额(单位:分)
     * @param string $subject 商品描述
     * @param string $callbackUrl 异步通知地址
     * @return array 包含 prepay_id 和调起支付所需参数
     */
    public function createOrder($outOrderNo, $totalAmount, $subject, $callbackUrl)
    {
        $url = 'https://developer.toutiao.com/api/apps/ecpay/v1/create_order';
        // 1. 构建请求参数
        $params = [
            'app_id'        => $this->appId,
            'out_order_no'  => $outOrderNo,
            'total_amount'  => $totalAmount, // 注意:抖音接口金额单位是分
            'subject'       => $subject,
            'body'          => $subject,
            'valid_time'    => 300, // 订单有效时间,单位秒
            'notify_url'    => $callbackUrl,
            'pay_type'      => 'ALIPAY, WECHAT', // 允许的支付方式,可选
        ];
        // 2. 生成签名(关键步骤)
        // 抖音签名规则:将所有参数(不包括 sign)按 key 升序排序,拼接成 key=value 形式,最后连接 salt
        ksort($params);
        $signStr = '';
        foreach ($params as $key => $value) {
            if ($value !== '' && $key !== 'sign') {
                $signStr .= $key . '=' . $value . '&';
            }
        }
        $signStr .= 'salt=' . $this->salt;
        // 计算 MD5 签名,并转大写
        $params['sign'] = strtoupper(md5($signStr));
        // 3. 发起 POST 请求(使用 https)
        $result = $this->httpPost($url, $params);
        // 4. 解析响应
        $data = json_decode($result, true);
        if ($data['err_no'] == 0 && $data['err_tips'] == 'success') {
            $prepayId = $data['data']['order_id']; // 抖音返回的 prepay_id
            // 返回给前端调起支付所需的参数
            return $this->getPayParams($prepayId);
        } else {
            // 记录错误日志
            return ['error' => $data['err_tips']];
        }
    }
    /**
     * 构造前端调起支付所需的签名参数
     * @param string $orderId 抖音返回的 prepay_id
     * @return array
     */
    private function getPayParams($orderId)
    {
        $params = [
            'app_id'       => $this->appId,
            'sign_type'    => 'MD5',
            'order_id'     => $orderId,
            'timestamp'    => time(),
        ];
        // 同样需要签名
        ksort($params);
        $signStr = '';
        foreach ($params as $key => $value) {
            if ($value !== '' && $key !== 'other_settle_params') {
                $signStr .= $key . '=' . $value . '&';
            }
        }
        $signStr .= 'salt=' . $this->salt;
        $params['sign'] = strtoupper(md5($signStr));
        return $params;
    }
    // HTTP 请求函数(省略 curl 实现)
    private function httpPost($url, $data) {
        // 使用 cURL 实现 POST 请求
    }
}
// 使用示例
$pay = new DouyinPay();
$params = $pay->createOrder('ORDER123456', 100, '测试商品', 'https://yourdomain.com/pay/notify');
echo json_encode($params);

异步通知处理 (Notify URL)

抖音在用户支付成功后,会发送 POST 请求到你填写的 notify_url你的服务器必须正确响应并返回 {"status": "success"}

<?php
// notify.php
// 1. 获取抖音 POST 过来的 JSON 数据
$rawData = file_get_contents('php://input');
$data = json_decode($rawData, true);
// 2. 商户验证签名 (这里用同样的 salt 计算)
$salt = '你的支付密钥';
// 抖音的回调参数通常包含:app_id, order_id, out_order_no, total_amount, ... , sign
$sign = $data['sign'];
unset($data['sign']); // 去除 sign 字段用于计算签名
ksort($data);
$signStr = '';
foreach ($data as $key => $value) {
    if ($value !== '' && $key !== 'other_settle_params') {
        $signStr .= $key . '=' . $value . '&';
    }
}
$signStr .= 'salt=' . $salt;
$calculatedSign = strtoupper(md5($signStr));
// 3. 验证签名
if ($sign !== $calculatedSign) {
    // 签名错误,可能是伪造通知
    http_response_code(400);
    echo json_encode(['status' => 'fail']);
    exit;
}
// 4. 验证业务数据
$orderNo = $data['out_order_no']; // 你的商户订单号
$amount = $data['total_amount'];  // 支付金额(分)
$orderId = $data['order_id'];     // 抖音支付订单号
// 5. 处理业务逻辑(更新订单状态、加余额等)
// 注意:需要避免重复通知处理(幂等性)
$order = getOrderByOutNo($orderNo);
if ($order['status'] == 'unpaid' && $order['amount'] == $amount) {
    updateOrderStatus($orderNo, 'paid');
    // 记录支付成功日志
}
// 6. 必须返回 success 给抖音
echo json_encode(['status' => 'success']);
?>

常见关键问题

签名算法

  • 抖音签名规则:将所有非空参数(keyvalue)按 key ASCII 升序拼接,格式为 key1=value1&key2=value2...&salt=你的Salt
  • 特别注意app_secretsalt 的区别,通常在生成签名时使用 salt(商户密钥),而 app_secret 用于接口调用鉴权(Token获取)。一定要仔细看文档的“签名”部分

金额单位

  • 抖音支付:通常以 为单位(如 100 表示 1 元)。
  • 其他接口:有些平台接口(如查询)可能以元为单位,务必根据文档区分。

安全注意事项

  • 密钥不要硬编码:建议存储环境变量或配置文件中,不要出现在代码库。
  • 验证回调IP(可选):抖音支付通常有固定的回调IP范围,可以验证来源。
  • 防止重放攻击:在通知处理中加入订单状态检查,确保只更新一次。

调试工具

  • 抖音开放平台提供了接口调试工具,可以方便地模拟请求和验证签名。
  • 打开 沙箱模式(如果支持)进行测试。

补充:PC/Web网站对接

如果是PC网站,流程稍有不同:

  1. 你的后端调用 https://open.douyin.com/api/ecpay/b2c/orders/create(或类似接口)获取 order_id
  2. 前端通过生成一个 支付链接 或通过 抖音扫码 完成支付。
  3. 用户扫码/点击后,跳转到抖音App或抖音收银台完成支付。
  4. 同样需要回调通知。

对接抖音支付的核心在于:

  1. 搞懂签名流程(排序 + 拼接 Salt + MD5)。
  2. 正确处理异步通知(验签 + 幂等性 + 返回 success)。
  3. 使用沙箱测试(先模拟,再上线)。

建议直接访问 抖音开放平台 -> 文档 -> 支付能力 获取最新版接口文档和SDK(官方有提供PHP SDK,推荐直接使用)。

抱歉,评论功能暂时关闭!