IdentityController.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. <?php
  2. namespace api\modules\v1\controllers\user;
  3. use api\modules\v1\forms\user\AlipayMiniForm;
  4. use api\modules\v1\forms\user\WechatForm;
  5. use common\enums\AddonsEnum;
  6. use common\enums\EventNameEnum;
  7. use common\enums\RedisKeyEnum;
  8. use common\enums\StatusEnum;
  9. use common\events\user\UserCancellationEvent;
  10. use common\events\user\UserLoginEvent;
  11. use common\events\user\UserRegisterEvent;
  12. use common\expand\alipay\auth\src\OauthTokenService;
  13. use common\helpers\ArrayHelper;
  14. use common\helpers\sms\Sms;
  15. use common\models\common\MallSetting;
  16. use common\models\mall\MallAddons;
  17. use common\models\user\User;
  18. use common\models\user\UserInfo;
  19. use Yii;
  20. use api\controllers\OnAuthController;
  21. use common\enums\addons\MallAddonsEnum;
  22. use common\enums\ApiStatusEnum;
  23. use yii\db\Exception;
  24. use yii\helpers\Json;
  25. /**
  26. * Class IdentityController
  27. * @package api\modules\user\controllers
  28. */
  29. class IdentityController extends OnAuthController
  30. {
  31. public $modelClass = '';
  32. /**
  33. *
  34. * 不用进行登录验证的方法
  35. *
  36. * 例如: ['index', 'update', 'create', 'view', 'delete']
  37. * 默认全部需要验证
  38. *
  39. * @var array
  40. */
  41. protected $authOptional = ['login','bind', 'mobile-login', 'jssdk-config','register-sms-code', 'register', 'up-pwd', 'auth-login',
  42. 'mini-login','app-auth-login','auth-phone','auth-alipay-mini','mobile-alipay-mini','save-wechat',
  43. 'forget-password','mobile-alipay-mini-by-code'
  44. ];
  45. public function actionForgetPassword(){
  46. try {
  47. if (\Yii::$app->request->isPost) {
  48. $params = Yii::$app->request->post();
  49. $res = Yii::$app->services->validate->validate($params, [
  50. [['mobile', 'captcha', 'password'], 'required'],
  51. ['mobile', 'match', 'pattern' => '/[0-9]+$/', 'message' => '请输入正确的手机号码'],
  52. [['mobile'], 'integer'],
  53. ['password', 'string', 'length' => [6, 11]],
  54. ]);
  55. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  56. //短信验证码
  57. if (YII_ENV == 'prod') {
  58. if (!Sms::checkValidateCode($params['mobile'], $params['captcha'],Sms::SMS_TYPE_UPDATE_PASS)) return $this->error('验证码不正确');
  59. }
  60. $user = User::findOne(['mobile'=>$params['mobile'],'mall_id'=>$this->mall_id,'status'=>[StatusEnum::ENABLED,StatusEnum::DISABLED]]);
  61. if(empty($user)) return $this->error('此手机号未注册');
  62. if(empty($user->status)) return $this->error('此手机号被禁用');
  63. $user->password = Yii::$app->getSecurity()->generatePasswordHash(trim($params['password']));
  64. if ($user->save() === false) return $this->error(User::getStaticError());
  65. return $this->success('设置成功');
  66. }
  67. } catch (\Exception $e) {
  68. return $this->error($e->getMessage());
  69. }
  70. }
  71. /**
  72. * h5注册
  73. * @return \yii\web\Response
  74. */
  75. public function actionRegister()
  76. {
  77. try {
  78. if (\Yii::$app->request->isPost) {
  79. $params = Yii::$app->request->post();
  80. $mall_id = $this->mall_id;
  81. $res = Yii::$app->services->validate->validate($params, [
  82. [['mobile', 'password', 'confirm_password'], 'required'],
  83. [['captcha'], 'safe'],
  84. ['mobile', 'match', 'pattern' => '/[0-9]+$/', 'message' => '请输入正确的手机号码'],
  85. ['invite_mobile', 'match', 'pattern' => '/[0-9]+$/', 'message' => '请输入正确的推荐人手机号码'],
  86. ['password', 'string', 'length' => [6, 11]],
  87. ['password', 'match', 'pattern' => '/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9a-zA-Z]+$/', 'message' => '密码必须是字母加数字'],
  88. ['confirm_password', 'compare', 'compareAttribute' => 'password', 'message' => '两次密码不一致'],
  89. [['nickname'], 'string'],
  90. ['mobile', function ($attribute) use ($mall_id) {
  91. $where[] = ['mall_id' => $mall_id];
  92. $where[] = ['or', ['mobile' => trim($this->$attribute)], ['username' => trim($this->$attribute)]];
  93. if (User::getUser($where)) $this->addError($attribute, '手机号码已存在');
  94. }],
  95. ]);
  96. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  97. // 获取公共配置
  98. $basic = Yii::$app->services->setting->mall->get($this->mall_id, 'basic');
  99. $basic['is_write_name'] = !isset($basic['is_write_name']) ? 0 : $basic['is_write_name']; // 要不要强制填写昵称
  100. if ($basic['is_write_name']) { // 要
  101. if (empty($params['nickname'])) {
  102. return $this->error('昵称不能为空');
  103. }
  104. } else { // 不要
  105. $params['nickname'] = '游客' . substr(time(), -4) . mt_rand(100, 999);
  106. }
  107. $mall_setting = Yii::$app->services->setting->mall->get($mall_id, 'user');
  108. $check_sms_code_value = $mall_setting['check_sms_code'] ?? 1;
  109. if(empty($params['captcha']) && $check_sms_code_value) return $this->error('请输入验证码');
  110. //短信验证码 开启验证码注册才检查
  111. if (YII_ENV == 'prod' && $check_sms_code_value) {
  112. //短信验证码
  113. if (!Sms::checkValidateCode($params['mobile'], $params['captcha'],Sms::SMS_TYPE_REGISTER)) return $this->error('验证码不正确');
  114. }
  115. $params['mall_id'] = $this->mall_id;
  116. $params['username'] = $params['mobile'];
  117. $params['parent_id'] = $this->parent_id;
  118. $params['password'] = Yii::$app->getSecurity()->generatePasswordHash($params['password']);
  119. $params['source'] = empty($this->source) ? User::SOURCE_SHARE_INDEX : $this->source;
  120. $params['platform'] = User::PLATFORM_H5;
  121. $res = User::setData($params);
  122. if ($res === false) return $this->error(User::getStaticError());
  123. // 触发注册成功事件,事务提交完成后触发
  124. $event = new UserRegisterEvent($this->mall_id);
  125. $data = ['user_id' => $res->id, 'platform' => 'h5'];
  126. Yii::$app->services->events->dispatch($event, $data, $event->listeners);
  127. return $this->success('注册成功');
  128. }
  129. } catch (\Exception $e) {
  130. return $this->error($e->getMessage());
  131. }
  132. }
  133. /**
  134. * h5登录
  135. * @return mixed|void
  136. */
  137. public function actionLogin()
  138. {
  139. try {
  140. if (Yii::$app->request->isPost) {
  141. $params = Yii::$app->request->post();
  142. $res = Yii::$app->services->validate->validate($params, [
  143. [['username'], 'required'],
  144. [['captcha', 'password', 'device_type', 'device_mac'], 'safe'],
  145. ]);
  146. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  147. $params['mall_id'] = $this->mall_id;
  148. $user = User::loginByH5($params);
  149. if ($user === false) return $this->error(User::getStaticError());
  150. $token = Yii::$app->services->apiAccessToken->getAccessToken($user, 'api');
  151. // 触发登录成功事件,事务提交完成后触发
  152. $event = new UserLoginEvent($this->mall_id);
  153. Yii::$app->services->events->dispatch($event, [
  154. 'mall_id' => $this->mall_id,
  155. 'nickname' => $user->nickname,
  156. 'user_id' => $user->id,
  157. 'platform' => 'h5',
  158. 'ip' => ArrayHelper::get_client_ip(),
  159. 'device_type' => $params['device_type'] ?? '',
  160. 'device_mac' => $params['device_mac'] ?? '',
  161. ], $event->listeners);
  162. return $this->success('登录成功', $token);
  163. }
  164. } catch (\Exception $e) {
  165. return $this->error($e->getMessage());
  166. }
  167. }
  168. /**
  169. * 登出
  170. *
  171. * @return array|mixed
  172. */
  173. public function actionLogout()
  174. {
  175. if (Yii::$app->services->apiAccessToken->disableByAccessToken(Yii::$app->user->identity->access_token)) return $this->success('退出成功');
  176. return $this->error('退出失败');
  177. }
  178. /**
  179. * 权限验证
  180. *
  181. * @param string $action 当前的方法
  182. * @param null $model 当前的模型类
  183. * @param array $params $_GET变量
  184. * @throws \yii\web\BadRequestHttpException
  185. */
  186. public function checkAccess($action, $model = null, $params = [])
  187. {
  188. // 方法名称
  189. if (in_array($action, ['index', 'view', 'update', 'create', 'delete'])) {
  190. throw new \yii\web\BadRequestHttpException('权限不足');
  191. }
  192. }
  193. /**
  194. * 获取注册短信验证码
  195. * @return mixed|void
  196. * @throws \Overtrue\EasySms\Exceptions\NoGatewayAvailableException
  197. */
  198. public function actionRegisterSmsCode()
  199. {
  200. $params = Yii::$app->request->post();
  201. $res = Yii::$app->services->validate->validate($params, [
  202. [['mobile'], 'required', 'message' => '请输入手机号码'],
  203. [['mobile','area_code'], 'integer'],
  204. [['sms_type'], 'string'],
  205. ]);
  206. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  207. $area_code = '';// 初始化区号
  208. $gateways = 'domestic';// 默认国内短信
  209. // 检测是登录并且区号不为空则使用国际短信
  210. if (!empty($this->user) && !empty($this->user->area_code)&&$this->user->area_code!=86) {
  211. $gateways = 'international';
  212. $area_code = $this->user->area_code;
  213. }
  214. // 判断是否有区号
  215. if (!empty($params['area_code']) && $params['area_code'] != 86) {
  216. $gateways = 'international';
  217. $area_code = $params['area_code'];
  218. }
  219. $notice_sms_status = \Yii::$app->services->setting->mall->get($this->mall_id, 'notice_sms.status');
  220. if(empty($notice_sms_status)) return $this->error('短信提醒未开启');
  221. //$params['sms_type'] = $params['sms_type'] ?: 'register';
  222. $params['sms_type'] = $params['sms_type'] ?: '';
  223. $sms = new Sms($this->mall_id, $gateways);
  224. try {
  225. if ($sms->sendCaptcha($params['mobile'], $area_code,$params['sms_type']) === false) return $this->error('发送失败');
  226. }catch (\Exception $e){
  227. return $this->error($e->getMessage());
  228. }
  229. return $this->success('发送成功');
  230. }
  231. /**
  232. * @desc:授权登录
  233. * @Author: hua
  234. * @Date: 2021/10/22
  235. * @Time: 16:51
  236. * @Copyright: copyright (c) 2021 广东七件事集团
  237. * @return mixed|void
  238. */
  239. public function actionAuthLogin()
  240. {
  241. return $this->_handleAuth('weixin');
  242. // $requests = Yii::$app->request;
  243. // $wechat_form = new WechatForm(['mall_id'=>$this->mall_id]);
  244. // $params_data = @file_get_contents('php://input');
  245. // if (!empty($params_data)) $json_data = json_decode($params_data, true);
  246. // $params = array_merge($requests->get(), $requests->post(), $json_data ?? []);
  247. // $res = Yii::$app->services->validate->validate($params, [
  248. // [['code', 'encryptedData', 'iv', 'key'], 'string'],
  249. // [['user_id', 'activity_id', 'share_user_id'], "integer"]
  250. // ]);
  251. // if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  252. // $params['mall_id'] = $this->mall_id;
  253. // $params['source'] = empty($this->source) ? User::SOURCE_SHARE_INDEX : $this->source;
  254. // $result = $wechat_form->authorized($params);
  255. // if ($result === false) return $this->error($wechat_form::getStaticError());
  256. // return $this->success('成功', $result);
  257. }
  258. /**
  259. * @desc:小程序授权登录
  260. * @Author: hua
  261. * @Date: 2021/10/22
  262. * @Time: 9:37
  263. * @Copyright: copyright (c) 2021 广东七件事集团
  264. * @return mixed|void
  265. */
  266. public function actionMiniLogin()
  267. {
  268. return $this->_handleAuth('mp-weixin');
  269. // $requests = Yii::$app->request;
  270. // $wechat_form = new WechatForm(['mall_id'=>$this->mall_id]);
  271. // $params_data = @file_get_contents('php://input');
  272. // if (!empty($params_data)) $json_data = json_decode($params_data, true);
  273. // $params = array_merge($requests->get(), $requests->post(), $json_data ?? []);
  274. // $res = Yii::$app->services->validate->validate($params, [
  275. // [['code', 'encryptedData', 'iv', 'key'], 'string'],
  276. // [['user_id', 'activity_id', 'share_user_id'], "integer"]
  277. // ]);
  278. // if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  279. // $params['mall_id'] = $this->mall_id;
  280. // $params['source'] = empty($this->source) ? User::SOURCE_SHARE_INDEX : $this->source;
  281. // $result = $wechat_form->miniAuthorized($params);
  282. // if ($result === false) return $this->error($wechat_form::getStaticError());
  283. // return $this->success('成功', $result);
  284. }
  285. /**
  286. * app端微信授权登录
  287. * @Author: zal
  288. * @Date: 2020-12-24
  289. * @Time: 17:33
  290. * @return array
  291. * @throws \Exception
  292. */
  293. public function actionAppAuthLogin()
  294. {
  295. return $this->_handleAuth('app-weixin');
  296. // $requests = Yii::$app->request;
  297. // $wechat_form = new WechatForm(['mall_id'=>$this->mall_id]);
  298. // $params_data = @file_get_contents('php://input');
  299. // if (!empty($params_data)) $json_data = json_decode($params_data, true);
  300. // $params = array_merge($requests->get(), $requests->post(), $json_data ?? []);
  301. // $res = Yii::$app->services->validate->validate($params, [
  302. // [['userData'], 'string'],
  303. // [['user_id', 'activity_id', 'share_user_id'], "integer"],
  304. // ]);
  305. // if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  306. // $params['mall_id'] = $this->mall_id;
  307. // $params['user_id'] = $this->user_id;
  308. // $params['source'] = empty($this->source) ? User::SOURCE_SHARE_INDEX : $this->source;
  309. // $result = $wechat_form->appAuthLogin($params);
  310. // if ($result === false) return $this->error($wechat_form::getStaticError());
  311. // return $this->success('成功', $result);
  312. }
  313. /**
  314. * 授权处理
  315. * @Author bing
  316. * @DateTime 2021-12-08 10:50:35
  317. * @copyright: Copyright (c) 2020 广东七件事集团
  318. * @return mixed/void
  319. * @param $scene
  320. */
  321. private function _handleAuth($scene){
  322. $requests = Yii::$app->request;
  323. $params_data = @file_get_contents('php://input');
  324. if (!empty($params_data)) $json_data = json_decode($params_data, true);
  325. $params = array_merge($requests->get(), $requests->post(), $json_data ?? []);
  326. $rules = [
  327. [['code', 'encryptedData', 'iv', 'key'], 'string'],
  328. [['user_id', 'activity_id', 'share_user_id'], "integer"],
  329. [['device_type', 'device_mac'], 'safe'],
  330. ];
  331. switch($scene){
  332. case 'weixin' :
  333. $method = 'authorized';
  334. break;
  335. case 'mp-weixin' :
  336. $method = 'miniAuthorized';
  337. break;
  338. case 'app-weixin' :
  339. $rules = [
  340. [['userData'], 'string'],
  341. [['user_id', 'activity_id', 'share_user_id'], "integer"],
  342. [['platform'], "string"],
  343. ];
  344. $params['user_id'] = $this->user_id;
  345. $method = 'appAuthLogin';
  346. break;
  347. }
  348. $res = Yii::$app->services->validate->validate($params,$rules);
  349. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  350. $params['mall_id'] = $this->mall_id;
  351. $params['source'] = empty($this->source) ? User::SOURCE_SHARE_INDEX : $this->source;
  352. $wechat_form = new WechatForm(['mall_id'=>$this->mall_id]);
  353. $result = $wechat_form->$method($params);
  354. if ($result === false){
  355. $is_log_off_del = \Yii::$app->services->setting->mall->get($this->mall_id, 'user.is_log_off_del');
  356. if (!empty($is_log_off_del)) {
  357. if($wechat_form::getStaticError()=='账号已注销'){
  358. return $this->success($wechat_form::getStaticError());
  359. }
  360. }
  361. return $this->error($wechat_form::getStaticError());
  362. }
  363. if(isset($result['user_id'])) unset($result['user_id']);
  364. return $this->success('操作成功', $result);
  365. }
  366. /**
  367. * @desc:小程序授权手机号
  368. * @Author: hua
  369. * @Date: 2021/10/22
  370. * @Time: 14:20
  371. * @Copyright: copyright (c) 2021 广东七件事集团
  372. * @return mixed|void
  373. */
  374. public function actionAuthPhone()
  375. {
  376. return $this->_handleBindMobile('mp_weixin');
  377. // $requests = Yii::$app->request;
  378. // $wechat_form = new WechatForm(['mall_id'=>$this->mall_id]);
  379. // $params_data = @file_get_contents('php://input');
  380. // if (!empty($params_data)) $json_data = json_decode($params_data, true);
  381. // $params = array_merge($requests->get(), $requests->post(), $json_data ?? []);
  382. // $res = Yii::$app->services->validate->validate($params, [
  383. // [['code', 'encryptedData', 'iv', 'key'], 'string'],
  384. // [['user_id', 'activity_id', 'share_user_id'], "integer"]
  385. // ]);
  386. // if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  387. // $params['mall_id'] = $this->mall_id;
  388. // $params['user_id'] = $this->user_id;
  389. // $params['parent_id'] = $this->parent_id;
  390. // $params['source'] = empty($this->source) ? User::SOURCE_SHARE_INDEX : $this->source;
  391. // $result = $wechat_form->authorizedMobilePhone($params);
  392. // if ($result === false) return $this->error($wechat_form::getStaticError());
  393. // return $this->success('成功', $result);
  394. }
  395. /**
  396. * @desc:绑定绑定手机号码
  397. * @Author: hua
  398. * @Date: 2021/10/22
  399. * @Time: 14:32
  400. * @Copyright: copyright (c) 2021 广东七件事集团
  401. * @return mixed
  402. */
  403. public function actionBind()
  404. {
  405. return $this->_handleBindMobile();
  406. // $requests = Yii::$app->request;
  407. // $params =$requests->post();
  408. // $res = Yii::$app->services->validate->validate($params, [
  409. // [["mobile",'captcha','openid','platform'],'string']
  410. // ]);
  411. // if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  412. // $params['user_id'] = $this->user_id;
  413. // $params['mall_id'] = $this->mall_id;
  414. // $params['parent_id'] = $this->parent_id;
  415. // $result = User::bind($params);
  416. // if ($result === false) return $this->error(User::getStaticError());
  417. // return $this->success('成功', $result);
  418. }
  419. private function _handleBindMobile($scene=''){
  420. $requests = Yii::$app->request;
  421. switch ($scene){
  422. case "mp_weixin":
  423. $params_data = @file_get_contents('php://input');
  424. Yii::error("小程序授权信息:" . $params_data);
  425. if (!empty($params_data)) $json_data = json_decode($params_data, true);
  426. $params = array_merge($requests->get(), $requests->post(), $json_data ?? []);
  427. $rules = [
  428. [['code', 'encryptedData', 'iv', 'key'], 'string'],
  429. [['user_id', 'activity_id', 'share_user_id', 'source'], "integer"],
  430. [['invite_mobile'], "safe"],
  431. ['invite_mobile', 'match', 'pattern' => '/[0-9]+$/', 'message' => '请输入正确的推荐人手机号码'],
  432. [['encryptedData'],'required']
  433. ];
  434. $params['source'] = empty($this->source) ? User::SOURCE_SHARE_INDEX : $this->source;
  435. $obj = new WechatForm(['mall_id'=>$this->mall_id]);
  436. $method = 'authorizedMobilePhone';
  437. break;
  438. default:
  439. $params =$requests->post();
  440. $rules = [
  441. [["mobile",'captcha','openid','platform'],'string'],
  442. [['invite_mobile'], "safe"],
  443. ['invite_mobile', 'match', 'pattern' => '/[0-9]+$/', 'message' => '请输入正确的推荐人手机号码'],
  444. ];
  445. $obj = new User();
  446. $method = 'bind';
  447. break;
  448. }
  449. $res = Yii::$app->services->validate->validate($params, $rules);
  450. $params['mall_id'] = $this->mall_id;
  451. $params['user_id'] = $this->user_id;
  452. $params['parent_id'] = $this->parent_id;
  453. Yii::error("注册的参数:" . Json::encode($params));
  454. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  455. $result = $obj->$method($params);
  456. if ($result === false) return $this->error($obj::getStaticError());
  457. return $this->success('操作成功', $result);
  458. }
  459. /**
  460. * @desc:desc
  461. * @Author: hua
  462. * @Date: 2021/10/26
  463. * @Time: 14:15
  464. * @Copyright: copyright (c) 2021 广东七件事集团
  465. * @return mixed|void
  466. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  467. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  468. * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
  469. * @throws \Psr\SimpleCache\InvalidArgumentException
  470. */
  471. public function actionJssdkConfig()
  472. {
  473. try{
  474. $wechat_form = new WechatForm(['mall_id'=>$this->mall_id]);
  475. if (empty(Yii::$app->params['wechatConfig']['app_id'])) return $this->error('请设置公众号配置');
  476. $result = $wechat_form->getJsSdkConfig();
  477. return $this->success('操作成功', $result);
  478. }catch(\Exception $e){
  479. return $this->error($e->getMessage());
  480. }
  481. }
  482. public function actionCancellation()
  483. {
  484. try {
  485. $user_id = $this->user_id;
  486. if(empty($user_id)) return $this->error('请先登录');
  487. $params = Yii::$app->request->post();
  488. $res = Yii::$app->services->validate->validate($params, [
  489. [['captcha'], 'required'],
  490. [['captcha'], 'safe'],
  491. ]);
  492. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  493. if (!Sms::checkValidateCode($this->user['mobile'], $params['captcha'], Sms::SMS_TYPE_USER_CANCELLATION)) throw new Exception('验证码不正确');
  494. Yii::$app->services->apiAccessToken->disableByAccessToken(Yii::$app->user->identity->access_token);
  495. $res = User::updateAll(['status' => StatusEnum::DISABLED], ['id'=>$user_id]);
  496. if ($res === false) return $this->error(User::getStaticError());
  497. $event = new UserCancellationEvent($this->mall_id);
  498. \Yii::$app->services->events->dispatch($event, [
  499. 'mall_id' => $this->mall_id,
  500. 'user_id' => $user_id,
  501. 'operator_user_id' => $user_id,
  502. ], $event->listeners);
  503. return $this->success('操作成功');
  504. }catch (Exception $e){
  505. return $this->error($e->getMessage());
  506. }
  507. }
  508. public function actionSmsCode()
  509. {
  510. $params = Yii::$app->request->post();
  511. $res = Yii::$app->services->validate->validate($params, [
  512. [['area_code'], 'integer'],
  513. [['sms_type'], 'string'],
  514. ]);
  515. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  516. $area_code = '';// 初始化区号
  517. $gateways = 'domestic';// 默认国内短信
  518. // 检测是登录并且区号不为空则使用国际短信
  519. if (!empty($this->user) && !empty($this->user->area_code)&&$this->user->area_code!=86) {
  520. $gateways = 'international';
  521. $area_code = $this->user->area_code;
  522. }
  523. // 判断是否有区号
  524. if (!empty($params['area_code']) && $params['area_code'] != 86) {
  525. $gateways = 'international';
  526. $area_code = $params['area_code'];
  527. }
  528. $notice_sms_status = \Yii::$app->services->setting->mall->get($this->mall_id, 'notice_sms.status');
  529. if(empty($notice_sms_status)) return $this->error('短信提醒未开启');
  530. $params['mobile'] = $this->user['mobile'];
  531. $params['sms_type'] = $params['sms_type'] ?: '';
  532. $sms = new Sms($this->mall_id, $gateways);
  533. try {
  534. if ($sms->sendCaptcha($params['mobile'], $area_code,$params['sms_type']) === false) return $this->error('发送失败');
  535. }catch (\Exception $e){
  536. return $this->error($e->getMessage());
  537. }
  538. return $this->success('发送成功');
  539. }
  540. /**
  541. * 支付宝小程序授权登录
  542. * @desc 根据authCode 获取用户信息调用 alipay.system.oauth.token 取得 user_id 和 token(授权令牌)。
  543. * 使用的 scope 包含 auth_user,则服务端继续使用所取得的 token 调用 alipay.user.info.share 最终获得用户信息。
  544. * @return mixed|void
  545. * @throws \Exception
  546. */
  547. public function actionAuthAlipayMini()
  548. {
  549. $params = Yii::$app->request->post();
  550. $rules = [
  551. [['authCode'], 'string'],
  552. ];
  553. $res = Yii::$app->services->validate->validate($params, $rules);
  554. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  555. $form = new AlipayMiniForm($this->mall_id);
  556. $result = $form->authorize($params['authCode'], $this->parent_id);
  557. if(!$result){
  558. \Yii::error('actionAuthAlipayMini:'.$form->getError());
  559. return $this->error($form->getError());
  560. }
  561. return $this->success('操作成功',$result);
  562. }
  563. /**
  564. * 支付宝小程序授权手机号
  565. * @return mixed|void
  566. */
  567. public function actionMobileAlipayMini()
  568. {
  569. $params = Yii::$app->request->post();
  570. $rules = [
  571. [['data','openid'], 'string'],
  572. ];
  573. $res = Yii::$app->services->validate->validate($params, $rules);
  574. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  575. $data = json_decode($params['data'],true);
  576. $new_params['mall_id'] = $this->mall_id;
  577. $new_params['user_id'] = $this->user_id;
  578. $new_params['parent_id'] = $this->parent_id;
  579. $new_params['encryptData'] = $data['response'];
  580. $new_params['openid'] = $params['openid'];
  581. $form = new AlipayMiniForm($this->mall_id);
  582. $result = $form->authorizedMobilePhone($new_params);
  583. if(!$result){
  584. return $this->error($form->getError());
  585. }
  586. return $this->success('操作成功',$result);
  587. }
  588. public function actionMobileAlipayMiniByCode()
  589. {
  590. try{
  591. $requests = Yii::$app->request;
  592. $params =$requests->post();
  593. $rules = [
  594. [['mobile','captcha','open_id'],'string'],
  595. [['invite_mobile'], "safe"],
  596. ['invite_mobile', 'match', 'pattern' => '/[0-9]+$/', 'message' => '请输入正确的推荐人手机号码'],
  597. [['mobile','captcha','open_id'],'required'],
  598. ];
  599. $res = Yii::$app->services->validate->validate($params, $rules);
  600. if ($res === false) return $this->error(Yii::$app->services->validate->getErrorMessage());
  601. $form = new AlipayMiniForm($this->mall_id);
  602. $result = $form->bindMobileBySms($params['open_id'],$params['mobile'],$params['captcha']);
  603. if(!$result){
  604. return $this->error($form->getError());
  605. }
  606. return $this->success('操作成功',$result);
  607. }catch (\Exception $e){
  608. return $this->error($e->getMessage());
  609. }
  610. }
  611. /**
  612. * 根据open_id 修改微信头像昵称
  613. * @return mixed|void
  614. */
  615. public function actionSaveWechat()
  616. {
  617. try{
  618. $rules = [
  619. [['openid', 'nickName', 'avatarUrl'], 'string'],
  620. // [['openid', 'nickName', 'avatarUrl'], 'required'],
  621. [['openid'], 'required'],
  622. [['nickName'], 'required', 'message' => '请输入昵称'],
  623. [['avatarUrl'], 'required', 'message' => '请上传头像'],
  624. ];
  625. $params = Yii::$app->request->post();
  626. $res = Yii::$app->services->validate->validate($params, $rules);
  627. if ($res === false) throw new \Exception(Yii::$app->services->validate->getErrorMessage());
  628. $where = [['mall_id' => $this->mall_id], ['status' => [StatusEnum::ENABLED, StatusEnum::DISABLED]]];
  629. $where[] = ['platform' => 'mp-wx'];
  630. if (!empty($params["openid"])) $where[] = ['openid' => $params["openid"]];
  631. //if (!empty($params["platform"])) $where[] = ['platform' => $params["platform"]];
  632. $user_info = UserInfo::getOne($where);
  633. if(!$user_info){
  634. $info = [
  635. 'user_id' => 0,
  636. 'mall_id' => $this->mall_id,
  637. 'openid' => $params['openid'],
  638. 'platform_data' => json_encode($params),
  639. 'platform' => User::PLATFORM_MP_WX
  640. ];
  641. UserInfo::setData($info);
  642. }else{
  643. if(!$user_info->user_id){
  644. $platform_data = json_decode($user_info->platform_data,true);
  645. $platform_data['headimgurl'] = $params['avatarUrl'];
  646. $platform_data['avatarUrl'] = $params['avatarUrl'];
  647. $platform_data['nickName'] = $params['nickName'];
  648. $user_info->platform_data = json_encode($platform_data);
  649. $user_info->save();
  650. }
  651. }
  652. return $this->success('操作成功');
  653. }catch(\Exception $e){
  654. return $this->error($e->getMessage());
  655. }
  656. }
  657. /**
  658. * 获取支付宝优惠券access token
  659. * @return mixed|void|null
  660. */
  661. public function actionGetAlipayVoucherAccessToken()
  662. {
  663. try {
  664. $rules = [
  665. [['code'], 'string'],
  666. [['code'], 'required', 'message' => '请输入code'],
  667. ];
  668. $params = Yii::$app->request->get();
  669. $res = Yii::$app->services->validate->validate($params, $rules);
  670. if ($res === false) throw new \Exception(Yii::$app->services->validate->getErrorMessage());
  671. // 校验当前系统是否安装了支付宝商家券插件
  672. if (!MallAddons::isInstall($this->mall_id, AddonsEnum::ADDONS_NAME_ALIPAY_MCH_COUPON)) {
  673. throw new \Exception('您还未安装当前插件');
  674. }
  675. $res = (new OauthTokenService([
  676. 'mall_id' => $this->mall_id,
  677. 'code' => $params['code']
  678. ]))->exec();
  679. if (empty($res['access_token'])) throw new \Exception('获取token失败');
  680. // 缓存
  681. // "alipay:voucher:access_token:{$this->user_id}"
  682. Yii::$app->cache->set(RedisKeyEnum::suffix(RedisKeyEnum::ALIPAY_ACCESS_TOKEN, "voucher:{$this->user_id}"),
  683. $res['access_token'], $res['expires_in'] - 10);
  684. return $this->success('获取成功');
  685. } catch (\Exception $e) {
  686. return $this->error($e->getMessage());
  687. }
  688. }
  689. }