企微短剧业务系统

TokenService.php 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <?php
  2. namespace App\Service;
  3. use App\Log;
  4. use App\RedisModel;
  5. class TokenService
  6. {
  7. const SUITE_ACCESS_TOKEN = 'Playlet::SuitAccessToken_';
  8. const PROVIDER_ACCESS_TOKEN = 'Playlet::AccessToken_';
  9. const ACCESS_TOKEN_RDS = 'Playlet::AccessTokenBySecret_';
  10. const JSAPI_TICKET_RDS = 'Playlet::JsapiTicket_';
  11. const APP_JSAPI_TICKET_RDS = 'Playlet::AppJsapiTicket_';
  12. /**
  13. * 获取预授权码
  14. * */
  15. public static function getPreAuthCode($suiteId, $suiteSecret)
  16. {
  17. # 获取预授权码API地址
  18. $preAuthCodeUrl = config('qyWechat.pre_auth_code');
  19. # 获取令牌
  20. $accessToken = self::getAuthToken($suiteId, $suiteSecret);
  21. $preAuthCodeUrl .= $accessToken;
  22. $postData = [
  23. 'component_appid' => $suiteId
  24. ];
  25. $response = HttpService::httpPost($preAuthCodeUrl, json_encode($postData));
  26. if($response === false) {
  27. Log::logError('预授权码API请求失败', [], 'PreAuthCode');
  28. return false;
  29. }
  30. $responseData = json_decode($response, true);
  31. if(empty($responseData) || (isset($responseData['errcode']) && $responseData['errcode'] != 0)) {
  32. # 写入日志
  33. Log::logError('预授权码API请求响应结果异常', $responseData, 'PreAuthCode');
  34. return false;
  35. }
  36. $preAuthCode = $responseData['pre_auth_code'];
  37. return $preAuthCode;
  38. }
  39. /**
  40. * 获取服务商凭证
  41. * @param $corpid string 服务商的corpid
  42. * */
  43. public static function getProviderToken($corpid, $suiteSecret)
  44. {
  45. $accessTokenStr = RedisModel::get(TokenService::PROVIDER_ACCESS_TOKEN. $corpid);
  46. if(!empty($accessTokenStr)) {
  47. $accessTokenData = json_decode($accessTokenStr, true);
  48. $expire = $accessTokenData['expire'];
  49. $accessToken = $accessTokenData['provider_access_token'] ?? '';
  50. if($expire <= time() || empty($accessToken)) {
  51. $accessToken = self::getProviderAccessToken($corpid, $suiteSecret);
  52. }
  53. } else {
  54. $accessToken = self::getProviderAccessToken($corpid, $suiteSecret);
  55. }
  56. return $accessToken;
  57. }
  58. /**
  59. * 获取第三方应用access_token
  60. * 令牌有效期2小时
  61. * */
  62. public static function getAuthToken($suiteId, $suiteSecret)
  63. {
  64. $accessTokenStr = RedisModel::get(TokenService::SUITE_ACCESS_TOKEN. md5($suiteId));
  65. if(!empty($accessTokenStr)) {
  66. $accessTokenData = json_decode($accessTokenStr, true);
  67. $expire = $accessTokenData['expire'];
  68. $accessToken = isset($accessTokenData['suite_access_token']) ?
  69. $accessTokenData['suite_access_token'] : '';
  70. if($expire <= time() || empty($accessToken)) {
  71. $accessToken = self::getSuiteAccessToken($suiteId, $suiteSecret);
  72. }
  73. } else {
  74. $accessToken = self::getSuiteAccessToken($suiteId, $suiteSecret);
  75. }
  76. return $accessToken;
  77. }
  78. /**
  79. * 获取第三方应用凭证
  80. * @param $corpid string 服务商的corpid
  81. * */
  82. public static function getProviderAccessToken($corpid, $suiteSecret, $retry=0)
  83. {
  84. $redisKey = TokenService::PROVIDER_ACCESS_TOKEN. $corpid;
  85. # 获取令牌API地址
  86. $apiComponentTokenUrl = config('qyWechat.get_provider_token');
  87. $postData = [
  88. 'corpid' => $corpid,
  89. 'provider_secret' => $suiteSecret,
  90. ];
  91. $response = HttpService::httpPost($apiComponentTokenUrl, json_encode($postData));
  92. $responseData = json_decode($response, true);
  93. if($response === false || empty($responseData) || isset($responseData['errcode'])) {
  94. if($retry <= 5) {
  95. $retry++;
  96. return self::getProviderAccessToken($corpid, $suiteSecret, $retry);
  97. }
  98. Log::logError('服务商凭证获取API请求失败', ['postData' => $postData, 'response' => $responseData], 'ProviderAccessToken');
  99. return false;
  100. }
  101. $accessToken = $responseData['provider_access_token'];
  102. $saveData = [
  103. 'provider_access_token' => $accessToken,
  104. 'expire' => time() + 7000
  105. ];
  106. # 将accessToken存入Redis
  107. RedisModel::set($redisKey, json_encode($saveData));
  108. RedisModel::expire($redisKey, 7200);
  109. return $accessToken;
  110. }
  111. /**
  112. * 获取第三方应用凭证
  113. * */
  114. public static function getSuiteAccessToken($suiteId, $suiteSecret, $retry=0)
  115. {
  116. $redisKey = TokenService::SUITE_ACCESS_TOKEN. md5($suiteId);
  117. # 获取令牌API地址
  118. $apiComponentTokenUrl = config('qyWechat.component_url');
  119. # 获取验证票据
  120. $suiteTicket = RedisModel::get('Playlet::Ticket' . md5($suiteId));
  121. $postData = [
  122. 'suite_id' => $suiteId,
  123. 'suite_secret' => $suiteSecret,
  124. 'suite_ticket' => $suiteTicket
  125. ];
  126. Log::logInfo('postData:', [
  127. 'postData' => $postData,
  128. 'rds' => 'Playlet::Ticket' . md5($suiteId)
  129. ], 'SuiteAccessToken');
  130. $response = HttpService::httpPost($apiComponentTokenUrl, json_encode($postData));
  131. if($response === false) {
  132. if($retry <= 5) {
  133. $retry++;
  134. return self::getSuiteAccessToken($suiteId, $suiteSecret, $retry);
  135. }
  136. Log::logError('第三方平台令牌获取API请求失败', [], 'SuiteAccessToken');
  137. return false;
  138. }
  139. $responseData = json_decode($response, true);
  140. if(empty($responseData) || isset($responseData['errcode'])) {
  141. if($retry <= 5) {
  142. $retry++;
  143. return self::getSuiteAccessToken($suiteId, $suiteSecret, $retry);
  144. }
  145. Log::logError('第三方平台令牌获取API请求响应结果异常', $responseData, 'SuiteAccessToken');
  146. return false;
  147. }
  148. $accessToken = $responseData['suite_access_token'];
  149. $saveData = [
  150. 'suite_access_token' => $accessToken,
  151. 'expire' => time() + 7000
  152. ];
  153. # 将accessToken存入Redis
  154. RedisModel::set($redisKey, json_encode($saveData));
  155. RedisModel::expire($redisKey, 7200);
  156. return $accessToken;
  157. }
  158. /**
  159. * 获取授权方(企业)凭证
  160. * */
  161. public static function getCorpToken($corpid, $permanentCode, $suiteId, $suiteTicket, $retry=0)
  162. {
  163. # 获取SuiteAccessToken
  164. $suiteAccessToken = TokenService::getSuiteAccessToken($suiteId, $suiteTicket);
  165. # 获取永久授权码链接
  166. $permanentCodeUri = config('qyWechat.get_corp_token');
  167. $permanentCodeUri .= $suiteAccessToken;
  168. $postData = array('auth_corpid' => $corpid, 'permanent_code' => $permanentCode);
  169. $response = HttpService::httpPost($permanentCodeUri, json_encode($postData));
  170. $responseData = json_decode($response, true);
  171. if(isset($responseData['errcode']) && $responseData['errcode']) {
  172. if($retry <=5) {
  173. $retry++;
  174. TokenService::getCorpToken($corpid, $permanentCode, $suiteId, $suiteTicket, $retry);
  175. }
  176. Log::logError('授权方凭证获取失败', $responseData, 'CorpTokenGet');
  177. return false;
  178. }
  179. $accessToken = isset($responseData['access_token']) ? $responseData['access_token'] : null;
  180. if(empty($accessToken)) {
  181. if($retry <=5) {
  182. $retry++;
  183. TokenService::getCorpToken($corpid, $permanentCode, $suiteId, $suiteTicket, $retry);
  184. }
  185. Log::logError('授权方凭证获取失败', $responseData, 'CorpTokenGet');
  186. return false;
  187. }
  188. return $accessToken;
  189. }
  190. }