diff --git a/application/admin/controller/Third.php b/application/admin/controller/Third.php
new file mode 100644
index 0000000..ac7dc77
--- /dev/null
+++ b/application/admin/controller/Third.php
@@ -0,0 +1,66 @@
+model = new \app\admin\model\Third;
+ }
+
+ /**
+ * 查看
+ */
+ public function index()
+ {
+ $this->relationSearch = true;
+ //设置过滤方法
+ $this->request->filter(['strip_tags']);
+ if ($this->request->isAjax()) {
+ //如果发送的来源是Selectpage,则转发到Selectpage
+ if ($this->request->request('keyField')) {
+ return $this->selectpage();
+ }
+ list($where, $sort, $order, $offset, $limit) = $this->buildparams();
+ $total = $this->model
+ ->with(['user'])
+ ->where($where)
+ ->order($sort, $order)
+ ->count();
+
+ $list = $this->model
+ ->with(['user'])
+ ->where($where)
+ ->order($sort, $order)
+ ->limit($offset, $limit)
+ ->select();
+ foreach ($list as $index => $item) {
+ if ($item->user) {
+ $item->user->visible(['nickname']);
+ }
+ }
+ $list = collection($list)->toArray();
+ $result = array("total" => $total, "rows" => $list);
+
+ return json($result);
+ }
+ return $this->view->fetch();
+ }
+
+}
diff --git a/application/admin/lang/zh-cn/third.php b/application/admin/lang/zh-cn/third.php
new file mode 100644
index 0000000..a3aa09c
--- /dev/null
+++ b/application/admin/lang/zh-cn/third.php
@@ -0,0 +1,17 @@
+ 'ID',
+ 'User_id' => '会员ID',
+ 'Platform' => '平台',
+ 'Apptype' => '类型',
+ 'Unionid' => 'UnionID',
+ 'Openid' => 'OpenID',
+ 'Openname' => '第三方会员昵称',
+ 'Access_token' => 'AccessToken',
+ 'Expires_in' => '有效期',
+ 'Createtime' => '创建时间',
+ 'Updatetime' => '更新时间',
+ 'Logintime' => '登录时间',
+ 'Expiretime' => '过期时间'
+];
diff --git a/application/admin/model/Third.php b/application/admin/model/Third.php
new file mode 100644
index 0000000..66d3be0
--- /dev/null
+++ b/application/admin/model/Third.php
@@ -0,0 +1,56 @@
+belongsTo("User", 'user_id', 'id')->setEagerlyType(0);
+ }
+}
diff --git a/application/admin/validate/Third.php b/application/admin/validate/Third.php
new file mode 100644
index 0000000..f9766b4
--- /dev/null
+++ b/application/admin/validate/Third.php
@@ -0,0 +1,26 @@
+ [],
+ 'edit' => [],
+ ];
+}
diff --git a/application/admin/view/third/index.html b/application/admin/view/third/index.html
new file mode 100644
index 0000000..6fc9d97
--- /dev/null
+++ b/application/admin/view/third/index.html
@@ -0,0 +1,23 @@
+
+ {:build_heading()}
+
+
+
diff --git a/application/api/controller/Index.php b/application/api/controller/Index.php
index 24c615e..3fac732 100644
--- a/application/api/controller/Index.php
+++ b/application/api/controller/Index.php
@@ -20,4 +20,25 @@ class Index extends Api
{
$this->success('请求成功');
}
+
+
+
+
+ /**
+ * @ApiTitle(init接口,小程序初始化参数接口)
+ * @ApiSummary(小程序初始化参数接口)
+ * @ApiRoute(/api/index/init)
+ * @ApiMethod(GET)
+ * @ApiReturn({
+ "code" => 1,
+ "msg" => "获取成功",
+ "data" => {}
+ *})
+ */
+ public function init() {
+
+ $this->success('',[]);
+ }
+
+
}
diff --git a/application/api/controller/User.php b/application/api/controller/User.php
index a46a8fb..d379570 100644
--- a/application/api/controller/User.php
+++ b/application/api/controller/User.php
@@ -7,7 +7,10 @@ use app\common\controller\Api;
use app\common\library\Ems;
use app\common\library\Sms;
use fast\Random;
+use think\Cache;
use think\Config;
+use think\Db;
+use think\Log;
use think\Validate;
use app\admin\library\Wechat;
@@ -16,7 +19,7 @@ use app\admin\library\Wechat;
*/
class User extends Api
{
- protected $noNeedLogin = ['login', 'mobilelogin', 'register', 'resetpwd', 'changeemail', 'changemobile', 'third'];
+ protected $noNeedLogin = ["registerLogin",'getOpenid','decodeData','login', 'mobilelogin', 'register', 'resetpwd', 'changeemail', 'changemobile', 'third'];
protected $noNeedRight = '*';
protected $miniConfig;
@@ -25,6 +28,9 @@ class User extends Api
{
$this->miniConfig = (new Wechat)->getMiniConfig();
parent::_initialize();
+ if (!Config::get('fastadmin.usercenter')) {
+ $this->error(__('User center already closed'));
+ }
}
@@ -33,7 +39,7 @@ class User extends Api
/**
* @ApiTitle(获取小程序openid信息)
* @ApiSummary(根据前端code换取openid信息)
- * @ApiRoute(/getOpenid)
+ * @ApiRoute(/api/user/getOpenid)
* @ApiMethod(GET)
* @ApiParams(name="code",type="string",required=true,description="前端code值")
* @ApiHeaders(name = "brand-key", type = "string",require = true, description = "应用key")
@@ -51,8 +57,6 @@ class User extends Api
public function getOpenid(){
$code = $this->request->param('code/s');
-
-
try {
$result = LoginService::getInstance(['mini_config' => $this->miniConfig])->getOpenid($code);
} catch (\WeChat\Exceptions\LocalCacheException $e){
@@ -60,13 +64,14 @@ class User extends Api
} catch (\Exception $e){
$this->error($e->getMessage());
}
+ Cache::set('wechat_mini_code'.$code.$result['openid'],"1",60);
$this->success('',$result);
}
/**
* @ApiTitle(加密信息解密)
* @ApiSummary(解密微信信息)
- * @ApiRoute(/decodeData)
+ * @ApiRoute(/api/user/decodeData)
* @ApiMethod(POST)
* @ApiParams(name = "iv", type = "string",required=true)
* @ApiParams(name = "encryptedData", type = "string",required=true)
@@ -92,24 +97,71 @@ class User extends Api
-
-
- public function _initialize()
- {
- parent::_initialize();
-
- if (!Config::get('fastadmin.usercenter')) {
- $this->error(__('User center already closed'));
+ /**
+ * @ApiTitle(微信小程序授权登录注册通用[支持静默登录])
+ * @ApiSummary(登录注册通用-支持静默登录)
+ * @ApiRoute(/api/user/registerLogin)
+ * @ApiMethod(POST)
+ * @ApiParams(name = "mobile", type = "string",required=false,description = "mobile 静默非必传,手机授权必传")
+ * @ApiParams(name = "unionid", type = "string",required=false, description = "unionid 非必传")
+ * @ApiParams(name = "apptype", type = "string",required=false, description = "应用类型默认miniapp")
+ * @ApiParams(name = "platform", type = "string",require=false, description = "平台标识默认wechat")
+ * @ApiParams(name = "openid", type = "string", require=true, description = "授权的openid")
+ * @ApiParams(name = "keeptime", type = "string", require=false, description = "token保持时间,默认0永久")
+ * @ApiParams(name = "code", type = "string", require=true, description = "授权的code")
+ * @ApiReturn({
+ "code" => 1,
+ "msg" => "获取成功",
+ "data" => {‘token’:xxxxx,'errcode':0(如果为30001则是需要重新授权)}
+ *})
+ */
+ public function registerLogin(){
+ $extend= $params = [];
+ $extend['mobile'] = $this->request->param('mobile/s','');
+ $params['unionid'] = $this->request->param('unionid/s','');
+ $params['apptype'] = $this->request->param('apptype/s','miniapp');
+ $params['openid'] = $this->request->param('openid/s','');
+ $code = $this->request->param('code/s','');
+ if(empty($code)){
+ $this->error(__('缺少code'));
}
+ $wechat_mini_code = Cache::get('wechat_mini_code'.$code.$params['openid']);
+ if(!$wechat_mini_code)$this->error("授权code已过期或已使用,请重新发起授权!",['errcode'=>30002]);
+
+ $platform = $this->request->param('platform/s','wechat');
+ //推荐人:逻辑未实现
+ $rec_user_id = $this->request->param('rec_user_id',0,'xilufitness_get_id_value');
+ $keeptime = $this->request->param('keeptime/d',0);
+ //access_token
+
+ try {
+ \addons\third\library\Service::loginAndRegisterByMobile($platform, $params, $extend, $keeptime);
+ } catch (\Exception $e){
+ Log::log($e->getMessage());
+ $this->error($e->getMessage(),['errcode'=>$e->getCode()]);
+ }
+ Cache::rm('wechat_mini_code'.$code.$params['openid']);
+ $this->success('获取成功', ['token' => $this->auth->getToken()]);
}
+
+
+
+
+
+
/**
* 会员中心
*/
public function index()
{
- $this->success('', ['welcome' => $this->auth->nickname]);
+ $data = [
+ 'welcome' => $this->auth->nickname,
+ 'user_info'=>$this->auth->getUserinfo()
+ ];
+ $data['user_info']["avatar"] = $data['user_info']["avatar"]? cdnurl($data['user_info']["avatar"],true):$data['user_info']["avatar"];
+ $this->success('调用成功',$data);
}
/**
@@ -230,34 +282,56 @@ class User extends Api
* 修改会员个人信息
*
* @ApiMethod (POST)
+ * @ApiParams (name="update_fields", type="json", required=true, description="本次需要更新的用户字段json格式:更新谁传谁的字段名,比如:只更新头像和昵称 则 json=['avatar','nickname']")
* @ApiParams (name="avatar", type="string", required=true, description="头像地址")
* @ApiParams (name="username", type="string", required=true, description="用户名")
* @ApiParams (name="nickname", type="string", required=true, description="昵称")
+ * @ApiParams (name="realname", type="string", required=true, description="姓名")
+ * @ApiParams (name="gender", type="string", required=true, description="性别:0女 1男")
+ * @ApiParams (name="birthday", type="string", required=true, description="出生日期:日期字符串 比如”1995-9-20")
+ * @ApiParams (name="work", type="string", required=true, description="职业")
* @ApiParams (name="bio", type="string", required=true, description="个人简介")
*/
public function profile()
{
$user = $this->auth->getUser();
- $username = $this->request->post('username');
- $nickname = $this->request->post('nickname');
- $bio = $this->request->post('bio');
- $avatar = $this->request->post('avatar', '', 'trim,strip_tags,htmlspecialchars');
- if ($username) {
+ $update_fields = $this->request->post('update_fields/a',[]);
+// var_dump($update_fields);die;
+
+ if(!$update_fields)$this->error(__('请指定要更新的字段!'));
+ $username = $this->request->post('username/s');
+ $nickname = $this->request->post('nickname/s');
+ $realname = $this->request->post('realname/s');
+ $gender = $this->request->post('gender/d');
+ $birthday = $this->request->post('birthday/s');
+ $work = $this->request->post('work/s');
+ $bio = $this->request->post('bio/s',null);
+ $avatar = $this->request->post('avatar', null, 'trim,strip_tags,htmlspecialchars');
+
+
+ if ($username && in_array('username', $update_fields)) {
$exists = \app\common\model\User::where('username', $username)->where('id', '<>', $this->auth->id)->find();
if ($exists) {
$this->error(__('Username already exists'));
}
$user->username = $username;
}
- if ($nickname) {
+ if ($nickname && in_array('nickname', $update_fields)) {
$exists = \app\common\model\User::where('nickname', $nickname)->where('id', '<>', $this->auth->id)->find();
if ($exists) {
$this->error(__('Nickname already exists'));
}
$user->nickname = $nickname;
}
- $user->bio = $bio;
- $user->avatar = $avatar;
+ if(in_array('bio', $update_fields))$user->bio = $bio;
+ if($avatar!==null && in_array('avatar', $update_fields))$user->avatar = $avatar;
+ if(in_array('realname', $update_fields))$user->realname = $realname;
+ if(in_array('gender', $update_fields)){
+ if(!in_array($gender, [1,2]))$this->error(__('请输入正确的性别!'));
+ $user->gender = $gender;
+ }
+ if(in_array('birthday', $update_fields))$user->birthday = $birthday;
+ if(in_array('work', $update_fields))$user->work = $work;
$user->save();
$this->success();
}
diff --git a/application/common/library/Auth.php b/application/common/library/Auth.php
index f3ed90f..cea4d32 100644
--- a/application/common/library/Auth.php
+++ b/application/common/library/Auth.php
@@ -26,7 +26,7 @@ class Auth
//默认配置
protected $config = [];
protected $options = [];
- protected $allowFields = ['id', 'username', 'nickname', 'mobile', 'avatar', 'score'];
+ protected $allowFields = ['id', 'username', 'nickname', 'mobile', 'avatar', 'score', 'realname', 'work', 'gender', 'birthday', 'bio'];
public function __construct($options = [])
{
diff --git a/application/index/controller/Third.php b/application/index/controller/Third.php
new file mode 100644
index 0000000..2dd4c7e
--- /dev/null
+++ b/application/index/controller/Third.php
@@ -0,0 +1,200 @@
+app = new Application($config);
+
+ $auth = $this->auth;
+ //监听注册登录事件
+ Hook::add('user_login_successed', function ($user) use ($auth) {
+ $expire = input('post.keeplogin') ? 30 * 86400 : 0;
+ Cookie::set('uid', $user->id, $expire);
+ Cookie::set('token', $auth->getToken(), $expire);
+ });
+ Hook::add('user_register_successed', function ($user) use ($auth) {
+ Cookie::set('uid', $user->id);
+ Cookie::set('token', $auth->getToken());
+ });
+ }
+
+ /**
+ * 准备绑定
+ */
+ public function prepare()
+ {
+ $platform = $this->request->request('platform', '');
+ if (!in_array($platform, ['wechat', 'weibo', 'qq'])) {
+ $this->error("未找到指定平台");
+ }
+ $url = $this->request->get('url', '/', 'trim,xss_clean');
+
+ // 授权成功后的回调
+ $thirdinfo = Session::get("third-{$platform}");
+ if (!$thirdinfo) {
+ $this->error("操作失败,请返回重试");
+ }
+
+ $apptype = Service::getApptype();
+ $openid = $thirdinfo['openid'] ?? '';
+ $unionid = $thirdinfo['unionid'] ?? '';
+
+ // 如果是登录状态,直接跳到绑定
+ if ($this->auth->id) {
+ $isBind = Service::isBindThird($platform, $openid, '', $unionid);
+ if ($isBind) {
+ $this->error("已经绑定其它账号,无法进行绑定");
+ }
+ $this->redirect(url("index/third/bind") . "?" . http_build_query(['platform' => $platform, 'url' => $url]));
+ }
+
+ if ($this->request->isPost()) {
+ $mobile = $this->request->post("mobile");
+ $platform = $this->request->post("platform");
+ $captcha = $this->request->post("captcha");
+ $nickname = $thirdinfo['userinfo']['nickname'] ?? '';
+
+ if (!Sms::check($mobile, $captcha, 'bind')) {
+ $this->error(__('验证码不正确'));
+ }
+
+ $user = \app\common\model\User::where('mobile', $mobile)->find();
+ if ($user) {
+ $isBind = \addons\third\model\Third::where('platform', $platform)->where('user_id', $user['id'])->find();
+ if ($isBind) {
+ $this->error('该手机号已经占用');
+ }
+
+ $result = $this->auth->direct($user->id);
+ } else {
+ $extend = array_filter(['nickname' => $nickname]);
+ $result = $this->auth->register($mobile, Random::alnum(), '', $mobile, $extend);
+ }
+ // 账号创建成功则添加绑定第三方绑定
+ if ($result) {
+ \addons\third\model\Third::create(['user_id' => $this->auth->id, 'platform' => $platform, 'apptype' => $apptype, 'openid' => $openid, 'unionid' => $unionid, 'openname' => $nickname], true);
+ }
+
+ //删除临时Session
+ Session::delete("third-{$platform}");
+
+ //绑定成功,跳转到之前页面
+ $this->success("绑定成功", $url);
+ }
+
+ $this->view->assign('userinfo', $thirdinfo['userinfo']);
+ $this->view->assign('platform', $platform);
+ $this->view->assign('url', $url);
+ $this->view->assign('bindurl', url("index/third/bind") . '?' . http_build_query(['platform' => $platform, 'url' => $url]));
+ $this->view->assign('captchaType', config('fastadmin.user_register_captcha'));
+ $this->view->assign('title', "账号绑定");
+
+ return $this->view->fetch();
+ }
+
+ /**
+ * 绑定账号
+ */
+ public function bind()
+ {
+ $platform = $this->request->request('platform', '');
+ if (!in_array($platform, ['wechat', 'weibo', 'qq'])) {
+ $this->error("未找到指定平台");
+ }
+ $url = $this->request->get('url', $this->request->server('HTTP_REFERER', '', 'trim'), 'trim');
+ if (!$platform) {
+ $this->error("参数不正确");
+ }
+
+ $apptype = $platform == 'wechat' ? Service::getApptype() : '';
+
+ // 授权成功后的回调
+ $thirdinfo = Session::get("third-{$platform}");
+ if (!$thirdinfo) {
+ $this->redirect(addon_url('third/index/connect', [':platform' => $platform]) . '?url=' . urlencode($url));
+ }
+ $third = \addons\third\model\Third::where('user_id', $this->auth->id)->where('platform', $platform)->find();
+ if ($third) {
+ $this->error("已绑定账号,请勿重复绑定");
+ }
+ $time = time();
+ $values = [
+ 'platform' => $platform,
+ 'apptype' => $apptype,
+ 'user_id' => $this->auth->id,
+ 'unionid' => $thirdinfo['unionid'] ?? '',
+ 'openid' => $thirdinfo['openid'],
+ 'openname' => $thirdinfo['userinfo']['nickname'] ?? '',
+ 'access_token' => $thirdinfo['access_token'],
+ 'refresh_token' => $thirdinfo['refresh_token'],
+ 'expires_in' => $thirdinfo['expires_in'],
+ 'logintime' => $time,
+ 'expiretime' => $time + $thirdinfo['expires_in'],
+ ];
+ $isBind = Service::isBindThird($platform, $values['openid'], '', $values['unionid']);
+ if ($isBind) {
+ $this->error("已经绑定其它账号,无法进行绑定");
+ }
+ $third = \addons\third\model\Third::create($values);
+ if ($third) {
+
+ //删除临时Session
+ Session::delete("third-{$platform}");
+
+ $this->success("账号绑定成功", $url);
+ } else {
+ $this->error("账号绑定失败,请重试", $url);
+ }
+ }
+
+ /**
+ * 解绑账号
+ */
+ public function unbind()
+ {
+ $platform = $this->request->request('platform', '');
+ if (!in_array($platform, ['wechat', 'weibo', 'qq'])) {
+ $this->error("未找到指定平台");
+ }
+ $apptype = $platform == 'wechat' ? Service::getApptype() : '';
+
+ $third = \addons\third\model\Third::where('user_id', $this->auth->id)
+ ->where('platform', $platform)
+ ->where(function ($query) use ($platform, $apptype) {
+ if ($platform == 'wechat') {
+ $query->where('apptype', $apptype);
+ }
+ })
+ ->find();
+ if (!$third) {
+ $this->error("未找到指定的账号绑定信息");
+ }
+ Session::delete("third-{$platform}");
+ $third->delete();
+ $this->success("账号解绑成功");
+ }
+}
diff --git a/application/index/view/third/prepare.html b/application/index/view/third/prepare.html
new file mode 100644
index 0000000..e9fe868
--- /dev/null
+++ b/application/index/view/third/prepare.html
@@ -0,0 +1,76 @@
+
+
+ {if isset($userinfo['avatar'])}
+
+
+
{$userinfo.nickname|default=''|htmlentities}
+
+ {/if}
+
+
+
+
diff --git a/public/assets/js/backend/third.js b/public/assets/js/backend/third.js
new file mode 100644
index 0000000..a3c2d70
--- /dev/null
+++ b/public/assets/js/backend/third.js
@@ -0,0 +1,61 @@
+define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
+
+ var Controller = {
+ index: function () {
+ // 初始化表格参数配置
+ Table.api.init({
+ extend: {
+ index_url: 'third/index' + location.search,
+ add_url: 'third/add',
+ edit_url: 'third/edit',
+ del_url: 'third/del',
+ multi_url: 'third/multi',
+ table: 'third',
+ }
+ });
+
+ var table = $("#table");
+
+ // 初始化表格
+ table.bootstrapTable({
+ url: $.fn.bootstrapTable.defaults.extend.index_url,
+ pk: 'id',
+ sortName: 'id',
+ fixedColumns: true,
+ fixedRightNumber: 1,
+ columns: [
+ [
+ {checkbox: true},
+ {field: 'id', title: __('Id')},
+ {field: 'user_id', title: __('User_id'), formatter: Table.api.formatter.search},
+ {field: 'user.nickname', title: __('Nickname')},
+ {field: 'platform', title: __('Platform'), formatter: Table.api.formatter.flag, searchList: {'wechat': '微信', 'qq': 'QQ', 'weibo': '微博'}, custom: {'wechat': 'success', 'qq': 'info', 'weibo': 'danger'}},
+ {field: 'apptype', title: __('Apptype'), formatter: Table.api.formatter.normal, searchList: {'mp': '公众号', 'wxapp': '小程序', 'web': 'PC端'}},
+ {field: 'openid', title: __('Openid')},
+ {field: 'unionid', title: __('Unionid')},
+ {field: 'openname', title: __('Openname'), formatter: Table.api.formatter.search},
+ {field: 'createtime', title: __('Createtime'), sortable: true, operate: 'RANGE', addclass: 'datetimerange', formatter: Table.api.formatter.datetime},
+ {field: 'updatetime', title: __('Updatetime'), visible: false, sortable: true, operate: 'RANGE', addclass: 'datetimerange', formatter: Table.api.formatter.datetime},
+ {field: 'logintime', title: __('Logintime'), operate: 'RANGE', addclass: 'datetimerange', formatter: Table.api.formatter.datetime},
+ {field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
+ ]
+ ]
+ });
+
+ // 为表格绑定事件
+ Table.api.bindevent(table);
+ },
+ add: function () {
+ Controller.api.bindevent();
+ },
+ edit: function () {
+ Controller.api.bindevent();
+ },
+ api: {
+ bindevent: function () {
+ Form.api.bindevent($("form[role=form]"));
+ }
+ }
+ };
+ return Controller;
+});