WeappLoginTrait2.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. <?php
  2. namespace App\Traits;
  3. use App\Services\LoginService;
  4. use EasyWeChat\Factory;
  5. use Txj\Elastic\Facades\ES;
  6. use Illuminate\Support\Facades\Cache;
  7. use Illuminate\Support\Facades\Request;
  8. /**
  9. * 微信小程序 登录及绑定
  10. *
  11. * Trait WeappLoginTrait2
  12. * @package App\Traits
  13. */
  14. trait WeappLoginTrait2
  15. {
  16. public string $wechatConfigName = 'default';
  17. /**
  18. * 是否开启登录日志记录
  19. *
  20. * @var bool
  21. */
  22. private bool $is_open_login_log = false;
  23. /**
  24. * 微信小程序登录操作,如果已经绑定则直接登录,没有绑定,则需要绑定手机号
  25. *
  26. * @return String
  27. * @throws \EasyWeChat\Kernel\Exceptions\DecryptException
  28. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  29. * @throws \Exception
  30. */
  31. public function wxBind()
  32. {
  33. $requestData = Request::all();
  34. $code = $requestData['code'] ?? '';
  35. $wxInfo = $requestData['userInfo'] ?? '';
  36. $iv = $requestData['iv'] ?? '';
  37. $encryptedData = $requestData['encryptedData'] ?? '';
  38. if (empty($iv) || empty($code) || empty($wxInfo) || empty($encryptedData)) {
  39. return responseMessage(2001, '参数错误');
  40. }
  41. $config = config('wechat.mini_program.' . $this->wechatConfigName);
  42. $miniProgram = Factory::miniProgram($config);
  43. $info = $miniProgram->auth->session($code);
  44. $decryptedData = $miniProgram->encryptor->decryptData($info['session_key'], $iv, $encryptedData);
  45. if (empty($decryptedData)) {
  46. return responseMessage(2003, '登录失败,请重试!');
  47. }
  48. $wxInfo['openid'] = $wx_openid = $decryptedData['openId'] ?? '';
  49. $wxInfo['unionid'] = $wx_unionid = $decryptedData['unionId'] ?? '';
  50. if (empty($wx_openid)) {
  51. return responseMessage(2004, '授权登录失败');
  52. }
  53. //根据unionid,openid判断该用户是否已经存在,如果存在则登录跳转
  54. $flag = false;
  55. $memberInfo = ES::table($this->memberSetAlias)->where(['wx_openid' => $wx_openid])->first();
  56. if ($memberInfo) {
  57. $flag = true;
  58. } else {
  59. if ($wx_unionid) {
  60. $memberInfo = ES::table($this->memberSetAlias)->where(['wx_unionid' => $wx_unionid])->first();
  61. if ($memberInfo) {
  62. $flag = true;
  63. }
  64. }
  65. }
  66. if ($flag) {
  67. //更新用户登录的openid
  68. $avatar = $wxInfo['avatar'] ?? $wxInfo['avatarUrl'];
  69. ES::table($this->memberSetAlias)->updateEntityById($memberInfo['id'], ['wx_unionid' => $wx_unionid, 'wx_openid' => $wx_openid, 'avatar' => $avatar]);
  70. $loginService = new LoginService($this->siteAliasName);
  71. $encryptArr = $loginService->setLoginCookie($memberInfo);
  72. //微信登录的时候,保存的微信接口返回的微信用户信息
  73. $key = 'weapp:userInfo:' . $encryptArr['token'];
  74. Cache::put($key, $wxInfo, 7200);
  75. //微信登录的时候,保存的微信接口返回的微信用户信息
  76. $key2 = 'weapp:session_key:' . $encryptArr['token'];
  77. Cache::put($key2, $info, 7200);
  78. return responseMessage(1001, 'success', $encryptArr);
  79. } else {
  80. //微信登录的时候,保存的微信接口返回的微信用户信息
  81. $key = 'weapp:userInfo:' . $code;
  82. Cache::put($key, $wxInfo, 7200);
  83. //微信登录的时候,保存的微信接口返回的微信用户信息
  84. $key2 = 'weapp:session_key:' . $code;
  85. Cache::put($key2, $info, 7200);
  86. return responseMessage(1002, 'success', $code);
  87. }
  88. }
  89. /**
  90. * 微信小程序绑定手机号
  91. */
  92. public function wxBindIn()
  93. {
  94. $requestData = Request::all();
  95. $key = $requestData['key'] ?? '';
  96. $code = $requestData['code'] ?? '';
  97. $iv = $requestData['iv'] ?? '';
  98. $encryptedData = $requestData['encryptedData'] ?? '';
  99. if (empty($key) || empty($code) || empty($iv) || empty($encryptedData)) {
  100. return responseMessage(2001, '参数错误');
  101. }
  102. //获取微信的信息
  103. $key2 = 'weapp:userInfo:' . $key;
  104. $weInfo = Cache::get($key2);
  105. if (empty($weInfo)) {
  106. return responseMessage(2003, '微信登录失败,请重试!');
  107. }
  108. $key2 = 'weapp:session_key:' . $key;
  109. $sessionInfo = Cache::get($key2);
  110. if (empty($sessionInfo)) {
  111. return responseMessage(2004, '微信登录失败,请重试!');
  112. }
  113. $miniProgram = app('wechat.mini_program');
  114. $decryptedData = $miniProgram->encryptor->decryptData($sessionInfo['session_key'], $iv, $encryptedData);
  115. if (empty($decryptedData)) {
  116. return responseMessage(2002, '登录失败,请重试!');
  117. }
  118. $mobile = $decryptedData['purePhoneNumber'];
  119. $openid = $weInfo['openid'] ?? '';
  120. $token = $this->saveBindAppMember($weInfo, $mobile, $openid);
  121. if ($token) {
  122. return responseMessage(1001, 'success', $token);
  123. } else {
  124. return responseMessage(2003, '操作失败,请重试!');
  125. }
  126. }
  127. private function saveBindAppMember($weInfo, $mobile, $openid)
  128. {
  129. if (isset($weInfo['raw']['unionid']) && $weInfo['raw']['unionid']) {
  130. $wx_unionid = $weInfo['raw']['unionid'];
  131. } else {
  132. $wx_unionid = $weInfo['unionid'] ?? '';
  133. }
  134. $username = $weInfo['nickName'] ?? $weInfo['nickname'];
  135. //保存到数据库
  136. $data = [
  137. 'mobile' => $mobile,
  138. 'wx_username' => $username,
  139. 'wx_unionid' => $wx_unionid,
  140. 'avatar' => $weInfo['avatar'] ?? $weInfo['avatarUrl'],
  141. 'status' => 1,
  142. 'is_audit' => 0
  143. ];
  144. $data['wx_openid'] = $openid;
  145. // 判断当前的手机号是否存在,如果存在则更新
  146. $isExist = ES::table($this->memberSetAlias)->where('mobile', $mobile)->where('is_delete', 0)->first();
  147. if ($isExist) {
  148. $id = $isExist['id'];
  149. $is_success = ES::table($this->memberSetAlias)->toRefresh()->updateEntityById($id, $data);
  150. } else {
  151. $is_success = ES::table($this->memberSetAlias)->toRefresh()->insertGetId($data);
  152. $id = $is_success;
  153. }
  154. if ($is_success) {
  155. $memberInfo = ES::table($this->memberSetAlias)->find($id); //设置登录状态
  156. $loginService = new LoginService($this->siteAliasName);
  157. return $loginService->setLoginCookie($memberInfo);
  158. } else {
  159. return false;
  160. }
  161. }
  162. public function loginOut(Request $request)
  163. {
  164. $tokenValue = $this->getToken();
  165. $loginServer = new LoginService($this->siteAliasName);
  166. if (empty($tokenValue)) {
  167. return responseMessage(2001, '操作失败!');
  168. } else {
  169. $loginServer->clearLoginInfo($tokenValue);
  170. return responseMessage(1001, '操作成功!');
  171. }
  172. }
  173. /**
  174. * 获取小程序的二维码
  175. *
  176. * @return String
  177. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  178. * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
  179. */
  180. public function getQrcode()
  181. {
  182. $requestData = Request::all();
  183. $path = $requestData['path'] ?? '';
  184. if (empty($path)) {
  185. return responseMessage(2001, '路径不正确');
  186. }
  187. // 分享二维码
  188. $path .= '?share_key=' . base64_encode(($this->memberSetAlias == 'business' ? 1 : 2) . ':' . $this->userId);
  189. $root_path = public_path('static/upload/store_qrcode/');
  190. $filename = md5($path) . '.jpg';
  191. if (file_exists($root_path . '/' . $filename)) {
  192. return responseMessage(1001, '', '/upload/store_qrcode/' . $filename);
  193. } else {
  194. $config = config('wechat.mini_program.' . $this->wechatConfigName);
  195. $miniProgram = Factory::miniProgram($config);
  196. $response = $miniProgram->app_code->get($path, [
  197. 'width' => 430,
  198. 'auto_color' => false,
  199. 'line_color' => [
  200. 'r' => 0,
  201. 'g' => 0,
  202. 'b' => 0,
  203. ],
  204. ]);
  205. // 保存小程序码到文件
  206. if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
  207. $filename = $response->saveAs($root_path, $filename);
  208. return responseMessage(1001, '', '/upload/store_qrcode/' . $filename);
  209. } else {
  210. return responseMessage(2002, '未知错误');
  211. }
  212. }
  213. }
  214. }