UserMp.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. <?php
  2. /**
  3. * @package merchant
  4. *
  5. * @author xaboy
  6. * @day 2020/6/18
  7. *
  8. *
  9. */
  10. namespace app\controller\api\user;
  11. use app\common\dao\user\UnionUsersDao;
  12. use app\common\repositories\article\AgreementRepository;
  13. use app\common\repositories\merchant\order\OrderMerchantRepository;
  14. use app\common\repositories\user\UnionUsersRepository;
  15. use applet\WXBizDataCrypt;
  16. use crmeb\basic\BaseController;
  17. use app\common\repositories\user\UserRepository;
  18. use crmeb\services\MiniProgramService;
  19. use think\App;
  20. use think\Exception;
  21. use think\facade\Cache;
  22. use think\facade\Db;
  23. use think\facade\Log;
  24. class UserMp extends BaseController
  25. {
  26. public $repository;
  27. private $appid;
  28. private $secret;
  29. public function __construct(App $app, UserRepository $repository)
  30. {
  31. parent::__construct($app);
  32. $this->repository = $repository;
  33. //点餐小程序
  34. // $this->appid = 'wx10669a2eca032216';
  35. // $this->secret = '0e71d5c636fdb9bf1c79c403db70f739';
  36. // $this->appid = 'wx7b4d857deb0447f3';
  37. // $this->secret = '643efbd7f3cd6398df1e7adb441afceb';
  38. $this->appid = 'wx9082e5ac2fdb513f';
  39. $this->secret = 'e334c41e1c4aa962f65d1882092fbda6';
  40. }
  41. public function getUserUnionid(){
  42. $data = $this->request->params(['code','source']);
  43. if(!$data['code'] || $data['code'] == '' || $data['code'] =='undefined') {
  44. return app('json')->fail("异常操作");
  45. }
  46. // $appid = 'wx7b4d857deb0447f3';
  47. // $secret = '643efbd7f3cd6398df1e7adb441afceb';
  48. $appid = 'wx9082e5ac2fdb513f';
  49. $secret = 'e334c41e1c4aa962f65d1882092fbda6';
  50. $url = "https://api.weixin.qq.com/sns/jscode2session?appid=".$appid."&secret=".$secret."&js_code=".$data['code']."&grant_type=authorization_code";
  51. $get = curlGet($url);
  52. if(!$get){
  53. return app('json')->fail($url);
  54. }
  55. $get['cache_key'] = md5(time() . $data['code']);
  56. try {
  57. Cache::set('mp_code_' . $get['cache_key'], $get['session_key'], 86400);
  58. }catch (\Exception $exception) {
  59. Log::error($exception->getMessage());
  60. }
  61. return app('json')->success($get);
  62. }
  63. /**
  64. * 小程序一键登录(合并 getUserUnionid + applet_phone)
  65. * 接收 code、encryptedData、iv,内部调用微信接口获取 session_key,解密手机号后注册/登录
  66. * @param UserRepository $repository
  67. * @return \think\response\Json
  68. */
  69. public function mpLogin(UserRepository $repository)
  70. {
  71. try {
  72. $data = $this->request->params(['code', 'encryptedData', 'iv', 'share_id', 'source']);
  73. if (!$data['code'] || $data['code'] == '' || $data['code'] == 'undefined') {
  74. return app('json')->fail('code参数缺失');
  75. }
  76. if (!$data['encryptedData'] || $data['encryptedData'] == '') {
  77. return app('json')->fail('encryptedData参数缺失');
  78. }
  79. if (!$data['iv'] || $data['iv'] == '') {
  80. return app('json')->fail('iv参数缺失');
  81. }
  82. $appid = 'wx9082e5ac2fdb513f';
  83. $secret = 'e334c41e1c4aa962f65d1882092fbda6';
  84. // 1. 调用微信 jscode2session 接口获取 session_key
  85. $url = "https://api.weixin.qq.com/sns/jscode2session?appid=" . $appid . "&secret=" . $secret . "&js_code=" . $data['code'] . "&grant_type=authorization_code";
  86. $wxResult = curlGet($url);
  87. if (!$wxResult || !isset($wxResult['session_key'])) {
  88. Log::error('mpLogin jscode2session失败: ' . json_encode($wxResult));
  89. return app('json')->fail('微信登录凭证校验失败');
  90. }
  91. $sessionKey = $wxResult['session_key'];
  92. // 2. 解密手机号
  93. $sessionKey = str_replace(' ', '+', $sessionKey);
  94. $encryptedData = str_replace(' ', '+', $data['encryptedData']);
  95. $iv = str_replace(' ', '+', $data['iv']);
  96. $pc = new WXBizDataCrypt($appid, $sessionKey);
  97. $errCode = $pc->decryptData($encryptedData, $iv, $decryptData);
  98. if ($errCode != 0) {
  99. return app('json')->fail('手机号解密失败');
  100. }
  101. $decryptData = json_decode($decryptData, true);
  102. $phone = $decryptData['purePhoneNumber'] ?? '';
  103. if ($phone == '') {
  104. return app('json')->fail('未获取到手机号');
  105. }
  106. if (!preg_match("/^1[3456789]{1}\d{9}$/", $phone) && !preg_match("/^[569]\d{7}$/", $phone)) {
  107. return app('json')->fail('手机号格式错误');
  108. }
  109. // 3. 注册或登录
  110. $userRes = Db::name('user')->where('account', $phone)->find();
  111. $isnew = false;
  112. if (!$userRes) {
  113. $spreadUid = 0;
  114. if (!empty($data['share_id'])) {
  115. $spreadUid = Db::name('product_share')->where('id', $data['share_id'])->value('uid');
  116. if (!intval($spreadUid)) {
  117. $spreadUid = 0;
  118. }
  119. }
  120. $repository->registr($phone, 123456, 'APP', '', '', '', $spreadUid);
  121. $isnew = true;
  122. }
  123. $user = $repository->accountByUser($phone);
  124. $user = $repository->mainUser($user);
  125. $tokenInfo = $repository->createToken($user);
  126. $repository->loginAfter($user);
  127. return app('json')->success(array_merge($repository->returnToken($user, $tokenInfo), ['is_new' => $isnew ? 1 : 0]));
  128. } catch (\Exception $e) {
  129. Db::name('log')->insert(['data' => 'mpLogin出错:' . $e->getFile() . ':' . $e->getLine() . '【' . $e->getMessage() . '】']);
  130. return app('json')->fail('登录失败');
  131. }
  132. }
  133. public function getPhoneToBind(){
  134. $data = $this->request->params([
  135. 'cache_key',
  136. 'iv',
  137. 'encryptedData',
  138. 'third_user_id',
  139. 'source'
  140. ]);
  141. $session_key = Cache::get('mp_code_' . $data['cache_key']);
  142. $appid = $this -> appid;
  143. $secret = $this -> secret;
  144. if($data['source'] && $data['source'] == 'cxb'){
  145. $appid = env('WECHAT_MP.APPID');
  146. $secret = env('WECHAT_MP.SECRET');
  147. }
  148. //解密获取用户信息urldecode
  149. $returnCode = $this -> decryptData($session_key,$data['encryptedData'],$data['iv'],$userInfo,$appid);
  150. if($returnCode != 0){
  151. return app('json')->fail($returnCode);
  152. }
  153. $userInfo = json_decode($userInfo,true);
  154. if (!$userInfo || !isset($userInfo['purePhoneNumber'])) return app('json')->fail('手机号码获取失败');
  155. $phone = $userInfo['purePhoneNumber'];
  156. $repository = app()->make(UserRepository::class);
  157. $user = $repository->thirdBinding($phone, false,'MP',$data['third_user_id'],1,"http://". $this->request->host(true));//2222
  158. if($user){
  159. $userRepository = app()->make(UserRepository::class);
  160. $userInfo1 = $userRepository->getOne(['uid' => $user['uid']]);
  161. //绑定线下充值金额
  162. $unionUsersRepository = app()->make(UnionUsersRepository::class);
  163. $orderMerchantRepository = app()->make(OrderMerchantRepository::class);
  164. $notBind = $unionUsersRepository->getAllNotBind($data['third_user_id']);
  165. if ($notBind) {
  166. $orderMerchantRepository->doBindUser($userInfo1, 1);
  167. $userAccount = Db::name("UserAccount");
  168. $userAccount -> insert(['type'=>1,'uid'=>$user['uid'],'nickname'=>$notBind['nickname'],'avater'=>$notBind['avatar']]);
  169. }
  170. $user = $repository->accountByUser($userInfo['purePhoneNumber']);
  171. $tokenInfo = $repository->createToken($user);
  172. $repository->loginAfter($user);
  173. return app('json')->success($repository->returnToken($user, $tokenInfo));
  174. }else{
  175. return app('json')->fail("绑定失败");
  176. }
  177. }
  178. public function getUser(){
  179. $data = $this->request->params(['unionid','nickname','avatar']);
  180. if(!$data['unionid'] || $data['unionid'] == '' || $data['unionid'] =='undefined'){
  181. return app('json')->fail("异常操作");
  182. }
  183. $repository = app()->make(UserRepository::class);
  184. $result = $repository ->wechatCheck($data['unionid']);
  185. if(isset($result['code']) && $result['code'] == 200){
  186. //用户已注册并绑定了手机号码
  187. $user = $repository->accountByUser($result['user']['account']);
  188. $tokenInfo = $repository->createToken($user);
  189. $repository->loginAfter($user);
  190. return app('json')->success($repository->returnToken($user, $tokenInfo));
  191. }
  192. else{
  193. try {
  194. if($data['avatar'] && $data['avatar'] != ''){
  195. $data['avatar'] = str_replace('"', '', $data['avatar']);
  196. }
  197. Db::transaction(function () use ($data,$repository) {
  198. $unionData = [
  199. 'unionid' => $data['unionid'],
  200. 'nickname' => $data['nickname'] ? : time(),
  201. 'avatar' => $data['avatar'] ? : 'https://cdn.bjtdba.com/vod/image/2025-01-21/20250121180855764.png',
  202. 'is_lock' => 1,
  203. 'lock_time' => date('Y-m-d H:i:s'),
  204. 'balance' => 0,
  205. 'give_money' => 0,
  206. 'pension' => 0,
  207. 'type' => 1,
  208. ];
  209. $unionUsersDao = app()->make(UnionUsersDao::class);
  210. $unionUsersRepository = app()->make(UnionUsersRepository::class);
  211. $unionUser = $unionUsersRepository->getWhere(['unionid' => $data['unionid']]);
  212. if (!$unionUser) {
  213. $unionUsersDao->create($unionData);
  214. } else {
  215. $updateData = [
  216. 'nickname' => $data['nickname'] ? : time(),
  217. 'avatar' => $data['avatar'] ? : 'https://cdn.bjtdba.com/vod/image/2025-01-21/20250121180855764.png',
  218. 'update_time' => date('Y-m-d H:i:s')
  219. ];
  220. $unionUsersDao->update($unionUser->id, $updateData);
  221. }
  222. });
  223. } catch (\Throwable $e) {
  224. Log::info($e->getMessage());
  225. }
  226. }
  227. return app("json")->fail($result['msg']);
  228. }
  229. /**
  230. * 检验数据的真实性,并且获取解密后的明文.
  231. * @param $sessionKey string sessionKey
  232. * @param $encryptedData string 加密的用户数据
  233. * @param $iv string 与用户数据一同返回的初始向量
  234. * @param $data string 解密后的原文
  235. *
  236. * @return int 成功0,失败返回对应的错误码
  237. */
  238. public function decryptData($sessionKey,$encryptedData, $iv, &$data, $appid)
  239. {
  240. if (strlen($sessionKey) != 24) {
  241. return -41001;
  242. }
  243. $aesKey=base64_decode($sessionKey);
  244. if (strlen($iv) != 24) {
  245. return -41002;
  246. }
  247. $aesIV=base64_decode($iv);
  248. $aesCipher=base64_decode($encryptedData);
  249. $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
  250. $dataObj=json_decode( $result );
  251. if( $dataObj == NULL )
  252. {
  253. return -41003;
  254. }
  255. if( $dataObj->watermark->appid != $appid )
  256. {
  257. return -41003;
  258. }
  259. $data = $result;
  260. return 0;
  261. }
  262. }