查看: 718|回复: 1

fastadmin+uniapp实现公众号登录

[复制链接]

748

主题

39

回帖

3907

积分

管理员

总舵主

积分
3907
QQ
发表于 2025-1-4 18:27:10 | 显示全部楼层 |阅读模式
代码:


  1.    
  2.     /**
  3.      * 公众号登录
  4.      */
  5.     public function mplogin()
  6.     {
  7.         // 参数
  8.         $params = $this->request->param();
  9.         // 公众号CODE
  10.         if (!empty($params['code'])) {
  11.             // 系统配置
  12.             $config = Config::get('nianbao');
  13.             // 未开启登录
  14.             if ($config['login_type'] == 0) {
  15.                 $this->error('系统未开启登录');
  16.             }
  17.             // 用户已登录
  18.             if ($this->auth->isLogin()) {
  19.                 $this->error('用户已登录', null, 300);
  20.             }
  21.             \think\Log::record('未登录执行1');
  22.             // 支付配置
  23.             $epay = get_addon_config('epay');
  24.             $appid = $epay['wechat']['app_id'];
  25.             $secret = $epay['wechat']['app_secret'];
  26.             $code = $params['code'];
  27.             $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$appid}&secret={$secret}&code={$code}&grant_type=authorization_code";
  28.             $response = Http::post($url);
  29.             \think\Log::record($response);
  30.             $data = json_decode($response, true);
  31.             if (isset($data['errcode'])) {
  32.                 $this->error('错误码:'.$data['errcode'].',错误信息:'.$data['errmsg']);
  33.             }
  34.             // 公众号注册登录
  35.             $third = null;
  36.             //存在openid则先判断是否存在对应账号
  37.             if ($data['openid']) {
  38.                 $third = Third::get(['platform' => 'wechat', 'openid' => $data['openid']], 'user');
  39.             }
  40.             if ($third) {
  41.                 \think\Log::record('已存在第三方粉丝数据');
  42.                 if (!$third->user) {
  43.                     \think\Log::record('第三方粉丝数据未绑定用户ID');
  44.                     $third->delete();
  45.                     $third = null;
  46.                 } else {
  47.                     //如果已存在第三方账号且已绑定用户ID则直接登录
  48.                     \think\Log::record('已存在第三方粉丝数据且已绑定');
  49.                     $direct = $this->auth->direct($third->user_id);
  50.                     if ($direct) {
  51.                         \think\Log::record('已存在第三方粉丝数据且已绑定并登录成功');
  52.                         $userinfo = $this->auth->getUserinfo();
  53.                         $userinfo['openid'] = $data['openid'];
  54.                         $third->save(['logintime' => time()]);
  55.                         // 处理头像
  56.                         $userinfo['avatarUrl'] = cdnurl($userinfo['avatar'], true);
  57.                         // 返回值
  58.                         $return = [
  59.                             'openid' => $data['openid'],
  60.                             'userinfo' => $userinfo
  61.                         ];
  62.                         $this->success('登录成功', $return);
  63.                     } else {
  64.                         \think\Log::record('已存在第三方粉丝数据且已绑定并登录失败');
  65.                         $this->error('授权登录失败,请重试!');
  66.                     }
  67.                 }
  68.             }
  69.             // 当前时间戳
  70.             $time = time();
  71.             // 默认昵称
  72.             $nickname = '微信用户';
  73.             // 第三方粉丝表单
  74.             $values = [
  75.                 'platform'      => 'wechat',
  76.                 'apptype'       => 'mp',
  77.                 'openid'        => $data['openid'],
  78.                 'openname'      => $nickname,
  79.                 'access_token'  => $data['access_token'] ?? '',
  80.                 'refresh_token' => $data['refresh_token'] ?? '',
  81.                 'expires_in'    => $data['expires_in'],
  82.                 'logintime'     => $time,
  83.                 'expiretime'    => $time + $data['expires_in'],
  84.             ];
  85.             // 如果用户已登录则第三方粉丝表直接绑定该用户
  86.             if ($this->auth->id) {
  87.                 \think\Log::record('已存在第三方粉丝数据且已绑定并登录成功');
  88.                 $values['user_id'] = $this->auth->id;
  89.                 Third::create($values, true);
  90.                 $userinfo = $this->auth->getUserinfo();
  91.                 $userinfo['openid'] = $data['openid'];
  92.                 // 处理头像
  93.                 $userinfo['avatarUrl'] = cdnurl($userinfo['avatar'], true);
  94.                 // 返回值
  95.                 $return = [
  96.                     'openid' => $data['openid'],
  97.                     'userinfo' => $userinfo
  98.                 ];
  99.                 $this->success('登录成功', $return);
  100.             }
  101.             // 用户未登录也未创建第三方粉丝账号执行以下代码
  102.             // 先随机一个用户名,随后再变更为u+数字id
  103.             $username = Random::alnum(20);
  104.             $email = $data['openid'] . '@wechat.com';
  105.             Db::startTrans();
  106.             $result = false;
  107.             try {
  108.                 // 注册会员账号
  109.                 $extend = [
  110.                     'group_id' => 1,
  111.                     'avatar' => $config['avatar']
  112.                 ];
  113.                 $register = $this->auth->register($username, Random::alnum(6), $email, '', $extend);
  114.                 if (!$register) {
  115.                     throw new Exception($this->auth->getError());
  116.                 }
  117.                 // 注册后获取会员信息
  118.                 $user = $this->auth->getUser();
  119.                 // 重置用户名
  120.                 $username = $time . 'u' . $user->id;
  121.                 $fields = [];
  122.    
  123.                 //判断用户名和邮箱是否已存在
  124.                 $existusername = UserModel::getByUsername($username);
  125.                 if (!$existusername) {
  126.                     $fields['username'] = $username;
  127.                 }
  128.                 $existemail = UserModel::getByEmail($email);
  129.                 if (!$existemail) {
  130.                     $fields['email'] = $email;
  131.                 }
  132.    
  133.                 //如果昵称为空或为微信用户则修改
  134.                 if (!$user['nickname'] || $user['nickname'] == '微信用户') {
  135.                     $fields['nickname'] = $nickname = $fields['username'];
  136.                 }
  137.    
  138.                 if ($nickname) {
  139.                     $fields['nickname'] = xss_clean(strip_tags($nickname));
  140.                 }
  141.    
  142.                 // 更新会员资料
  143.                 $user = UserModel::get($user->id);
  144.                 $user->save($fields);
  145.                 if (!$third) {
  146.                     // 保存第三方信息
  147.                     $values['user_id'] = $this->auth->id;
  148.                     Third::create($values, true);
  149.                 }
  150.                 $result = true;
  151.                 Db::commit();
  152.             } catch (\Exception $e) {
  153.                 Db::rollback();
  154.                 \think\Log::record($e->getMessage());
  155.                 $this->auth->logout();
  156.                 $result = false;
  157.             }
  158.             if ($result === false) {
  159.                 $this->error('公众号登录失败');
  160.             }
  161.             $userinfo = $this->auth->getUserinfo();
  162.             $userinfo['openid'] = $data['openid'];
  163.             // 处理头像
  164.             $userinfo['avatarUrl'] = cdnurl($userinfo['avatar'], true);
  165.             // 返回值
  166.             $return = [
  167.                 'openid' => $data['openid'],
  168.                 'userinfo' => $userinfo
  169.             ];
  170.             $this->success('登录成功', $return);
  171.         }
  172.         $this->error('code参数不正确');
  173.     }
复制代码

uniapp端:
  1. <template>
  2.         <view class="container">
  3.                 <view class="nui-userbox">
  4.                         <view class="nui-user-left">
  5.                                 <image :src="userinfo.avatarUrl" class="nui-avatar" mode="widthFix"></image>
  6.                         </view>
  7.                         <view class="nui-user-right">
  8.                                 <view class="nui-nickname">
  9.                                         {{userinfo.nickname}}
  10.                                 </view>
  11.                         </view>
  12.                 </view>
  13.                 <tui-footer :fixed="false" :copyright="copyright"></tui-footer>
  14.                 <!-- 登录弹窗 -->
  15.                 <tui-modal :show="loginbox" :maskClosable="false" @cancel="hideLogin" :custom="true">
  16.                         <view class="tui-modal-custom">
  17.                                 <view class="tui-prompt-title">提示</view>
  18.                                 <view class="tui-modal-custom-text">您尚未登录,请先登录</view>
  19.                                 <view class="tui-btn-box">
  20.                                         <view class="nui-btn">
  21.                                                 <tui-button height="72rpx" :size="28" type="gray" shape="circle" @click="notLogin">暂不登录</tui-button>
  22.                                         </view>
  23.                                         <view class="nui-btn">
  24.                                                 <!-- #ifdef H5 -->
  25.                                                 <tui-button height="72rpx" :size="28" type="warning" shape="circle" @click="hfivelogin">去登录</tui-button>
  26.                                                 <!-- #endif -->
  27.                                                 <!-- #ifdef MP-WEIXIN -->
  28.                                                 <tui-button height="72rpx" :size="28" type="green" shape="circle" @click="authlogin">授权登录</tui-button>
  29.                                                 <!-- #endif -->
  30.                                         </view>
  31.                                 </view>
  32.                         </view>
  33.                 </tui-modal>
  34.                 <!-- 授权获取手机号 -->
  35.                 <tui-modal :show="mobileloginbox" :maskClosable="false" @cancel="hideMobileLogin" :custom="true">
  36.                         <view class="tui-modal-custom">
  37.                                 <view class="tui-prompt-title">授权获取您的手机号</view>
  38.                                 <view class="tui-modal-custom-text">只差最后一步,绑定手机即可登录哦</view>
  39.                                 <view class="tui-btn-box">
  40.                                         <view class="nui-btn">
  41.                                                 <tui-button height="72rpx" :size="28" type="gray" shape="circle" @click="notLogin">拒绝授权</tui-button>
  42.                                         </view>
  43.                                         <view class="nui-btn">
  44.                                                 <!-- #ifdef MP-WEIXIN -->
  45.                                                 <tui-button height="72rpx" :size="28" type="green" shape="circle" openType="getPhoneNumber" @getphonenumber="bindgetphonenumber">授权手机号</tui-button>
  46.                                                 <!-- #endif -->
  47.                                         </view>
  48.                                 </view>
  49.                         </view>
  50.                 </tui-modal>
  51.         </view>
  52. </template>

  53. <script>
  54.         const app = getApp();
  55.         export default {
  56.                 data() {
  57.                         return {
  58.                                 userinfo: {
  59.                                         avatarUrl: '/static/mine_def_touxiang_3x.png',
  60.                                         nickname: '请先登录'
  61.                                 },
  62.                                 appid: '',//公众号appid
  63.                                 scope: 'snsapi_base',
  64.                                 openid: '',
  65.                                 loginbox: false,//登录弹框
  66.                                 mobileloginbox: false,//授权手机号弹框
  67.                                 copyright: '©2024 企业登记',
  68.                         }
  69.                 },
  70.                 onLoad() {
  71.                         uni.setNavigationBarColor({
  72.                                 backgroundColor: app.globalData.topbgcolor,
  73.                                 frontColor: app.globalData.toptcolor
  74.                         })
  75.                         let that = this;
  76.                         that.tui.request('user/index').then((res) => {
  77.                                 console.log(res)
  78.                                 if (res.code == 1) {
  79.                                         that.appid = res.data.appid,//公众号appid
  80.                                         that.copyright = res.data.copyright;
  81.                                         if (res.data.userinfo) {
  82.                                                 that.userinfo = res.data.userinfo;
  83.                                                 that.openid = res.data.openid;
  84.                                                 uni.setStorageSync('userinfo', res.data.userinfo);
  85.                                                 uni.setStorageSync('openid', res.data.openid);
  86.                                         }
  87.                                         // #ifdef H5
  88.                                         if (!res.data.login) {
  89.                                                 if (that.isWeiXin()) {
  90.                                                         console.log('在微信内')
  91.                                                         let code = that.getUrlCode('code');
  92.                                                         if (code) {
  93.                                                                 console.log(code)
  94.                                                                 // Url有code参数
  95.                                                                 that.checkWeChatCode(code);
  96.                                                         } else {
  97.                                                                 // Url没有code参数,需要发起公众号授权
  98.                                                                 that.getWeChatCode();
  99.                                                         }
  100.                                                 } else {
  101.                                                         that.loginbox = true;
  102.                                                 }
  103.                                         }
  104.                                         // #endif
  105.                                 }
  106.                         })
  107.                 },
  108.                 onShow() {
  109.                         let that = this;
  110.                         var userinfo = uni.getStorageSync('userinfo');
  111.                         if (!that.isWeiXin()) {
  112.                                 if (!userinfo) {
  113.                                         that.loginbox = true;
  114.                                 } else {
  115.                                         that.tui.request('user/checklogin').then((res) => {
  116.                                                 console.log(res);
  117.                                                 if (res.code == 1) {
  118.                                                         that.hideLogin();
  119.                                                         that.userinfo = res.data.userinfo;
  120.                                                         that.openid = res.data.openid;
  121.                                                         uni.setStorageSync('userinfo', res.data.userinfo);
  122.                                                         uni.setStorageSync('openid', res.data.openid);
  123.                                                 } else if (res.code == 200) {
  124.                                                         uni.removeStorageSync('userinfo');
  125.                                                         that.loginbox = true;
  126.                                                 } else {
  127.                                                         uni.showModal({
  128.                                                                 title: '提示',
  129.                                                                 content: res.msg,
  130.                                                                 showCancel: false,
  131.                                                                 success() {
  132.                                                                         uni.reLaunch({
  133.                                                                                 url: '/pages/index/index'
  134.                                                                         })
  135.                                                                 }
  136.                                                         })
  137.                                                 }
  138.                                         })
  139.                                 }
  140.                         }
  141.                 },
  142.                 methods: {
  143.                         // 关闭登录框
  144.                         hideLogin() {
  145.                                 this.loginbox = false;
  146.                         },
  147.                         // 关闭授权手机号弹框
  148.                         hideMobileLogin() {
  149.                                 this.mobileloginbox = false;
  150.                         },
  151.                         // 暂不登录
  152.                         notLogin() {
  153.                                 this.hideLogin();
  154.                                 uni.navigateBack();
  155.                         },
  156.                         // H5登录
  157.                         hfivelogin() {
  158.                                 this.hideLogin();
  159.                                 uni.navigateTo({
  160.                                         url: '/pages/user/login'
  161.                                 })
  162.                         },
  163.                         // 小程序授权登录
  164.                         authlogin() {
  165.                                 // #ifdef MP-WEIXIN
  166.                                 uni.login({
  167.                                         onlyAuthorize: true,
  168.                                         success(t) {
  169.                                                 console.log(t)
  170.                                                 that.tui.request('user/authlogin', {
  171.                                                         code: t.code
  172.                                                 }).then((res) => {
  173.                                                         console.log(res)
  174.                                                         if (res.code == 1) {
  175.                                                                 that.userinfo = res.data.userinfo;
  176.                                                                 uni.setStorageSync('userinfo', res.data.userinfo);
  177.                                                                 uni.setStorageSync('openid', res.data.openid);
  178.                                                                 uni.showToast({
  179.                                                                         title: res.msg,
  180.                                                                         icon: 'none'
  181.                                                                 })
  182.                                                         } else if (res.code == 2) {
  183.                                                                 // 获取openid成功
  184.                                                                 that.openid = res.data.openid;
  185.                                                                 that.loginbox = true;
  186.                                                         } else {
  187.                                                                 uni.showModal({
  188.                                                                         title: '提示',
  189.                                                                         content: res.msg,
  190.                                                                         success() {
  191.                                                                                 uni.reLaunch({
  192.                                                                                         url: '/pages/index/index'
  193.                                                                                 })
  194.                                                                         }
  195.                                                                 })
  196.                                                         }
  197.                                                 })
  198.                                         },
  199.                                         fail(t) {
  200.                                                 console.log(t)
  201.                                                 uni.showModal({
  202.                                                         title: '提示',
  203.                                                         content: '授权失败,请稍后重试!',
  204.                                                         success() {
  205.                                                                 uni.reLaunch({
  206.                                                                         url: '/pages/index/index'
  207.                                                                 })
  208.                                                         }
  209.                                                 })
  210.                                         }
  211.                                 })
  212.                                 // #endif
  213.                         },
  214.                         // 微信授权登录
  215.                         bindgetphonenumber(e) {
  216.                                 console.log(e)
  217.                                 this.hideLogin();
  218.                                 var that = this;
  219.                                 if (e.errMsg == 'getPhoneNumber:fail user deny') {
  220.                                         uni.showModal({
  221.                                                 title: '提示',
  222.                                                 content: '无法获取你的手机号',
  223.                                                 showCancel: false,
  224.                                                 success() {
  225.                                                         that.loginbox = true;
  226.                                                 }
  227.                                         })
  228.                                         return;
  229.                                 }
  230.                                 // 推广商户
  231.                                 var hotel_id = uni.getStorageSync('hotel_id') || 0;
  232.                                 // 注册登录
  233.                                 that.tui.request('user/mobilelogin', {
  234.                                         code: e.code,
  235.                                         openid: that.openid,
  236.                                         hotel_id: hotel_id
  237.                                 }).then((res) => {
  238.                                         // console.log(res)
  239.                                         if (res.code == 1) {
  240.                                                 // uni.removeStorageSync('hotel_id');
  241.                                                 that.userinfo = res.data.userinfo;
  242.                                                 uni.setStorageSync('userinfo', res.data.userinfo);
  243.                                         }
  244.                                         uni.showToast({
  245.                                                 title: res.msg,
  246.                                                 icon: 'none'
  247.                                         })
  248.                                 })
  249.                         },
  250.                         // 判断是否微信内访问
  251.                         isWeiXin() {
  252.                                 let ua = window.navigator.userAgent.toLowerCase();
  253.                                 // console.log(ua)
  254.                                 if (ua.match(/MicroMessenger/i) == 'micromessenger') {
  255.                                         return true;
  256.                                 } else {
  257.                                         return false;
  258.                                 }
  259.                         },
  260.                         // 获取公众号授权登录回调结果code
  261.                         getUrlCode(name) {
  262.                                 return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [, ''])[1].replace(/\+/g, '%20')) || null
  263.                         },
  264.                         // 发起公众号授权获取code
  265.                         getWeChatCode() {
  266.                                 // console.log(this.appid)
  267.                                 let appid = this.appid;
  268.                                 let local = encodeURIComponent(window.location.href);
  269.                                 let scope = this.scope;
  270.                                 window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${local}&response_type=code&scope=${scope}&state=1#wechat_redirect`;
  271.                         },
  272.                         // 将code发送服务端获取用户openid
  273.                         checkWeChatCode(code) {
  274.                                 var that = this;
  275.                                 if (code) {
  276.                                         // 这里需要有一个逻辑判断公众号授权用户未注册自动注册并登录,已注册就登录
  277.                                         that.tui.request('user/mplogin', {
  278.                                                 code: code
  279.                                         }).then((res) => {
  280.                                                 console.log(res)
  281.                                                 if (res.code == 1) {
  282.                                                         that.openid = res.data.openid;
  283.                                                         that.userinfo = res.data.userinfo;
  284.                                                         uni.setStorageSync('userinfo', res.data.userinfo);
  285.                                                         uni.setStorageSync('openid', res.data.openid);
  286.                                                 } else {
  287.                                                         uni.showModal({
  288.                                                                 title: '提示',
  289.                                                                 content: res.msg,
  290.                                                                 showCancel: false,
  291.                                                                 success() {
  292.                                                                         uni.reLaunch({
  293.                                                                                 url: '/pages/index/index'
  294.                                                                         })
  295.                                                                 }
  296.                                                         })
  297.                                                 }
  298.                                         })
  299.                                 }
  300.                         }
  301.                 }
  302.         }
  303. </script>

  304. <style>
  305.         page {
  306.                 background-color: #f5f5f5;
  307.         }
  308.        
  309.         .nui-userbox {
  310.                 display: flex;
  311.                 justify-content: space-between;
  312.                 align-items: center;
  313.                 padding: 30rpx;
  314.                 box-sizing: border-box;
  315.                 background-color: #ffffff;
  316.         }
  317.         .nui-user-left {
  318.                 width: 25%;
  319.         }
  320.         .nui-avatar {
  321.                 width: 90%;
  322.                 height: auto;
  323.                 display: block;
  324.                 border-radius: 50%;
  325.         }
  326.         .nui-user-right {
  327.                 width: 75%;
  328.         }
  329.         /* 登录框 */
  330.         .tui-modal-custom {
  331.                 text-align: center;
  332.         }
  333.        
  334.         .tui-modal-custom-text {
  335.                 font-size: 30rpx;
  336.                 color: #333;
  337.                 padding: 30rpx 0 50rpx;
  338.         }
  339.        
  340.         .tui-prompt-title {
  341.                 padding-bottom: 20rpx;
  342.                 font-size: 34rpx;
  343.         }
  344.         .tui-btn-box {
  345.                 display: flex;
  346.                 justify-content: space-between;
  347.                 align-items: center;
  348.         }
  349.         .nui-btn {
  350.                 width: 45%;
  351.         }
  352. </style>
复制代码


道不同,不相为谋!理想要有,万一实现了呢?

748

主题

39

回帖

3907

积分

管理员

总舵主

积分
3907
QQ
 楼主| 发表于 2025-1-6 10:55:41 | 显示全部楼层
  1. /**
  2.      * 检查登录
  3.      */
  4.     public function checklogin()
  5.     {
  6.         // 系统配置
  7.         $config = Config::get('nianbao');
  8.         // 请求参数
  9.         $params = $this->request->param();
  10.         // 开启登录
  11.         if ($config['login_type'] == 1) {
  12.             if (!$this->auth->isLogin()) {
  13.                 $this->error('您尚未登录或登录已失效', null, 200);
  14.             } else {
  15.                 $userinfo = $this->auth->getUserinfo();
  16.                 // 头像
  17.                 $userinfo['avatarUrl'] = cdnurl($userinfo['avatar'], true);
  18.                 // 第三方会员
  19.                 $third = Third::where(['user_id'=>$this->auth->id, 'platform'=>$params['platform'], 'apptype'=>$params['apptype']])->find();
  20.                 $openid = '';
  21.                 if (!empty($third)) {
  22.                     $openid = $third->openid;
  23.                 }
  24.                 $this->success('用户已登录', ['userinfo'=>$userinfo, 'openid'=>$openid]);
  25.             }
  26.         }
  27.         $this->error('系统未开启登录');
  28.     }
复制代码


道不同,不相为谋!理想要有,万一实现了呢?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注公众号

相关侵权、举报、投诉及建议等,请发 E-mail:2513533699@qq.com

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.|鲁ICP备19000917号|鲁公网安备37078302000320号

在本版发帖
关注公众号
QQ客服返回顶部