畅捷通 认证体系:appTicket + Token 双向认证流程详解

一、认证方式概述

畅捷通 T+ 开放平台采用自建应用认证方式,这是一种基于 appTicket 推送 + Token 签发的双向认证机制。

graph LR

二、认证流程全貌

sequenceDiagram

三、appTicket 接收与解密

3.1 推送机制

畅捷通平台每 10 分钟向配置的回调 URL 推送一次 appTicket,有效期为 30 分钟。推送格式为:

{
    "encryptMsg": "Base64编码的AES加密密文"
}

3.2 AES 解密实现

// sync_helper.php 核心解密逻辑
function decryptAppTicket($encryptMsg, $secretKey) {
    $decoded = base64_decode($encryptMsg);
  
    // AES-128-ECB 解密
    $decrypted = openssl_decrypt(
        $decoded,
        'AES-128-ECB',
        $secretKey,
        OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING
    );
  
    // 手动去除 PKCS5 填充
    $pad = ord($decrypted[strlen($decrypted) - 1]);
    $decrypted = substr($decrypted, 0, -$pad);
  
    // 解析 JSON
    $data = json_decode($decrypted, true);
    return $data['bizContent']['appTicket'];
}

3.3 多密钥兼容策略

实际部署中,可能存在更换 secretKey 的情况。系统采用多密钥尝试 + 双重解密模式的容错机制:

flowchart TD

3.4 resend 主动触发

当需要立即获取最新 appTicket 时,通过 resend 接口触发平台重新推送:

// resend_appTicket.php 核心逻辑
$url = 'https://openapi.chanjet.com/auth/appTicket/resend';
$body = json_encode([
    'appKey'    => $config['appKey'],
    'appSecret' => $config['appSecret'],
]);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => $body,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 30,
]);
$response = curl_exec($ch);
curl_close($ch);

四、Token 生成与刷新

4.1 generateToken 接口

POST https://openapi.chanjet.com/v1/common/auth/selfBuiltApp/generateToken
Content-Type: application/x-www-form-urlencoded

appKey={appKey}
&certificate={certificate}
&appTicket={appTicket}
&grantType=app_ticket

4.2 响应结构

{
    "success": true,
    "data": {
        "accessToken":  "eyJhbGc...",
        "refreshToken": "def502...",
        "expiresIn": 518400,
        "refreshExpiresIn": 2505600
    }
}

4.3 Token 生命周期管理

stateDiagram-v2

4.4 getValidToken() 实现要点

function getValidToken(&$config) {
    // 1. 检查 Token 是否存在且未过期
    $now = time();
    $tokenExpiry = $config['token_expiry'] ?? 0;
  
    if (!empty($config['openToken']) && $now < ($tokenExpiry - 600)) {
        return $config['openToken']; // Token 有效,直接返回
    }
  
    // 2. 如果 Token 存在且未完全过期,尝试 refreshToken
    if (!empty($config['refreshToken']) && $now < ($config['refresh_expiry'] ?? 0)) {
        $token = refreshToken($config);
        if ($token) return $token;
    }
  
    // 3. 走完整流程:resend → 解密 → generateToken
    resendAppTicket($config);
    sleep(2);
  
    $appTicket = getAppTicketFromFile();
    $tokenData = generateToken($config['appKey'], $config['certificate'], $appTicket);
  
    // 4. 持久化到 config.json
    $config['openToken']     = $tokenData['accessToken'];
    $config['refreshToken']  = $tokenData['refreshToken'];
    $config['token_expiry']  = time() + $tokenData['expiresIn'];
    $config['refresh_expiry'] = time() + $tokenData['refreshExpiresIn'];
    saveConfig($config);
  
    return $config['openToken'];
}

五、业务 API 调用的认证注入

每次调用畅捷通业务 API 时,需要在 Header 中携带三要素:

function callTplusApi($appKey, $appSecret, $openToken, $url, $body) {
    $headers = [
        "Content-Type: application/json",
        "appKey: {$appKey}",
        "appSecret: {$appSecret}",
        "openToken: {$openToken}",
    ];
  
    return callApi($url, json_encode($body), $headers);
}

六、安全机制总结

graph TD

凭据时效用途
certificate 长期有效 结合 appTicket 换取 Token
appTicket 30 分钟 一次性令牌,用于 generateToken
accessToken 6 天 日常 API 调用
refreshToken 29 天 刷新 accessToken(无需 appTicket)
posted @ 2026-06-19 16:01  chenheoa  阅读(0)  评论(0)    收藏  举报