TencentImFriendService.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. <?php
  2. namespace App\Services;
  3. use App\Exceptions\TencentImFriendException;
  4. use App\Models\User;
  5. use App\Models\UserFriendApplyRecord;
  6. use App\Traits\TencentIm;
  7. use Illuminate\Support\Arr;
  8. use Illuminate\Support\Facades\DB;
  9. class TencentImFriendService
  10. {
  11. use TencentIm;
  12. const ADD_FRIEND_TYPE_SINGLE = 'Add_Type_Single'; //表示单向加好友
  13. const ADD_FRIEND_TYPE_BOTH = 'Add_Type_Both'; //表示双向加好友
  14. const IM_IDENTIFIER_PREFIX = 'IM_USER_';
  15. const CHECK_FRIEND_TYPE_SINGLE = 'CheckResult_Type_Single'; //只会检查 From_Account 的好友表中是否有 To_Account,不会检查 To_Account 的好友表中是否有 From_Account
  16. const CHECK_FRIEND_TYPE_BOTH = 'CheckResult_Type_Both'; //既会检查 From_Account 的好友表中是否有 To_Account,也会检查 To_Account 的好友表中是否有 From_Account
  17. const ADD_FRIEND_ADD_SOURCE_TYPE_ADDRESS_BOOK = 'AddSource_Type_100'; //加好友来源 通讯录
  18. const TENCENT_REST_APIS = [
  19. 'friendAddItem' => 'v4/sns/friend_add', //单个添加好友,
  20. 'friendGet' => 'v4/sns/friend_get', //拉取好友,
  21. 'friendCheck' => 'v4/sns/friend_check', //校验好友
  22. ];
  23. static public function verifyUserApplyFriendExists(User $fromUser, User $toUser)
  24. {
  25. }
  26. //添加好友记录
  27. public function addApplyFriendRecord(User $user, array $options = [])
  28. {
  29. try {
  30. DB::beginTransaction();
  31. $toUser = User::find($options['to_user_id']);
  32. if (!$toUser) {
  33. throw new TencentImFriendException('好友账号不存在');
  34. }
  35. //检测是否已经有记录
  36. $friendApplyRecordModel = UserFriendApplyRecord::query()
  37. ->where(['from_user_id' => $user->id, 'to_user_id' => $toUser->id])
  38. ->latest()
  39. ->first();
  40. if ($friendApplyRecordModel) {
  41. if (UserFriendApplyRecord::APPLY_STATUS_100 === $friendApplyRecordModel->apply_status) {
  42. throw new TencentImFriendException('已发出好友添加申请,请勿重复操作');
  43. }
  44. if (UserFriendApplyRecord::APPLY_STATUS_101 === $friendApplyRecordModel->apply_status) {
  45. throw new TencentImFriendException('已经是好友关系,请勿重复操作');
  46. }
  47. if (UserFriendApplyRecord::APPLY_STATUS_101 === $friendApplyRecordModel->apply_status) {
  48. throw new TencentImFriendException('已经是好友关系,请勿重复操作');
  49. }
  50. }
  51. if (!$friendApplyRecordModel) {
  52. $friendApplyRecordModel = new UserFriendApplyRecord();
  53. }
  54. //添加发起申请记录
  55. $applyData = [
  56. 'from_user_id' => $user->id,
  57. 'to_user_id' => $toUser->id,
  58. 'type' => UserFriendApplyRecord::APPLY_TYPE_100,
  59. 'apply_status' => UserFriendApplyRecord::APPLY_STATUS_102,
  60. 'apply_raw_data' => [
  61. 'remark' => $options['remark'] ?? '',
  62. 'group' => $options['group_id'] ?? '',
  63. ],
  64. ];
  65. $friendApplyRecordModel->fill($applyData);
  66. //添加接收
  67. if (!$friendApplyRecordModel->save()) {
  68. throw new \Exception('写入好友申请记录失败');
  69. }
  70. DB::commit();
  71. return $friendApplyRecordModel;
  72. } catch (\Exception $e) {
  73. DB::rollBack();
  74. return ['error' => $e->getMessage()];
  75. } catch (TencentImFriendException $e) {
  76. DB::rollBack();
  77. return ['error' => $e->getMessage()];
  78. }
  79. }
  80. /**
  81. * 发起添加 IM 好友 (单个用户)
  82. * @param string $fromAccount
  83. * @param string $toAccount
  84. * @param array $options
  85. * @return \Psr\Http\Message\ResponseInterface
  86. * @throws TencentImFriendException
  87. * @throws \App\Exceptions\TencentImAccountException
  88. * @throws \App\Exceptions\TencentImException
  89. * @throws \GuzzleHttp\Exception\GuzzleException
  90. */
  91. public function friendAddItem(string $fromAccount, string $toAccount, array $options = [])
  92. {
  93. //TODO 请求添加好友前先拉取好友状态
  94. $this->restApiName = self::TENCENT_REST_APIS['friendAddItem'];
  95. $baseApiHost = $this->getTencentImRestApiBaseHost();
  96. $params = self::prepareFriendAddItemOptions($fromAccount, $toAccount, $options);
  97. $apiResult = $this->requestApi($baseApiHost, $params);
  98. self::verifyApiResult($apiResult);
  99. if ($apiResult['ResultItem'][0]['ResultInfo'] || ($apiResult['ResultItem'][0]['ResultCode'] != 0)) {
  100. throw new TencentImFriendException('添加好友失败: ' . $apiResult['ResultItem'][0]['ResultInfo']);
  101. }
  102. return $apiResult;
  103. }
  104. //拉取好友
  105. public function friendGet(string $fromAccount, int $pageStartIndex = 0)
  106. {
  107. $this->restApiName = self::TENCENT_REST_APIS['friendGet'];
  108. $baseApiHost = $this->getTencentImRestApiBaseHost();
  109. $params = [
  110. 'From_Account' => $fromAccount,
  111. 'StartIndex' => $pageStartIndex,
  112. 'StandardSequence' => $StandardSequence ?? 0,
  113. 'CustomSequence' => $CustomSequence ?? 0
  114. ];
  115. $apiResult = $this->requestApi($baseApiHost, $params);
  116. dd($apiResult);
  117. }
  118. //检验好友
  119. public function friendCheck(string $fromAccount, array $toAccounts, string $checkType = self::ADD_FRIEND_TYPE_BOTH)
  120. {
  121. $this->restApiName = self::TENCENT_REST_APIS['friendCheck'];
  122. $baseApiHost = $this->getTencentImRestApiBaseHost();
  123. $params = [
  124. 'From_Account' => $fromAccount,
  125. 'To_Account' => $toAccounts,
  126. 'CheckType' => 'CheckResult_Type_Both'
  127. ];
  128. $apiResult = $this->requestApi($baseApiHost, $params);
  129. self::verifyApiResult($apiResult);
  130. return $apiResult;
  131. }
  132. /**
  133. * 构建添加好友api 请求数组
  134. * @param string $fromAccount 需要添加好友的用户IM id
  135. * @param string $toAccount 被申请添加好友的用户IM id
  136. * @param array $options
  137. * @param string $options ['AddType'] 加好友方式
  138. * @param string $options ['AddSource'] 好友来源
  139. * @param string $options ['ForceAddFlags'] 管理员强制加好友标记:1表示强制加好友,0表示常规加好友方式
  140. * @param string $options ['Remark'] 好友备注
  141. * @param string $options ['AddWording'] 形成好友关系时的附言信息
  142. * @param string $options ['GroupName'] 分组信息,添加好友时只允许设置一个分组
  143. * @return array
  144. */
  145. static public function prepareFriendAddItemOptions(string $fromAccount, string $toAccount, array $options)
  146. {
  147. // string $addType = self::ADD_FRIEND_TYPE_BOTH,
  148. // string $addSource = self::ADD_FRIEND_ADD_SOURCE_TYPE_ADDRESS_BOOK,
  149. // string $remark = '',
  150. // bool $forceAddFlags = false
  151. $result = [
  152. 'From_Account' => $fromAccount,
  153. // 'AddSource' => $options['AddSource'] ?? self::ADD_FRIEND_ADD_SOURCE_TYPE_ADDRESS_BOOK, //好友来源
  154. 'AddType' => $options['AddType'] ?? self::ADD_FRIEND_TYPE_BOTH, //加好友方式
  155. 'ForceAddFlags' => empty($options['ForceAddFlags']) ? 0 : ($options['ForceAddFlags'] ? 1 : 0), //管理员强制加好友标记:1表示强制加好友,0表示常规加好友方式
  156. ];
  157. $AddFriendItem = [];
  158. $AddFriendItem['To_Account'] = $toAccount;
  159. //好友来源
  160. $AddFriendItem['AddSource'] = $options['AddSource'] ?? self::ADD_FRIEND_ADD_SOURCE_TYPE_ADDRESS_BOOK;
  161. //好友备注
  162. if (!empty($options['Remark'])) {
  163. $AddFriendItem['Remark'] = $options['Remark'];
  164. }
  165. //形成好友关系时的附言信息
  166. if (!empty($options['AddWording'])) {
  167. $AddFriendItem['AddWording'] = $options['AddWording'];
  168. }
  169. //分组信息,添加好友时只允许设置一个分组
  170. if (!empty($options['GroupName'])) {
  171. $AddFriendItem['GroupName'] = $options['GroupName'] ? 1 : 0;
  172. }
  173. $result['AddFriendItem'][] = $AddFriendItem;
  174. unset($options);
  175. unset($AddFriendItem);
  176. return $result;
  177. }
  178. }