where('user_id', $user_id) ->field([ 'password', 'user_id', 'openid', 'frozen' ]) ->find(); if (empty($toUserInfo)) { throw new \Exception('用户不存在'); } if ($userInfo['species'] setInc('species', $num); Users::where('user_id', $userInfo['user_id'])->setDec('species', $num); Users::where('user_id', $userInfo['user_id'])->setInc('species_give', $num); $tospec = new UserSpecies(); $toid = $tospec->add($user_id, 2, 1, $num, "获得好友赠送鸡蛋"); $fromspec = new UserSpecies(); $fromid = $fromspec->add($userInfo['user_id'], 3, 2, $num, "赠送给好友鸡蛋"); $guanlian = new UserGive(); $guanlian->add($toid, $fromid); Db::commit(); return [ 'code' => ReturnCode::SUCCESS_CODE, 'msg' => '登录成功', 'data' => '' ]; } catch (\Exception $e) { Db::rollback(); Log::write('会员登录失败: ' . $e->getMessage(), 'error'); return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => '会员登录失败' . $e->getMessage() ]; } } /** * 用户登录 * * @throws \Exception */ public function login() { $account = Request::param('account'); // 微信小程序返回用户信息 $password = Request::param('password'); // 微信小程序返回用户信息 Db::startTrans(); try { $userModel = new Users(); $userInfo = $userModel->getUserByAccount($account, 1, [ 'password', 'user_id', 'openid', 'frozen' ]); if (empty($userInfo)) { throw new \Exception('账号不存在'); } if ($userInfo['password'] != md5($password)) { throw new \Exception('密码不正确'); } if ($userInfo['frozen'] != 1) { throw new \Exception('用户已被冻结'); } $getToken = $this->setToken($userInfo['user_id'], 1); $openid = $userInfo['openid']; Db::commit(); return [ 'code' => ReturnCode::SUCCESS_CODE, 'msg' => '登录成功', 'data' => [ 'openid' => $openid, 'token' => $getToken ] ]; } catch (\Exception $e) { Db::rollback(); Log::write('会员登录失败: ' . $e->getMessage(), 'error'); return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => '会员登录失败' . $e->getMessage() ]; } } /** * 用户注册 * * @throws \Exception */ public function register() { $account = Request::param('account'); // 微信小程序返回用户信息 $password = Request::param('password'); // 微信小程序返回用户信息 $rpassword = Request::param('rpassword'); // 微信小程序返回用户信息 Db::startTrans(); try { if (! isStringNumberLessThan($account)) { throw new \Exception('请输入正确得电话号码格式,11位电话号码'); } if (strlen($password) > 25) { throw new \Exception('密码长度最长25个字符'); } if ($password != $rpassword) { throw new \Exception('两次密码不一致'); } $userModel = new Users(); $userInfo = $userModel->getUserByAccount($account, 1, [ 'password', 'user_id', 'openid' ]); if (! empty($userInfo)) { throw new \Exception('账号已存在'); } $ip = $_SERVER["REMOTE_ADDR"]; $avatarUrl = 'https://thirdwx.qlogo.cn/mmopen/vi_32/4MwaJwuQl7orrLGWacxPBw3VLJUcGad8QHYiaZ5NE3LhrvIVzDRF7AJuVXtlSCtEx79Jbjibe4OlvibTUgoEk9MKA/132'; $user = [ 'account' => $account, // 用户账号 'password' => md5($password), // 用户头像url 'nickname' => generateChineseNickname(4), // 用户昵称 'head' => $avatarUrl, // 用户头像url 'session_key' => '', // 用户sessionKey 'unionid' => '', 'openid' => '', 'oauth' => 'acc', 'reg_ip' => $ip, // 注册IP 'login_ip' => $ip, // 登录IP 'reg_time' => time(), // 注册时间 'login_time' => time() ]; // 登陆时间 $userInfo = $userModel->addUserDataInfo($user); $getToken = $this->setToken($userInfo['user_id'], 2); $openid = $userInfo['openid']; Db::commit(); return [ 'code' => ReturnCode::SUCCESS_CODE, 'msg' => '登录成功', 'data' => [ 'openid' => $openid, 'token' => $getToken ] ]; } catch (\Exception $e) { Db::rollback(); Log::write('会员登录失败: ' . $e->getMessage(), 'error'); return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => '会员登录失败' . $e->getMessage() ]; } } protected function TestEntry() { $openid = Request::param('openid'); // 微信小程序返回用户信息 Db::startTrans(); try { if (empty($openid)) { $user_openid = 'oBhyo4slnVBdThGdOoMsw3n11l'; } $userModel = new Users(); $userInfo = $userModel->getUserByAccount($openid, 2); if ($userInfo) { if (! isset($userInfo) || empty($userInfo)) { throw new \Exception('用户不存在'); } if ($userInfo['frozen'] != 1) { throw new \Exception('用户已被冻结'); } $getToken = $this->setToken($userInfo['user_id'], 1); $openid = $userInfo['openid']; } else { $ip = $_SERVER["REMOTE_ADDR"]; $nickname = '测试'; $avatarUrl = 'https://thirdwx.qlogo.cn/mmopen/vi_32/4MwaJwuQl7orrLGWacxPBw3VLJUcGad8QHYiaZ5NE3LhrvIVzDRF7AJuVXtlSCtEx79Jbjibe4OlvibTUgoEk9MKA/132'; $user = [ 'nickname' => $nickname, // 用户昵称 'head' => $avatarUrl, // 用户头像url 'openid' => $openid, // 用户openId 'session_key' => '', // 用户sessionKey 'unionid' => '', 'oauth' => 'cs', 'reg_ip' => $ip, // 注册IP 'login_ip' => $ip, // 登录IP 'reg_time' => time(), // 注册时间 'login_time' => time() ]; // 登陆时间 $userInfo = $userModel->addUserDataInfo($user); $getToken = $this->setToken($userInfo['user_id'], 2); $openid = $userInfo['openid']; } Db::commit(); return [ 'code' => ReturnCode::SUCCESS_CODE, 'msg' => '登录成功', 'data' => [ 'token' => $getToken, 'openid' => $openid ] ]; } catch (\Exception $e) { Db::rollback(); Log::write('会员登录失败: ' . $e->getMessage(), 'error'); return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => '会员登录失败' ]; } } /** * 微信抖音登录 * * @param string $oauth * 'dy'|'wx' * @return array */ protected function wxLogin($oauth = "wx") { $code = Request::param('code'); // 微信返回code switch ($oauth) { case 'wx': $logsList = $this->weixin_s(zf_cache("web_info.wxAppid"), zf_cache("web_info.dyAppSecret"), $code); break; case 'dy': $logsList = $this->dY_Info(zf_cache("web_info.dyAppid"), zf_cache("web_info.dyAppSecret"), $code); break; case 'wxapp': $logsList = $this->wxOauth2(zf_cache("web_info.appid"), zf_cache("web_info.appsecret"), $code); break; case 'wxh5': $logsList = $this->wxOauth2(zf_cache("web_info.h5Appid"), zf_cache("web_info.h5AppSecret"), $code); break; default: return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => '平台选择错误' ]; } if (isset($logsList->errcode) && ! empty($logsList['errcode'])) { return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => "接口调用错误:" . $logsList['errmsg'] ]; } $unionid = ""; $session_key = ""; // 防止第二次访问动态链接报错 // 判断是否获取到当前用户的openid if (! isset($logsList->openid) || empty($logsList->openid)) { return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => '未获取到openid' ]; } $open_id = $logsList->openid; if (isset($logsList->unionid) && ! empty($logsList->unionid)) { $unionid = $logsAccessToken->unionid; } if (isset($logsList->session_key) && ! empty($logsList->session_key)) { $session_key = $logsList->session_key; } if (isset($logsList->access_token) && ! empty($logsList->access_token)) { $session_key = $logsList->access_token; } Db::startTrans(); try { $userModel = new Users(); // 判断用户是否存在 $userInfo = $userModel->getUserByAccount($open_id, 2); // 用户不存在,创建用户 if (empty($userInfo)) { $nickname = ""; $avatarUrl = ""; switch ($oauth) { case 'wx': case 'dy': $user_info = Request::param('user_info'); // 微信小程序返回用户信息 if (! isset($user_info) || empty($user_info)) { throw new \Exception('未获取到user_info'); } if (isset($user_info->nickName) && ! empty($user_info->nickName)) { $nickname = $this->emoji_encode($user_info['nickName']); } if (isset($user_info->avatarUrl) && ! empty($user_info->avatarUrl)) { $avatarUrl = $user_info['avatarUrl']; } break; case 'wxapp': case 'wxh5': $user_info = $this->wxUserInfo($logsList->access_token, $logsList->openid); if (isset($user_info->errcode) && ! empty($user_info['errcode'])) { throw new \Exception("接口调用错误:" . $user_info['errmsg']); } if (isset($user_info->nickname) && ! empty($user_info->nickname)) { $nickname = $this->emoji_encode($user_info->nickname); } if (isset($user_info->headimgurl) && ! empty($user_info->headimgurl)) { $avatarUrl = $user_info->headimgurl; } break; default: throw new \Exception('平台选择错误'); } $ip = $_SERVER["REMOTE_ADDR"]; $user = [ 'nickname' => $nickname, // 用户昵称 'head' => $avatarUrl, // 用户头像url 'openid' => $open_id, // 用户openId 'session_key' => $session_key, // 用户sessionKey 'unionid' => $unionid, 'oauth' => $oauth, 'reg_ip' => $ip, // 注册IP 'login_ip' => $ip, // 登录IP 'reg_time' => time(), // 注册时间 'login_time' => time() ]; // 登陆时间 $userInfo = $userModel->addUserDataInfo($user); $getToken = $this->setToken($userInfo['user_id'], 2); } else { if ($userInfo['frozen'] != 1) { Db::rollback(); return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => '用户已被冻结' ]; } $getToken = $this->setToken($userInfo['user_id'], 1, $session_key); $open_id = $userInfo['openid']; } Db::commit(); return [ 'code' => ReturnCode::SUCCESS_CODE, 'msg' => '登录成功', 'data' => [ 'token' => $getToken, 'openid' => $open_id ] ]; } catch (\Exception $e) { Db::rollback(); Log::write('会员登录失败: ' . $e->getMessage(), 'error'); return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => '会员登录失败' ]; } } /** * 会员登录 * * platform 'wx': * platform 'dy': * platform 'wxapp': * platform 'wxh5': * platform 'cs': * * @return array */ public function doLogin() { $platform = Request::param('platform'); // 0 测试环境 1 微信小程序 2抖音小程序 if ($platform == "cs") { return $this->TestEntry(); } else { return $this->wxLogin($platform); } } /** * * @param string $userid * @param string $type * 1登录 2注册 * @param string $session_key * @return string */ public function setToken($userid, $type, $session_key = "") { $str = $userid . "T" . time(); $token = MD5($str); $uparray = array( 'token' => $token, 'login_ip' => $_SERVER["REMOTE_ADDR"], 'login_time' => time() ); if (! empty($session_key)) { $uparray['session_key'] = $session_key; } $str = '登陆成功'; if ($type == 2) { $str = '注册登陆成功'; } Users::where(array( 'user_id' => $userid ))->setField($uparray); $userLogModel = new UsersLog(); $userLogModel->addLog($userid, $type, $str); return $token; } /** * 微信通过code换取网页授权access_token web与app都是用这个 * * @param string $app_id * 公众号的唯一标识 * @param string $app_secret * 公众号的appsecret * @param string $code * 获取的code参数 * @return array 包含以下键的关联数组: * - access_token: string 访问令牌 * - expires_in: int 令牌过期时间(秒) * - refresh_token: string 刷新令牌 * - openid: string 用户OpenID * - scope: string 授权范围 拉取用户信息(需scope为 snsapi_userinfo) * - is_snapshotuser: int 是否为快照用户(1 表示是,0 表示否) * - unionid: string 用户UnionID(如果有) * @throws Exception 如果获取令牌失败,则抛出异常 */ public function wxOauth2($app_id, $app_secret, $code) { // 发送请求,获取用户openid和access_token $logsList = httpRequest('https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $app_id . '&secret=' . $app_secret . '&code=' . $code . '&grant_type=authorization_code', 'get'); return json_decode($logsList); } /** * 拉取用户信息(需scope为 snsapi_userinfo) web与app都是用这个 * * @param string $access_token * @param string $openid * @return array 包含以下键的关联数组: * - openid: string 普通用户的标识,对当前开发者账号唯一 * - nickname: string 普通用户昵称 * - sex: int 普通用户性别,1 为男性,2 为女性 * - province: string 普通用户个人资料填写的省份 * - city: string 普通用户个人资料填写的城市 * - country: string 国家,如中国为 CN * - headimgurl: string 用户头像,最后一个数值代表正方形头像大小(有 0、46、64、96、132 数值可选,0 代表 640*640 正方形头像),用户没有头像时该项为空 * - privilege: string 用户特权信息,json 数组,如微信沃卡用户为(chinaunicom) * - unionid: string 用户统一标识。针对一个微信开放平台账号下的应用,同一用户的 unionid 是唯一的。 */ public function wxUserInfo($access_token, $openid) { // 获取当前用户信息 返回国家地区语言版本,zh_CN 简体,zh_TW 繁体,en 英语 $user_info = httpRequest('https://api.weixin.qq.com/sns/userinfo?access_token=' . $access_token . '&openid=' . $openid . '&lang=zh_CN', 'get'); return json_decode($user_info); } /** * * @param string $appid * 公众号的唯一标识 * @param string $secret * 公众号的appsecret * @param string $js_code * 前端传来的code * @return array 包含以下键的关联数组: * - errmsg: string 错误信息 * - errcode: int 错误码 * - session_key: string 会话密钥 * - openid: string 用户OpenID * - unionid: string 用户UnionID(如果有) * @throws Exception 如果获取令牌失败,则抛出异常 */ public function weixin_s($appid, $secret, $js_code) { $logsList = httpRequest('https://api.weixin.qq.com/sns/jscode2session?appid=' . $appid . '&secret=' . $secret . '&js_code=' . $js_code . '&grant_type=authorization_code', 'get'); return json_decode($logsList); } /** * * @param string $appid * @param string $secret * @param string $js_code * @return array 包含以下键的关联数组: * - errmsg: string 错误信息 * - errcode: int 错误码 * - session_key: string 会话密钥 * - openid: string 用户OpenID * - unionid: string 用户UnionID(如果有) * @throws Exception 如果获取令牌失败,则抛出异常 */ public function dY_Info($appid, $secret, $js_code) { $logsList = httpRequest('https://minigame.zijieapi.com/mgplatform/api/apps/jscode2session?appid=' . $appid . '&secret=' . $secret . '&code=' . $js_code, 'get'); return json_decode($logsList); } // 将表情进行转义 用于存储的时候 function emoji_encode($str) { $strEncode = ''; $length = mb_strlen($str, 'utf-8'); for ($i = 0; $i = 4) { $strEncode .= '[[EMOJI:' . rawurlencode($_tmpStr) . ']]'; } else { $strEncode .= $_tmpStr; } } return $strEncode; } /** * 用户反馈 * * @return array */ public function feedback($userInfo) { $content = Request::param('content'); // 0 测试环境 1 微信小程序 2抖音小程序 $title = Request::param('title'); // 0 测试环境 1 微信小程序 2抖音小程序 $thumb = Request::param('thumb'); // 0 测试环境 1 微信小程序 2抖音小程序 Db::startTrans(); try { $mess = new Message(); if (! isset($title)) { $title = ""; } if (! isset($thumb)) { $title = ""; } $res = $mess->addMessageData($userInfo['user_id'], $title, 0, $content, $thumb = '', 1); // $where_time = strtotime(date('Y-m-d').'00:00:00'); // $userFo = UsersMessage::where('user_id',$userInfo['user_id'])->setInc('game_level',1); Db::commit(); return [ 'code' => ReturnCode::SUCCESS_CODE, '操作成功', 'data' => $res ]; } catch (\Exception $e) { Db::rollback(); Log::write('操作失败: ' . $e->getMessage(), 'error'); return [ 'code' => ReturnCode::ERROR_CODE, 'msg' => $e->getMessage() ]; } } /** * 分享 * @param string $url 分享出去后跳转的链接 * @return array mixed */ public function getApiTicketAction($url) { $appid = zf_cache("web_info.appid"); $secret = zf_cache("web_info.appsecret"); $jsapiTicket = $this->getJsapiTicket(); $timestamp = time(); $nonceStr = $this->createNonceStr(); // 构造一个随机数,用来生成签名的一部分 $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url"; // 签名算法先按照ascII码排序 $signature = sha1($string); // 对排序好的字符串加密 return array( 'appId' => $appid, 'nonceStr' => $nonceStr, 'timestamp' => $timestamp, 'signature' => $signature ); } // 构造一个随机数,用来生成签名的一部分 public function createNonceStr($length = 16) { // 生成随机16个字符的字符串 $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; $str = ""; for ($i = 0; $i find(); if ($access_token_list['ticket_expires_time'] > time()) { $ticket = $access_token_list['ticket']; return $ticket; } else { if ($access_token_list['expires_time'] > time()) { $token = $access_token_list['access_token']; } else { $res = file_get_contents('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $appid . '&secret=' . $secret); $res = json_decode($res, true); if (isset($res['errcode']) && ! empty($res['errcode'])) { throw new \Exception($res['errmsg']); } $token = $res['access_token']; } $res2 = file_get_contents("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" . $token . "&type=jsapi"); $res2 = json_decode($res, true); if (isset($res2['errcode']) && ! empty($res2['errcode'])) { throw new \Exception($res2['errmsg']); } $ticket = $res2['ticket']; // ticket 不能频繁的访问接口来获取,在每次获取后,我们把它保存到数据库中。 if ($ticket) { $data = array( 'access_token' => $token, 'expires_time' => $time, 'expires_in' => '7000', 'ticket' => $ticket, 'ticket_expires_time' => $time ); AccessToken::where('id', 1)->update($data); // 把获得的token存储到数据库中 } return $ticket; } } }