Commit bdd6d174 authored by 刘小敏's avatar 刘小敏

fix(xhs): 改用静态凭证回传转化事件

parent dd5ce668
......@@ -5,13 +5,18 @@ namespace addons\shopro\service\xhs;
use app\admin\model\shopro\xhs\ConversionLog as ConversionLogModel;
/**
* 小红书聚光 Marketing API 转化回传服务
* 小红书聚光「种草直达」转化回传服务
*
* 负责调用小红书开放平台接口回传转化事件
* 包含 Token 管理、API 调用、重试逻辑
* 负责调用小红书转化回传 API 上报转化事件
*
* ⚠️ 使用前需在聚光开放平台 (ad-market.xiaohongshu.com) 申请应用,
* 并在环境变量中配置 PHP_XHS_APP_KEY / PHP_XHS_APP_SECRET
* ⚠️ 凭证说明:
* app_id + access_token 由小红书运营/销售侧提供(静态凭证),非 OAuth 动态获取。
* 配置方式:
* - 环境变量: PHP_XHS_APP_ID / PHP_XHS_ACCESS_TOKEN
* - 或 shopro 配置表 code=xhs_ad 组中配置 APP_ID / ACCESS_TOKEN
*
* 注意:OAuth 接口(app_key + app_secret → /oauth/token)用于管理类 API,
* 转化回传 API 不使用 OAuth token,此处保留 getAccessToken() 仅供其他场景参考。
*/
class ConversionService
{
......@@ -38,23 +43,23 @@ class ConversionService
* @return string|null
* @throws \Exception
*/
public function getAccessToken()
{
// 检查缓存
$cached = redis_cache('?' . self::TOKEN_CACHE_KEY);
if ($cached) {
$tokenData = json_decode($cached, true);
if ($tokenData && isset($tokenData['token'])) {
$now = time();
if ($tokenData['expires_at'] > ($now + self::TOKEN_REFRESH_AHEAD)) {
return $tokenData['token'];
}
}
}
// 获取新 Token
return $this->refreshAccessToken();
}
// public function getAccessToken()
// {
// // 检查缓存
// $cached = redis_cache('?' . self::TOKEN_CACHE_KEY);
// if ($cached) {
// $tokenData = json_decode($cached, true);
// if ($tokenData && isset($tokenData['token'])) {
// $now = time();
// if ($tokenData['expires_at'] > ($now + self::TOKEN_REFRESH_AHEAD)) {
// return $tokenData['token'];
// }
// }
// }
// // 获取新 Token
// return $this->refreshAccessToken();
// }
/**
* 强制刷新 Access Token
......@@ -62,40 +67,40 @@ class ConversionService
* @return string|null
* @throws \Exception
*/
private function refreshAccessToken()
{
$appKey = $this->getConfig('APP_KEY', '');
$appSecret = $this->getConfig('APP_SECRET', '');
// private function refreshAccessToken()
// {
// $appKey = $this->getConfig('APP_KEY', '');
// $appSecret = $this->getConfig('APP_SECRET', '');
if (empty($appKey) || empty($appSecret)) {
throw new \Exception('小红书聚光 API 凭证未配置(PHP_XHS_APP_KEY / PHP_XHS_APP_SECRET)');
}
// if (empty($appKey) || empty($appSecret)) {
// throw new \Exception('小红书聚光 API 凭证未配置(PHP_XHS_APP_KEY / PHP_XHS_APP_SECRET)');
// }
$url = self::API_BASE . self::TOKEN_URL;
$params = [
'app_key' => $appKey,
'app_secret' => $appSecret,
'grant_type' => 'client_credentials',
];
// $url = self::API_BASE . self::TOKEN_URL;
// $params = [
// 'app_key' => $appKey,
// 'app_secret' => $appSecret,
// 'grant_type' => 'client_credentials',
// ];
$response = $this->httpPost($url, $params);
// $response = $this->httpPost($url, $params);
if (empty($response['access_token'])) {
throw new \Exception('获取 access_token 失败: ' . json_encode($response));
}
// if (empty($response['access_token'])) {
// throw new \Exception('获取 access_token 失败: ' . json_encode($response));
// }
$token = $response['access_token'];
$expiresIn = intval($response['expires_in'] ?? 7200);
// $token = $response['access_token'];
// $expiresIn = intval($response['expires_in'] ?? 7200);
// 缓存 Token
$tokenData = [
'token' => $token,
'expires_at' => time() + $expiresIn,
];
redis_cache(self::TOKEN_CACHE_KEY, json_encode($tokenData), $expiresIn);
// // 缓存 Token
// $tokenData = [
// 'token' => $token,
// 'expires_at' => time() + $expiresIn,
// ];
// redis_cache(self::TOKEN_CACHE_KEY, json_encode($tokenData), $expiresIn);
return $token;
}
// return $token;
// }
/**
* 回传转化事件到小红书(对齐官方「种草直达」API 文档)
......@@ -120,15 +125,19 @@ class ConversionService
}
// 获取 app_id 和 access_token
$appId = $this->getConfig('APP_ID', '');
try {
$accessToken = $this->getAccessToken();
} catch (\Exception $e) {
return ['success' => false, 'response' => '获取 Token 失败: ' . $e->getMessage()];
}
// 注意:转化回传 API 的 access_token 不同于管理 API 的 OAuth token
// 官方文档说明:"app_id和access_token需要联系您的产品获取",即由小红书运营/销售侧提供的静态凭证
$appId = config('shopro.xhs_app_id');
$accessToken = config('shopro.xhs_access_token');
custom_log('[xhs.context] 配置调试:app_id:'.$appId.'accessToken:'.$accessToken, 0, 'xhs_ad', 'info');
if (empty($appId)) {
return ['success' => false, 'response' => 'app_id 未配置'];
return ['success' => false, 'response' => 'app_id 未配置(需联系小红书运营获取)'];
}
if (empty($accessToken)) {
return ['success' => false, 'response' => 'access_token 未配置(需联系小红书运营获取)'];
}
// 转换事件类型为小红书平台编码
......@@ -365,30 +374,30 @@ class ConversionService
return $map[$type] ?? 0;
}
/**
* 获取配置(优先环境变量,其次 shopro 配置组)
*
* @param string $key
* @param mixed $default
* @return mixed
*/
private function getConfig($key, $default = null)
{
// 1. 优先环境变量(如 PHP_XHS_APP_KEY / PHP_XHS_APP_SECRET
$envKey = 'PHP_XHS_' . strtoupper($key);
$envValue = getenv($envKey);
if ($envValue !== false && $envValue !== '') {
return $envValue;
}
// 2. 从 shopro 配置组中获取(需先在 fa_shopro_config 表添加 code=xhs_ad 的配置组)
$config = sheep_config('xhs_ad');
if ($config && isset($config[$key])) {
return $config[$key];
}
return $default;
}
// /**
// * 获取配置(优先环境变量,其次 shopro 配置组)
// *
// * @param string $key
// * @param mixed $default
// * @return mixed
// */
// private function getConfig($key, $default = null)
// {
// 1. 优先环境变量(如 PHP_XHS_APP_ID / PHP_XHS_ACCESS_TOKEN
// $envKey = 'PHP_XHS_' . strtoupper($key);
// $envValue = getenv($envKey);
// if ($envValue !== false && $envValue !== '') {
// return $envValue;
// }
// // 2. 从 shopro 配置组中获取(需先在 fa_shopro_config 表添加 code=xhs_ad 的配置组)
// $config = sheep_config('xhs_ad');
// if ($config && isset($config[$key])) {
// return $config[$key];
// }
// return $default;
// }
/**
* HTTP POST (form-urlencoded)
......
......@@ -335,7 +335,12 @@ return [
'obs_access_key' => 'HPUAWU3GPS8HEWX9JFLG',
'obs_secret_key' => 'Jj7Vt1WnU69pWG6QplBmHBkaw6WM4oLU1AZa9Z9n',
'obs_endpoint' => 'obs.cn-east-3.myhuaweicloud.com', // 根据区域修改
'obs_bucket' => 'beevera'
'obs_bucket' => 'beevera',
// 小红书配置
'xhs_app_id' => Env::get('xhs.app_id', ''),
'xhs_access_token' => Env::get('xhs.access_token', ''),
],
];
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment