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. $sin = sha1("{$encrypted}{$sessionKey}");
  56. $decrypted = json_decode($decrypted,true);
  57. if(empty($decrypted)){
  58. throw new \Exception('解密数据错误');
  59. }
  60. return $decrypted;
  61. }
  62. /**
  63. * 校验access token 是否过期
  64. * @return mixed
  65. */
  66. private function checkAccessToken() : string
  67. {
  68. try {
  69. $dir = storage_path('app/bytedance');
  70. if (!is_dir($dir)) mkdir($dir, 0755);
  71. if (!is_file($this->accessTokenFile)) touch($this->accessTokenFile);
  72. $accessToken = file_get_contents($this->accessTokenFile);
  73. $accessToken = $accessToken ? json_decode($accessToken,true) : null;
  74. if (empty($accessToken) || $accessToken['expires_at'] < time()) {
  75. $accessToken = $this->getAccessToken();
  76. }else{
  77. $accessToken = $accessToken['access_token'];
  78. }
  79. return $accessToken;
  80. } catch (\Exception $e) {
  81. }
  82. }
  83. /**
  84. * 获取 access token
  85. * @throws \Exception
  86. */
  87. private function getAccessToken() : string
  88. {
  89. $res = $this->post(ByteDanceAPI::ACCESS_TOKEN, [
  90. 'grant_type' => 'client_credential'
  91. ]);
  92. if (!empty($res['err_no'])) {
  93. throw new \Exception('获取access token 错误');
  94. }
  95. file_put_contents($this->accessTokenFile, json_encode([
  96. 'access_token' => $res['access_token'],
  97. 'expires_at' => $res['expiresAt']
  98. ]));
  99. return $res['access_token'];
  100. }
  101. /**
  102. * 接口请求
  103. *
  104. * @param string $uri
  105. * @param array $data
  106. * @return array|mixed
  107. * @throws \Exception
  108. */
  109. private function post($uri = '', $data = []) : array
  110. {
  111. try {
  112. $data = array_merge($data,[
  113. 'appid' => $this->appId,
  114. 'secret' => $this->secret,
  115. ]);
  116. $client = new Client();
  117. $res = $client->post($uri, [
  118. 'verify' => false,
  119. 'headers' => ['Content-Type' => 'application/json'],
  120. 'body' => json_encode($data)
  121. ]);
  122. $stringBody = (string)$res->getBody();
  123. $res = json_decode($stringBody, true);
  124. if(!empty($res['err_no'])){
  125. throw new \Exception("请求字节跳动API接口错误,错误码:{$res['err_no']},错误信息:{$res['err_tips']}");
  126. }
  127. return $res['data'];
  128. } catch (GuzzleException $e) {
  129. trace($e->getMessage(), 'error');
  130. throw new \Exception($e->getMessage());
  131. }
  132. }
  133. }