OpenApi.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. <?php namespace App\Servers\WeiBan;
  2. use Ixudra\Curl\Facades\Curl;
  3. use App\Facades\Servers\Logs\Log;
  4. use App\Models\WeiBan\Taglist;
  5. /**
  6. * 微信小程序
  7. *
  8. */
  9. class OpenApi
  10. {
  11. // 微伴接口API
  12. private $domain = 'https://open.weibanzhushou.com';
  13. // 微伴接口调用接口凭证
  14. private $accessToken = null;
  15. // 返回结果
  16. public function __construct(){
  17. // 接口凭证不存在则获取
  18. if( is_null($this->accessToken) ) $this->accessToken = $this->getAccessToken();
  19. }
  20. /**
  21. * 获取接口调用凭证
  22. *
  23. */
  24. public function getAccessToken(){
  25. // 从缓存获取数据
  26. $corpId = config('weiban.corp_id');
  27. $secret = config('weiban.secret');
  28. // 如果没有配置
  29. if( !$corpId || !$secret ) return '';//['error'=>'请先配置微伴助手接口参数'];
  30. // 缓存key
  31. $key = 'weiban:corpid:access_token:'.$corpId;
  32. // 获取凭证
  33. $accessToken = cache($key);
  34. // 如果存在凭证
  35. if( $accessToken ) return $accessToken;
  36. // 组装接口
  37. $url = $this->domain.'/open-api/access_token/get';
  38. // 获取凭证
  39. $result = Curl::to($url)->withData(['corp_id'=>$corpId,'secret'=>$secret])->asJson(true)->post();
  40. // 如果没有返回
  41. if( !isset($result['errcode']) ) {
  42. // 记录错误信息
  43. Log::error('weiban_openai/access_token','未获取到凭证');
  44. return '';
  45. }
  46. // 调用失败
  47. if( $result['errcode'] != 0 ) {
  48. // 记录错误信息
  49. Log::error('weiban_openai/access_token',$result['errcode'].'=>'.$result['errmsg']);
  50. return '';
  51. }
  52. // 调用成功,缓存调用凭证
  53. cache([$key=>$result['access_token']],$result['expires_in']);
  54. // 返回凭证
  55. return $result['access_token'];
  56. }
  57. /**
  58. * 获取更新的用户列表
  59. *
  60. * @param int $limit 每页条数
  61. * @param int $offset 列表偏移。用于迭代获取所有数据,默认值为0
  62. * @param int $startTime 时间筛选开始时间,时间戳格式。
  63. * @param string $source 客户关联信息的类型,可选external_user(用户信息), remark(客户详情页的基本信息和自定义信息), staff_relation(客户关系), tag_relation(标签数据)。
  64. * (注:返回的数据是external_user的updated_at,source选external_user外的其他条件是筛选(remark:客户更新基本信息, staff_relation:客户更新关系,tag_relation: 客户更新标签)时间。)
  65. *
  66. */
  67. public function getUserList($limit,$offset,$startTime=0,$source='remark'){
  68. // 获取调用凭证
  69. $accessToken = $this->getAccessToken();
  70. // 如果没有返回
  71. if( !$accessToken ) return ['total'=>0,'user_list'=>[]];
  72. // 参数
  73. $param = ['order'=>'asc','source'=>$source,'start_update_time'=>$startTime,'limit'=>$limit,'offset'=>$offset,'access_token'=>$accessToken];
  74. // 组装接口
  75. $url = $this->domain.'/open-api/external_user/update/list';
  76. // 调用接口
  77. $result = Curl::to($url)->withData($param)->asJson(true)->get();
  78. // 如果没有返回
  79. if( !isset($result['errcode']) ) {
  80. Log::error('weiban_openai/external_user_update',$source.'=>未获取到用户列表');
  81. return ['total'=>0,'user_list'=>[]];
  82. }
  83. // 如果是凭证错误,递归
  84. if( $result['errcode'] == '10001' ) return $this->getUserList($limit,$offset,$startTime);
  85. // 调用失败
  86. if( $result['errcode'] != 0 ) {
  87. Log::error('weiban_openai/external_user_update',$source.'=>'.$result['errcode'].'=>'.$result['errmsg']);
  88. return ['total'=>0,'user_list'=>[]];
  89. }
  90. // 返回结果
  91. return ['total'=>$result['total'],'user_list'=>$result['external_user_list']];
  92. }
  93. /**
  94. * 获取手机号用户
  95. *
  96. * @param string $phone 手机号
  97. *
  98. */
  99. public function getUserListByPhone($phone){
  100. // 获取调用凭证
  101. $accessToken = $this->getAccessToken();
  102. // 如果没有返回
  103. if( !$accessToken ) return [];
  104. // 参数
  105. $param = ['phone_number'=>$phone,'access_token'=>$accessToken];
  106. // 组装接口
  107. $url = $this->domain.'/open-api/external_user/list';
  108. // 调用接口
  109. $result = Curl::to($url)->withData($param)->asJson(true)->get();
  110. // 如果没有返回
  111. if( !isset($result['errcode']) ) {
  112. Log::error('weiban_openai/external_user_list','未获取到用户列表');
  113. return [];
  114. }
  115. // 如果是凭证错误,递归
  116. if( $result['errcode'] == '10001' ) return $this->getUserListByPhone($phone);
  117. // 调用失败
  118. if( $result['errcode'] != 0 ) {
  119. Log::error('weiban_openai/external_user_list',$result['errcode'].'=>'.$result['errmsg']);
  120. return [];
  121. }
  122. // 返回结果
  123. return $result['external_user_list'];
  124. }
  125. /**
  126. * 获取用户详情
  127. *
  128. * @param string 客户id。对应企业微信客户 id
  129. *
  130. */
  131. public function getUserDetail($id) {
  132. // 获取调用凭证
  133. $accessToken = $this->getAccessToken();
  134. // 如果没有返回
  135. if( !$accessToken ) return [];
  136. // 组装接口
  137. $url = $this->domain.'/open-api/external_user/get';
  138. // 调用接口
  139. $result = Curl::to($url)->withData(['id'=>$id,'access_token'=>$accessToken])->asJson(true)->get();
  140. // 如果没有返回
  141. if( !isset($result['errcode']) ) {
  142. Log::error('weiban_openai/external_user_get',$id.'=>接口未返回数据');
  143. return [];
  144. }
  145. // 如果是凭证错误,递归
  146. if( $result['errcode'] == '10001' ) return $this->getUserDetail($id);
  147. // 调用失败
  148. if( $result['errcode'] != 0 ) {
  149. Log::error('weiban_openai/external_user_get',$id.'=>'.$result['errcode'].'=>'.$result['errmsg']);
  150. return [];
  151. }
  152. // 返回结果
  153. return $result['external_user'];
  154. }
  155. /**
  156. * 获取标签列表
  157. *
  158. * @param int $limit 每页条数
  159. * @param int $offset 列表偏移。用于迭代获取所有数据,默认值为0
  160. *
  161. * @return array 标签列表
  162. *
  163. * */
  164. public function getTagList($limit=100,$offset=0){
  165. // 获取调用凭证
  166. $accessToken = $this->getAccessToken();
  167. // 如果没有返回
  168. if( !$accessToken ) return [];
  169. // 组装接口
  170. $url = $this->domain.'/open-api/tag/list';
  171. // 调用接口
  172. $result = Curl::to($url)->withData(['access_token'=>$accessToken,'limit'=>$limit,'offset'=>$offset])->asJson(true)->get();
  173. // 如果没有返回
  174. if( !isset($result['errcode']) ) {
  175. Log::error('weiban_openai/tag_list','接口未返回数据');
  176. return [];
  177. }
  178. // 如果是凭证错误,递归
  179. if( $result['errcode'] == '10001' ) return $this->getTagList($limit,$offset);
  180. // 如果调用结果失败
  181. if( $result['errcode'] != 0 ) {
  182. Log::error('weiban_openai/tag_list',$result['errcode'].'=>'.$result['errmsg']);
  183. return [];
  184. }
  185. // 如果列表偏移量小于标签总数
  186. if( $offset < $result['total'] ) {
  187. // 休眠一秒钟,避免超限错误
  188. sleep(1);
  189. // 获取下一页
  190. $result['tag_list'] = array_merge($result['tag_list'],$this->getTagList($limit,$offset+$limit));
  191. }
  192. // 修改数据
  193. (new Taglist)->upsertData($result['tag_list']);
  194. // 返回结果
  195. return $result['tag_list'];
  196. }
  197. /**
  198. * 批量更新客户企业标签
  199. *
  200. * */
  201. public function markTags($extUserid,$addTags,$rmTags,$staffId){
  202. // 获取调用凭证
  203. $accessToken = $this->getAccessToken();
  204. // 如果没有返回
  205. if( !$accessToken ) return [];
  206. // 组装接口
  207. $url = $this->domain.'/open-api/tag/batch_update?access_token='.$accessToken;
  208. $param = ['staff_id'=>$staffId,'external_user_id'=>$extUserid,'add_tag_id_list'=>$addTags,'remove_tag_id_list'=>$rmTags];
  209. // 调用接口
  210. $result = Curl::to($url)->withData($param)->asJson(true)->post();
  211. // 如果没有返回
  212. if( !isset($result['errcode']) ) {
  213. Log::error('weiban_openai/tag_batch_update','接口未返回数据',$result);
  214. return false;
  215. }
  216. // 如果是凭证错误,递归
  217. if( $result['errcode'] == '10001' ) return $this->markTags($extUserid,$addTags,$rmTags,$staffId);
  218. // 如果调用结果失败
  219. if( $result['errcode'] != 0 ) {
  220. Log::error('weiban_openai/tag_batch_update',$result['errcode'].'=>'.$result['errmsg']);
  221. return false;
  222. }
  223. // 返回结果
  224. return true;
  225. }
  226. }
  227. ?>