一、说明
二、代码
<?php
namespace app\common\libs;
use app\common\exception\BaseException;
class DouYinApi
{
private $host;
private $appKey;
private $appSecret;
private $accessToken;
private $refreshToken;
private $versionNumber;
private $versionNumberStr;
public function __construct()
{
$this->host = 'https://openapi-fxg.jinritemai.com';
$this->appKey = '你的抖音后台的appKey';
$this->appSecret = '你的抖音后台的appSecret';
$this->versionNumber = '2';
$this->versionNumberStr = 'v' . $this->versionNumber;
$result = self::handleToken();
$this->accessToken = $result['access_token'];
$this->refreshToken = $result['refresh_token'];
}
public function handleToken($createToken = true)
{
if ($createToken) {
$param = [
'code' => '',
'grant_type' => 'authorization_self',
'shop_id' => '你抖音店铺的ID',
];
$method = 'token.create';
} else {
$param = [
'refresh_token' => $this->refreshToken,
'grant_type' => 'refresh_token',
];
$method = 'token.refresh';
}
$timestamp = time();
$result = self::fetch($method, $param);
if ($result['code'] != 10000) {
throw new BaseException($result['message']);
} else {
$data = $result['data'];
$accessToken = $data['access_token'];
$refreshToken = $data['refresh_token'];
$expireTime = $timestamp + $data['expires_in'];
return [
'access_token' => $accessToken,
'refresh_token' => $refreshToken,
];
}
}
function fetch($method, $param, $accessToken = false, $paramJsonAddToUrl = true)
{
$timestamp = time();
$paramJson = $param ? self::marshal($param) : '{}';
$sign = self::sign($method, $timestamp, $paramJson);
$methodPath = str_replace('.', '/', $method);
$url = $this->host . '/' . $methodPath .
'?method=' . urlencode($method) .
'&app_key=' . urlencode($this->appKey);
if ($accessToken) {
$url .= '&access_token=' .urlencode($this->accessToken);
}
$url .= '×tamp=' . urlencode(strval($timestamp)) .
'&v=' . urlencode($this->versionNumber) .
'&sign=' . $sign;
if ($paramJsonAddToUrl) {
$url .= '¶m_json=' . $paramJson;
}
$url .= '&sign_method=' . urlencode('hmac-sha256');
$opts = array('http' =>
array(
'method' => 'POST',
'header' => "Accept: */*\r\n" .
"Content-type: application/json;charset=UTF-8\r\n",
'content' => $paramJson
)
);
$context = stream_context_create($opts);
$result = file_get_contents($url, false, $context);
return json_decode($result,true);
}
function sign($method, $timestamp, $paramJson)
{
$paramPattern = 'app_key' . $this->appKey . 'method' . $method . 'param_json' . $paramJson . 'timestamp' . $timestamp . $this->versionNumberStr;
$signPattern = $this->appSecret . $paramPattern . $this->appSecret;
return hash_hmac("sha256", $signPattern, $this->appSecret);
}
function marshal(array $param)
{
self::rec_ksort($param);
$s = json_encode($param, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return $s;
}
function rec_ksort(array &$arr)
{
$kstring = true;
foreach ($arr as $k => &$v) {
if (!is_string($k)) {
$kstring = false;
}
if (is_array($v)) {
self::rec_ksort($v);
}
}
if ($kstring) {
ksort($arr);
}
}
}
三、代码运行需知
- 在
__construct() 方法 $this->appKey 中加上你的真实appKey - 在
__construct() 方法 $this->appSecret 中加上你的真实appSecret - 在
handleToken() 方法 shop_id 中加上你真实的抖音店铺ID
四、功能扩展
- 加一张数据表
third_shop(第三方店铺表) :存放第三方店铺(比如:抖音)的信息,表的字段大致有:id;shop_name:店铺名;third_shop_id:第三方店铺的ID,source:店铺来源(抖音,京东,天猫);app_key,app_secret,access_token,refresh_token,expire_time:过期时间;status:状态(0-关闭;1-启用),create_time,update_time ... - 我们要对接抖音前,在
third_shop 中写好 id;shop_name:店铺名;third_shop_id:第三方店铺的ID,source:店铺来源(抖音,京东,天猫);app_key,app_secret;status:状态(0-关闭;1-启用),create_time,update_time .... - 在
__construct() 中先查询店铺的信息,如果 access_token为空 或者 expire_time过期时间 小于 当前时间 ,则需要重新生成 access_token,refresh_token,expire_time:过期时间 在 handleToken() 中加上third_shop 表 更新操作;否则取数据表中未过期的 access_token,refresh_token 用于接口调用
五、接口调用需要注意的点
- 1、param为空的问题:param为空,$paramJson字符串的值为
{} ,而不是 [] - 2、rec_ksort递归调用的问题:
rec_ksort中调用rec_ksort方式要和marshal中调用rec_ksort方式一致 - 3、paramJson何时传的问题:如果接口请求数据太大,GET请求可能会超出最大值,则
fetch() 中 $paramJsonAddToUrl 可试着传 false
六、接口文档中的 ‘坑’(以订单列表接口为例)
1、请求参数、响应参数 代表的具体值不清晰
2、页码从第0页开始(这个属于需要注意的点)
3、金额 是元 还是 分,不清晰
- 不给的话,那就默认为:
分
|