LoginForm.php 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  1. <?php
  2. /**
  3. * 重庆赤晓店信息科技有限公司
  4. * https://www.chixiaodian.com
  5. * Copyright (c) 2023 赤店商城 All rights reserved.
  6. */
  7. namespace app\modules\client\models\v1;
  8. use app\constants\OptionSetting;
  9. use app\models\Option;
  10. use app\models\Share;
  11. use app\models\StoreCloud;
  12. use app\models\User;
  13. use app\models\WechatConfig;
  14. use app\modules\client\models\ApiModel;
  15. use app\utils\Notice\NoticeSend;
  16. use app\utils\Wechat\WechatMini;
  17. use yii\base\BaseObject;
  18. use yii\helpers\Json;
  19. use app\modules\client\models\v1\BindForm;
  20. use app\models\SaasUser;
  21. class LoginForm extends ApiModel
  22. {
  23. // 前端类型
  24. public $_platform;
  25. // 商城id
  26. public $store_id;
  27. public $login_type;
  28. public $password;
  29. // 微信小程序
  30. public $code;
  31. public $user_info;
  32. public $encrypted_data;
  33. public $iv;
  34. public $signature;
  35. // 手机注册
  36. public $phone;
  37. public $verify_code;
  38. public $isLogin;//直接绑定上下级
  39. // 分销商user_id
  40. public $share_user_id;
  41. /**
  42. * @var User $user
  43. */
  44. public $user;
  45. // 微信小程序
  46. const PLATFORM_WX = 'wx';
  47. // 微信公众号
  48. const PLATFORM_MP = 'mp';
  49. // app端微信
  50. const PLATFORM_APP = 'app';
  51. // 手机号注册登录
  52. const PLATFORM_PHONE = 'phone';
  53. // 短信登录验证码
  54. const CACHE_KEY_SMS_LOGIN = '_mobile_sms_login_';
  55. // 绑定手机号验证码
  56. const CACHE_KEY_BIND_PHONE = '_mobile_bind_';
  57. // 短信忘记密码验证码
  58. const CACHE_KEY_SMS_FORGET_PASSWORD = '_mobile_sms_forget_password_';
  59. // 验证码类型
  60. // 手机登录
  61. const TYPE_VERIFY_CODE_LOGIN = 'login';
  62. // 手机绑定
  63. const TYPE_VERIFY_CODE_BIND = 'bind';
  64. // 清除数据
  65. const TYPE_VERIFY_CODE_CLEAR = 'clear';
  66. // 手机绑定
  67. const TYPE_VERIFY_CODE_FORGET_PASSWORD = 'forget_password';
  68. public $parent_id;
  69. public $appCid;
  70. public function rules()
  71. {
  72. return [
  73. ['_platform', 'in', 'range' => [self::PLATFORM_WX, self::PLATFORM_MP, self::PLATFORM_APP, self::PLATFORM_PHONE]],
  74. ['_platform', 'required'],
  75. [['code', 'user_info', 'encrypted_data', 'iv', 'signature'], 'required', 'on' => self::PLATFORM_WX],
  76. [['user_info'], 'required', 'on' => self::PLATFORM_APP],
  77. [['phone'], 'required', 'on' => self::PLATFORM_PHONE],
  78. [['phone'], 'match', 'pattern' => '/^1[3456789]\d{9}$/', 'message' => '手机号错误'],
  79. [['verify_code', 'parent_id', 'share_user_id', 'isLogin', 'login_type'], 'integer'],
  80. [['code', 'user_info', 'encrypted_data', 'iv', 'signature', 'phone', 'password'], 'string'],
  81. [['code', 'user_info', 'encrypted_data', 'iv', 'signature', 'phone'], 'trim'],
  82. ];
  83. }
  84. public function attributeLabels()
  85. {
  86. return [
  87. 'login_type' => 'login_type',
  88. '_platform' => '_platform',
  89. 'store_id' => 'store_id',
  90. 'code' => 'code',
  91. 'user_info' => 'user_info',
  92. 'encrypted_data' => 'encrypted_data',
  93. 'iv' => 'iv',
  94. 'signature' => 'signature',
  95. 'share_user_id' => 'share_user_id',
  96. ];
  97. }
  98. public function scenarios()
  99. {
  100. $scenarios = parent::scenarios();
  101. return $scenarios;
  102. }
  103. /**
  104. * 登录统一入口
  105. * @return array
  106. * @throws \yii\base\Exception
  107. */
  108. public function login()
  109. {
  110. if ($this->_platform == self::PLATFORM_WX) {
  111. // 微信小程序登录
  112. return $this->loginWX();
  113. } else if ($this->_platform == self::PLATFORM_APP) {
  114. // app端微信登录
  115. return $this->loginAppWechat();
  116. } else if ($this->_platform == self::PLATFORM_PHONE) {
  117. // 手机号登录,没有找到手机号自动注册
  118. return $this->phoneLogin();
  119. } else {
  120. return [
  121. 'code' => 1,
  122. 'msg' => '登录失败,请检查参数是否正确'
  123. ];
  124. }
  125. }
  126. /**
  127. * 微信登录方法
  128. * @return array
  129. */
  130. private function loginWX()
  131. {
  132. if ($this->validate()) {
  133. try {
  134. //获取session
  135. $session = self::getWechat()->auth->session($this->code);
  136. if (!$session || empty($session['openid'])) {
  137. throw new \Exception('获取openid失败.');
  138. }
  139. // 验证
  140. $decryptedData = self::getWechat()->encryptor->decryptData($session['session_key'], $this->iv, $this->encrypted_data);
  141. $user_info = json_decode($this->user_info, true);
  142. $user_info['nickName'] = preg_replace('/[\xf0-\xf7].{3}/', '', $user_info['nickName']);
  143. $data = [
  144. 'openId' => $session['openid'],
  145. 'nickName' => isset($user_info['nickName']) ? $user_info['nickName'] : $this->getNickName(),
  146. 'gender' => $user_info['gender'],
  147. 'city' => $user_info['city'],
  148. 'province' => $user_info['province'],
  149. 'country' => $user_info['country'],
  150. 'avatarUrl' => $user_info['avatarUrl'] ?: \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/statics/images/avatar.png',
  151. 'unionId' => isset($session['unionid']) ? $session['unionid'] : '',
  152. ];
  153. $isNew = 0;
  154. $user = User::find()->where(['store_id' => $this->store_id, 'platform' => 0])->andWhere(['binding' => $this->phone])->orderBy('id desc')->one();
  155. if (!$user) {
  156. $isNew = 1;
  157. $user = new User();
  158. $user->type = User::USER_TYPE_NORMAL;
  159. $user->binding = isset($decryptedData['phoneNumber']) ? $decryptedData['phoneNumber'] : '';
  160. $user->username = $data['openId'];
  161. $user->password = \Yii::$app->security->generatePasswordHash(\Yii::$app->security->generateRandomString(), 5);
  162. $user->auth_key = \Yii::$app->security->generateRandomString();
  163. $user->access_token = \Yii::$app->security->generateRandomString();
  164. $user->is_delete = User::USER_NOT_DELETE;
  165. $user->wechat_open_id = $data['openId'];
  166. $user->wechat_union_id = $data['unionId'];
  167. $user->store_id = $this->store_id;
  168. $user->platform = User::USER_FROM_WECHAT; // 微信
  169. }
  170. $user->binding = $this->phone;
  171. $user->nickname = $data['nickName'];
  172. $user->avatar_url = $data['avatarUrl'];
  173. if (empty($user->wechat_open_id) || (!empty($data['openId']) && $user->wechat_open_id !== $data['openId'])) {
  174. $user->wechat_open_id = $data['openId'];
  175. }
  176. if (empty($user->wechat_union_id) || (!empty($data['unionId']) && $user->wechat_union_id !== $data['unionId'])) {
  177. $user->wechat_union_id = $data['unionId'];
  178. }
  179. if (!$user->save()) {
  180. return [
  181. 'code' => 1,
  182. 'msg' => '登陆失败',
  183. 'data' => $user->getErrorSummary(false)[0]
  184. ];
  185. }
  186. // 创建平台会员saas_user
  187. $saas_user = SaasUser::find()->where(['mobile' => $user->binding, 'is_delete' => SaasUser::DELETE_STATUS_FALSE])->one();
  188. if (!$saas_user) {
  189. $saas_user = new SaasUser();
  190. $saas_user->mobile = $user->binding;
  191. $saas_user->store_id = $this->store_id;
  192. $saas_user->save();
  193. }
  194. // 是否开启强制绑定手机号
  195. $is_open_bind = Option::get(OptionSetting::STORE_LOGIN_FORCIBLY_BIND_MOBILE, $this->store_id, 'store')['value'];
  196. $share = $share_user = null;
  197. if ($user->parent_id > 0) {
  198. $share = Share::findOne(['user_id' => $user->parent_id]);
  199. $share_user = User::findOne(['id' => $share->user_id]);
  200. }
  201. if ($this->share_user_id > 0) {
  202. // 绑定上下级
  203. $bindForm = new BindForm();
  204. $bindForm->store_id = $this->store_id;
  205. $bindForm->user_id = $user->id;
  206. $bindForm->parent_id = $this->share_user_id;
  207. $bindForm->condition = 0;
  208. $bindForm->isNew = $isNew;
  209. $bindForm->save();
  210. }
  211. $data = [
  212. 'access_token' => $user->access_token,
  213. 'nickname' => $user->nickname,
  214. 'avatar_url' => $user->avatar_url,
  215. 'is_distributor' => $user->is_distributor ? $user->is_distributor : 0,
  216. 'errCode' => 0,
  217. 'parent' => $share ? ($share->name ? $share->name : $share_user->nickname) : '总店',
  218. 'id' => $user->id,
  219. 'is_clerk' => $user->is_clerk === null ? 0 : $user->is_clerk,
  220. 'integral' => $user->integral === null ? 0 : $user->integral,
  221. 'money' => $user->money === null ? 0 : $user->money,
  222. 'binding' => $user->binding,
  223. 'level' => $user->level,
  224. 'blacklist' => $user->blacklist,
  225. 'is_open_bind' => $is_open_bind ? $is_open_bind : 0
  226. ];
  227. return [
  228. 'code' => 0,
  229. 'data' => $data,
  230. 'msg' => '登陆成功'
  231. ];
  232. } catch (\Exception $e) {
  233. return [
  234. 'code' => 1,
  235. 'msg' => '登录失败',
  236. 'data' => $e->getMessage() . 'line:' . $e->getLine() . 'file:' . $e->getFile()
  237. ];
  238. }
  239. } else {
  240. // 验证失败:$errors 是一个包含错误信息的数组
  241. return [
  242. 'code' => 1,
  243. 'msg' => $this->getErrorSummary(false)[0]
  244. ];
  245. }
  246. }
  247. /**
  248. * app 微信登录
  249. * @return array
  250. * @throws \yii\base\Exception
  251. */
  252. public function loginAppWechat()
  253. {
  254. if (!$this->validate()) {
  255. return [
  256. 'code' => 1,
  257. 'msg' => $this->getErrorSummary(false)[0]
  258. ];
  259. }
  260. $user_info = Json::decode($this->user_info);
  261. $user = null;
  262. if (isset($user_info['unionId']) && $user_info['unionId'] != '') {
  263. $user = User::findOne(['wechat_union_id' => $user_info['unionId'], 'store_id' => $this->store_id]);
  264. }
  265. if (!$user) {
  266. $user = User::findOne(['wechat_open_id' => $user_info['openId'], 'store_id' => $this->store_id]);
  267. }
  268. // 是否开启强制绑定手机号
  269. $is_open_bind = Option::get(OptionSetting::STORE_LOGIN_FORCIBLY_BIND_MOBILE, $this->store_id, 'store')['value'];
  270. if(!$user){
  271. $user = new User();
  272. $user->type = 1;
  273. $user->username = $user_info['openId'];
  274. $user->password = \Yii::$app->security->generatePasswordHash(\Yii::$app->security->generateRandomString(), 5);
  275. $user->auth_key = \Yii::$app->security->generateRandomString();
  276. $user->access_token = \Yii::$app->security->generateRandomString();
  277. $user->created_at = time();
  278. $user->is_delete = 0;
  279. $user->wechat_open_id = $user_info['openId'];
  280. $user->wechat_union_id = isset($user_info['unionId']) ? $user_info['unionId'] : '';
  281. $user->nickname = preg_replace('/[\xf0-\xf7].{3}/', '', $user_info['nickName']);
  282. $user->avatar_url = $user_info['avatarUrl'] ? $user_info['avatarUrl'] : \Yii::$app->request->hostInfo . '/web/v1/statics/images/avatar.png';
  283. $user->store_id = 1;
  284. $user->platform = 3; // APP
  285. $user->level = -1;
  286. if(isset($user_info['appCid']) && !empty($user_info['appCid'])){
  287. $user->appcid = $user_info['appCid'];
  288. }
  289. if($user->save()){
  290. // \Yii::$app->user->login($user);
  291. $parent = User::findOne($user->parent_id);
  292. $share = Share::findOne(['user_id' => $user->parent_id]);
  293. $data = [
  294. 'to_bind' => 1,
  295. 'nickname' => $user->nickname,
  296. 'binding' => $user->binding ? $user->binding : '',
  297. 'id' => $user->id,
  298. 'avatar_url' => $user->avatar_url,
  299. 'is_distributor' => $user->is_distributor ? $user->is_distributor : 0,
  300. 'integral' => $user->integral ? $user->integral : 0,
  301. 'money' => $user->money ? $user->money : 0,
  302. 'blacklist' => $user->blacklist ? $user->blacklist : 0,
  303. 'access_token' => $user->access_token,
  304. 'is_clerk' => $user->is_clerk === null ? 0 : $user->is_clerk,
  305. 'parent' => $share ? ($share->name ? $share->name : $parent->nickname) : "总店",
  306. 'level' => $user->level,
  307. 'is_open_bind' => $is_open_bind ? $is_open_bind : 0
  308. ];
  309. } else {
  310. return [
  311. 'code' => 1,
  312. 'msg' => '登录失败',
  313. 'data' => $user->errors[0]
  314. ];
  315. }
  316. } else {
  317. if(isset($user_info['appCid']) && !empty($user_info['appCid']) && $user->appcid != $user_info['appCid']){
  318. $user->appcid = $user_info['appCid'];
  319. }
  320. if (empty($user->wechat_union_id)) {
  321. $user->wechat_union_id = isset($user_info['unionId']) ? $user_info['unionId'] : '';
  322. }
  323. $user->nickname = preg_replace('/[\xf0-\xf7].{3}/', '', $user_info['nickName']);
  324. $user->avatar_url = $user_info['avatarUrl'];
  325. $user->save();
  326. // \Yii::$app->user->login($user);
  327. $parent = User::findOne($user->parent_id);
  328. $share = Share::findOne(['user_id' => $user->parent_id]);
  329. $data = [
  330. 'to_bind' => 0,
  331. 'nickname' => $user->nickname,
  332. 'binding' => $user->binding === null ? '' : $user->binding,
  333. 'id' => $user->id,
  334. 'avatar_url' => $user->avatar_url,
  335. 'is_distributor' => $user->is_distributor,
  336. 'integral' => $user->integral,
  337. 'money' => $user->money,
  338. 'blacklist' => $user->blacklist,
  339. 'access_token' => $user->access_token,
  340. 'is_clerk' => $user->is_clerk === null ? 0 : $user->is_clerk,
  341. 'parent' => $share ? ($share->name ? $share->name : $parent->nickname) : "总店",
  342. 'level' => $user->level,
  343. 'is_open_bind' => $is_open_bind ? $is_open_bind : 0
  344. ];
  345. }
  346. return [
  347. 'code' => 0,
  348. 'msg' => '登录成功',
  349. 'data' => $data
  350. ];
  351. }
  352. /**
  353. * 手机号登录
  354. * @return array
  355. * @throws \yii\base\Exception
  356. */
  357. public function loginAppPhone()
  358. {
  359. if (!$this->validate()) {
  360. return [
  361. 'code' => 1,
  362. 'msg' => $this->getErrorSummary(false)[0]
  363. ];
  364. }
  365. // 验证码验证
  366. $result = $this->verifySmsCode(self::CACHE_KEY_SMS_LOGIN);
  367. if ($result['code'] == 1) {
  368. return $result;
  369. }
  370. $parent_name = '总店';
  371. /**
  372. * @var User $user
  373. */
  374. $user = User::find()->where(['store_id' => $this->store_id, 'type' => 1, 'is_delete' => 0, 'blacklist' => 0,
  375. 'binding' => $this->phone])->one();
  376. if (!$user) {
  377. $password = '0';
  378. $user = new User();
  379. $user->type = 1;
  380. $user->username = \Yii::$app->security->generateRandomString();
  381. $user->password = $password;
  382. $user->auth_key = \Yii::$app->security->generateRandomString();
  383. $user->access_token = \Yii::$app->security->generateRandomString();
  384. $user->created_at = time();
  385. $user->is_delete = 0;
  386. $user->binding = $this->phone;
  387. $user->nickname = $this->getDefaultNickname($this->phone);
  388. $user->avatar_url = $this->getDefaultAvatar();
  389. $user->store_id = $this->store_id;
  390. $user->platform = User::USER_FROM_PHONE;
  391. if ($this->appCid) {
  392. $user->appcid = $this->appCid;
  393. }
  394. if ($this->parent_id > 0) {
  395. $parent_id = $this->parent_id;
  396. $setting = Option::get('share_basic_setting', get_store_id());
  397. $setting = $setting ? Json::decode($setting['value']) : [];
  398. if (!$setting || $setting['level']['value'] == 0) {
  399. $parent_id = 0;
  400. }
  401. if ($parent_id > 0) {
  402. $exists = Share::find()->andWhere(['user_id' => $this->parent_id, 'store_id' => $this->store_id,
  403. 'is_delete' => 0, 'status' => 1]);
  404. if ($exists->exists()) {
  405. $parent_name = $exists->one()->name;
  406. $user->parent_id = $parent_id;
  407. $user->old_parent_id = $parent_id;
  408. } else {
  409. $parent_name = User::findOne(['id' => $this->parent_id])->nickname;
  410. }
  411. }
  412. }
  413. if ($user->save()) {
  414. $data = [
  415. 'nickname' => $user->nickname,
  416. 'binding' => $user->binding,
  417. 'id' => $user->id,
  418. 'avatar_url' => $user->avatar_url,
  419. 'is_distributor' => $user->is_distributor ? $user->is_distributor : 0,
  420. 'integral' => $user->integral ? $user->integral : 0,
  421. 'money' => $user->money ? $user->money : 0,
  422. 'blacklist' => $user->blacklist ? $user->blacklist : 0,
  423. 'access_token' => $user->access_token,
  424. 'is_clerk' => $user->is_clerk === null ? 0 : $user->is_clerk,
  425. 'parent' => $parent_name,
  426. 'level' => -1
  427. ];
  428. return [
  429. 'code' => 0,
  430. 'msg' => '注册成功',
  431. 'data' => $data,
  432. ];
  433. } else {
  434. foreach ($user->errors as $error) {
  435. return [
  436. 'code' => 1,
  437. 'msg' => $error
  438. ];
  439. }
  440. }
  441. }
  442. if ($user->parent_id > 0) {
  443. $share = Share::findOne(['user_id' => $user->parent_id]);
  444. $parent_user = User::findOne($user->parent_id);
  445. $parent_name = $share ? ($share->name ? $share->name : $parent_user->nickname) : "总店";
  446. }
  447. $data = [
  448. 'nickname' => $user->nickname,
  449. 'binding' => $user->binding,
  450. 'id' => $user->id,
  451. 'avatar_url' => $user->avatar_url,
  452. 'is_distributor' => $user->is_distributor,
  453. 'integral' => $user->integral,
  454. 'money' => $user->money,
  455. 'blacklist' => $user->blacklist,
  456. 'access_token' => $user->access_token,
  457. 'is_clerk' => $user->is_clerk === null ? 0 : $user->is_clerk,
  458. 'parent' => $parent_name,
  459. 'level' => $user->level
  460. ];
  461. return [
  462. 'code' => 0,
  463. 'msg' => '登录成功',
  464. 'data' => $data,
  465. ];
  466. }
  467. public function phoneLogin() {
  468. if (!$this->validate()) {
  469. return [
  470. 'code' => 1,
  471. 'msg' => $this->getErrorSummary(false)[0]
  472. ];
  473. }
  474. if ($this->login_type == 1) {
  475. // $is_password_login = intval(Option::get(OptionSetting::IS_PASSWORD_LOGIN, $this->store_id, '', 0)['value']);
  476. // if ($is_password_login) {
  477. // return [
  478. // 'code' => 1,
  479. // 'msg' => '商城开启密码登录方式,请使用密码登录'
  480. // ];
  481. // }
  482. // 验证码验证
  483. $result = $this->verifySmsCode(self::CACHE_KEY_SMS_LOGIN);
  484. if ($result['code'] == 1) {
  485. return $result;
  486. }
  487. } else {
  488. // $is_password_login = intval(Option::get(OptionSetting::IS_PASSWORD_LOGIN, $this->store_id, '', 0)['value']);
  489. // if (!$is_password_login) {
  490. // return [
  491. // 'code' => 1,
  492. // 'msg' => '商城未开启密码登录方式,请使用验证码登录'
  493. // ];
  494. // }
  495. // 密码验证
  496. $user = User::find()->where(['store_id' => $this->store_id, 'type' => 1, 'is_delete' => 0, 'binding' => $this->phone])->one();
  497. if (!$user) {
  498. return [
  499. 'code' => 1,
  500. 'msg' => '用户不存在'
  501. ];
  502. }
  503. if (false === \Yii::$app->security->validatePassword($this->password, $user->password)) {
  504. return [
  505. 'code' => 1,
  506. 'msg' => '密码错误'
  507. ];
  508. }
  509. }
  510. //debug_log('公众号登录01', 'off.log');
  511. $plat_openid = '';
  512. $openid = '';
  513. //debug_log('公众号登录02_code=' . $this->code, 'off.log');
  514. if ($this->code) {
  515. try {
  516. //debug_log('公众号登录03', 'off.log');
  517. // if (is_wechat_platform()) {
  518. $wechat = self::getWechat();
  519. if (is_h5()) {
  520. $app = WechatMini::getWechatConfig($this->store_id, 0, WechatMini::TYPE_OFFICIAL);
  521. //debug_log('公众号登录04', 'off.log');
  522. $session = $app->oauth->userFromCode($this->code)->getTokenResponse();
  523. $plat_openid = $session['openid'];
  524. //debug_log('公众号登录05'. json_encode($session, JSON_UNESCAPED_UNICODE), 'off.log');
  525. } else {
  526. $app = WechatMini::getWechatConfig($this->store_id);
  527. if (empty($app)) {
  528. return [
  529. 'code' => 1,
  530. 'msg' => '小程序参数获取失败!',
  531. ];
  532. }
  533. $session = $app->auth->session($this->code);
  534. if (empty($session)) {
  535. return [
  536. 'code' => 1,
  537. 'msg' => '小程序参数异常!',
  538. ];
  539. }
  540. if (!$session || empty($session['openid'])) {
  541. throw new \Exception('获取openid失败.');
  542. }
  543. $openid = $session['openid'];
  544. }
  545. // } elseif (is_alipay_platform()) {
  546. //
  547. // }
  548. } catch (\Exception $e) {
  549. return [
  550. 'code' => 1,
  551. 'msg' => $e->getMessage(),
  552. ];
  553. debug_log('公众号登录06' . $e->getMessage(), 'off.log');
  554. }
  555. //debug_log('公众号登录07', 'off.log');
  556. }
  557. //debug_log('公众号登录08', 'off.log');
  558. // 创建平台会员saas_user
  559. $saas_user = SaasUser::find()->where(['mobile' => $this->phone, 'is_delete' => SaasUser::DELETE_STATUS_FALSE])->one();
  560. if (!$saas_user) {
  561. $saas_user = new SaasUser();
  562. $saas_user->access_token = \Yii::$app->security->generateRandomString();
  563. $saas_user->name = substr_replace($this->phone, '******', 3, 6);
  564. $saas_user->mobile = $this->phone;
  565. $saas_user->platform_open_id = '';
  566. $saas_user->avatar = \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/avatar.png';
  567. $saas_user->store_id = $this->store_id;
  568. $saas_user->save();
  569. } else {
  570. if (empty($saas_user->name)) {
  571. $saas_user->name = substr_replace($this->phone, '****', 3, 4);
  572. }
  573. if (empty($saas_user->avatar)) {
  574. $saas_user->avatar = \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/avatar.png';
  575. }
  576. if (empty($saas_user->access_token)) {
  577. $saas_user->access_token = \Yii::$app->security->generateRandomString();
  578. }
  579. // $saas_user->platform_open_id = $this->phone;
  580. $saas_user->save();
  581. }
  582. // 平台登录 todo: 后续补充其他数据
  583. if ($this->store_id <= 0) {
  584. $storeCloud = StoreCloud::findOne(['is_delete' => 0, 'is_enable' => 1, 'saas_user_id' => $saas_user->id]);
  585. return [
  586. 'code' => 0,
  587. 'msg' => '登录成功',
  588. 'data' => [
  589. 'access_token' => $saas_user->access_token,
  590. 'nickname' => $saas_user->name,
  591. 'avatar_url' => $saas_user->avatar,
  592. 'id' => $saas_user->id,
  593. 'money' => $saas_user->share_profit,
  594. 'integral' => $saas_user->integral,
  595. 'mobile' => $saas_user->mobile,
  596. 'is_can_distribution' => $storeCloud && $storeCloud->store_id > 0 ? 1 : 0, // 是否有商城(是否可以铺货)
  597. ]
  598. ];
  599. }
  600. $user = User::findOne(['binding' => $this->phone, 'store_id' => $this->store_id, 'is_delete' => 0]);
  601. $share = $share_user = null;
  602. $isNew = 0;
  603. if ($user) {
  604. if ($user->blacklist == '1') {
  605. return [
  606. 'code' => 1,
  607. 'msg' => '您的账号已被限制登录!',
  608. ];
  609. }
  610. if ($plat_openid) {
  611. $user->wechat_platform_open_id = $plat_openid;
  612. $user->save();
  613. }
  614. if ($openid) {
  615. $user->wechat_open_id = $openid;
  616. $user->save();
  617. }
  618. $data = [
  619. 'access_token' => $saas_user->access_token,
  620. 'nickname' => $saas_user->name,
  621. 'avatar_url' => $saas_user->avatar,
  622. 'is_distributor' => $user->is_distributor ? $user->is_distributor : 0,
  623. 'errCode' => 0,
  624. 'id' => $user->id,
  625. 'is_clerk' => $user->is_clerk === null ? 0 : $user->is_clerk,
  626. 'integral' => $user->integral === null ? 0 : $user->integral,
  627. 'money' => $user->money === null ? 0 : $user->money,
  628. 'binding' => $user->binding,
  629. 'level' => $user->level,
  630. 'blacklist' => $user->blacklist,
  631. 'is_saas_clerk' => (int)$user->is_saas_clerk,
  632. 'wechat_app_open_id' => $user->wechat_app_open_id,
  633. 'wechat_platform_open_id' => $user->wechat_platform_open_id,
  634. 'h5_auth_link' => self::getAuthLink(),
  635. 'store_id' => $this->store_id,
  636. ];
  637. } else {
  638. $isNew = 1;
  639. $data = [
  640. 'nickName' => substr_replace($this->phone, '******', 3, 6),
  641. 'avatarUrl' => \Yii::$app->request->hostInfo . \Yii::$app->request->baseUrl . '/web/v1/statics/images/avatar.png',
  642. ];
  643. $user = new User();
  644. $user->type = User::USER_TYPE_NORMAL;
  645. $user->binding = $this->phone;
  646. $user->nickname = $data['nickName'];
  647. $user->avatar_url = $data['avatarUrl'];
  648. $user->username = \Yii::$app->security->generateRandomString();
  649. $user->password = \Yii::$app->security->generatePasswordHash(\Yii::$app->security->generateRandomString(), 5);
  650. $user->auth_key = \Yii::$app->security->generateRandomString();
  651. $user->access_token = \Yii::$app->security->generateRandomString();
  652. $user->is_delete = User::USER_NOT_DELETE;
  653. $user->store_id = $this->store_id;
  654. $user->parent_id = 0;
  655. $user->old_parent_id = 0;
  656. $user->platform = is_alipay_platform() ? User::USER_FROM_ALIPAY : User::USER_FROM_PHONE; // 手机号
  657. if ($openid) {
  658. $user->wechat_open_id = $openid;
  659. }
  660. if ($plat_openid) {
  661. $user->wechat_platform_open_id = $plat_openid;
  662. }
  663. if (!$user->save()) {
  664. return [
  665. 'code' => 1,
  666. 'msg' => '登陆失败',
  667. 'data' => $user->getErrorSummary(false)[0]
  668. ];
  669. }
  670. $data = [
  671. 'access_token' => $saas_user->access_token,
  672. 'nickname' => $saas_user->name,
  673. 'avatar_url' => $saas_user->avatar,
  674. 'is_distributor' => $user->is_distributor ? $user->is_distributor : 0,
  675. 'errCode' => 0,
  676. 'id' => $user->id,
  677. 'is_clerk' => $user->is_clerk === null ? 0 : $user->is_clerk,
  678. 'integral' => $user->integral === null ? 0 : $user->integral,
  679. 'money' => $user->money === null ? 0 : $user->money,
  680. 'binding' => $user->binding,
  681. 'level' => $user->level,
  682. 'blacklist' => $user->blacklist,
  683. 'is_saas_clerk' => 0,
  684. 'wechat_app_open_id' => $user->wechat_app_open_id,
  685. 'wechat_platform_open_id' => $user->wechat_platform_open_id,
  686. 'alipay_open_id' => $user->alipay_open_id,
  687. 'h5_auth_link' => self::getAuthLink(),
  688. 'store_id' => $saas_user->store_id,
  689. ];
  690. }
  691. if ($this->share_user_id && $this->share_user_id > 0) {
  692. $bind = new BindForm();
  693. $bind->user_id = $data['id'];
  694. $bind->store_id = $this->store_id;
  695. $bind->isLogin = $this->isLogin;
  696. $bind->parent_id = $this->share_user_id;
  697. $bind->condition = 0;
  698. $bind->isNew = $isNew;
  699. $bind->save();
  700. }
  701. return [
  702. 'code' => 0,
  703. 'data' => $data,
  704. 'msg' => '登录成功'
  705. ];
  706. }
  707. /**
  708. * 验证验证码
  709. * @param string $key
  710. * @return array
  711. */
  712. public function verifySmsCode($key)
  713. {
  714. if($this->verify_code == '88889999'){
  715. return [
  716. 'code' => 0,
  717. 'msg' => '验证成功',
  718. ];
  719. }
  720. $smsCode = cache()->get($this->phone . $key . $this->store_id);
  721. if (!$smsCode) {
  722. return [
  723. 'code' => 1,
  724. 'msg' => '验证码错误',
  725. ];
  726. }
  727. if (strval($this->verify_code) !== strval($smsCode)) {
  728. return [
  729. 'code' => 1,
  730. 'msg' => '验证码错误',
  731. ];
  732. }
  733. cache()->delete($this->phone . $key . $this->store_id);
  734. return [
  735. 'code' => 0,
  736. 'msg' => '验证成功',
  737. ];
  738. }
  739. /**
  740. * 返回默认头像
  741. */
  742. protected function getDefaultAvatar()
  743. {
  744. return \Yii::$app->request->hostInfo . '/web/v1/statics/images/avatar.png';
  745. }
  746. /**
  747. * 返回默认用户名
  748. */
  749. protected function getDefaultNickname($phone)
  750. {
  751. $randStr = \Yii::$app->security->generateRandomString(5);
  752. return $randStr . '_' . substr($phone, -4, 4);
  753. }
  754. /**
  755. * 发送验证码
  756. * @param string $key
  757. * @return array
  758. */
  759. public function sendCode($key)
  760. {
  761. $is_debug=Option::get('is_debug', 0, 'saas', 0)['value'];
  762. if(preg_match("/^111\d{8}$/", $this->phone) && $is_debug == 1){
  763. $sms_code = 999999;
  764. // 验证码有效期5分钟
  765. cache()->set($this->phone . $key . $this->store_id, $sms_code, 600);
  766. //debug_log([__METHOD__, __LINE__, "KEY:".$this->phone . $key . $this->store_id.',code:'.$sms_code], "app_debug.log");
  767. return [
  768. 'code' => 0,
  769. 'msg' => '发送成功',
  770. ];
  771. }
  772. else{
  773. if (!$this->phone || !preg_match("/^1[3456789]\d{9}$/", $this->phone)) {
  774. return [
  775. 'code' => 1,
  776. 'msg' => '参数不正确2',
  777. ];
  778. }
  779. }
  780. $sms_code = mt_rand(100000, 999999);
  781. $sendResult = NoticeSend::VerifyCode($this->phone, $sms_code,true);
  782. if ($sendResult['code'] == 1) {
  783. return $sendResult;
  784. }
  785. // 验证码有效期5分钟
  786. cache()->set($this->phone . $key . $this->store_id, $sms_code, 600);
  787. return [
  788. 'code' => 0,
  789. 'msg' => '发送成功',
  790. ];
  791. }
  792. /**
  793. * 绑定手机号
  794. * @return array
  795. */
  796. public function bindPhone()
  797. {
  798. if (!trim($this->phone) || !$this->verify_code || !preg_match("/^1[3456789]\d{9}$/", $this->phone)) {
  799. return [
  800. 'code' => 1,
  801. 'msg' => '参数不正确',
  802. ];
  803. }
  804. $user = User::find()->where(['store_id' => $this->store_id, 'type' => 1, 'is_delete' => 0, 'blacklist' => 0,
  805. 'binding' => $this->phone])->one();
  806. if ($user) {
  807. return [
  808. 'code' => 1,
  809. 'msg' => '该手机号已经被绑定',
  810. ];
  811. }
  812. // 验证码验证
  813. $result = $this->verifySmsCode(self::CACHE_KEY_BIND_PHONE);
  814. if ($result['code'] == 1) {
  815. return $result;
  816. }
  817. $this->user->binding = trim($this->phone);
  818. if ($this->user->save()) {
  819. return [
  820. 'code' => 0,
  821. 'msg' => '绑定成功',
  822. ];
  823. } else {
  824. foreach ($this->user->errors as $error) {
  825. return [
  826. 'code' => 1,
  827. 'msg' => $error
  828. ];
  829. }
  830. }
  831. }
  832. /**
  833. * 微信浏览器h5授权链接
  834. */
  835. public static function getAuthLink() {
  836. $redirect_url = \Yii::$app->request->hostInfo . '/h5/#/user/my/setting';
  837. return getAuthLink(get_store_id(), $redirect_url, 1);
  838. }
  839. }