Passport.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2021 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\api\controller;
  13. use app\api\model\User as UserModel;
  14. use app\api\model\UserCoupon as UserCouponModel;
  15. use app\api\model\Wxapp as WxappModel;
  16. use app\api\model\Order as OrderModel;
  17. use app\api\model\Coupon as CouponModel;
  18. use app\api\service\passport\Login as LoginService;
  19. use app\api\service\passport\Captcha as CaptchaService;
  20. use app\api\service\passport\SmsCaptcha as SmsCaptchaService;
  21. use app\api\service\User as UserService;
  22. use app\common\enum\order\PayStatus;
  23. use app\common\library\weixin\WXBizDataCrypt;
  24. use app\common\model\UserOauth;
  25. use think\cache\driver\Redis;
  26. use think\facade\Log;
  27. use app\common\model\SmsCode;
  28. /**
  29. * 用户认证模块
  30. * Class Passport
  31. * @package app\api\controller
  32. */
  33. class Passport extends Controller
  34. {
  35. /**
  36. * 登录接口 (需提交手机号、短信验证码、第三方用户信息)
  37. * 该登录接口暂未使用
  38. *
  39. * @return array|\think\response\Json
  40. * @throws \app\common\exception\BaseException
  41. * @throws \think\db\exception\DataNotFoundException
  42. * @throws \think\db\exception\DbException
  43. * @throws \think\db\exception\ModelNotFoundException
  44. */
  45. public function login()
  46. {
  47. // 执行登录
  48. $LoginService = new LoginService;
  49. // if (!$LoginService->login($this->postForm())) {
  50. if (!$LoginService->login($this->request->post())) {
  51. return $this->renderError($LoginService->getError());
  52. }
  53. // 用户信息
  54. $userInfo = $LoginService->getUserInfo();
  55. $token = $LoginService->getToken((int)$userInfo['user_id']);
  56. /*
  57. $user_id = $userInfo['user_id'];
  58. $cache_token_key = 'xcx_token_'.$user_id;
  59. Cache::set($cache_token_key, $token, 3600);*/
  60. //添加登录后领取新人券的功能
  61. $this->receiveCoupon($userInfo);
  62. return $this->renderSuccess([
  63. 'userId' => (int)$userInfo['user_id'],
  64. 'token' => $LoginService->getToken((int)$userInfo['user_id'])
  65. ], '登录成功');
  66. }
  67. //未下过单的用户登录后静默领取新人优惠券
  68. private function receiveCoupon($userInfo){
  69. //有支付成功的订单就不发新人券了
  70. if(OrderModel::where(['user_id'=>$userInfo['user_id'],'pay_status'=>PayStatus::SUCCESS])->count()){
  71. return true;
  72. }
  73. //获取还能领取的新人券列表
  74. $couponList = CouponModel::where(['send_type'=>20,'audit_status'=>10,'status'=>1])->where('end_time','>',date('Y-m-d H:i:s'))->select();
  75. foreach ($couponList as $coupon){
  76. for ($i=0;$i<$coupon['limit_receive_cnt'];$i++){
  77. $model = new UserCouponModel;
  78. $res = $model->receiveLogin($coupon,$userInfo);
  79. if (!$res) {
  80. continue;
  81. }
  82. if($res){
  83. //领了新人券,写个缓存值1,下次请求告知前端刚领了,
  84. //然后将值改为2,就表示已经领过了
  85. $this->receiveRds($userInfo['user_id']);
  86. }
  87. }
  88. }
  89. return true;
  90. }
  91. //写个缓存 value 1 代表刚领了,2 代表领过了
  92. public function receiveRds($user_id){
  93. $key = (new UserCouponModel)->getUserCouponRdsKey($user_id);
  94. $rds = new Redis(config('cache.stores.redis'));
  95. $value = $rds->get($key);
  96. if($value==null){
  97. $rds->set($key,1);
  98. }
  99. }
  100. /**
  101. * 微信小程序快捷登录 (需提交wx.login接口返回的code、微信用户公开信息)
  102. * 实现流程:判断openid是否存在 -> 存在: 更新用户登录信息 -> 返回userId和token
  103. * -> 不存在: 返回false, 调用 解密用户手机号接口
  104. * @return array|\think\response\Json
  105. * @throws \app\common\exception\BaseException
  106. * @throws \think\db\exception\DataNotFoundException
  107. * @throws \think\db\exception\DbException
  108. * @throws \think\db\exception\ModelNotFoundException
  109. */
  110. public function mpWxLogin()
  111. {
  112. // 微信小程序一键登录
  113. $LoginService = new LoginService;
  114. $params = $this->request->post();
  115. if (!$LoginService->mpWxLogin($params)) {
  116. return $this->renderError($LoginService->getError());
  117. }
  118. // 获取登录成功后的用户信息
  119. $userInfo = $LoginService->getUserInfo();
  120. //添加登录后领取新人券的功能
  121. $this->receiveCoupon($userInfo);
  122. return $this->renderSuccess([
  123. 'userId' => (int)$userInfo['user_id'],
  124. 'token' => $LoginService->getToken((int)$userInfo['user_id']),
  125. 'openid' => $userInfo['open_id']
  126. ], '登录成功');
  127. }
  128. //手机号登录注册
  129. public function mobile(){
  130. $params = $this->request->post();
  131. if (empty($params['mobile'])) {
  132. return $this->renderError("请输入手机号");
  133. }
  134. if(empty($params['sms_code'])){
  135. return $this->renderError("请输入验证码");
  136. }
  137. $mobile = $params['mobile'];
  138. $sms_code = $params['sms_code'];
  139. $openid = '';
  140. if ($sms_code != '000000' || env('APP_DEBUG') == false){
  141. $sms = SmsCode::where("mobile",$mobile)->where('is_use',0)->where("create_time",'>',time()-3000)->order(['id'=>'desc'])->find();
  142. if(empty($sms)){
  143. return $this->renderError("请获取手机验证码");
  144. }
  145. if($sms->code!=$sms_code){
  146. return $this->renderError("验证码不正确");
  147. }
  148. $sms->is_use = 1;
  149. $sms->save();
  150. }
  151. $LoginService = new LoginService;
  152. $user = UserModel::detail(['mobile' => $mobile]);
  153. if($user){
  154. // $user->open_id = ''
  155. // $user->save();
  156. // $userOauth = UserOauth::where('user_id', $user->user_id)->find();
  157. // if (!empty($userOauth)) {
  158. // $userOauth->oauth_id = $openid;
  159. // $userOauth->save();
  160. // }
  161. $params = $this->request->post();
  162. $params = array_merge($params,['mobile' => $mobile]);
  163. $params['oauth'] = "MOBILE"; // 手机号
  164. $params['isParty'] = false;
  165. $params['unionid'] = $info['unionid'] ?? '';
  166. if (!$LoginService->login($params)) {
  167. return $this->renderError($LoginService->getError());
  168. }
  169. }else{
  170. //注册新用户
  171. // 1.调用名厨之家第三方应用注册接口注册用户并返回用户信息
  172. // $postData = [
  173. // 'mobile' => (string)$mobile,
  174. // 'openid' => '',
  175. // 'source' => 12
  176. // ];
  177. //$cur_url = config('chef.serv_cookhome').'/api/wx/third_platform_register';
  178. //$res = curl_post($cur_url, $postData);
  179. //$res = json_decode($res, true);
  180. // 获取名厨用户id
  181. //$chef_user_id = $res['id'];
  182. // 2.本地数据库写入用户信息
  183. $params = $this->request->post();
  184. $params['mobile'] = (string)$params['mobile'];
  185. $params['oauth'] = "MOBILE"; // 手机号
  186. $params['isParty'] = false;
  187. $params['openid'] = '';
  188. $params['unionid'] = $info['unionid'] ?? '';
  189. $params = array_merge($params,['userId' => 0, 'mobile' => $mobile]);
  190. if (!$LoginService->login($params)) {
  191. return $this->renderError($LoginService->getError());
  192. }
  193. }
  194. // 获取登录成功后的用户信息
  195. $user = $LoginService->getUserInfo();
  196. //添加登录后领取新人券的功能
  197. $this->receiveCoupon($user);
  198. return $this->renderSuccess([
  199. 'userId' => (int)$user['user_id'],
  200. 'token' => $LoginService->getToken((int)$user['user_id']),
  201. 'result' => []
  202. ], '登录成功');
  203. }
  204. /**
  205. * Notes:解密用户手机号
  206. *
  207. * Author: zhangs
  208. * DateTime: 2021/9/27 11:42
  209. * @return mixed
  210. */
  211. public function mpWxMobile()
  212. {
  213. $params = $this->request->post();
  214. if (empty($params['openid']) || empty($params['encryptedData']) || empty($params['iv'])) {
  215. return $this->renderError("请绑定手机号");
  216. }
  217. $openid = $params['openid'];
  218. $iv = $params['iv'];
  219. $encryptedData = $params['encryptedData'];
  220. $rds = new Redis(config('cache.stores.redis'));
  221. $key = LoginService::OPEN_ID_KEY.$openid;
  222. $info = $rds->get($key);
  223. if (empty($info)) {
  224. return $this->renderError('请重新授权获取手机号!');
  225. }
  226. // 获取当前小程序信息
  227. $wxConfig = WxappModel::getWxappCache();
  228. $sessionKey = $info['session_key'];
  229. $pc = new WXBizDataCrypt($wxConfig['app_id'], $sessionKey);
  230. $errCode = $pc->decryptData($encryptedData, $iv, $data);
  231. if($errCode == 0){
  232. $LoginService = new LoginService;
  233. $result = json_decode($data);
  234. $mobile = $result->phoneNumber;
  235. $user = UserModel::detail(['mobile' => $mobile]);
  236. if($user){
  237. $user->open_id = $openid;
  238. $user->save();
  239. $userOauth = UserOauth::where('user_id', $user->user_id)->find();
  240. if (!empty($userOauth)) {
  241. $userOauth->oauth_id = $openid;
  242. $userOauth->save();
  243. }
  244. $params = $this->request->post();
  245. $params = array_merge($params,['mobile' => $mobile]);
  246. $params['oauth'] = "MP-WEIXIN"; // 微信小程序
  247. $params['isParty'] = true;
  248. $params['unionid'] = $info['unionid'] ?? '';
  249. if (!$LoginService->login($params)) {
  250. return $this->renderError($LoginService->getError());
  251. }
  252. }else{
  253. //注册新用户
  254. // 1.调用名厨之家第三方应用注册接口注册用户并返回用户信息
  255. // $postData = [
  256. // 'mobile' => $mobile,
  257. // 'openid' => $openid,
  258. // 'source' => 12
  259. // ];
  260. // $res = curl_post(config('chef.serv_cookhome').'/api/wx/third_platform_register', $postData);
  261. // $res = json_decode($res, true);
  262. // // 获取名厨用户id
  263. // $chef_user_id = $res['id'];
  264. // 2.本地数据库写入用户信息
  265. $params = $this->request->post();
  266. $params['oauth'] = 'MP-WEIXIN';
  267. $params['isParty'] = true;
  268. $params['unionid'] = $info['unionid'] ?? '';
  269. $params = array_merge($params,['userId' => 0, 'mobile' => $mobile]);
  270. if (!$LoginService->login($params)) {
  271. return $this->renderError($LoginService->getError());
  272. }
  273. /* $sharerId = intval($params['sharerId']??0);
  274. Log::error('分享者000'.$sharerId);
  275. if ($sharerId > 0){
  276. Log::error('分享者'.$sharerId);
  277. $flag = UserModel::updateNormalUserRelation($sharerId);
  278. if ($flag !== true){
  279. Log::error('分享者'.$sharerId.'变更用户'. json_encode($flag) .'上级关系失败');
  280. }
  281. }*/
  282. }
  283. // 获取登录成功后的用户信息
  284. $user = $LoginService->getUserInfo();
  285. //添加登录后领取新人券的功能
  286. $this->receiveCoupon($user);
  287. return $this->renderSuccess([
  288. 'userId' => (int)$user['user_id'],
  289. 'token' => $LoginService->getToken((int)$user['user_id']),
  290. 'result' => $result
  291. ], '登录成功');
  292. }else{
  293. return $this->renderError('请重新授权获取手机号');
  294. }
  295. }
  296. /**
  297. * 小程序自动领取新人优惠券
  298. * @author: zjwhust
  299. * @Time: 2022/1/11 13:58
  300. */
  301. public function autoCoupon(){
  302. $user = UserService::getCurrentLoginUser(true);
  303. //添加登录后领取新人券的功能
  304. $this->receiveCoupon($user);
  305. return $this->renderSuccess();
  306. }
  307. /**
  308. * Notes:更新微信用户信息
  309. * Author: zhangs
  310. * DateTime: 2021/10/8 11:52
  311. * @return mixed
  312. */
  313. public function updateWxUserInfo()
  314. {
  315. $params = $this->request->post();
  316. $userInfo = UserService::getCurrentLoginUser(true);
  317. $LoginService = new LoginService;
  318. $ret = $LoginService->updateWxUserInfo($params, $userInfo);
  319. if ($ret === false) {
  320. return $this->renderError('更新失败');
  321. }
  322. return $this->renderSuccess([], '更新成功');
  323. }
  324. /**
  325. * 图形验证码
  326. * @return array|\think\response\Json
  327. */
  328. public function captcha()
  329. {
  330. $CaptchaService = new CaptchaService;
  331. return $this->renderSuccess($CaptchaService->create());
  332. }
  333. /**
  334. * 发送短信验证码
  335. * @return array|\think\response\Json
  336. */
  337. public function sendSmsCaptcha()
  338. {
  339. $SmsCaptchaService = new SmsCaptchaService;
  340. if (!$SmsCaptchaService->sendSmsCaptcha($this->postForm())) {
  341. return $this->renderError($SmsCaptchaService->getError());
  342. }
  343. return $this->renderSuccess('发送成功,请注意查收');
  344. }
  345. /**
  346. * 修改普通用户绑定门店信息
  347. * @return array|\think\response\Json
  348. * @throws \app\common\exception\BaseException
  349. * @throws \think\db\exception\DataNotFoundException
  350. * @throws \think\db\exception\DbException
  351. * @throws \think\db\exception\ModelNotFoundException
  352. */
  353. public function changeUpperUser(){
  354. $params = $this->request->post();
  355. $sharerId = intval($params['sharerId']??0);
  356. $isScan = intval($params['isScanCode']??0);
  357. Log::debug('分享者A--'.$sharerId);
  358. if ($sharerId <= 0){
  359. Log::error('分享者'.$sharerId);
  360. return $this->renderError('参数有误');
  361. }
  362. $flag = UserModel::updateNormalUserRelation($sharerId,$isScan);
  363. if ($flag !== true){
  364. return $this->renderError('更新失败');
  365. }
  366. return $this->renderSuccess([], '更新成功');
  367. }
  368. }