Customer.php 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. <?php
  2. /*
  3. * FecShop file.
  4. *
  5. * @link http://www.fecshop.com/
  6. * @copyright Copyright (c) 2016 FecShop Software LLC
  7. * @license http://www.fecshop.com/license/
  8. */
  9. namespace fecshop\services;
  10. use Yii;
  11. use yii\web\IdentityInterface;
  12. /**
  13. * Customer service.
  14. * @property \fecshop\services\Customer\Address $address
  15. * @property \fecshop\services\customer\Newsletter $newsletter
  16. * @property \fecshop\services\customer\Affiliate $affiliate
  17. * @property \fecshop\services\customer\Coupon $coupon
  18. * @property \fecshop\services\customer\DropShip $dropship
  19. * @property \fecshop\services\customer\Favorite $favorite
  20. * @property \fecshop\services\customer\Message $message
  21. * @property \fecshop\services\customer\Order $order
  22. * @property \fecshop\services\customer\Point $point
  23. * @property \fecshop\services\customer\Review $review
  24. * @property \fecshop\services\customer\Wholesale $wholesale
  25. * @property \fecshop\services\customer\Facebook $facebook
  26. * @property \fecshop\services\customer\Google $google
  27. *
  28. * @method getPrimaryKey() see [[\fecshop\services\Customer::actionGetPrimaryKey()]]actionGetByPrimaryKey
  29. * @method \fecshop\models\mysqldb\Customer|null getByPrimarykey($val) see [[\fecshop\services\Customer::actionGetByPrimaryKey()]]
  30. * @method \fecshop\models\mysqldb\Customer|null getUserIdentityByEmail($email) see [[\fecshop\services\Customer::actionGetUserIdentityByEmail()]]
  31. * @method loginByAccessToken($type = null) see [[\fecshop\services\Customer::actionLoginByAccessToken()]]
  32. * @author Terry Zhao <2358269014@qq.com>
  33. * @since 1.0
  34. */
  35. class Customer extends Service
  36. {
  37. const USER_LOGIN_SUCCESS_REDIRECT_URL_KEY = 'usr_login_success_redirect_url';
  38. /**
  39. * @var array
  40. *
  41. * example:
  42. * ```php
  43. * [
  44. * 'customer_register' => [
  45. * 'min_name_length' => 1,
  46. * ]
  47. * ]
  48. * ```
  49. */
  50. public $customer_register;
  51. protected $_customerModelName = '\fecshop\models\mysqldb\Customer';
  52. /**
  53. * @var \fecshop\models\mysqldb\Customer
  54. */
  55. protected $_customerModel;
  56. protected $_customerLoginModelName = '\fecshop\models\mysqldb\customer\CustomerLogin';
  57. /**
  58. * @var \fecshop\models\mysqldb\customer\CustomerLogin
  59. */
  60. protected $_customerLoginModel;
  61. protected $_customerRegisterModelName = '\fecshop\models\mysqldb\customer\CustomerRegister';
  62. /**
  63. * @var \fecshop\models\mysqldb\customer\CustomerRegister
  64. */
  65. protected $_customerRegisterModel;
  66. public function init()
  67. {
  68. // 对于 api端口,设置Yii::$app->user->enableSession = false;
  69. // 下面的代码注释掉,对于使用到user组件的,在相应的模块部分设置 Yii::$app->user->enableSession = false;
  70. // if(Yii::$service->store->isApiStore()){
  71. // Yii::$app->user->enableSession = false;
  72. //}
  73. parent::init();
  74. list($this->_customerModelName, $this->_customerModel) = Yii::mapGet($this->_customerModelName);
  75. list($this->_customerLoginModelName, $this->_customerLoginModel) = Yii::mapGet($this->_customerLoginModelName);
  76. list($this->_customerRegisterModelName, $this->_customerRegisterModel) = Yii::mapGet($this->_customerRegisterModelName);
  77. $appName = Yii::$service->helper->getAppName();
  78. $this->customer_register = [
  79. 'min_name_length' => (int)Yii::$app->store->get($appName.'_account', 'min_name_length'), // 注册账号的firstname, lastname的最小长度
  80. 'max_name_length' => (int)Yii::$app->store->get($appName.'_account', 'max_name_length'), // 注册账号的firstname, lastname的最大长度
  81. 'min_pass_length' => (int)Yii::$app->store->get($appName.'_account', 'min_pass_length'), // 注册账号的密码的最小长度
  82. 'max_pass_length' => (int)Yii::$app->store->get($appName.'_account', 'max_pass_length'), // 注册账号的密码的最大长度
  83. ];
  84. }
  85. /**
  86. * 注册用户名字的最小长度.
  87. * @return int|null
  88. */
  89. protected function actionGetRegisterNameMinLength()
  90. {
  91. if (isset($this->customer_register['min_name_length'])) {
  92. return $this->customer_register['min_name_length'];
  93. }
  94. return null;
  95. }
  96. /**
  97. * 注册用户名字的最大长度.
  98. * @return int|null
  99. */
  100. protected function actionGetRegisterNameMaxLength()
  101. {
  102. if (isset($this->customer_register['max_name_length'])) {
  103. return $this->customer_register['max_name_length'];
  104. }
  105. return null;
  106. }
  107. /**
  108. * 注册用户密码的最小长度.
  109. * @return int|null
  110. */
  111. protected function actionGetRegisterPassMinLength()
  112. {
  113. if (isset($this->customer_register['min_pass_length'])) {
  114. return $this->customer_register['min_pass_length'];
  115. }
  116. return null;
  117. }
  118. /**
  119. * 注册用户密码的最大长度.
  120. * @return int|null
  121. */
  122. protected function actionGetRegisterPassMaxLength()
  123. {
  124. if (isset($this->customer_register['max_pass_length'])) {
  125. return $this->customer_register['max_pass_length'];
  126. }
  127. return null;
  128. }
  129. /**
  130. * @param array $data
  131. *
  132. * example:
  133. *
  134. * ```php
  135. * $data = ['email' => 'user@example.com', 'password' => 'your password'];
  136. * $loginStatus = \Yii::$service->customer->login($data);
  137. * ```
  138. *
  139. * @return bool
  140. */
  141. protected function actionLogin($data)
  142. {
  143. $model = $this->_customerLoginModel;
  144. $model->password = $data['password'];
  145. $model->email = $data['email'];
  146. $loginStatus = $model->login();
  147. $errors = $model->errors;
  148. if (empty($errors)) {
  149. // 合并购物车数据
  150. Yii::$service->cart->mergeCartAfterUserLogin();
  151. // 发送登录信息到trace系统
  152. Yii::$service->page->trace->sendTraceLoginInfoByApi($data['email']);
  153. } else {
  154. Yii::$service->helper->errors->addByModelErrors($errors);
  155. }
  156. return $loginStatus;
  157. }
  158. /**
  159. * Register customer account.
  160. * @param array $param
  161. * 数据格式如下:
  162. * ```php
  163. * [
  164. * 'email',
  165. * 'firstname',
  166. * 'lastname',
  167. * 'password'
  168. * ]
  169. * ```
  170. * @return bool whether the customer is registered ok
  171. */
  172. protected function actionRegister($param)
  173. {
  174. $model = $this->_customerRegisterModel;
  175. $model->attributes = $param;
  176. if ($model->validate()) {
  177. $model->created_at = time();
  178. $model->updated_at = time();
  179. if (Yii::$service->email->customer->registerAccountIsNeedEnableByEmail) {
  180. $model->generateRegisterEnableToken();
  181. $model->status = $model::STATUS_REGISTER_DISABLE;
  182. }
  183. $saveStatus = $model->save();
  184. if (!$saveStatus) {
  185. $errors = $model->errors;
  186. Yii::$service->helper->errors->addByModelErrors($errors);
  187. return false;
  188. }
  189. // 如果用户勾选了订阅邮件,那么添加到订阅
  190. if ($param['is_subscribed'] == 1) {
  191. Yii::$service->customer->newsletter->subscribe($param['email'], true);
  192. }
  193. // 发送注册信息到trace系统
  194. Yii::$service->page->trace->sendTraceRegisterInfoByApi($model->email);
  195. return true;
  196. } else {
  197. $errors = $model->errors;
  198. Yii::$service->helper->errors->addByModelErrors($errors);
  199. return false;
  200. }
  201. }
  202. /**
  203. * Check whether the given email is registered
  204. * @param string $email
  205. * @return bool whether the given email is registered
  206. */
  207. protected function actionIsRegistered($email)
  208. {
  209. $customer = $this->_customerModel->findOne(['email' => $email]);
  210. if ($customer['email']) {
  211. return true;
  212. } else {
  213. return false;
  214. }
  215. }
  216. /**
  217. * Save the customer info.
  218. * @param array $param
  219. * 数据格式如下:
  220. * ['email' => 'xxx', 'password' => 'xxxx','firstname' => 'xxx','lastname' => 'xxx']
  221. * @return bool
  222. */
  223. protected function actionSave($param)
  224. {
  225. $primaryKey = $this->getPrimaryKey();
  226. $primaryVal = isset($param[$primaryKey]) ? $param[$primaryKey] : '';
  227. if ($primaryVal) {
  228. $model = $this->_customerRegisterModel;
  229. $model->attributes = $param;
  230. if (!$model->validate()) {
  231. $errors = $model->errors;
  232. Yii::$service->helper->errors->addByModelErrors($errors);
  233. return false;
  234. }
  235. $model = $this->getByPrimaryKey($primaryVal);
  236. if ($model[$primaryKey]) {
  237. unset($param[$primaryKey]);
  238. $param['updated_at'] = time();
  239. $password = isset($param['password']) ? $param['password'] : '';
  240. if ($password) {
  241. $model->setPassword($password);
  242. unset($param['password']);
  243. }
  244. $saveStatus = Yii::$service->helper->ar->save($model, $param);
  245. if ($saveStatus) {
  246. return true;
  247. } else {
  248. $errors = $model->errors;
  249. Yii::$service->helper->errors->addByModelErrors($errors);
  250. return false;
  251. }
  252. }
  253. } else {
  254. if ($this->register($param)) {
  255. return true;
  256. }
  257. }
  258. return false;
  259. }
  260. /**
  261. * @param int $customerId
  262. * @deprecated 该方法已废弃
  263. */
  264. protected function actionViewInfo($customerId)
  265. {
  266. }
  267. /**
  268. * Change customer's password
  269. * @param string $password
  270. * @param int|string|IdentityInterface $identity this can be customer id, customer email, or customer
  271. * @return bool
  272. * @throws \InvalidArgumentException if $identity is invalid
  273. */
  274. protected function actionChangePassword($password, $identity)
  275. {
  276. if (is_int($identity)) {
  277. $customer_id = $identity;
  278. $customerModel = $this->_customerModel->findIdentity($customer_id);
  279. } elseif (is_string($identity)) {
  280. $email = $identity;
  281. $customerModel = $this->_customerModel->findByEmail($email);
  282. } elseif (is_object($identity) && $identity instanceof IdentityInterface) {
  283. $customerModel = $identity;
  284. } else {
  285. throw new \InvalidArgumentException('$identity can only be customer id, customer email, or customer');
  286. }
  287. if ($customerModel['email']) {
  288. $customerModel->updated_at = time();
  289. $customerModel->setPassword($password);
  290. $customerModel->save();
  291. return true;
  292. } else {
  293. return false;
  294. }
  295. }
  296. /**
  297. * 得到category model的全名.
  298. */
  299. protected function actionGetModelName()
  300. {
  301. $model = new $this->_customerModelName();
  302. return get_class($model);
  303. }
  304. /**
  305. * @param int $val
  306. * @return \fecshop\models\mysqldb\Customer
  307. */
  308. protected function actionGetByPrimaryKey($val)
  309. {
  310. $one = $this->_customerModel->findOne($val);
  311. $primaryKey = $this->getPrimaryKey();
  312. if ($one[$primaryKey]) {
  313. return $one;
  314. } else {
  315. return new $this->_customerModelName();
  316. }
  317. }
  318. /**
  319. * @param $password|string
  320. * @param $customerId|int or String or Object
  321. * change customer password.
  322. * 更改密码,然后,清空token
  323. */
  324. protected function actionChangePasswordAndClearToken($password, $identity)
  325. {
  326. if (is_int($identity)) {
  327. $customer_id = $identity;
  328. $customerModel = $this->_customerModel->findIdentity($customer_id);
  329. } elseif (is_string($identity)) {
  330. $email = $identity;
  331. $customerModel = $this->_customerModel->findByEmail($email);
  332. } elseif (is_object($identity)) {
  333. $customerModel = $identity;
  334. } else {
  335. Yii::$service->helper->errors->add('identity is not right');
  336. return null;
  337. }
  338. if (strlen($password) < 6 || strlen($password) > 30) {
  339. Yii::$service->helper->errors->add('Password length must be greater than 6, less than 30');
  340. return null;
  341. }
  342. $customerModel->setPassword($password);
  343. $customerModel->removePasswordResetToken();
  344. $customerModel->updated_at = time();
  345. $customerModel->save();
  346. return true;
  347. }
  348. /**
  349. * @param $password|string
  350. * @param $customerId|int or String or Object
  351. * change customer password.
  352. * 更改密码,然后,清空token
  353. */
  354. protected function actionRegisterEnableByTokenAndClearToken($token)
  355. {
  356. $identity = $this->findByRegisterEnableToken($token);
  357. if (!$identity['id']) {
  358. Yii::$service->helper->errors->add('token is invalid');
  359. return false;
  360. }
  361. $identity->status = $identity::STATUS_ACTIVE;
  362. $identity->updated_at = time();
  363. return $identity->save();
  364. }
  365. /**
  366. * @deprecated 已废弃
  367. */
  368. protected function actionChangeNameAndPassword($data)
  369. {
  370. }
  371. /**
  372. * @deprecated 已废弃
  373. */
  374. protected function actionGetCurrentAccount()
  375. {
  376. }
  377. /**
  378. * Get customer by email address
  379. * @param string $email
  380. * @return \fecshop\models\mysqldb\Customer|null return customer or null if not found
  381. */
  382. protected function actionGetUserIdentityByEmail($email)
  383. {
  384. $one = $this->_customerModel->findByEmail($email);
  385. if ($one['email']) {
  386. return $one;
  387. } else {
  388. return null;
  389. }
  390. }
  391. // 得到可用的账户
  392. protected function actionGetAvailableUserIdentityByEmail($email)
  393. {
  394. $one = $this->_customerModel->findAvailableByEmail($email);
  395. if ($one['email']) {
  396. return $one;
  397. } else {
  398. return null;
  399. }
  400. }
  401. /**
  402. * 生成resetToken,用来找回密码
  403. * @param string|IdentityInterface $identify identity can be customer email, or customer object
  404. * @return string|null 生成的resetToken,如果生成失败返回false
  405. */
  406. protected function actionGeneratePasswordResetToken($identify)
  407. {
  408. if (is_string($identify)) {
  409. $email = $identify;
  410. $one = $this->getUserIdentityByEmail($email);
  411. } else {
  412. $one = $identify;
  413. }
  414. if ($one) {
  415. $one->generatePasswordResetToken();
  416. $one->updated_at = time();
  417. $one->save();
  418. return $one->password_reset_token;
  419. }
  420. return false;
  421. }
  422. /**
  423. * 生成resetToken,用来找回密码
  424. * @param string|IdentityInterface $identify identity can be customer email, or customer object
  425. * @return string|null 生成的resetToken,如果生成失败返回false
  426. */
  427. protected function actionGenerateRegisterEnableToken($identify)
  428. {
  429. if (is_string($identify)) {
  430. $email = $identify;
  431. $one = $this->actionGetAvailableUserIdentityByEmail($email);
  432. } else {
  433. $one = $identify;
  434. }
  435. if ($one) {
  436. $one->generateRegisterEnableToken();
  437. $one->updated_at = time();
  438. $one->save();
  439. return $one->register_enable_token;
  440. }
  441. return false;
  442. }
  443. /**
  444. * @param string $token the password reset token
  445. * 通过PasswordResetToken 得到user.
  446. * @return \fecshop\models\mysqldb\Customer|null returns customer or null if not found
  447. */
  448. protected function actionFindByPasswordResetToken($token)
  449. {
  450. return $this->_customerModel->findByPasswordResetToken($token);
  451. }
  452. protected function actionFindByRegisterEnableToken($token)
  453. {
  454. return $this->_customerModel->findByRegisterEnableToken($token);
  455. }
  456. /**
  457. * @param $url|string
  458. * **注意**:该方法不能在接口类型里面使用
  459. * 在一些功能中,需要用户进行登录操作,等用户操作成功后,应该跳转到相应的页面中,这里通过session存储需要跳转到的url。
  460. * 某些页面 , 譬如评论页面,需要用户登录后才能进行登录操作,那么可以通过这个方法把url set 进去,登录成功
  461. * 后,页面不会跳转到账户中心,而是需要操作的页面中。
  462. */
  463. protected function actionSetLoginSuccessRedirectUrl($url)
  464. {
  465. return Yii::$service->session->set($this::USER_LOGIN_SUCCESS_REDIRECT_URL_KEY, $url);
  466. }
  467. /**
  468. * @param $url|string
  469. * **注意**:该方法不能在接口类型里面使用
  470. * **注意**:该方法不能在接口类型里面使用
  471. * 在一些功能中,需要用户进行登录操作,等用户操作成功后,应该跳转到相应的页面中,这里通过session得到需要跳转到的url。
  472. */
  473. protected function actionGetLoginSuccessRedirectUrl()
  474. {
  475. $url = Yii::$service->session->get($this::USER_LOGIN_SUCCESS_REDIRECT_URL_KEY);
  476. return $url ? $url : '';
  477. }
  478. /**
  479. * @param $urlKey | String
  480. * **注意**:该方法不能在接口类型里面使用
  481. * 登录用户成功后,进行url跳转。
  482. */
  483. protected function actionLoginSuccessRedirect($urlKey = '')
  484. {
  485. $url = $this->getLoginSuccessRedirectUrl();
  486. if ($url) {
  487. // 这个优先级最高
  488. // 在跳转之前,去掉这个session存储的值。跳转后,这个值必须失效。
  489. Yii::$service->session->remove($this::USER_LOGIN_SUCCESS_REDIRECT_URL_KEY);
  490. //echo Yii::$service->session->get($this::USER_LOGIN_SUCCESS_REDIRECT_URL_KEY);
  491. //exit;
  492. return Yii::$service->url->redirect($url);
  493. } elseif ($urlKey) {
  494. return Yii::$service->url->redirectByUrlKey($urlKey);
  495. } else {
  496. return Yii::$service->url->redirectHome();
  497. }
  498. }
  499. /**
  500. * 得到status为删除状态的值
  501. */
  502. protected function actionGetStatusDeleted()
  503. {
  504. $model = $this->_customerModel;
  505. return $model::STATUS_DELETED;
  506. }
  507. /**
  508. * 得到status为激活状态的值
  509. */
  510. protected function actionGetStatusActive()
  511. {
  512. $model = $this->_customerModel;
  513. return $model::STATUS_ACTIVE;
  514. }
  515. /**
  516. * Get primary key field name.
  517. */
  518. protected function actionGetPrimaryKey()
  519. {
  520. return 'id';
  521. }
  522. /**
  523. * Get customer collection by filter array
  524. * @param array $filter
  525. * filter example:
  526. * [
  527. * 'numPerPage' => 20,
  528. * 'pageNum' => 1,
  529. * 'orderBy' => ['_id' => SORT_DESC, 'sku' => SORT_ASC ],
  530. * 'where' => [
  531. * ['>','price','1'],
  532. * ['<','price','10'],
  533. * ['sku' => 'uk10001'],
  534. * ],
  535. * 'asArray' => true,
  536. * ]
  537. * @return array
  538. */
  539. protected function actionColl($filter = [])
  540. {
  541. $query = $this->_customerModel->find();
  542. $query = Yii::$service->helper->ar->getCollByFilter($query, $filter);
  543. return [
  544. 'coll' => $query->all(),
  545. 'count'=> $query->limit(null)->offset(null)->count(),
  546. ];
  547. }
  548. /**
  549. * Remove customer by primary key value
  550. * @param int $id the primary key value
  551. * @return bool
  552. * @throws
  553. */
  554. public function remove($id)
  555. {
  556. if (!$id) {
  557. Yii::$service->helper->errors->add('remove id is empty');
  558. return false;
  559. }
  560. $model = $this->_customerModel->findOne($id);
  561. if (isset($model[$this->getPrimaryKey()]) && !empty($model[$this->getPrimaryKey()])) {
  562. $model->delete();
  563. } else {
  564. Yii::$service->helper->errors->add("customer Remove Errors:ID:$id is not exist.");
  565. return false;
  566. }
  567. return true;
  568. }
  569. /**
  570. * @param $user_ids | Array , 子项为Int类型
  571. * @return Array ,数据格式为:
  572. * ['id' => 'email']
  573. * 得到customer id 和customer email的对应数组。
  574. */
  575. protected function actionGetEmailByIds($user_ids)
  576. {
  577. $arr = [];
  578. if (is_array($user_ids) && !empty($user_ids)) {
  579. $data = $this->_customerModel->find()->where([
  580. 'in', 'id', $user_ids,
  581. ])->all();
  582. if (is_array($data) && !empty($data)) {
  583. foreach ($data as $one) {
  584. $arr[$one['id']] = $one['email'];
  585. }
  586. }
  587. }
  588. return $arr;
  589. }
  590. //2. 创建第三方用户的账户,密码自动生成
  591. /**
  592. * @param $user | Array ,example:
  593. * ['first_name' => $first_name,'last_name' => $last_name,'email' => $email,]
  594. * @param $type | String 代表第三方登录的名称,譬如google,facebook
  595. * @return bool
  596. * 如果用户emai存在,则直接登录,成功后返回true
  597. * 如果用户不存在,则注册用户,然后直接登录,成功后返回true
  598. */
  599. protected function actionRegisterThirdPartyAccountAndLogin($user, $type)
  600. {
  601. // 查看邮箱是否存在
  602. $email = $user['email'];
  603. $customer_one = Yii::$service->customer->getUserIdentityByEmail($email);
  604. if ($customer_one) {
  605. $loginStatus = \Yii::$app->user->login($customer_one);
  606. if ($loginStatus) {
  607. $customer_one->generateAccessToken();
  608. $customer_one->access_token_created_at = time();
  609. $customer_one->save();
  610. return $this->setHeaderAccessToken($customer_one->access_token);
  611. }
  612. // 不存在,注册。
  613. } else {
  614. if (!(isset($user['password']) && $user['password'])) {
  615. $user['password'] = $this->getRandomPassword();
  616. }
  617. $registerData = [
  618. 'email' => $email,
  619. 'firstname' => $user['first_name'],
  620. 'lastname' => $user['last_name'],
  621. 'password' => $user['password'],
  622. 'type' => $type,
  623. ];
  624. $registerStatus = Yii::$service->customer->register($registerData);
  625. if ($registerStatus) {
  626. return Yii::$service->customer->loginAndGetAccessToken($registerData['email'], $registerData['password']);
  627. }
  628. }
  629. return false;
  630. }
  631. /**
  632. * 生成账户密码
  633. */
  634. protected function getRandomPassword()
  635. {
  636. srand((float) microtime() * 1000000); //create a random number feed.
  637. $ychar = '0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z';
  638. $list = explode(',', $ychar);
  639. for ($i = 0; $i < 6; $i++) {
  640. $randnum = rand(0, 35); // 10+26;
  641. $authnum .= $list[$randnum];
  642. }
  643. //return $authnum;
  644. return $authnum;
  645. }
  646. /**
  647. * @param $identity | Object, customer model
  648. * #param $duration
  649. * 通过identity 进行登陆账户
  650. * 通过
  651. */
  652. public function loginByIdentityAndGetAccessToken($identity, $wx_session_key='', $duration = 0)
  653. {
  654. $header = Yii::$app->request->getHeaders();
  655. if (isset($header['access-token']) && $header['access-token']) {
  656. $accessToken = $header['access-token'];
  657. }
  658. // 如果request header中有access-token,则查看这个 access-token 是否有效
  659. if ($accessToken) {
  660. $access_token_identity = Yii::$app->user->loginByAccessToken($accessToken);
  661. if ($access_token_identity !== null) {
  662. $access_token_created_at = $access_token_identity->access_token_created_at;
  663. $timeout = Yii::$service->session->timeout;
  664. if ($access_token_created_at + $timeout > time()) {
  665. return $accessToken;
  666. }
  667. }
  668. }
  669. // 执行登陆
  670. if (!$duration) {
  671. if (Yii::$service->session->timeout) {
  672. $duration = Yii::$service->session->timeout;
  673. }
  674. }
  675. //var_dump($identity);exit;
  676. if (\Yii::$app->user->login($identity, $duration)) {
  677. $identity->generateAccessToken();
  678. $identity->access_token_created_at = time();
  679. $identity->wx_session_key = $wx_session_key;
  680. $identity->save();
  681. // 执行购物车合并等操作。
  682. Yii::$service->cart->mergeCartAfterUserLogin();
  683. $this->setHeaderAccessToken($identity->access_token);
  684. return $identity->access_token;
  685. }
  686. }
  687. /** AppServer 部分使用的函数
  688. * @param $email | String
  689. * @param $password | String
  690. * 无状态登录,通过email 和password进行登录
  691. * 登录成功后,合并购物车,返回accessToken
  692. * ** 该函数是未登录用户,通过参数进行登录需要执行的函数。
  693. */
  694. protected function actionLoginAndGetAccessToken($email, $password)
  695. {
  696. $header = Yii::$app->request->getHeaders();
  697. if (isset($header['access-token']) && $header['access-token']) {
  698. $accessToken = $header['access-token'];
  699. }
  700. // 如果request header中有access-token,则查看这个 access-token 是否有效
  701. if ($accessToken) {
  702. $identity = Yii::$app->user->loginByAccessToken($accessToken);
  703. if ($identity !== null) {
  704. $access_token_created_at = $identity->access_token_created_at;
  705. $timeout = Yii::$service->session->timeout;
  706. if ($access_token_created_at + $timeout > time()) {
  707. return $accessToken;
  708. }
  709. }
  710. }
  711. // 如果上面access-token不存在
  712. $data = [
  713. 'email' => $email,
  714. 'password' => $password,
  715. ];
  716. if (Yii::$service->customer->login($data)) {
  717. $identity = Yii::$app->user->identity;
  718. $identity->generateAccessToken();
  719. $identity->access_token_created_at = time();
  720. $identity->save();
  721. // 执行购物车合并等操作。
  722. Yii::$service->cart->mergeCartAfterUserLogin();
  723. $this->setHeaderAccessToken($identity->access_token);
  724. return $identity->access_token;
  725. }
  726. }
  727. /**
  728. * Logs in a user by the given access token.
  729. * Token is passed through headers. So you can get it from the key 'access-token'.
  730. * @param $type
  731. * @return IdentityInterface|null the identity associated with the given access token. Null is returned if
  732. * the access token is invalid.
  733. * @see [[\yii\web\User::loginByAccessToken()]]
  734. */
  735. protected function actionLoginByAccessToken($type = null)
  736. {
  737. $header = Yii::$app->request->getHeaders();
  738. if (isset($header['access-token']) && $header['access-token']) {
  739. $accessToken = $header['access-token'];
  740. } else {
  741. return null;
  742. }
  743. /** @var \fecshop\models\mysqldb\Customer|null $identity */
  744. $identity = Yii::$app->user->loginByAccessToken($accessToken, $type);
  745. if ($identity !== null) {
  746. $access_token_created_at = $identity->access_token_created_at;
  747. $timeout = Yii::$service->session->timeout;
  748. // 如果时间没有过期,则返回 identity
  749. if ($access_token_created_at + $timeout > time()) {
  750. // 如果时间没有过期,但是快要过期了,在过$updateTimeLimit段时间就要过期,那么更新access_token_created_at。
  751. $updateTimeLimit = Yii::$service->session->updateTimeLimit;
  752. if ($access_token_created_at + $timeout <= (time() + $updateTimeLimit)) {
  753. $identity->access_token_created_at = time();
  754. $identity->save();
  755. }
  756. return $identity;
  757. } else {
  758. $this->logoutByAccessToken();
  759. return null;
  760. }
  761. }
  762. return null;
  763. }
  764. /**
  765. * @param $openid | string
  766. * 通过微信的openid 得到 user
  767. */
  768. protected function actionGetByWxOpenid($openid)
  769. {
  770. $one = $this->_customerModel->findOne(['wx_openid' => $openid]);
  771. $primaryKey = $this->getPrimaryKey();
  772. if ($one[$primaryKey]) {
  773. return $one;
  774. }
  775. return null;
  776. }
  777. /**
  778. * 通过accessToek的方式,进行登出从操作。
  779. */
  780. public function logoutByAccessToken()
  781. {
  782. $userComponent = Yii::$app->user;
  783. $identity = $userComponent->identity;
  784. if ($identity !== null) {
  785. if (!Yii::$app->user->isGuest) {
  786. $identity->access_token = null;
  787. $identity->access_token_created_at = null;
  788. $identity->save();
  789. }
  790. $userComponent->switchIdentity(null);
  791. // 刷新uuid
  792. Yii::$service->session->reflushUUID();
  793. }
  794. return $userComponent->getIsGuest();
  795. }
  796. protected function actionSetHeaderAccessToken($accessToken)
  797. {
  798. if ($accessToken) {
  799. Yii::$app->response->getHeaders()->set('access-token', $accessToken);
  800. return true;
  801. }
  802. }
  803. /**
  804. * @param $days | Int 天数
  805. * 得到最近X天的注册用户
  806. * 下面的数据是为了后台的customer 注册数统计
  807. */
  808. public function getPreMonthCustomer($days)
  809. {
  810. // 得到一个月前的时间戳
  811. $preMonthTime = strtotime("-$days days");
  812. $filter = [
  813. 'select' => ['created_at', 'email' ],
  814. 'numPerPage' => 10000000,
  815. 'pageNum' => 1,
  816. 'where' => [
  817. ['>=', 'created_at', $preMonthTime]
  818. ],
  819. 'asArray' => true,
  820. ];
  821. $data = $this->coll($filter);
  822. $coll = $data['coll'];
  823. $dateArr = Yii::$service->helper->format->getPreDayDateArr($days);
  824. $customerArr = $dateArr;
  825. if (is_array($coll) && !empty($coll)) {
  826. foreach ($coll as $order) {
  827. $created_at = $order['created_at'];
  828. $created_at_str = date("Y-m-d", $created_at);
  829. if (isset($customerArr[$created_at_str])) {
  830. $customerArr[$created_at_str] += 1;
  831. }
  832. }
  833. }
  834. return [
  835. '用户注册数' => $customerArr,
  836. ];
  837. }
  838. }