ByteDance.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <?php
  2. namespace App\Helper;
  3. use App\Helper\Bytedance\ByteDanceAPI;
  4. use GuzzleHttp\Client;
  5. use GuzzleHttp\Exception\GuzzleException;
  6. class ByteDance
  7. {
  8. private $appId = null;
  9. private $appKey = null;
  10. private $secret = null;
  11. private $accessTokenFile = null;
  12. private $accessToken = null;
  13. /**
  14. * @param array $config
  15. * @return $this
  16. */
  17. public function factory($config = [])
  18. {
  19. $this->appId = $config['app_id'];
  20. $this->appKey = $config['app_key'];
  21. $this->secret = $config['app_secret'];
  22. $this->accessTokenFile = storage_path('app/bytedance/bytedance_access_token.json');
  23. $this->accessToken = $this->checkAccessToken();
  24. return $this;
  25. }
  26. /**
  27. * @param string $code
  28. * @param string $anonymousCode
  29. * @return array|mixed
  30. * @throws \Exception
  31. */
  32. public function login($code = '',$anonymousCode = '')
  33. {
  34. return $this->post(ByteDanceAPI::LOGIN, [
  35. 'code' => $code,
  36. 'anonymous_code' => $anonymousCode,
  37. ]);
  38. }
  39. /**
  40. * @param string $sessionKey
  41. * @param string $iv
  42. * @param string $encrypted
  43. * @return array
  44. * @throws \Exception
  45. */
  46. public function decryptData(string $sessionKey, string $iv, string $encrypted): array
  47. {
  48. $decrypted = openssl_decrypt(
  49. base64_decode($encrypted,true),
  50. 'AES-128-CBC',
  51. base64_decode($sessionKey),
  52. OPENSSL_RAW_DATA,
  53. base64_decode($iv)
  54. );
  55. $decrypted = json_decode($decrypted,true);
  56. if(empty($decrypted)){
  57. throw new \Exception('解密数据错误');
  58. }
  59. return $decrypted;
  60. }
  61. /**
  62. * 校验access token 是否过期
  63. * @return mixed
  64. */
  65. private function checkAccessToken() : string
  66. {
  67. try {
  68. $dir = storage_path('app/bytedance');
  69. if (!is_dir($dir)) mkdir($dir, 0755);
  70. if (!is_file($this->accessTokenFile)) touch($this->accessTokenFile);
  71. $accessToken = file_get_contents($this->accessTokenFile);
  72. $accessToken = $accessToken ? json_decode($accessToken,true) : null;
  73. if (empty($accessToken) || $accessToken['expires_at'] < time()) {
  74. $accessToken = $this->getAccessToken();
  75. }else{
  76. $accessToken = $accessToken['access_token'];
  77. }
  78. return $accessToken;
  79. } catch (\Exception $e) {
  80. }
  81. }
  82. /**
  83. * 获取 access token
  84. * @throws \Exception
  85. */
  86. private function getAccessToken() : string
  87. {
  88. $res = $this->post(ByteDanceAPI::ACCESS_TOKEN, [
  89. 'grant_type' => 'client_credential'
  90. ]);
  91. if (!empty($res['err_no'])) {
  92. throw new \Exception('获取access token 错误');
  93. }
  94. file_put_contents($this->accessTokenFile, json_encode([
  95. 'access_token' => $res['access_token'],
  96. 'expires_at' => $res['expiresAt']
  97. ]));
  98. return $res['access_token'];
  99. }
  100. /**
  101. * 接口请求
  102. *
  103. * @param string $uri
  104. * @param array $data
  105. * @return array|mixed
  106. * @throws \Exception
  107. */
  108. private function post($uri = '', $data = []) : array
  109. {
  110. try {
  111. $data = array_merge($data,[
  112. 'appid' => $this->appId,
  113. 'secret' => $this->secret,
  114. ]);
  115. $client = new Client();
  116. $res = $client->post($uri, [
  117. 'verify' => false,
  118. 'headers' => ['Content-Type' => 'application/json'],
  119. 'body' => json_encode($data)
  120. ]);
  121. $stringBody = (string)$res->getBody();
  122. $res = json_decode($stringBody, true);
  123. if(!empty($res['err_no'])){
  124. throw new \Exception("请求字节跳动API接口错误,错误码:{$res['err_no']},错误信息:{$res['err_tips']}");
  125. }
  126. return $res['data'];
  127. } catch (GuzzleException $e) {
  128. trace($e->getMessage(), 'error');
  129. throw new \Exception($e->getMessage());
  130. }
  131. }
  132. }