123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918 |
- <?php
- /**
- * Created by PhpStorm.
- * User: shensong
- * Date: 2022/3/16
- * Time: 16:50
- */
- namespace App\Service;
- # 爬取企业微信数据
- use App\Log;
- use App\Models\AuthorizeCorp;
- use App\Models\ChatGroup;
- use App\Models\Customer;
- use App\Models\CustomerDetails;
- use App\Models\CustomerTag;
- use App\Models\DjDepartment;
- use App\Models\DjUser;
- use App\Models\Tag;
- use App\Models\TagGroup;
- use App\RedisModel;
- use App\Support\EmailQueue;
- use App\Support\qyApi\QyCommon;
- class wechatWorkService
- {
- CONST SYNC_CORP_CUSTOMER = 'Playlet::SyncCorpCustomer';
- CONST SYNC_FAIL_USER_RDS = 'Playlet::SyncCorpCustomerFailUser';
- public static function getCorCustomerList($corpid)
- {
- $requestData = [
- 'corpid' => $corpid
- ];
- if(empty($corpid)) {
- Log::logInfo('getCorCustomerList 企业id为空 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return [['error' => '企业id为空'], 2004];
- }
- // 判断键是否存在
- $redisKey = 'Playlet::getCorCustomerList-'.$corpid;
- $value = RedisModel::get($redisKey);
- if(!empty($value)) {
- Log::logInfo('getCorCustomerList 操作太快 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return [['error' => '操作太快'], 2007];
- }
- // 根据企业id获取accessToken
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '全量获取企业部门、标签和员工信息');
- if(empty($accessToken)) {
- Log::logInfo('getCorCustomerList 获取企业access_token失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return [['error' => '获取企业access_token失败'], 2000];
- }
- // 根据企业获取部门列表
- $departmentList = self::getCorDepartmentList($corpid, $accessToken);
- if(empty($departmentList)) {
- Log::logInfo('getCorCustomerList 部门权限获取失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return [['error' => '部门权限获取失败'], 2001];
- }
- // 将部门信息保存到本地
- foreach($departmentList as $department) {
- $departmentId = $department['id'];
- $res = wechatWorkService::getDepartmentInfo($departmentId, $corpid, $accessToken);
- if(!empty($res)) {
- DjDepartment::departmentInfoSave($corpid, $res);
- }
- $res = wechatWorkService::departmentUserList($corpid, $departmentId, $accessToken);
- if(isset($res['errcode']) && $res['errcode'] == 0) {
- if(!empty($res['userlist'])) {
- // 将员工信息保存入库
- foreach($res['userlist'] as $user) {
- $userId = DjUser::departmentUserSave($corpid, $user);
- }
- } else {
- Log::logInfo('getCorCustomerList 获取内部员工信息为空 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- }
- } else {
- Log::logInfo('getCorCustomerList 获取内部员工信息失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return [['error' => '获取内部员工信息失败'], 2002];
- }
- }
- # 获取所有企业标签
- $data1 = wechatWorkService::getCorTagList($corpid);
- if(!empty($data1)) {
- // Log::logInfo('getCorCustomerList 获取企业标签失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- // return [['error' => '获取企业标签失败'], 2005];
- // } else {
- $re1 = wechatWorkService::tagDataSave($corpid, 1, $data1);
- if(!$re1) {
- Log::logInfo('getCorCustomerList 保存企业标签失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return [['error' => '保存企业标签失败'], 2006];
- }
- }
- # 获取所有客户群
- RedisModel::lPush(ChatGroup::CHAT_GROUP_BASIC_INFO_RDS, json_encode(['corpid' => $corpid], 256));
- // 获取所有已激活客服列表
- $followUserList = DjUser::getUserIdList($corpid);
- $followUserList = json_decode(json_encode($followUserList), 1);
- // 循环处理配置了客户联系功能的员工,拉取对应的客户信息
- // 如果使用没有配置联系我的内部员工id来请求数据的话,接口会返回user_id异常的错误信息
- $followUserListArr = array_chunk($followUserList, 100);
- foreach ($followUserListArr as $userArr) {
- $value['corpid'] = $corpid;
- $value['user_list'] = $userArr;
- RedisModel::lPush(AuthorizeCorp::SYNC_CORP_CUSTOMER, json_encode($value));
- }
- RedisModel::set($redisKey, time());
- RedisModel::expire($redisKey, 600);
- return [['info' => '获取成功'], 0];
- }
- public static function syncCorpData($corpid)
- {
- $requestData = [
- 'corpid' => $corpid
- ];
- $subject = config('app.name') . '于' . date('d日H:i:s') . '响应异常';
- try{
- if(empty($corpid)) {
- Log::logError('syncCorpData',[
- 'params' => $requestData,
- 'errmsg' => '企微id为空',
- ], 'interface');
- return [['error' => '企业id为空'], 2004];
- }
- // 判断键是否存在
- $redisKey = 'Playlet::getCorCustomerList-'.$corpid;
- $value = RedisModel::get($redisKey);
- if(!empty($value)) {
- Log::logError('syncCorpData', [
- 'params' => $requestData,
- 'errmsg' => '请求频率超限制',
- ], 'interface');
- return [['error' => '操作太快'], 2007];
- }
- // 根据企业id获取accessToken
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '全量获取企业部门、标签和员工信息');
- if(empty($accessToken)) {
- Log::logError('syncCorpData', [
- 'params' => $requestData,
- 'errmsg' => '获取企业access_token失败',
- ], 'interface');
- return [['error' => '获取企业access_token失败'], 2000];
- }
- // 根据企业获取部门列表
- $departmentResponse = QyCommon::simplelist($corpid);
- if(isset($departmentResponse['errcode']) && $departmentResponse['errcode'] == 0) {
- $departmentList = $departmentResponse['department_id'];
- } else {
- Log::logError('syncCorpData', [
- 'params' => $requestData,
- 'errmsg' => '部门权限获取失败',
- 'response' => $departmentResponse,
- ], 'interface');
- $content = '同步企微信息--获取授权部门列表失败';
- EmailQueue::rPush($subject, nl2br($content), ['song.shen@kuxuan-inc.com'], config('app.name'));
- return [['error' => '部门权限获取失败'], 2001];
- }
- if(empty($departmentList)) {
- Log::logError('syncCorpData', [
- 'params' => $requestData,
- 'errmsg' => '获取部门列表为空',
- 'response' => $departmentResponse,
- ], 'interface');
- return [['error' => '获取部门列表为空'], 2009];
- }
- // 将部门信息保存到本地
- foreach($departmentList as $department) {
- $departmentId = $department['id'];
- $departmentInfoResponse = QyCommon::get_department_info($corpid, $departmentId);
- if(isset($departmentInfoResponse['errcode']) && $departmentInfoResponse['errcode'] == 0) {
- $departmentInfo = $departmentInfoResponse['department'];
- if(!empty($departmentInfo)) {
- DjDepartment::departmentInfoSave($corpid, $departmentInfo);
- }
- }
- $res = wechatWorkService::departmentUserList($corpid, $departmentId, $accessToken);
- if(isset($res['errcode']) && $res['errcode'] == 0) {
- if(!empty($res['userlist'])) {
- // 将员工信息保存入库
- foreach($res['userlist'] as $user) {
- $userId = DjUser::departmentUserSave($corpid, $user);
- }
- } else {
- Log::logInfo('syncCorpData 获取内部员工信息为空 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- }
- } else {
- Log::logInfo('syncCorpData 获取内部员工信息失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return [['error' => '获取内部员工信息失败'], 2002];
- }
- }
- # 获取所有企业标签
- $data1 = wechatWorkService::getCorTagList($corpid);
- if(empty($data1)) {
- Log::logInfo('syncCorpData 获取企业标签失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return [['error' => '获取企业标签失败'], 2005];
- } else {
- $re1 = wechatWorkService::tagDataSave($corpid, 1, $data1);
- if(!$re1) {
- Log::logInfo('syncCorpData 保存企业标签失败 request:'.json_encode($requestData, JSON_UNESCAPED_UNICODE), [], 'interface');
- return [['error' => '保存企业标签失败'], 2006];
- }
- }
- $followUserList = DjUser::getUserIdList($corpid);
- $followUserList = json_decode(json_encode($followUserList), 1);
- // 循环处理配置了客户联系功能的员工,拉取对应的客户信息
- // 如果使用没有配置联系我的内部员工id来请求数据的话,接口会返回user_id异常的错误信息
- $followUserListArr = array_chunk($followUserList, 100);
- foreach ($followUserListArr as $userArr) {
- $value['corpid'] = $corpid;
- $value['user_list'] = $userArr;
- RedisModel::lPush(AuthorizeCorp::SYNC_CORP_CUSTOMER, json_encode($value));
- }
- RedisModel::set($redisKey, time());
- RedisModel::expire($redisKey, 600);
- return [['info' => '获取成功'], 0];
- } catch (\Exception $exception) {
- Log::logError('syncCorpData',[
- 'params' => $requestData,
- 'exception' => $exception->getMessage(),
- 'file' => $exception->getFile(),
- 'line' => $exception->getLine(),
- 'trace' => $exception->getTraceAsString(),
- ], 'interface');
- $subject = config('app.name') . '于' . date('d日H:i:s') . '抛出异常';
- $content = $exception->getMessage() . "\r\n\r\n" . $exception->getTraceAsString();
- EmailQueue::rPush($subject, nl2br($content), ['song.shen@kuxuan-inc.com'], config('app.name'));
- return [['errcode' => '系统异常'], 400];
- }
- }
- // 根据企业id获取企业部门列表
- public static function getCorDepartmentList($corpid, $accessToken = null)
- {
- if(empty($corpid) && empty($accessToken)) {
- return [];
- }
- if(empty($accessToken)) {
- //根据企业id获取对应的access_token
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '根据企业id获取企业部门列表');
- }
- // 部门id。获取指定部门及其下的子部门(以及子部门的子部门等等,递归)。 如果不填,默认获取全量组织架构
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/department/simplelist?access_token='.$accessToken.'&id=';
- $result = HttpService::httpGet($url);
- $result = json_decode($result, 1);
- Log::logInfo('获取企业部门列表,URL'.$url, (array)$result, 'department');
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- // 请求成功
- $departmentList = $result['department_id'];
- return $departmentList;
- } else {
- // 请求失败,将响应数据写入日志
- EmailQueue::rPush('获取企业部门列表失败', json_encode([
- 'corpid' => $corpid, 'result' => (array)$result
- ]), ['song.shen@kuxuan-inc.com'], '猎羽');
- return [];
- }
- }
- // 根据部门id获取部门详情
- public static function getDepartmentInfo($departmentId, $corpid, $accessToken = null)
- {
- if((empty($corpid) && empty($accessToken)) || empty($departmentId)) {
- return [];
- }
- if(empty($accessToken)) {
- //根据企业id获取对应的access_token
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '根据部门id获取部门详情');
- }
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/department/get?access_token='.$accessToken.'&id='.$departmentId;
- $result = HttpService::httpGet($url);
- $result = json_decode($result, 1);
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- return $result['department'];
- } else {
- // 请求失败,将响应数据写入日志
- Log::logError('获取部门详情失败,URL:'.$url, (array)$result, 'department');
- EmailQueue::rPush('获取部门详情失败', json_encode([
- 'corpid' => $corpid, 'department_id' => $departmentId, 'result' => (array)$result
- ]), ['song.shen@kuxuan-inc.com'], '猎羽');
- return [];
- }
- }
- // 获取部门下的员工列表
- public static function departmentUserList($corpid, $departmentId, $accessToken = null)
- {
- if((empty($corpid) && empty($accessToken)) || empty($departmentId)) {
- return [];
- }
- if(empty($accessToken)) {
- //根据企业id获取对应的access_token
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '获取部门下的员工列表');
- }
- $fetchChild = 1; // 是否递归获取子部门下面的成员:1-递归获取,0-只获取本部门
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token='.$accessToken.'&department_id='.$departmentId.'&fetch_child='.$fetchChild;
- $result = HttpService::httpGet($url);
- $result = json_decode($result, 1);
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- return $result;
- } else {
- // 请求失败,将响应数据写入日志
- Log::logError('获取部门下的成员列表失败,URL:'.$url, (array)$result, 'get_department_user_list');
- EmailQueue::rPush('获取部门下的成员列表失败', json_encode([
- 'corpid' => $corpid, 'department_id' => $departmentId, 'result' => (array)$result
- ]), ['song.shen@kuxuan-inc.com'], '猎羽');
- return [];
- }
- }
- // 根据内容员工获取外部客户外层方法(有分页,需要循环获取)
- public static function getCustomerListByUserId($corpid, $userList, $accessToken = null)
- {
- if(empty($corpid) || empty($userList)) {
- return [];
- }
- $params = [
- 'userid_list' => $userList,
- 'cursor' => '',
- 'limit' => 100
- ];
- $flag = true;
- $result = null;
- $count = 0;
- while ($flag) {
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '根据员工获取外部客户');
- try{
- $result = wechatWorkService::getCustomerListMethod($params, $accessToken, $corpid);
- // if($corpid == 'wwdfec0bcee287d5c5') {
- // Log::logInfo('同步客户', ['corpid' => $corpid, 'user_list' => $userList, 'res' =>$result], 'get_corp_customer_list');
- // }
- if(!$result) {
- $flag = false;
- }
- if(!empty($result['external_contact_list'])) {
- // 将数据保存入库,并进行翻页查询
- self::userCustomerDataSave($result['external_contact_list'], $corpid);
- $count += count($result['external_contact_list']);
- }
- # 全部都没有许可时直接返回错误码
- if(isset($result['errcode']) && $result['errcode'] == 701008) {
- foreach($userList as $userId) {
- RedisModel::lPush(self::SYNC_FAIL_USER_RDS, json_encode([
- 'corpid' => $corpid, 'user_id' => $userId
- ]));
- }
- $flag = false;
- }
- if(isset($result['errcode']) && $result['errcode'] == 60111) {
- # 部分客服userid不存在(在放入队列之后客服离职了)
- // 提取客服userid,将异常userid从数据中排除,然后将处理好的数据重新赛回待处理队列
- $errmsg = $result['errmsg'] ?? '';
- preg_match("/`(.*)`/i", $errmsg, $userArr);
- if(isset($userArr[1]) && !empty($userArr[1])) {
- $userId = $userArr[1];
- $key = array_search($userId, $userList);
- unset($userList[$key]);
- RedisModel::lPush(AuthorizeCorp::DAILY_SYNC_CORP_CUSTOMER, json_encode([
- 'corpid' => $corpid,
- 'user_list' => array_values($userList),
- ]));
- } else {
- EmailQueue::rPush('同步客服对应客户列表中处理userid异常', json_encode([
- 'corpid' => $corpid,
- 'user_list' => $userList,
- 'result' => $result
- ]), ['song.shen@kuxuan-inc.com'], '猎羽');
- }
- $flag = false;
- }
- # 部分客服没有许可时会返回无许可客服列表
- if(!empty($result['fail_info']['unlicensed_userid_list']) && empty($params['cursor'])) {
- foreach($result['fail_info']['unlicensed_userid_list'] as $userId) {
- RedisModel::lPush(self::SYNC_FAIL_USER_RDS, json_encode([
- 'corpid' => $corpid, 'user_id' => $userId
- ]));
- }
- }
- if(empty($result['next_cursor'])) {
- $flag = false;
- } else {
- $params['cursor'] = $result['next_cursor'];
- }
- } catch (\Exception $exception) {
- Log::logError('获取企业微信客户数据异常',[
- 'exception' => $exception->getMessage(),
- 'file' => $exception->getFile(),
- 'line' => $exception->getLine(),
- ], 'sync_corp_customer_exception');
- $subject = config('app.name') . '于' . date('d日H:i:s') . '抛出异常';
- $content = $exception->getMessage() . "\r\n\r\n" . $exception->getTraceAsString();
- EmailQueue::rPush($subject, nl2br($content), ['song.shen@kuxuan-inc.com'], config('app.name'));
- }
- }
- self::checkoutResponse($corpid, $userList, $count);
- Log::logInfo('获取客户列表结果记录', [
- 'corpid' => $corpid, 'user_list' => $userList, 'count' => $count
- ], 'get_corp_customer_list');
- }
- // 根据内部员工获取外部联系客户具体方法
- public static function getCustomerListMethod($params, $accessToken, $corpid, $retry = 0)
- {
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user?access_token='.$accessToken;
- $result = HttpService::httpPost($url, json_encode($params), true);
- $result = mb_convert_encoding($result, "UTF-8");
- $result = json_decode($result, 1);
- if((empty($result) || (isset($result['errcode']) && in_array($result['errcode'], [-1]))) && $retry < 5) {
- sleep(2);
- $retry++;
- return self::getCustomerListMethod($params, $accessToken, $corpid, $retry);
- }
- if(isset($result['errcode']) && in_array($result['errcode'], [0, 701008, 60111, 610023])) {
- return $result;
- } else {
- // 请求失败,将响应数据写入日志
- Log::logError('获取内部员工对应的外部联系人列表失败:URL'.$url.', 请求参数:'.json_encode(array_merge($params, ['corpid' => $corpid])),
- (array)$result, 'get_user_customer_list');
- EmailQueue::rPush('获取内部员工对应的外部联系人列表失败', json_encode([
- 'url' => $url, 'params' => array_merge($params, ['corpid' => $corpid]), 'result' => (array)$result
- ]), ['song.shen@kuxuan-inc.com'], '猎羽');
- return false;
- }
- }
- public static function checkoutResponse($corpid, $userList, $count) {
- # 当同步单个客服时,对比同步下来的客户数与客户总数,查看是否完全同步
- if(count($userList) == 1) {
- $response = QyCommon::getExternalContactList($corpid, current($userList));
- if(isset($response['errcode'])) {
- if(0 == $response['errcode']) {
- $customerCount = count($response['external_userid']);
- } else if (in_array($response['errcode'], [701008, 84061])) {
- $customerCount = 0;
- } else {
- $customerCount = 0;
- EmailQueue::rPush('获取客户列表结果异常', json_encode([
- 'corpid' => $corpid, 'user_id' => current($userList), 'response' => $response
- ]), ['song.shen@kuxuan-inc.com'], '猎羽系统');
- }
- if($customerCount > $count) {
- EmailQueue::rPush('批量获取客户数据数少于实际客户数', json_encode([
- 'corpid' => $corpid, 'user_id' => current($userList), 'real_count' => $customerCount, 'get_count' => $count
- ]), ['song.shen@kuxuan-inc.com'], '猎羽系统');
- }
- }
- }
- }
- // 内部员工以及外部客户联系等数据保存入库
- public static function userCustomerDataSave($data, $corpid)
- {
- try{
- foreach($data as $item) {
- // 企业成员客户跟进信息
- $followInfo = $item['follow_info'];
- // 客户基本信息
- $externalContact = $item['external_contact'];
- \DB::beginTransaction();
- // 保存客户信息,并返回客户id
- $customerId = Customer::externalContactDataSave($corpid, $externalContact);
- // 保存员工客户跟进信息
- if($customerId > 0) {
- // $followInfoId = CustomerRelation::followInfoDataSave($corpid, $followInfo, $customerId,
- // $externalContact['external_userid']);
- $followInfoId = CustomerDetails::followInfoDataSave($corpid, $followInfo, $customerId,
- $externalContact);
- // 自动打日期标签
- // TagService::autoMarkCustomerAddDateTag($corpid, $customerId, $followInfo);
- if($followInfoId > 0) {
- // // 如果标签列表不为空,则将标签信息也一并记录下来
- // if(isset($followInfo['tag_id']) && !empty($followInfo['tag_id'])) {
- // $customerRes = CustomerTag::customerTagSave($corpid, $followInfo, $externalContact,
- // $customerId);
- // if($customerRes > 0) {
- // \DB::commit();
- // } else {
- // \DB::rollBack();
- // }
- // } else {
- \DB::commit();
- // }
- } else {
- \DB::rollBack();
- }
- } else {
- \DB::rollBack();
- $params = $item;
- $params['corpid'] = $corpid;
- // 保存用户信息异常
- Log::logError('保存客户信息失败, 参数'.json_encode($params), [],
- 'external_contract_data_save');
- }
- }
- } catch (\Exception $exception) {
- EmailQueue::rPush('保存客户信息失败', $exception->getTraceAsString(), ['xiaohua.hou@kuxuan-inc.com'], '保存客户信息失败');
- \DB::rollBack();
- // 保存用户信息异常
- Log::logError('保存客户信息失败', [
- 'exception' => $exception->getMessage(),
- 'file' => $exception->getFile(),
- 'line' => $exception->getLine(),
- ], 'external_contract_data_save');
- }
- }
- // 获取配置了客户联系功能的成员列表
- public static function followUserList($corpid, $accessToken = null)
- {
- if(empty($corpid)) {
- return [];
- }
- if(empty($accessToken)) {
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '获取配置了客户联系功能的成员列表');
- }
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_follow_user_list?access_token='.$accessToken;
- $result = HttpService::httpGet($url);
- $result = json_decode($result, 1);
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- return [$result['follow_user'], 0];
- } else {
- $errcode = $result['errcode'] ?? null;
- // 请求失败,将响应数据写入日志
- Log::logError('获取配置了客户联系功能的成员列表失败,url:'.$url,
- (array)$result,
- 'follow_user_list');
- EmailQueue::rPush('获取配置了客户联系功能的成员列表失败', json_encode([
- 'corpid' => $corpid, 'result' => (array)$result
- ]), ['song.shen@kuxuan-inc.com'], '猎羽');
- return [[], $errcode];
- }
- }
- // 获取企业标签
- public static function getCorTagList($corpid, Array $tagId = [], Array $groupId = [], $accessToken = null)
- {
- if(empty($corpid) && empty($accessToken)) {
- return [];
- }
- if(empty($accessToken)) {
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '获取企业标签');
- }
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_corp_tag_list?access_token='.$accessToken;
- $params = [];
- if(!empty($tagId)) {
- $params['tag_id'] = $tagId;
- }
- if(!empty($groupId)) {
- $params['group_id'] = $groupId;
- }
- $result = HttpService::httpPost($url, json_encode($params), true);
- $result = json_decode($result, 1);
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- return $result['tag_group'];
- } else {
- // 请求失败,将响应数据写入日志
- Log::logError('获取企业下所有标签失败,url:'.$url,
- (array)$result,
- 'get_cor_tag_list');
- EmailQueue::rPush('获取企业下标签失败', json_encode([
- 'corpid' => $corpid, 'url' => $url, 'request' => (array)$result
- ]), ['song.shen@kuxuan-inc.com'], '猎羽');
- return [];
- }
- }
- // 获取所有企业规则组标签
- public static function getStrategyTagList($corpid, $strategyId = null, Array $tagId = [], Array $groupId = [], $accessToken = null)
- {
- if(empty($corpid) && empty($accessToken)) {
- return [];
- }
- if(empty($accessToken)) {
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '获取所有企业规则组标签');
- }
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_strategy_tag_list?access_token='.$accessToken;
- $params = [];
- if(!empty($strategyId)) {
- $params['strategy_id'] = $strategyId;
- }
- if(!empty($tagId)) {
- $params['tag_id'] = $tagId;
- }
- if(!empty($groupId)) {
- $params['group_id'] = $groupId;
- }
- $result = HttpService::httpPost($url, json_encode($params), true);
- $result = json_decode($result, 1);
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- return $result['tag_group'];
- } else {
- // 请求失败,将响应数据写入日志
- Log::logError('获取企业下所有规则组标签失败,URL:'.$url.',参数:'.json_encode($params),
- (array)$result,
- 'get_strategy_tag_list');
- return [];
- }
- }
- // 标签信息保存入库
- public static function tagDataSave($corpid, $type, $data)
- {
- if(empty($corpid) || empty($data)) {
- return false;
- }
- try{
- // 添加编辑标签
- if(isset($data['group_id'])) {
- $groupRes = TagGroup::dataSave($corpid, $type, $data);
- if(!empty($data['tag'])) {
- foreach($data['tag'] as $tag) {
- $tagRes = Tag::dataSave($corpid, $data['group_id'], $tag);
- if(0 == $tagRes) {
- return false;
- }
- }
- }
- if(0 == $groupRes) {
- return false;
- }
- } else {
- // 获取企业下所有标签
- foreach($data as $group) {
- $groupRes = TagGroup::dataSave($corpid, $type, $group);
- if(!empty($group['tag'])) {
- foreach($group['tag'] as $tag) {
- $tagRes = Tag::dataSave($corpid, $group['group_id'], $tag);
- if(0 == $tagRes) {
- return false;
- }
- }
- }
- if(0 == $groupRes) {
- return false;
- }
- }
- }
- } catch (\Exception $exception) {
- Log::logError('标签信息保存入库失败', [
- 'exception' => $exception->getMessage(),
- 'line' => $exception->getLine(),
- 'file' => $exception->getFile()
- ], 'tag_data_save');
- }
- return true;
- }
- /**
- * 根据客户跟进关系表中标签信息
- * @param $corpid -企业id
- * @param $type -标签类型 1企业标签 2用户自定义标签 3规则组标签
- * @param $data -标签数据
- * @return bool
- */
- public static function updateCustomerTag($corpid, $type, $data)
- {
- if(empty($corpid) || empty($data)) {
- return false;
- }
- \DB::begintransaction();
- foreach($data as $group) {
- $item['group_name'] = $group['group_name'];
- $item['type'] = $type;
- if(!empty($group['tag'])) {
- foreach($group['tag'] as $tag) {
- $item['tag_name'] = $tag['name'];
- $res = CustomerTag::updateCustomerTag($corpid, $tag['id'], $item);
- if($res == 0) {
- \DB::rollBack();
- return false;
- }
- }
- }
- }
- \DB::commit();
- return true;
- }
- /*
- * 创建企业标签
- * $corpid 企业id 获取access_token用
- * $groupId 标签组id 可为空
- * $groupName 标签组名称,最长为30个字符 可为空,$groupId和$groupName不能同时为空
- * $order 标签组次序值,order值大的排序靠前。有效的值范围是[0, 2^32) 可为空
- * $tag 标签数组
- * $name 标签名称,最长30个字符,必传
- * $order 标签次序值 可为空
- */
- public static function addCorpTag($corpid, $groupId, $groupName, $order, $tag, $accessToken = null)
- {
- if(empty($corpid) || empty($tag) || (empty($groupName) && empty($groupId))) {
- return false;
- }
- if(empty($accessToken)) {
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '创建企业标签');
- }
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_corp_tag?access_token='.$accessToken;
- $params['tag'] = $tag;
- if(!empty($groupId)) {
- $params['group_id'] = $groupId;
- }
- if(!empty($groupName)) {
- $params['group_name'] = $groupName;
- }
- if(!empty($order)) {
- $params['order'] = $order;
- }
- $result = HttpService::httpPost($url, json_encode($params), true);
- $result = json_decode($result, 1);
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- // 将数据保存入库
- $res = self::tagDataSave($corpid, 1, $result['tag_group']);
- if($res) {
- return true;
- } else {
- return false;
- }
- } else {
- Log::logError('新增企业标签失败, URL:'.$url.', 请求参数:'.json_encode($params), (array)$result,
- 'add_corp_tag');
- return false;
- }
- }
- /*
- * 编辑客户企业标签
- * @param $corpid string 企业id
- * @param $userId string 添加外部联系人的userid 必传
- * @param $externalUserId string 外部联系人userid 必传
- * @param $addTag array 要标记的标签id列表 可为空
- * @param $removeTag array 要移除的标签id列表 可为空 add_tag和remove_tag不可同时为空。
- * @param null $accessToken
- * @return bool
- */
- public static function markTag($corpid, $userId, $externalUserId, $addTag, $removeTag, $accessToken = null, $retry = 0)
- {
- if((empty($corpid) && empty($accessToken)) || empty($userId) || empty($externalUserId)) {
- return false;
- }
- if(empty($accessToken)) {
- $accessToken = AuthorizeCorp::getAccessToken($corpid, '编辑客户企业标签');
- }
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/externalcontact/mark_tag?access_token='.$accessToken;
- $params['userid'] = $userId;
- $params['external_userid'] = $externalUserId;
- if(!empty($addTag)) {
- $params['add_tag'] = $addTag;
- }
- if(!empty($removeTag)) {
- $params['remove_tag'] = $removeTag;
- }
- $result = HttpService::httpPost($url, json_encode($params), true);
- $result = json_decode($result, 1);
- Log::logInfo('客户打标签接口', [
- 'corpid' => $corpid,
- 'params' => $params,
- 'response' => $result
- ], 'markTag');
- $returnFlag = false;
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- //编辑成功了,还需要处理本地的数据
- TagService::updateLocalCustomerTagSecond($corpid, $userId, $externalUserId, $addTag, $removeTag);
- $returnFlag = true;
- } else {
- // 员工不在企微 跳过不处理
- if('60111' == $result['errcode']) {
- $returnFlag = true;
- }
- // 不存在的客户联系关系 跳过不处理
- if('84061' == $result['errcode']) {
- RedisModel::lPush(CustomerDetails::CUSTOMER_LOSS_INFO_RDS, json_encode([
- 'corpid' => $corpid,
- 'user_id' => $userId,
- 'external_userid' => $externalUserId
- ], 256));
- $returnFlag = true;
- }
- if(in_array($result['errcode'], [45033, 45035, -1])) {
- if($retry < 5){
- $retry++;
- $seconds = rand(1,5);
- sleep($seconds);
- return self::markTag($corpid, $userId, $externalUserId, $addTag, $removeTag, null, $retry);
- }
- }
- EmailQueue::rPush('【'.$corpid.'】客户打标签失败', json_encode([
- 'url' => $url, 'params' => $params, 'result' => $result
- ], 256), ['song.shen@kuxuan-inc.com'], '猎羽系统');
- }
- return $returnFlag;
- }
- public static function convertUseridToOpenid($corpid, $userId)
- {
- if(empty($corpid) || empty($userId)) {
- return false;
- }
- $accessToken = AuthorizeCorp::getAccessToken($corpid, 'UserId转换OpenId');
- $url = 'https://qyapi.weixin.qq.com/cgi-bin/user/convert_to_openid?access_token='.$accessToken;
- $params['userid'] = $userId;
- $result = HttpService::httpPost($url, json_encode($params), true);
- $result = json_decode($result, 1);
- if(isset($result['errcode']) && $result['errcode'] == 0) {
- // 请求成功了
- return $result['openid'];
- } else {
- return false;
- }
- }
- }
|