作者 lackoxygen

add all

  1 +/vendor/
  2 +.idea
  3 +composer.lock
  1 +{
  2 + "name": "lackoxygen/tiktok_open_sdk",
  3 + "type": "library",
  4 + "description": "抖音开放平台-sdk",
  5 + "autoload": {
  6 + "psr-4": {
  7 + "Lackoxygen\\TiktokOpen\\": "src/"
  8 + }
  9 + },
  10 + "autoload-dev": {
  11 + "psr-4": {
  12 + "Lackoxygen\\Tests\\": "tests/"
  13 + }
  14 + },
  15 + "authors": [
  16 + {
  17 + "name": "lackoxygen",
  18 + "email": "jingze666@gmail.com"
  19 + }
  20 + ],
  21 + "require": {
  22 + "pimple/pimple": "^3.5",
  23 + "guzzlehttp/guzzle": "^7.4",
  24 + "illuminate/support": "^8 || ^9",
  25 + "ext-openssl": "*"
  26 + }
  27 +}
  1 +<?php
  2 +
  3 +return [
  4 + //小程序
  5 + 'mini' => [
  6 + 'appid' => '',
  7 + 'secret' => '',
  8 + ],
  9 + 'wap' => [
  10 + 'app_key' => '',
  11 + 'app_secret' => ''
  12 + ],
  13 +];
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\Config;
  6 +use Lackoxygen\TiktokOpen\Mini\MiniProvider;
  7 +use Lackoxygen\TiktokOpen\Wap\WapProvider;
  8 +use Pimple\Container;
  9 +
  10 +/**
  11 + * @method WapProvider wap()
  12 + * @method MiniProvider mini()
  13 + */
  14 +class Application extends Container
  15 +{
  16 + /**
  17 + * @var array|string[]
  18 + */
  19 + private array $providers = [
  20 + 'wap' => WapProvider::class,
  21 + 'mini' => MiniProvider::class
  22 + ];
  23 +
  24 + /**
  25 + * @param Config $config
  26 + */
  27 + public function __construct(Config $config)
  28 + {
  29 + parent::__construct();
  30 + $this['config'] = $config;
  31 + $this[__CLASS__] = new \SplFixedArray(2);
  32 + }
  33 +
  34 + /**
  35 + * @param $name
  36 + * @param $provider
  37 + * @return void
  38 + */
  39 + protected function makeProvider($name, $provider)
  40 + {
  41 + if ($this->offsetExists($name)) {
  42 + return;
  43 + }
  44 + parent::register(new $provider($name));
  45 + }
  46 +
  47 + /**
  48 + * @param $name
  49 + * @param array $arguments
  50 + * @return $this|mixed
  51 + */
  52 + public function __call($name, array $arguments = [])
  53 + {
  54 + [$provider, $service] = $this[__CLASS__];
  55 + if ($provider && $service) {
  56 + if ($service === $name) {
  57 + return $this[$provider . '.' . $service];
  58 + }
  59 + goto rebuild;
  60 + } elseif (!$provider) {
  61 + $providerName = $this->providers[$name];
  62 + $this->makeProvider($name, $providerName);
  63 + $provider = $name;
  64 + $this[__CLASS__][0] = $provider;
  65 + return $this;
  66 + } else {
  67 + rebuild:
  68 + $service = $name;
  69 + $this[__CLASS__][1] = $service;
  70 + return $this[$provider . '.' . $service];
  71 + }
  72 + }
  73 +}
  74 +
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base;
  4 +
  5 +use Lackoxygen\TiktokOpen\Application;
  6 +use GuzzleHttp\Client;
  7 +use Pimple\Container;
  8 +use Pimple\ServiceProviderInterface;
  9 +
  10 +abstract class AbstractProvider implements ServiceProviderInterface
  11 +{
  12 + /**
  13 + * @var string $alias
  14 + */
  15 + protected string $alias;
  16 +
  17 + /**
  18 + * @var array
  19 + */
  20 + private array $preServices = [];
  21 +
  22 + /**
  23 + * @var array
  24 + */
  25 + protected array $services = [];
  26 +
  27 + /**
  28 + * @var Container $application
  29 + */
  30 + protected Container $application;
  31 +
  32 + /**
  33 + * @param string $alias
  34 + */
  35 + public function __construct(string $alias)
  36 + {
  37 + $this->alias = $alias;
  38 +
  39 + $this->addPreService('guzzleHttp', function (Application $app) {
  40 + return new Client(
  41 + [
  42 + 'base_uri' => $app['config']->getUrl(),
  43 + 'timeout' => $app['config']->getTimeout()
  44 + ]
  45 + );
  46 + });
  47 + }
  48 +
  49 + /**
  50 + * @param Container $pimple
  51 + * @return void
  52 + */
  53 + public function register(Container $pimple)
  54 + {
  55 + $this->application = $pimple;
  56 +
  57 + $this->registerServices($this->preServices, function (string $key) {
  58 + return $key;
  59 + });
  60 + $this->registerServices($this->services, function (string $key) {
  61 + return $this->alias . '.' . $key;
  62 + });
  63 + $this->application[$this->alias] = $this;
  64 + }
  65 +
  66 + /**
  67 + * @return array
  68 + */
  69 + protected function getServices(): array
  70 + {
  71 + return array_merge(
  72 + $this->preServices,
  73 + $this->services
  74 + );
  75 + }
  76 +
  77 + protected function addPreService($name, $service)
  78 + {
  79 + $this->preServices[$name] = $service;
  80 + }
  81 +
  82 + /**
  83 + * @param $services
  84 + * @param \Closure $callback
  85 + * @return void
  86 + */
  87 + protected function registerServices($services, \Closure $callback)
  88 + {
  89 + foreach ($services as $key => $value) {
  90 + if ($value instanceof \Closure) {
  91 + $service = call_user_func($value, $this->application);
  92 + } else {
  93 + $service = new $value($this->application);
  94 + }
  95 + $this->application[$callback($key)] = $service;
  96 + }
  97 + }
  98 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base;
  4 +
  5 +use Illuminate\Support\Facades\Cache as LaravelCache;
  6 +
  7 +class Cache
  8 +{
  9 + protected const PREFIX = 'tiktok.open.';
  10 +
  11 + public static function put(string $key, $value, $ttl): bool
  12 + {
  13 + return LaravelCache::put(self::PREFIX . $key, $value, $ttl);
  14 + }
  15 +
  16 + public static function get(string $key)
  17 + {
  18 + return LaravelCache::get(self::PREFIX . $key);
  19 + }
  20 +
  21 + public static function has(string $key): bool
  22 + {
  23 + return LaravelCache::has(self::PREFIX . $key);
  24 + }
  25 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base\Client;
  4 +
  5 +use Lackoxygen\TiktokOpen\Application;
  6 +use Lackoxygen\TiktokOpen\Base\Event\Fail;
  7 +use Lackoxygen\TiktokOpen\Base\Event\Request;
  8 +use Lackoxygen\TiktokOpen\Base\Event\Response;
  9 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  10 +use Lackoxygen\TiktokOpen\Base\Traits\BaseClient;
  11 +use Lackoxygen\TiktokOpen\Wap\Listener;
  12 +use GuzzleHttp\RequestOptions;
  13 +use Illuminate\Support\Facades\Event;
  14 +
  15 +class Client extends ServiceManager
  16 +{
  17 + use BaseClient;
  18 +
  19 + private string $requestOption = '';
  20 +
  21 + private bool $withSession = false;
  22 +
  23 + public function __construct(Application $app)
  24 + {
  25 + parent::__construct($app);
  26 +
  27 + $this->listen();
  28 + }
  29 +
  30 + protected function listen()
  31 + {
  32 + Event::listen(Request::class, [Listener::class, 'request']);
  33 + Event::listen(Response::class, [Listener::class, 'response']);
  34 + Event::listen(Fail::class, [Listener::class, 'fail']);
  35 + }
  36 +
  37 +
  38 + public function asForm(): Client
  39 + {
  40 + $this->requestOption = RequestOptions::FORM_PARAMS;
  41 +
  42 + return $this;
  43 + }
  44 +
  45 + public function asJson(): Client
  46 + {
  47 + $this->requestOption = RequestOptions::JSON;
  48 +
  49 + return $this;
  50 + }
  51 +
  52 + public function asMultipart(): Client
  53 + {
  54 + $this->requestOption = RequestOptions::MULTIPART;
  55 +
  56 + return $this;
  57 + }
  58 +
  59 + public function withSession(): Client
  60 + {
  61 + $this->withSession = true;
  62 +
  63 + return $this;
  64 + }
  65 +
  66 + public function refresh()
  67 + {
  68 + $this->requestOption = '';
  69 + $this->withSession = false;
  70 + }
  71 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base\Client;
  4 +
  5 +use GuzzleHttp\RequestOptions;
  6 +
  7 +class Request
  8 +{
  9 + protected string $method;
  10 +
  11 + protected string $format;
  12 +
  13 + protected string $path;
  14 +
  15 + protected array $data = [];
  16 +
  17 + protected array $headers = [];
  18 +
  19 + protected bool $withSession;
  20 +
  21 + public function __construct(
  22 + string $method,
  23 + string $format,
  24 + string $path,
  25 + array $data,
  26 + bool $withSession
  27 + )
  28 + {
  29 + $this->setMethod($method);
  30 +
  31 + $this->format = $format;
  32 + $this->path = $path;
  33 + $this->data = $data;
  34 + $this->withSession = $withSession;
  35 + }
  36 +
  37 + /**
  38 + * @param string $format
  39 + */
  40 + public function setFormat(string $format): void
  41 + {
  42 + $this->format = $format;
  43 + }
  44 +
  45 +
  46 + /**
  47 + * @param string $method
  48 + */
  49 + public function setMethod(string $method): void
  50 + {
  51 + $this->method = strtoupper($method);
  52 + }
  53 +
  54 + /**
  55 + * @param string $path
  56 + */
  57 + public function setPath(string $path): void
  58 + {
  59 + $this->path = $path;
  60 + }
  61 +
  62 + /**
  63 + * @param array $data
  64 + */
  65 + public function setData(array $data): void
  66 + {
  67 + $this->data = $data;
  68 + }
  69 +
  70 + /**
  71 + * @param array $headers
  72 + */
  73 + public function setHeaders(array $headers): void
  74 + {
  75 + $this->headers = $headers;
  76 + }
  77 +
  78 + /**
  79 + * @return string
  80 + */
  81 + public function getPath(): string
  82 + {
  83 + return $this->path;
  84 + }
  85 +
  86 + /**
  87 + * @return array
  88 + */
  89 + public function getData(): array
  90 + {
  91 + return $this->data;
  92 + }
  93 +
  94 + /**
  95 + * @return string
  96 + */
  97 + public function getFormat(): string
  98 + {
  99 + return $this->format;
  100 + }
  101 +
  102 + /**
  103 + * @return array
  104 + */
  105 + public function getHeaders(): array
  106 + {
  107 + return $this->headers;
  108 + }
  109 +
  110 + /**
  111 + * @return bool
  112 + */
  113 + public function isWithSession(): bool
  114 + {
  115 + return $this->withSession;
  116 + }
  117 +
  118 + protected function defaultFormat(): string
  119 + {
  120 + if ('GET' === $this->method) {
  121 + return RequestOptions::QUERY;
  122 + } else {
  123 + return RequestOptions::FORM_PARAMS;
  124 + }
  125 + }
  126 +
  127 + public function toArray(): array
  128 + {
  129 + $format = $this->format ?: $this->defaultFormat();
  130 +
  131 + return [
  132 + RequestOptions::HEADERS => $this->headers,
  133 + $format => $this->data,
  134 + ];
  135 + }
  136 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base;
  4 +
  5 +class Config
  6 +{
  7 + private string $url = '';
  8 +
  9 + private string $appKey = '';
  10 +
  11 + private string $appSecret = '';
  12 +
  13 + protected float $timeout = 5.0;
  14 +
  15 + /**
  16 + * @return string
  17 + */
  18 + public function getUrl(): string
  19 + {
  20 + return $this->url;
  21 + }
  22 +
  23 + /**
  24 + * @param string $url
  25 + */
  26 + public function setUrl(string $url): void
  27 + {
  28 + $this->url = $url;
  29 + }
  30 +
  31 + /**
  32 + * @return string
  33 + */
  34 + public function getAppKey(): string
  35 + {
  36 + return $this->appKey;
  37 + }
  38 +
  39 + /**
  40 + * @param string $appKey
  41 + */
  42 + public function setAppKey(string $appKey): void
  43 + {
  44 + $this->appKey = $appKey;
  45 + }
  46 +
  47 + /**
  48 + * @return string
  49 + */
  50 + public function getAppSecret(): string
  51 + {
  52 + return $this->appSecret;
  53 + }
  54 +
  55 + /**
  56 + * @param string $appSecret
  57 + */
  58 + public function setAppSecret(string $appSecret): void
  59 + {
  60 + $this->appSecret = $appSecret;
  61 + }
  62 +
  63 + /**
  64 + * @return float
  65 + */
  66 + public function getTimeout(): float
  67 + {
  68 + return $this->timeout;
  69 + }
  70 +
  71 + /**
  72 + * @param float $timeout
  73 + */
  74 + public function setTimeout(float $timeout): void
  75 + {
  76 + $this->timeout = $timeout;
  77 + }
  78 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base\Event;
  4 +
  5 +use Illuminate\Foundation\Events\Dispatchable;
  6 +
  7 +class Fail
  8 +{
  9 + use Dispatchable;
  10 +
  11 + public \Throwable $exception;
  12 +
  13 + public function __construct($exception)
  14 + {
  15 + $this->exception = $exception;
  16 + }
  17 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base\Event;
  4 +
  5 +use Lackoxygen\TiktokOpen\Application;
  6 +use Illuminate\Foundation\Events\Dispatchable;
  7 +
  8 +class Request
  9 +{
  10 + use Dispatchable;
  11 +
  12 + public \App\Pkgs\TiktokOpen\Base\Client\Request $request;
  13 +
  14 + public Application $application;
  15 +
  16 + public function __construct(Application $application, \App\Pkgs\TiktokOpen\Base\Client\Request $request)
  17 + {
  18 + $this->application = $application;
  19 + $this->request = $request;
  20 + }
  21 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base\Event;
  4 +
  5 +use Illuminate\Foundation\Events\Dispatchable;
  6 +use Psr\Http\Message\ResponseInterface;
  7 +
  8 +class Response
  9 +{
  10 + use Dispatchable;
  11 +
  12 + public ResponseInterface $response;
  13 +
  14 + public function __construct(ResponseInterface $response)
  15 + {
  16 + $this->response = $response;
  17 + }
  18 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base\Exception;
  4 +
  5 +class AnswerException extends Exception
  6 +{
  7 +
  8 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base\Exception;
  4 +
  5 +class Exception extends \Exception
  6 +{
  7 +
  8 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base;
  4 +
  5 +use Lackoxygen\TiktokOpen\Application;
  6 +
  7 +class ServiceManager
  8 +{
  9 + protected Application $app;
  10 +
  11 + /**
  12 + * @param Application $app
  13 + */
  14 + public function __construct(Application $app)
  15 + {
  16 + $this->app = $app;
  17 + }
  18 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base\Traits;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\Client\Request;
  6 +use Lackoxygen\TiktokOpen\Base\Event\Fail as FailEvent;
  7 +use Lackoxygen\TiktokOpen\Base\Event\Request as RequestEvent;
  8 +use Lackoxygen\TiktokOpen\Base\Event\Response as ResponseEvent;
  9 +use Lackoxygen\TiktokOpen\Base\Utils\Json;
  10 +use GuzzleHttp\Exception\ClientException;
  11 +
  12 +trait BaseClient
  13 +{
  14 + public function get($url, $params = [])
  15 + {
  16 + return $this->request('GET', $url, $params);
  17 + }
  18 +
  19 + public function post($url, $params = [])
  20 + {
  21 + return $this->request('POST', $url, $params);
  22 + }
  23 +
  24 + public function put($url, $params = [])
  25 + {
  26 + return $this->request('PUT', $url, $params);
  27 + }
  28 +
  29 + public function delete($url, $params = [])
  30 + {
  31 + return $this->request('DELETE', $url, $params);
  32 + }
  33 +
  34 + public function request(string $method, string $path, array $data = [])
  35 + {
  36 + $request = new Request(
  37 + $method,
  38 + $this->requestOption,
  39 + $path,
  40 + $data,
  41 + $this->withSession
  42 + );
  43 +
  44 + RequestEvent::dispatch($this->app, $request);
  45 +
  46 + try {
  47 + $response = $this->app['guzzleHttp']->request(
  48 + $method,
  49 + $path,
  50 + $request->toArray()
  51 + );
  52 + ResponseEvent::dispatch($response);
  53 + $response->getBody()->rewind();
  54 + return Json::unmarshal($response->getBody()->getContents());
  55 + } catch (ClientException $exception) {
  56 + FailEvent::dispatch($exception);
  57 + } finally {
  58 + $this->refresh();
  59 + }
  60 + }
  61 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Base\Utils;
  4 +
  5 +class Json
  6 +{
  7 + public static function marshal(array $array, $flags = JSON_UNESCAPED_UNICODE)
  8 + {
  9 + return \json_encode($array, $flags);
  10 + }
  11 +
  12 + public static function unmarshal(string $value)
  13 + {
  14 + return \json_decode($value, true);
  15 + }
  16 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Mini;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\AbstractProvider;
  6 +use Lackoxygen\TiktokOpen\Base\Client\Client;
  7 +use Lackoxygen\TiktokOpen\Mini\OAuth\OAuth;
  8 +
  9 +/**
  10 + * @method OAuth oauth()
  11 + */
  12 +class MiniProvider extends AbstractProvider
  13 +{
  14 + protected string $alias = 'mini';
  15 +
  16 + protected array $services = [
  17 + 'oauth' => OAuth::class,
  18 + ];
  19 +
  20 + public function __construct(string $alias)
  21 + {
  22 + parent::__construct($alias);
  23 +
  24 + $this->addPreService('client', Client::class);
  25 + }
  26 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Mini\OAuth;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class OAuth extends ServiceManager
  8 +{
  9 + public function jsCode(string $code = '', string $anonymousCode = '')
  10 + {
  11 + return $this->app['client']->asJson()
  12 + ->post(
  13 + 'api/apps/v2/jscode2session',
  14 + [
  15 + 'appid' => $this->app['config']->getAppKey(),
  16 + 'secret' => $this->app['config']->getAppSecret(),
  17 + 'code' => $code,
  18 + 'anonymous_code' => $anonymousCode,
  19 + ]
  20 + );
  21 + }
  22 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen;
  4 +
  5 +use Illuminate\Support\ServiceProvider;
  6 +use Lackoxygen\TiktokOpen\Base\Config;
  7 +
  8 +class TiktokOpenServiceProvider extends ServiceProvider
  9 +{
  10 + protected array $provides = ['mini', 'wap'];
  11 +
  12 + /**
  13 + * @return void
  14 + */
  15 + public function boot()
  16 + {
  17 + if ($this->app->runningInConsole()) {
  18 + $configPath = __DIR__ . '/../publish/tiktok.open.php';
  19 + $this->publishes([
  20 + $configPath => config_path('tiktok.open.php')
  21 + ], 'lackoxygen-tiktok-open');
  22 + }
  23 + }
  24 +
  25 + /**
  26 + * @return void
  27 + */
  28 + public function register()
  29 + {
  30 + foreach ($this->provides as $provide) {
  31 + $alias = sprintf('tiktok.%s', $provide);
  32 + $this->app->singleton($alias, function () use ($alias) {
  33 + $provideConfig = \config($alias);
  34 + $config = new Config();
  35 + $config->setAppKey($provideConfig['app_key']);
  36 + $config->setAppSecret($provideConfig['app_secret']);
  37 + $config->setUrl('https://open.douyin.com');
  38 +
  39 + return (new Application($config))->wap();
  40 + });
  41 + }
  42 + }
  43 +
  44 + /**
  45 + * @return string[]
  46 + */
  47 + public function provides(): array
  48 + {
  49 + return $this->provides;
  50 + }
  51 +}
  52 +
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\Data\Content;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class Fans extends ServiceManager
  8 +{
  9 + public function data(string $openid, string $accessToken)
  10 + {
  11 + return $this->app['client']
  12 + ->get(
  13 + '/fans/data/',
  14 + [
  15 + 'open_id' => $openid,
  16 + 'access_token' => $accessToken,
  17 + ]
  18 + );
  19 + }
  20 +
  21 + public function source(string $openid, string $accessToken)
  22 + {
  23 + return $this->app['client']
  24 + ->get(
  25 + '/data/extern/fans/source/',
  26 + [
  27 + 'open_id' => $openid,
  28 + 'access_token' => $accessToken,
  29 + ]
  30 + );
  31 + }
  32 +
  33 + public function favourite(string $openid, string $accessToken)
  34 + {
  35 + return $this->app['client']
  36 + ->get(
  37 + '/data/extern/fans/favourite/',
  38 + [
  39 + 'open_id' => $openid,
  40 + 'access_token' => $accessToken,
  41 + ]
  42 + );
  43 + }
  44 +
  45 + public function comment(string $openid, string $accessToken)
  46 + {
  47 + return $this->app['client']
  48 + ->get(
  49 + '/data/extern/fans/comment/',
  50 + [
  51 + 'open_id' => $openid,
  52 + 'access_token' => $accessToken,
  53 + ]
  54 + );
  55 + }
  56 +
  57 +
  58 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\Data\Content;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class HotSearch extends ServiceManager
  8 +{
  9 + public function sentences(string $accessToken)
  10 + {
  11 + return $this->app['client']
  12 + ->get(
  13 + '/hotsearch/sentences/',
  14 + [
  15 + 'access_token' => $accessToken,
  16 + ]
  17 + );
  18 + }
  19 +
  20 + public function trendingSentences(string $accessToken, int $cursor, int $count)
  21 + {
  22 + return $this->app['client']
  23 + ->get(
  24 + '/hotsearch/trending/sentences/',
  25 + [
  26 + 'access_token' => $accessToken,
  27 + 'cursor' => $cursor,
  28 + 'count' => $count
  29 + ]
  30 + );
  31 + }
  32 +
  33 + public function videos(string $accessToken, string $hotSentence)
  34 + {
  35 + return $this->app['client']
  36 + ->get(
  37 + '/hotsearch/videos/',
  38 + [
  39 + 'access_token' => $accessToken,
  40 + 'hot_sentence' => $hotSentence,
  41 + ]
  42 + );
  43 + }
  44 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\Data\Content;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class Star extends ServiceManager
  8 +{
  9 +
  10 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\Data\Content;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class User extends ServiceManager
  8 +{
  9 + public function item(string $openid, string $accessToken, int $dateType)
  10 + {
  11 + return $this->app['client']
  12 + ->get(
  13 + '/data/external/user/item/',
  14 + [
  15 + 'open_id' => $openid,
  16 + 'access_token' => $accessToken,
  17 + 'date_type' => $dateType
  18 + ]
  19 + );
  20 + }
  21 +
  22 + public function fans(string $openid, string $accessToken, int $dateType)
  23 + {
  24 + return $this->app['client']
  25 + ->get(
  26 + '/data/external/user/fans/',
  27 + [
  28 + 'open_id' => $openid,
  29 + 'access_token' => $accessToken,
  30 + 'date_type' => $dateType
  31 + ]
  32 + );
  33 + }
  34 +
  35 + public function like(string $openid, string $accessToken, int $dateType)
  36 + {
  37 + return $this->app['client']
  38 + ->get(
  39 + '/data/external/user/like/',
  40 + [
  41 + 'open_id' => $openid,
  42 + 'access_token' => $accessToken,
  43 + 'date_type' => $dateType
  44 + ]
  45 + );
  46 + }
  47 +
  48 + public function comment(string $openid, string $accessToken, int $dateType)
  49 + {
  50 + return $this->app['client']
  51 + ->get(
  52 + '/data/external/user/comment/',
  53 + [
  54 + 'open_id' => $openid,
  55 + 'access_token' => $accessToken,
  56 + 'date_type' => $dateType
  57 + ]
  58 + );
  59 + }
  60 +
  61 + public function share(string $openid, string $accessToken, int $dateType)
  62 + {
  63 + return $this->app['client']
  64 + ->get(
  65 + '/data/external/user/share/',
  66 + [
  67 + 'open_id' => $openid,
  68 + 'access_token' => $accessToken,
  69 + 'date_type' => $dateType
  70 + ]
  71 + );
  72 + }
  73 +
  74 + public function profile(string $openid, string $accessToken, int $dateType)
  75 + {
  76 + return $this->app['client']
  77 + ->get(
  78 + '/data/external/user/profile/',
  79 + [
  80 + 'open_id' => $openid,
  81 + 'access_token' => $accessToken,
  82 + 'date_type' => $dateType
  83 + ]
  84 + );
  85 + }
  86 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\Data\Content;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class Video extends ServiceManager
  8 +{
  9 + public function base(string $openid, string $accessToken, string $itemId)
  10 + {
  11 + return $this->app['client']
  12 + ->get(
  13 + '/data/external/item/base/',
  14 + [
  15 + 'open_id' => $openid,
  16 + 'access_token' => $accessToken,
  17 + 'item_id' => $itemId
  18 + ]
  19 + );
  20 + }
  21 +
  22 + public function like(string $openid, string $accessToken, string $itemId, int $dateType)
  23 + {
  24 + return $this->app['client']
  25 + ->get(
  26 + '/data/external/item/base/',
  27 + [
  28 + 'open_id' => $openid,
  29 + 'access_token' => $accessToken,
  30 + 'item_id' => $itemId,
  31 + 'date_type' => $dateType
  32 + ]
  33 + );
  34 + }
  35 +
  36 + public function comment(string $openid, string $accessToken, string $itemId, int $dateType)
  37 + {
  38 + return $this->app['client']
  39 + ->get(
  40 + '/data/external/item/comment/',
  41 + [
  42 + 'open_id' => $openid,
  43 + 'access_token' => $accessToken,
  44 + 'item_id' => $itemId,
  45 + 'date_type' => $dateType
  46 + ]
  47 + );
  48 + }
  49 +
  50 + public function play(string $openid, string $accessToken, string $itemId, int $dateType)
  51 + {
  52 + return $this->app['client']
  53 + ->get(
  54 + '/data/external/item/play/',
  55 + [
  56 + 'open_id' => $openid,
  57 + 'access_token' => $accessToken,
  58 + 'item_id' => $itemId,
  59 + 'date_type' => $dateType
  60 + ]
  61 + );
  62 + }
  63 +
  64 + public function share(string $openid, string $accessToken, string $itemId, int $dateType)
  65 + {
  66 + return $this->app['client']
  67 + ->get(
  68 + '/data/external/item/share/',
  69 + [
  70 + 'open_id' => $openid,
  71 + 'access_token' => $accessToken,
  72 + 'item_id' => $itemId,
  73 + 'date_type' => $dateType
  74 + ]
  75 + );
  76 + }
  77 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\Data;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +use Lackoxygen\TiktokOpen\Wap\Data\Content\Fans;
  7 +use Lackoxygen\TiktokOpen\Wap\Data\Content\HotSearch;
  8 +use Lackoxygen\TiktokOpen\Wap\Data\Content\Star;
  9 +use Lackoxygen\TiktokOpen\Wap\Data\Content\User;
  10 +use Lackoxygen\TiktokOpen\Wap\Data\Content\Video;
  11 +
  12 +/**
  13 + * @method User user()
  14 + * @method Video video()
  15 + * @method Fans fans()
  16 + * @method HotSearch hotSearch()
  17 + * @method Star star()
  18 + */
  19 +class Data extends ServiceManager
  20 +{
  21 + protected array $services = [
  22 + 'user' => User::class,
  23 + 'video' => Video::class,
  24 + 'fans' => Fans::class,
  25 + 'hotSearch' => HotSearch::class,
  26 + 'star' => Star::class
  27 + ];
  28 +
  29 + public function __call($name, $arguments)
  30 + {
  31 + $service = $this->services[$name];
  32 +
  33 + return new $service($this->app);
  34 + }
  35 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\Js;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class Js extends ServiceManager
  8 +{
  9 + public function ticket()
  10 + {
  11 + return $this->app['client']->withSession()->get(
  12 + '/js/getticket'
  13 + );
  14 + }
  15 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\Event\Request;
  6 +use Lackoxygen\TiktokOpen\Base\Event\Response;
  7 +use Lackoxygen\TiktokOpen\Base\Event\Fail;
  8 +
  9 +class Listener
  10 +{
  11 + public function request(Request $event)
  12 + {
  13 + if ($event->request->isWithSession()) {
  14 + $event->request->setData(
  15 + array_merge(
  16 + $event->request->getData(),
  17 + [
  18 + 'access_token' => $event->application['wap.session']->accessToken
  19 + ]
  20 + )
  21 + );
  22 + }
  23 + }
  24 +
  25 +
  26 + public function response(Response $event)
  27 + {
  28 +
  29 + }
  30 +
  31 +
  32 + public function fail(Fail $event)
  33 + {
  34 +
  35 + }
  36 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\OAuth;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class OAuth extends ServiceManager
  8 +{
  9 + public function accessToken(string $code)
  10 + {
  11 + return $this->app['client']->asForm()->post('/oauth/access_token/', [
  12 + 'grant_type' => 'authorization_code',
  13 + 'client_key' => $this->app['config']->getAppKey(),
  14 + 'client_secret' => $this->app['config']->getAppSecret(),
  15 + 'code' => $code
  16 + ]);
  17 + }
  18 +
  19 + public function connect(string $scope, string $redirectUri, string $optionalScope = '', string $state = '')
  20 + {
  21 + return $this->app['client']->get(
  22 + '/platform/oauth/connect/', [
  23 + 'client_key' => $this->app['config']->getAppKey(),
  24 + 'response_type' => 'code',
  25 + 'scope' => $scope,
  26 + 'optionalScope' => $optionalScope,
  27 + 'redirect_uri' => $redirectUri,
  28 + 'state' => $state
  29 + ]
  30 + );
  31 + }
  32 +
  33 +
  34 + public function renewRefreshToken(string $refreshToken)
  35 + {
  36 + return $this->app['client']->asForm()->post(
  37 + '/oauth/renew_refresh_token/',
  38 + [
  39 + 'client_key' => $this->app['config']->getAppKey(),
  40 + 'refresh_token' => $refreshToken
  41 + ]
  42 + );
  43 + }
  44 +
  45 +
  46 + public function clientToken()
  47 + {
  48 + return $this->app['client']->asForm()->post(
  49 + '/oauth/client_token/',
  50 + [
  51 + 'client_key' => $this->app['config']->getAppKey(),
  52 + 'client_secret' => $this->app['config']->getAppSecret(),
  53 + 'grant_type' => 'client_credential'
  54 + ]
  55 + );
  56 + }
  57 +
  58 +
  59 + public function refreshToken(string $refreshToken)
  60 + {
  61 +
  62 + return $this->app['client']->asForm()->post(
  63 + '/oauth/refresh_token/',
  64 + [
  65 + 'client_key' => $this->app['config']->getAppKey(),
  66 + 'grant_type' => 'refresh_token',
  67 + 'refresh_token' => $refreshToken
  68 + ]
  69 + );
  70 + }
  71 +
  72 +
  73 + public function authorizeV2($scope, $redirectUri, $state)
  74 + {
  75 + return $this->app['client']->get(
  76 + '/oauth/authorize/v2/',
  77 + [
  78 + 'client_key' => $this->app['config']->getAppKey(),
  79 + 'response_type' => 'code',
  80 + 'scope' => $scope,
  81 + 'redirect_uri' => $redirectUri,
  82 + 'state' => $state
  83 + ]
  84 + );
  85 + }
  86 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\Cache;
  6 +use Lackoxygen\TiktokOpen\Base\Exception\AnswerException;
  7 +use Lackoxygen\TiktokOpen\Base\Exception\Exception;
  8 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  9 +use Illuminate\Support\Arr;
  10 +use Illuminate\Support\Str;
  11 +
  12 +/**
  13 + * @property string $accessToken
  14 + * @property int $issueTime
  15 + * @property int $expiresIn
  16 + */
  17 +class Session extends ServiceManager
  18 +{
  19 + /**
  20 + * @var string $name
  21 + */
  22 + protected string $name = 'wap.session';
  23 +
  24 + /**
  25 + * @throws Exception
  26 + */
  27 + private function generateToken()
  28 + {
  29 + $response = $this->app['wap.oauth']->clientToken();
  30 +
  31 + try {
  32 + $this->storeResponse($response);
  33 + } catch (AnswerException $e) {
  34 + throw new Exception(
  35 + sprintf('Token creation exception, %s', $e->getMessage())
  36 + );
  37 + }
  38 + }
  39 +
  40 +
  41 + /**
  42 + * @throws AnswerException
  43 + */
  44 + private function storeResponse(array $response): void
  45 + {
  46 + $data = Arr::get($response, 'data', []);
  47 +
  48 + if (0 !== Arr::get($data, 'error_code')) {
  49 + throw new AnswerException(Arr::get($response, 'message'));
  50 + }
  51 + $expiresIn = (int)Arr::get($data, 'expires_in');
  52 +
  53 + $payload = [
  54 + 'access_token' => $data['access_token'],
  55 + 'issue_time' => time(),
  56 + 'expires_in' => $expiresIn,
  57 + ];
  58 +
  59 + Cache::put(
  60 + $this->name,
  61 + $payload,
  62 + $expiresIn - 30
  63 + );
  64 + }
  65 +
  66 + protected function get(string $key)
  67 + {
  68 + if (!Cache::has($this->name)) {
  69 +
  70 + $this->generateToken();
  71 + }
  72 +
  73 + $payload = Cache::get($this->name);
  74 +
  75 + return $payload[$key];
  76 + }
  77 +
  78 + public function __get($name)
  79 + {
  80 + $key = Str::snake($name);
  81 +
  82 + return $this->get($key);
  83 + }
  84 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\User;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class User extends ServiceManager
  8 +{
  9 + public function info(string $openid, string $accessToken)
  10 + {
  11 + return $this->app['client']->get(
  12 + '/oauth/userinfo/',
  13 + [
  14 + 'open_id' => $openid,
  15 + 'access_token' => $accessToken
  16 + ]
  17 + );
  18 + }
  19 +
  20 + public function fansList(string $openid, int $cursor, int $count, string $accessToken)
  21 + {
  22 + return $this->app['client']->get(
  23 + '/fans/list/',
  24 + [
  25 + 'open_id' => $openid,
  26 + 'cursor' => $cursor,
  27 + 'count' => $count,
  28 + 'access_token' => $accessToken,
  29 + ]
  30 + );
  31 + }
  32 +
  33 + public function followList(string $openid, int $cursor, int $count, string $accessToken)
  34 + {
  35 + return $this->app['client']->get(
  36 + '/following/list/',
  37 + [
  38 + 'open_id' => $openid,
  39 + 'cursor' => $cursor,
  40 + 'count' => $count,
  41 + 'access_token' => $accessToken
  42 + ]
  43 + );
  44 + }
  45 +
  46 + public function fansCheck(string $openid, string $followerOpenId, string $accessToken)
  47 + {
  48 + return $this->app['client']->get(
  49 + '/fans/check/',
  50 + [
  51 + 'open_id' => $openid,
  52 + 'follower_open_id' => $followerOpenId,
  53 + 'access_token' => $accessToken
  54 + ]
  55 + );
  56 + }
  57 +
  58 + public function decryptMobile($encryptedMobile)
  59 + {
  60 + $iv = substr($this->app['config']->getAppSecret(), 0, 16);
  61 + return \openssl_decrypt($encryptedMobile,
  62 + 'aes-256-cbc',
  63 + $this->app['config']->getAppSecret(),
  64 + 0,
  65 + $iv);
  66 + }
  67 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap\Video;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\ServiceManager;
  6 +
  7 +class Video extends ServiceManager
  8 +{
  9 + public function videoList(string $openid, string $accessToken, int $cursor, int $count)
  10 + {
  11 + return $this->app['client']
  12 + ->get(
  13 + '/video/list/',
  14 + [
  15 + 'open_id' => $openid,
  16 + 'access_token' => $accessToken,
  17 + 'cursor' => $cursor,
  18 + 'count' => $count,
  19 + ]
  20 + );
  21 + }
  22 +
  23 + public function videoData(string $openid, string $accessToken)
  24 + {
  25 + return $this->app['client']->asJson()->post(
  26 + '/video/data/',
  27 + [
  28 + 'open_id' => $openid,
  29 + 'access_token' => $accessToken,
  30 + ]
  31 + );
  32 + }
  33 +
  34 + public function shareId(bool $needCallback, string $sourceStyleId, string $defaultHashtag, string $linkParam)
  35 + {
  36 + return $this->app['client']->withSession()->get(
  37 + '/share-id/',
  38 + [
  39 + 'need_callback' => $needCallback,
  40 + 'source_style_id' => $sourceStyleId,
  41 + 'default_hashtag' => $defaultHashtag,
  42 + 'link_param' => $linkParam,
  43 + ]
  44 + );
  45 + }
  46 +
  47 + public function poiSearchKeyword($accessToken, int $cursor, int $count, string $keyword, string $city)
  48 + {
  49 + return $this->app['client']->get(
  50 + '/poi/search/keyword/',
  51 + [
  52 + 'access_token' => $accessToken,
  53 + 'cursor' => $cursor,
  54 + 'count' => $count,
  55 + 'keyword' => $keyword,
  56 + 'city' => $city,
  57 + ]
  58 + );
  59 + }
  60 +
  61 + public function videoSource(string $openid, string $accessToken)
  62 + {
  63 + return $this->app['client']->asJson()->post(
  64 + '/video/source/',
  65 + [
  66 + 'open_id' => $openid,
  67 + 'access_token' => $accessToken,
  68 + ]
  69 + );
  70 + }
  71 +
  72 +}
  1 +<?php
  2 +
  3 +namespace Lackoxygen\TiktokOpen\Wap;
  4 +
  5 +use Lackoxygen\TiktokOpen\Base\AbstractProvider;
  6 +use Lackoxygen\TiktokOpen\Base\Client\Client;
  7 +use Lackoxygen\TiktokOpen\Wap\{Data\Data, Js\Js, OAuth\OAuth, User\User, Video\Video};
  8 +
  9 +/**
  10 + * @method OAuth oauth()
  11 + * @method Js js()
  12 + * @method User user()
  13 + * @method Video video()
  14 + * @method Data data()
  15 + * @method Session session()
  16 + */
  17 +class WapProvider extends AbstractProvider
  18 +{
  19 + protected string $alias = 'wap';
  20 +
  21 + protected array $services = [
  22 + 'oauth' => OAuth::class,
  23 + 'js' => Js::class,
  24 + 'user' => User::class,
  25 + 'video' => Video::class,
  26 + 'data' => Data::class,
  27 + 'session' => Session::class
  28 + ];
  29 +
  30 + public function __construct(string $alias)
  31 + {
  32 + parent::__construct($alias);
  33 +
  34 + $this->addPreService('client', Client::class);
  35 + }
  36 +}
  37 +