WeiBanSync.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. <?php
  2. namespace App\Jobs;
  3. use App\Facades\Servers\Logs\Log;
  4. use Illuminate\Bus\Queueable;
  5. use Illuminate\Contracts\Queue\ShouldQueue;
  6. use Illuminate\Foundation\Bus\Dispatchable;
  7. use Illuminate\Queue\InteractsWithQueue;
  8. use Illuminate\Queue\SerializesModels;
  9. use App\Facades\Servers\WeiBan\OpenApi;
  10. use App\Models\WeiBan\Sync;
  11. use App\Models\Custom;
  12. use App\Models\WeiBan\External as WeiBanExternal;
  13. use App\Models\WeiBan\Follow as WeiBanFollow;
  14. use App\Models\WeiBan\Tags as WeiBanTags;
  15. use App\Models\City;
  16. use App\Models\CustomAddr;
  17. class WeiBanSync implements ShouldQueue
  18. {
  19. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  20. /**
  21. * 任务可尝试的次数
  22. *
  23. * @var int
  24. */
  25. public $tries = 3;
  26. /**
  27. * 队列参数
  28. * @var array|mixed
  29. */
  30. protected $extUser = [];
  31. /**
  32. * Create a new job instance.
  33. *
  34. * @return void
  35. */
  36. public function __construct($extUser=[])
  37. {
  38. // 获取参数赋值
  39. $this->extUser = $extUser;
  40. }
  41. /**
  42. * Execute the job.
  43. *
  44. * @return void
  45. */
  46. public function handle()
  47. {
  48. // 如果存在需要更新的的客户
  49. if( $this->extUser['id'] ){
  50. // 实例化
  51. $Sync = new Sync();
  52. // 尝试执行
  53. try{
  54. // 记录错误信息
  55. Log::error('weiban_sync','进行更新',$this->extUser);
  56. // 通过id查询详情信息
  57. $extUser = OpenApi::getUserDetail($this->extUser['id']);
  58. // 不存在客户信息,再次获取
  59. if( !$extUser ) $extUser = OpenApi::getUserDetail($this->extUser['id']);
  60. // 存在客户信息,则继续
  61. if( $extUser ) $this->sync_user($extUser);
  62. // 解除锁定
  63. $Sync->unlockSyncExtidMark($this->extUser['id']);
  64. // 记录错误信息
  65. Log::error('weiban_sync','更新成功',$this->extUser);
  66. } catch (\Exception $exception) {
  67. // 解除锁定
  68. $Sync->unlockSyncExtidMark($this->extUser['id']);
  69. // 记录错误信息
  70. Log::error('weiban_sync_error',$exception->getMessage().'尝试执行第'.$this->attempts().'次',$this->extUser);
  71. // 每次尝试执行 时间间隔
  72. $this->release($this->attempts() * 5);
  73. }
  74. }
  75. }
  76. /**
  77. * 同步
  78. *
  79. * */
  80. public function sync_user($extUser){
  81. // 实例
  82. $Custom = New Custom();
  83. $External = New WeiBanExternal();
  84. $Follow = New WeiBanFollow();
  85. $Tags = New WeiBanTags();
  86. // 获取结果
  87. $followList = $extUser['follow_staffs'];
  88. // 获取结构数据
  89. $extUser = ['id'=>$extUser['id'],'name'=>$extUser['name'],'avatar'=>str_ireplace('http://','https://',(string)$extUser['avatar']),'gender'=>$extUser['gender'],'type'=>$extUser['type'],'corp_name'=>(string)$extUser['corp_name'],'corp_full_name'=>(string)$extUser['corp_full_name'],'insert_time'=>$extUser['created_at'],'update_time'=>time(),'custom_uid'=>0];
  90. // 手机号
  91. $phone = '';
  92. // 标签处理
  93. $staffId = '';
  94. // 循环跟进客服
  95. foreach ( $followList as $follow ) {
  96. // 标签处理
  97. $this->tagsHandle($extUser['id'],$follow['staff_id'],$follow['tags'],$Tags);
  98. // 客服处理
  99. $this->staffHandle($follow,$extUser,$Follow);
  100. // 有手机号才获取手机号
  101. if( $follow['phone_number'] ) $phone = $follow['phone_number'];
  102. }
  103. // 如果没有客服,状态流失
  104. if( !$followList ) $extUser['status'] = 4;
  105. // 判断客户是否存在
  106. $oldExtUser = $External->query()->find($extUser['id'],['custom_uid']);
  107. // 如果存在账号的话获取客户UID
  108. if( $oldExtUser ) $extUser['custom_uid'] = ($oldExtUser->custom_uid);
  109. // 存在手机号,才创建账号
  110. if( $phone ) $extUser['custom_uid'] = $this->customHandle($phone,$extUser,$Custom);
  111. // 需要有客服,如果存在的旧账号但是 没有关联客户UID 还存在系统客户UID可关联
  112. if( $staffId && isset($oldExtUser['custom_uid']) && empty($oldExtUser['custom_uid']) && $extUser['custom_uid'] ){
  113. // 城市标签
  114. $this->cityTags($extUser,$staffId,$Custom);
  115. // 终端标签
  116. $this->shopTypeTag($staffId,$extUser);
  117. }
  118. // 新增或者修改
  119. $External->query()->upsert($extUser,'id',['name','avatar','gender','type','corp_name','corp_full_name','status','custom_uid','update_time']);
  120. }
  121. /**
  122. * 标签处理
  123. */
  124. private function tagsHandle($extId,$staffId,$tagList,WeiBanTags $Tags){
  125. // 如果标签不存在,删除客服给客户的标签
  126. if( !$tagList ) return $Tags->query()->where([['weiban_extid','=',$extId],['staff_id','=',$staffId]])->delete();
  127. // 查询客户的标签
  128. $oldTags = $Tags->getListByExtStaff($extId,$staffId);
  129. // 循环标签数据
  130. foreach ($tagList as $k=>$tag) {
  131. // 标签数据
  132. $tag['id'] = 0;
  133. // 获取结果
  134. foreach ($oldTags as $oldtag) {
  135. // 如果有相同的话,获取ID
  136. if( $oldtag['name'] == $tag['name'] && $oldtag['group'] == $tag['group'] ) $tag['id'] = $oldtag['id'];
  137. }
  138. // 如果没有ID
  139. if( !$tag['id'] ) {
  140. // 返回结果
  141. $tag['id'] = $Tags->add(['name'=>$tag['name'],'group'=>$tag['group'],'weiban_extid'=>$extId,'staff_id'=>$staffId]);
  142. }
  143. // 重组
  144. $follow['tags'][$k] = $tag;
  145. }
  146. // 如果不在标签内的,删除
  147. if( $follow['tags'] ) $Tags->query()->where([['weiban_extid','=',$extId],['staff_id','=',$staffId]])->whereNotIn('id',array_column($follow['tags'],'id'))->delete();
  148. // 返回结果
  149. return true;
  150. }
  151. /**
  152. * 注册处理
  153. */
  154. private function customHandle($phone,$extUser,Custom $Custom){
  155. // 是否已经注册
  156. $custom = $Custom->getOneByPhone($phone);
  157. // 如果已经注册
  158. $uid = $custom ? $Custom->edit($custom['uid'],['username'=>$extUser['name'],'userpic'=>$extUser['avatar'],'sex'=>$extUser['gender'],'weiban_extid'=>$extUser['id']]) : $Custom->add(['phone'=>$phone,'username'=>$extUser['name'],'userpic'=>$extUser['avatar'],'sex'=>$extUser['gender'],'weiban_extid'=>$extUser['id']]);
  159. // 成功,赋值
  160. return $uid;
  161. }
  162. /**
  163. * 客服处理
  164. */
  165. private function staffHandle($follow,$extUser,WeiBanFollow $Follow){
  166. // 备注手机号,如果存在,解析成数组,转字符串
  167. $follow['remark_mobiles'] = $follow['remark_mobiles'] ? implode(',',json_decode($follow['remark_mobiles'],true)): '';
  168. // 获取必要数据
  169. $follow = [
  170. 'staff_id'=>(string)$follow['staff_id'],
  171. 'staff_name'=>str_ireplace('http://','https://',(string)$follow['staff_name']),
  172. 'staff_avatar'=>(string)$follow['staff_avatar'],
  173. 'phone_number'=>(string)$follow['phone_number'],
  174. 'remark'=>(string)$follow['remark'],
  175. 'remark_state'=>(string)$follow['remark_state'],
  176. 'remark_corp_name'=>(string)$follow['remark_corp_name'],
  177. 'remark_mobiles'=>(string)$follow['remark_mobiles'],
  178. 'state_name'=>(string)$follow['state_name'],
  179. 'state_text'=>(string)$follow['state_text'],
  180. 'state_type'=>(string)$follow['state_type'],
  181. 'deleted_by'=>(string)$follow['deleted_by'],
  182. // 员工删除客户1,客户删除的2
  183. 'status'=>( $follow['deleted'] ? 1 : ( $follow['deleted_each_other'] ? 2 : 0)),
  184. 'weiban_extid'=>$extUser['id'],
  185. ];
  186. // 如果没有企微企业,使用客服备注的企业
  187. if( !$extUser['corp_name']) $extUser['corp_name'] = $follow['remark_corp_name'];
  188. // 判断客户是否跟进中
  189. $followId = $Follow->query()->where([['weiban_extid','=',$extUser['id']],['staff_id','=',$follow['staff_id']]])->value('id');
  190. // 有则更新,无则增加
  191. $followId ? $Follow->edit($followId,$follow) : $Follow->add($follow);
  192. }
  193. /**
  194. * 城市标签
  195. */
  196. private function cityTags($extUser,$staffId,Custom $Custom){
  197. // 实例化
  198. $City = New City();
  199. // 获取城市ID
  200. $cityId = $Custom->getValue($extUser['custom_uid'],'city_id');
  201. // 如果有城市
  202. if( !$cityId ) return ['info'=>'请先设置城市'];
  203. // 获取用户城市信息
  204. $city = $City->getOne($cityId);
  205. // 如果有城市信息
  206. if( !$city ) return ['info'=>'未查询到城市'];
  207. // 获取上级城市/省份
  208. $parentCity = $City->getOne($city['pid']);
  209. // 如果上级是省辖,获取省份
  210. if( isset($parentCity['name']) && $parentCity['name'] == '直辖县级' ) $parentCity = $City->getOne($parentCity['pid']);
  211. // 如果有获取到省份信息
  212. if( !$parentCity ) return ['info'=>'未查询到省份'];
  213. // 省份
  214. $province = str_ireplace(['自治区','壮族','回族','维吾尔','特别行政区','省'],'',$parentCity['name']);
  215. // 省份
  216. $cityName = str_ireplace(['自治州','自治县','蒙古','蒙古族','回族','藏族','维吾尔','苗族','彝族','壮族','布依族','朝鲜族','满族','侗族','瑶族','白族','土家族','哈尼族','哈萨克','傣族','黎族','傈僳族','佤族','畲族','拉祜族','水族','东乡族','纳西族','景颇族','柯尔克孜','土族','达斡尔族','仫佬族','羌族','布朗族','撒拉族','毛南族','仡佬族','锡伯','阿昌族','普米族','塔吉克','怒族','鄂温克族','德昂族','保安族','裕固族','塔塔尔','独龙族'],'',$city['name']);
  217. // 打省份标签
  218. if( !$province ) return ['info'=>'暂无省份数据'];
  219. // 打省份标签
  220. if( !$cityName ) return ['info'=>'暂无城市数据'];
  221. // 打省份标签
  222. $result['province'] = OpenApi::addTag($staffId,$extUser['id'],'省份',$province);
  223. // 打城市标签
  224. $result['cityNname'] = OpenApi::addTag($staffId,$extUser['id'],$province,$cityName);
  225. // 返回结果
  226. return ['success'=>'返回结果','result'=>$result];
  227. }
  228. /**
  229. * 终端类型标签
  230. *
  231. */
  232. public function shopTypeTag($staffId,$extUser){
  233. // 地址模型
  234. $Addr = New CustomAddr();
  235. // 打终端类型标签
  236. $shopType = (int) $Addr->query()->where([['custom_uid','=',$extUser['custom_uid']],['shop_type','>',0]])->value('shop_type');
  237. // 如果有地址信息
  238. switch ($shopType) {
  239. case '1':
  240. $shopType = '单店';
  241. break;
  242. case '3':
  243. $shopType = '连锁';
  244. break;
  245. case '4':
  246. $shopType = '第三终端';
  247. break;
  248. default:
  249. $shopType = '';
  250. break;
  251. }
  252. // 没有数据,直接结束
  253. if( !$shopType ) return ['info'=>'没有终端类型标签'];
  254. // 如果有终端类型
  255. $result = OpenApi::addTag($staffId,$extUser['id'],'企业类型',$shopType);
  256. // 数据返回
  257. return ['success'=>'返回结果','result'=>$result];
  258. }
  259. }