123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 |
- <?php
- namespace App\Services\OpenApi;
- use App\Cache\UserCache;
- use App\Consts\ErrorConst;
- use App\Consts\SysConst;
- use App\Dao\Channel\ChannelDao;
- use App\Dao\SendOrder\SendOrderDao;
- use App\Dao\User\UserDao;
- use App\Libs\TikTok\Application;
- use App\Libs\TikTok\MiniProgram\Application as MiniProgramApplication;
- use App\Libs\TikTok\OpenPlatform\Application as OpenPlatformApplication;
- use App\Libs\TikTok\Kernel\Exceptions;
- use App\Libs\Utils;
- use GuzzleHttp\Exception\GuzzleException;
- use App\Exceptions\ApiException;
- class OpenService
- {
- // private MiniProgramApplication $app;
- // private OpenPlatformApplication $openApp;
- private $app;
- private $openApp;
- private $userDao;
- private $channelDao;
- private $sendOrderDao;
- public function __construct(
- UserDao $userDao,
- ChannelDao $channelDao,
- SendOrderDao $sendOrderDao
- )
- {
- $this->userDao = $userDao;
- $this->channelDao = $channelDao;
- $this->sendOrderDao = $sendOrderDao;
- }
- /**
- * 实例化小程序
- *
- * @param array $param
- * @return $this
- */
- public function getInstance(array $param = []): OpenService
- {
- // 获取配置
- $config = $this->getConfig($param);
- $this->app = Application::miniProgram($config);
- return $this;
- }
- /**
- * 实例化小程序
- *
- * @param array $param
- * @return $this
- */
- public function getOpenInstance(array $param = []): OpenService
- {
- // 获取配置
- $config = $this->getConfig($param);
- $this->openApp = Application::openPlatform($config);
- return $this;
- }
- /**
- * @param $param
- * @return array
- */
- private function getConfig($param): array
- {
- $config = [
- 'app_id' => env('DOUYIN_APP_ID'),
- 'secret' => env('DOUYIN_APP_SECRET'),
- 'cache' => [
- 'type' => 'Redis',
- 'host' => env('REDIS_HOST'),
- 'port' => env('REDIS_PORT'),
- 'password' => env('REDIS_PASSWORD'),
- 'select' => env('REDIS_DB'),
- 'prefix' => '',
- 'serialize' => []
- ],
- ];
- // 基本参数
- $appId = getProp($param, 'app_id');
- $secret = getProp($param, 'secret');
- if ($appId) $config['app_id'] = $appId;
- if ($secret) $config['secret'] = $secret;
- // 沙箱模式
- if (getProp($param, 'sandbox')) {
- $config['http'] = [
- 'base_uri' => 'https://open-sandbox.douyin.com/api/',
- ];
- }
- return $config;
- }
- /**
- * @param bool $refresh
- * @return array
- * @throws Exceptions\HttpException
- * @throws Exceptions\InvalidArgumentException
- * @throws Exceptions\InvalidConfigException
- * @throws Exceptions\RuntimeException
- * @throws GuzzleException
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function getAccessToken(bool $refresh = false): array
- {
- $result = $this->app->access_token->getToken($refresh);
- dLog('openApi')->info('getAccessToken', $result);
- return $result;
- }
- /**
- * 登录
- *
- * @param int $sendOrderId
- * @param string $code
- * @param string $anonymousCode
- * @return array
- * @throws ApiException
- * @throws GuzzleException
- */
- public function code2Session(int $sendOrderId, string $code, string $anonymousCode = '')
- {
- dLog('openApi')->info('code2Session', compact('sendOrderId', 'code', 'anonymousCode'));
- try {
- $result = $this->app->auth->session($code, $anonymousCode);
- } catch (\Exception $e) {
- dLog('openApi')->info('code2Session-exception', [$e->getMessage()]);
- Utils::throwError(ErrorConst::SYS_EXCEPTION);
- }
- dLog('openApi')->info('code2Session-result', compact('result'));
- // 解析返回值
- $resultData = getProp($result, 'data', []);
- $unionId = getProp($resultData, 'unionid');
- $openId = getProp($resultData, 'openid');
- $newSessionKey = getProp($resultData, 'session_key');
- // 判断返回信息
- if (empty($openId) || empty($unionId)) {
- Utils::throwError(ErrorConst::USER_AUTH_FAIL);
- }
- // 获取派单信息(派单对应的站点id即为用户注册的站点id,无派单,则设置默认站点id)
- $sendOrder = $this->sendOrderDao->getSendOrderById($sendOrderId);
- $sendOrderChannelId = (int)getProp($sendOrder, 'distribution_channel_id', SysConst::DEFAULT_CHANNEL_ID);
- // 获取用户数据
- $user = $this->userDao->getUserByOpenIdAndUnionId($openId, $unionId);
- $uid = (int)getProp($user, 'id');
- $oldSessionKey = getProp($user, 'session_key');
- $userSendOrderId = (int)getProp($user, 'send_order_id', $sendOrderId);
- $channelId = (int)getProp($user, 'distribution_channel_id', $sendOrderChannelId);
- dLog('openApi')->info('code2Session-user', compact('uid', 'oldSessionKey'));
- // 计算token
- $isNewUser = false;
- [$oldToken, $newToken] = [md5($oldSessionKey), md5($newSessionKey)];
- if (empty($user)) {
- // 新建用户
- $user = $this->userDao->createUser([
- 'openid' => $openId,
- 'unionid' => $unionId,
- 'session_key' => $newSessionKey,
- 'token' => $newToken,
- 'distribution_channel_id' => $channelId,
- 'bind_time' => date('Y-m-d H:i:s'),
- 'sex' => 2,
- 'register_ip' => _getIp()
- ]);
- // 新uid
- $uid = getProp($user, 'id');
- if (!$uid) {
- Utils::throwError(ErrorConst::USER_INI_FAIL);
- }
- // 更新用户名
- $user->nickname = "用户" . $uid;
- $user->invite_code = (int)$uid + 100000;
- $user->save();
- // 新用户标识
- $isNewUser = true;
- } else {
- // 更新用户数据
- $this->userDao->updateUserById($uid, [
- 'session_key' => $newSessionKey,
- 'token' => $newToken,
- 'invite_code' => $uid + 100000,
- 'updated_at' => date('Y-m-d H:i:s')
- ]);
- }
- // 更新redis token数据
- UserCache::setTokenData($newToken, [
- 'uid' => $uid,
- 'distribution_channel_id' => $channelId,
- 'send_order_id' => $userSendOrderId,
- 'from_uid' => (int)getProp($user, 'from_uid'),
- ]);
- UserCache::delTokenData($oldToken);
- // 获取注册用户站点信息
- $channel = $this->channelDao->getChannelById($channelId);
- // 全局绑定(后续绑定逻辑需要用到这些字段)
- $site = app('siteData');
- $site->uid = (int)$uid;
- $site->token = $newToken;
- $site->channel_type = getProp($channel, 'channel_type', 'PERIOD');
- return ['uid' => $uid, 'token' => $newToken, 'distribution_channel_id' => $channelId, 'is_new_user' => $isNewUser];
- }
- /**
- * @param string $rawData
- * @param string $sessionKey
- * @param string $signature
- * @return bool
- */
- public function checkUserDataValid(string $rawData, string $sessionKey, string $signature): bool
- {
- if ($signature != sha1($rawData . $sessionKey)) {
- return false;
- }
- return true;
- }
- /**
- * 解密用户数据
- *
- * @param string $encryptedData
- * @param string $sessionKey
- * @param string $iv
- * @return array
- */
- public function decryptUserData(string $encryptedData, string $sessionKey, string $iv): array
- {
- if (empty($encryptedData) || empty($sessionKey) || empty($iv)) {
- return [];
- }
- try {
- $result = $this->app->encryptor->decryptData($sessionKey, $iv, $encryptedData);
- } catch (\Exception $e) {
- dLog('openApi')->info('decryptUserData-exception', [$e->getMessage()]);
- return [];
- }
- dLog('openApi')->info('decryptUserData', $result);
- return $result;
- }
- /**
- * 获取小程序端内分享链接
- *
- * @param string $path
- * @param string $query
- * @return array
- * @throws GuzzleException
- */
- public function generateShareLink(string $path = '', string $query = ''): array
- {
- try {
- $result = $this->app->share->generateLink($path, $query);
- } catch (\Exception $e) {
- dLog('openApi')->info('generateShareLink-exception', [$e->getMessage()]);
- return [];
- }
- dLog('openApi')->info('generateShareLink', $result);
- return $result;
- }
- /**
- * 查询已经生成的 link 的信息
- *
- * @param string $url_link
- * @return array
- */
- public function getShareQueryInfo(string $url_link = '')
- {
- try {
- $result = $this->app->share->getQueryInfo($url_link);
- } catch (\Exception $e) {
- dLog('openApi')->info('getShareQueryInfo-exception', [$e->getMessage()]);
- return [];
- }
- dLog('openApi')->info('getShareQueryInfo', $result);
- return $result;
- }
- public function createQRCode(string $path = '')
- {
- try {
- $result = $this->app->share->createQRCode($path);
- } catch (\Exception $e) {
- dLog('openApi')->info('createQRCode-exception', [$e->getMessage()]);
- return [];
- }
- dLog('openApi')->info('createQRCode', $result);
- return $result;
- }
- /**
- * @param string $openId
- * @param int $orderStatus
- * @param array $orderDetail
- * @return array
- * @throws GuzzleException
- */
- public function pushOrder(string $openId, int $orderStatus, array $orderDetail): array
- {
- try {
- $result = $this->app->order->push($openId, $orderStatus, $orderDetail);
- } catch (\Exception $e) {
- dLog('openApi')->info('pushOrder-exception', [$e->getMessage()]);
- return [];
- }
- dLog('openApi')->info('pushOrder', $result);
- return $result;
- }
- /**
- * 查询抖音开放能力列表
- *
- * @return array
- */
- public function permissionList(): array
- {
- try {
- $result = $this->app->capacity->queryPermissionList();
- } catch (\Exception $e) {
- dLog('openApi')->info('permissionList-exception', [$e->getMessage()]);
- return [];
- }
- dLog('openApi')->info('permissionList', $result);
- return $result;
- }
- /**
- * @param bool $refresh
- * @return array
- * @throws Exceptions\HttpException
- * @throws Exceptions\InvalidArgumentException
- * @throws Exceptions\InvalidConfigException
- * @throws Exceptions\RuntimeException
- * @throws GuzzleException
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function getClientToken(bool $refresh = false): array
- {
- $result = $this->openApp->access_token->getToken($refresh);
- dLog('openApi')->info('getClientToken', $result);
- return $result;
- }
- /**
- * @param string $serviceOpenId 客服号openId
- * @param array $data
- * @return array
- * @throws GuzzleException
- */
- public function senImMsg(string $serviceOpenId, array $data): array
- {
- dLog('openApi')->info('senImMsg-params', compact('serviceOpenId', 'data'));
- try {
- $result = $this->openApp->im->sendMsg($serviceOpenId, $data);
- } catch (\Exception $e) {
- dLog('openApi')->info('senImMsg-exception', [$e->getMessage()]);
- return [];
- }
- dLog('openApi')->info('senImMsg', $result);
- return $result;
- }
- /**
- * @return array
- */
- public function eventList()
- {
- try {
- $result = $this->openApp->event->eventList();
- } catch (\Exception $e) {
- dLog('openApi')->info('eventList-exception', [$e->getMessage()]);
- return [];
- }
- dLog('openApi')->info('eventList', $result);
- return $result;
- }
- }
|