Wechat.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <?php
  2. namespace app\common\Service\Third\Wechat;
  3. use app\common\Enum\ChannelEnum;
  4. use app\common\library\Auth;
  5. use app\common\model\ThirdOauth;
  6. use app\common\model\User as UserModel;
  7. use app\common\exception\BusinessException;
  8. class Wechat
  9. {
  10. // 平台
  11. protected $platform;
  12. // 转发服务
  13. protected $service;
  14. public function __construct($platform, $payload = [])
  15. {
  16. $this->platform = $platform;
  17. $this->service = $this->setPlatformService($payload);
  18. }
  19. public function getApp()
  20. {
  21. return $this->service->wechat;
  22. }
  23. /**
  24. * 微信登陆
  25. * @return array
  26. */
  27. public function login()
  28. {
  29. $wechatUser = $this->service->login();
  30. $oauthInfo = $this->createOrUpdateOauthInfo($wechatUser);
  31. $this->registerOrBindUser($oauthInfo, 0, ['mobile' => $wechatUser['mobile'] ?? '']);
  32. $oauthInfo->save();
  33. $auth = Auth::instance();
  34. $ret = $auth->direct($oauthInfo->user_id);
  35. if ($ret) {
  36. $oauthInfo->login_num += 1;
  37. return true;
  38. } else {
  39. $oauthInfo->user_id = 0;
  40. $oauthInfo->save();
  41. return false;
  42. }
  43. }
  44. /**
  45. * 微信绑定
  46. *
  47. * @return array
  48. */
  49. public function bind(Object $user)
  50. {
  51. $wechatUser = $this->service->bind();
  52. $oauthInfo = $this->createOrUpdateOauthInfo($wechatUser);
  53. if ($this->registerOrBindUser($oauthInfo, $user->id)) {
  54. return true;
  55. }
  56. return false;
  57. }
  58. /**
  59. * 微信解绑
  60. *
  61. * @return array
  62. */
  63. public function unbind()
  64. {
  65. $user = Auth::instance()->getUser();
  66. if (!$user->verification->mobile) {
  67. throw new BusinessException('请先绑定手机号后再进行操作');
  68. }
  69. $oauthInfo = ThirdOauth::where([
  70. 'user_id' => $user->id,
  71. 'platform' => $this->platform,
  72. 'provider' => 'wechat'
  73. ])->find();
  74. if ($oauthInfo) {
  75. $oauthInfo->delete();
  76. return true;
  77. }
  78. return false;
  79. }
  80. /**
  81. * 创建/更新用户认证信息
  82. *
  83. * @return think\Model
  84. */
  85. private function createOrUpdateOauthInfo($wechatUser, $extend = [])
  86. {
  87. $oauthInfo = ThirdOauth::getByOpenid($wechatUser['openid']);
  88. if (!$oauthInfo) { // 创建新的third_oauth条目
  89. $wechatUser['user_id'] = 0;
  90. if (!empty($wechatUser['unionid'])) { // unionid账号合并策略
  91. $unionOauthInfo = ThirdOauth::getByUnionid($wechatUser['unionid']);
  92. if ($unionOauthInfo) {
  93. $wechatUser['user_id'] = $unionOauthInfo->user_id;
  94. }
  95. }
  96. $wechatUser['provider'] = 'wechat';
  97. $wechatUser['platform'] = $this->platform;
  98. $wechatUser = array_merge($wechatUser, $extend);
  99. $thirdOauth = new ThirdOauth($wechatUser);
  100. $thirdOauth->allowField(true)->save();
  101. $oauthInfo = ThirdOauth::getByOpenid($wechatUser['openid']);
  102. } else { // 更新授权信息
  103. if ($this->platform === 'miniProgram') {
  104. unset($wechatUser['avatar']);
  105. unset($wechatUser['nickname']);
  106. }
  107. $oauthInfo->allowField(true)->save($wechatUser);
  108. }
  109. return $oauthInfo;
  110. }
  111. /**
  112. * 注册/绑定用户
  113. *
  114. * @return think\Model
  115. */
  116. private function registerOrBindUser($oauthInfo, $user_id = 0, $extend = [])
  117. {
  118. // 检查用户存在
  119. if ($oauthInfo->user_id) {
  120. $user = UserModel::get($oauthInfo->user_id);
  121. if ($user && $user_id > 0) {
  122. throw new BusinessException('该微信账号已绑定其他用户');
  123. }
  124. // 用户被删除,则重置第三方信息所绑定的用户id
  125. if (!$user) {
  126. $oauthInfo->user_id = 0;
  127. }
  128. }
  129. // 绑定用户
  130. if ($oauthInfo->user_id === 0 && $user_id > 0) {
  131. $user = UserModel::get($user_id);
  132. if ($user) {
  133. $oauthInfo->user_id = $user_id;
  134. return $oauthInfo->save();
  135. } else {
  136. throw new BusinessException('该用户暂不可绑定微信账号');
  137. }
  138. return false;
  139. }
  140. // 注册新用户
  141. if ($oauthInfo->user_id === 0 && $user_id === 0) {
  142. $auth = Auth::instance()->register($oauthInfo->nickname ?? '', '', '', $extend['mobile'] ?? '');
  143. $user = Auth::instance()->getUser();
  144. $oauthInfo->user_id = $user->id;
  145. return $oauthInfo->save();
  146. }
  147. }
  148. /**
  149. * 设置平台服务类
  150. *
  151. * @return class
  152. */
  153. private function setPlatformService($payload)
  154. {
  155. switch ($this->platform) {
  156. case 'officialAccount':
  157. $service = new OfficialAccount($payload);
  158. break;
  159. case 'miniProgram':
  160. $service = new MiniProgram($payload);
  161. break;
  162. case ChannelEnum::CHANNEL_IOS_APP:
  163. $service = new OpenPlatform($payload);
  164. break;
  165. case ChannelEnum::CHANNEL_ANDROID_APP:
  166. $service = new OpenPlatform($payload);
  167. break;
  168. }
  169. if (!isset($service)) throw new BusinessException('平台参数有误');
  170. return $service;
  171. }
  172. /**
  173. * 方法转发到驱动提供者
  174. *
  175. * @param string $funcname
  176. * @param array $arguments
  177. * @return void
  178. */
  179. public function __call($funcname, $arguments)
  180. {
  181. return $this->service->{$funcname}(...$arguments);
  182. }
  183. }