您当前的位置:首页 > 电脑百科 > 程序开发 > 移动端 > 小程序

「SpringCloud」微信小程序授权登录流程设计和实现

时间:2023-03-27 11:54:45  来源:  作者:AI全栈程序猿

 在前面的设计和实现中,我们的微服务开发平台通过JustAuth来实现第三方授权登录,通过集成公共组件,着实减少了很多工作量,大多数的第三方登录直接通过配置就可以实现。而在第三方授权登录中,微信小程序授权登录和App微信授权登录是两种特殊的第三方授权登录。
  JustAuth之所以能够将多种第三方授权登录服务整合在一起,抽象公共组件的原因是大多数的授权登录服务器都是遵循OAuth2.0协议开发,虽然略有不同但可通过适配器进行转换为统一接口。微信小程序授权登录和APP的微信授权登录也是OAutn2.0协议的授权登录,但在对接的流程中不是完整的OAuth2.0对接流程。
  通常的第三方授权登录过程中,获取token的state和code是在回调客户端url中获取的,而微信小程序授权登录和APP的微信授权登录获取token的state和code是使用微信提供的特定方法获取到的,然后通过微信传给客户端,客户端拿到code之后到后台取获取openid等微信用户信息。然后,再进行系统登录相关操作。

一、微信小程序授权登录、注册、绑定流程设计说明

  • 微信小程序授权登录、注册、绑定流程图:

 

  • 微信小程序授权登录、注册、绑定流程说明:
  1. 用户进入小程序。
  2. 小程序前端通过从缓存中获取是否有token来判定用户是否登录。
  3. 如果未登录,那么跳转到小程序登录页。
  4. 小程序前端执行微信登录方法wx.login获取微信登录的code(此时并未进行微信授权登录)。
  5. 小程序前端通过code向业务后台发送请求获取用户唯一的openid。
  6. 业务系统根据openid或者unionid判断该用户是否绑定了业务用户,并将是否绑定信息返回给前台。
  7. 如果没有绑定过,那么前端展示微信授权登录按钮。
  8. 用户点击“授权登录”按钮之后,小程序前端会获取到加密的用户信息。
  9. 小程序前端将加密的用户信息传到业务后台进行解密。
  10. 业务后台收到加密用户信息后,通过请求微信服务器解密用户信息,并将用户信息存储到业务系统表。
  11. 后台将解密后的用户信息(非私密信息)返回到小程序前台。
  12. 如果是没有绑定的,那么小程序前台弹出是否获取当前用户手机号的弹出框。
  13. 用户选择是否获取微信绑定的手机号来注册或绑定到业务系统的用户。
  14. 当用户点击统一获取手机号时,微信会返回加密后的手机号,然后前端将加密后的手机号发送到业务后台解密。
  15. 业务后台获取到手机号码之后,会根据手机号码在系统用户表中进行匹配,如果匹配到用户,那么直接返回小程序用户信息。
  16. 当用户不同意获取手机号时,那么小程序跳转到输入账号密码进行绑定页面。
  17. 当绑定操作执行成功之后,微信小程序调用第三方登录获取token方式,向业务后台获取token。
  18. 用户小程序授权登录、注册、绑定成功。

二、微信小程序授权登录、注册、绑定业务后台功能实现

  微信通过其开放平台提供小程序登录功能接口,我们的业务服务可以通过小程序的登录接口方便地获取微信提供的用户身份标识,进而将业务自身用户体系和微信用户相结合,从而更完美地在微信小程序中实现业务功能。
  微信小程序提供了对接登录的SDK,我们只需要按照其官方文档对接开发即可。同时也有很多开源组件将SDK再次进行封装,在业务开发中可以更快速的集成小程序各个接口的调用。
  出于快速开发的原则,同时也少走弯路、少踩坑,我们可以选择一款实现比较完善的组件进行微信小程序的对接。weixin-JAVA-miniapp是集成微信小程序相关SDK操作的工具包,我们在项目中集成此工具包来实现微信小程序授权登录。

1、引入weixin-java-miniapp相关maven依赖,目前发布版本为4.4.0正式版。

  一般在选择开源工具包时,我们不会选择最新版,而是选择稳定版本,但是微信的开放接口经常变动,这里为了能够兼容最新的微信小程序接口,我们在引用包的时候一定要选择更新版本,否则会影响部分接口的调用。

......
    <properties>
......
        <!-- 微信小程序版本号 -->
        <weixin-java-miniapp.version>4.4.0</weixin-java-miniapp.version>
    </properties>
......
            <dependency>
                <groupId>com.Github.binarywang</groupId>
                <artifactId>weixin-java-miniapp</artifactId>
                <version>${weixin-java-miniapp.version}</version>
            </dependency>
......

2、在配置文件application-dev.yml、application-test.yml、application-prod.yml中新增微信小程序需要的配置项。

  关于小程序如何注册,appid和appsecret如何获取,这里不展开讲,微信开放平台有详细的说明文档。

wx:
  miniapp:
    configs:
      - appid: #微信小程序appid
        secret: #微信小程序secret
        token: #微信小程序消息服务器配置的token
        aesKey: #微信小程序消息服务器配置的EncodingAESKey
        msgDataFormat: JSON

3、将weixin-java-miniapp配置类文件Wxmaconfiguration.java和WxMaProperties.java添加到我们的工程中。

  • WxMaConfiguration.java关键代码
......
@Data
@ConfigurationProperties(prefix = "wx.miniapp")
public class WxMaProperties {

    private List<Config> configs;

    @Data
    public static class Config {
        /**
         * 设置微信小程序的appid
         */
        private String appid;

        /**
         * 设置微信小程序的Secret
         */
        private String secret;

        /**
         * 设置微信小程序消息服务器配置的token
         */
        private String token;

        /**
         * 设置微信小程序消息服务器配置的EncodingAESKey
         */
        private String aesKey;

        /**
         * 消息格式,XML或者JSON
         */
        private String msgDataFormat;
    }

}
......
  • WxMaProperties.java关键代码
......
    private final WxMaProperties properties;

    @Autowired
    public WxMaConfiguration(WxMaProperties properties) {
        this.properties = properties;
    }

    @Bean
    public WxMaService wxMaService() {
        List<WxMaProperties.Config> configs = this.properties.getConfigs();
        if (configs == null) {
            throw new WxRuntimeException("配置错误!");
        }
        WxMaService maService = new WxMaServiceImpl();
        maService.setMultiConfigs(
            configs.stream()
                .map(a -> {
                    WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
                    config.setAppid(a.getAppid());
                    config.setSecret(a.getSecret());
                    config.setToken(a.getToken());
                    config.setAesKey(a.getAesKey());
                    config.setMsgDataFormat(a.getMsgDataFormat());
                    return config;
                }).collect(Collectors.toMap(WxMaDefaultConfigImpl::getAppid, a -> a, (o, n) -> o)));
        return maService;
    }
......

4、新建WxMaUserController.java用于实现微信小程序请求的相关接口。

  • 实现小程序登录的login接口,此接口会根据微信小程序前端传来的code进行获取用户session_key、openid/unionid,我们的业务系统会根据openid/unionid结合第三方登录表进行用户匹配,如果存在该用户则返回给小程序前台已存在的用户信息;如果不存在,说明该用户是第一次微信小程序登录,那么我们将获取到的微信唯一身份标识加密,并返回微信小程序前台进行下一步绑定账户或注册操作。
    /**
     * 登陆接口
     */
    @ApiOperation(value = "小程序登录接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "小程序code", dataType="String", paramType = "query"),
    })
    @GetMapping("/login")
    public Result<?> login(@PathVariable String appid, String code) {
        
        if (StringUtils.isBlank(code)) {
            return Result.error("code 不能为空");
        }

        if (!wxMaService.switchover(appid)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
        }
    
        WeChatMiniAppLoginDTO weChatMiniAppLoginDTO = new WeChatMiniAppLoginDTO();
        try {
            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
            weChatMiniAppLoginDTO.setOpenid(session.getOpenid());
            weChatMiniAppLoginDTO.setUnionid(session.getUnionid());
            // 通过openId获取在系统中是否是已经绑定过的用户,如果没有绑定,那么返回到前台,提示需要绑定或者注册用户
            LambdaQueryWrapper<JustAuthSocial> socialLambdaQueryWrapper = new LambdaQueryWrapper<>();
            // 如果微信开通了开放平台,那么各个渠道(小程序、公众号等)都会有统一的unionid,如果没开通,就仅仅使用openId
            if (StringUtils.isBlank(session.getUnionid()))
            {
                socialLambdaQueryWrapper.eq(JustAuthSocial::getOpenId, session.getOpenid())
                        .eq(JustAuthSocial::getSource, "WECHAT_MINI_APP");
            }
            else
            {
                socialLambdaQueryWrapper.eq(JustAuthSocial::getUnionId, session.getUnionid())
                        .and(e -> e.eq(JustAuthSocial::getSource, "WECHAT_MINI_APP")
                                .or().eq(JustAuthSocial::getSource, "WECHAT_OPEN")
                                .or().eq(JustAuthSocial::getSource, "WECHAT_MP")
                                .or().eq(JustAuthSocial::getSource, "WECHAT_ENTERPRISE")
                                .or().eq(JustAuthSocial::getSource, "WECHAT_APP"));
            }
            JustAuthSocial justAuthSocial = justAuthSocialService.getOne(socialLambdaQueryWrapper, false);
            if (null == justAuthSocial)
            {
                weChatMiniAppLoginDTO.setUserInfoAlready(false);
                weChatMiniAppLoginDTO.setUserBindAlready(false);
                justAuthSocial = new JustAuthSocial();
                justAuthSocial.setAccessCode(session.getSessionKey());
                justAuthSocial.setOpenId(session.getOpenid());
                justAuthSocial.setUnionId(session.getUnionid());
                justAuthSocial.setSource("WECHAT_MINI_APP");
                justAuthSocialService.save(justAuthSocial);
            } else {
                justAuthSocial.setAccessCode(session.getSessionKey());
                justAuthSocialService.updateById(justAuthSocial);
            }
    
            // 将socialId进行加密返回,用于前端进行第三方登录,获取token
            DES des = new DES(Mode.CTS, Padding.PKCS5Padding, secretKey.getBytes(), secretKeySalt.getBytes());
            // 这里将source+uuid通过des加密作为key返回到前台
            String socialKey = "WECHAT_MINI_APP" + StrPool.UNDERLINE + (StringUtils.isBlank(session.getUnionid()) ? session.getOpenid() : session.getUnionid());
            // 将socialKey放入缓存,默认有效期2个小时,如果2个小时未完成验证,那么操作失效,重新获取,在system:socialLoginExpiration配置
            redisTemplate.opsForValue().set(AuthConstant.SOCIAL_VALIDATION_PREFIX + socialKey, String.valueOf(justAuthSocial.getId()), socialLoginExpiration,
                    TimeUnit.SECONDS);
            String desSocialKey = des.encryptHex(socialKey);
            weChatMiniAppLoginDTO.setBindKey(desSocialKey);
            
            // 查询是否绑定用户
            // 判断此第三方用户是否被绑定到系统用户
            Result<Object> bindResult = justAuthService.userBindQuery(justAuthSocial.getId());
            if(null != bindResult && null != bindResult.getData() && bindResult.isSuccess())
            {
                weChatMiniAppLoginDTO.setUserInfoAlready(true);
                weChatMiniAppLoginDTO.setUserBindAlready(true);
            } else {
                // 这里需要处理返回消息,前端需要根据返回是否已经绑定好的消息来判断
                weChatMiniAppLoginDTO.setUserInfoAlready(false);
                weChatMiniAppLoginDTO.setUserBindAlready(false);
            }
            return Result.data(weChatMiniAppLoginDTO);
        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            return Result.error("小程序登录失败:" + e);
        } finally {
            WxMaConfigHolder.remove();//清理ThreadLocal
        }
    }
  • 实现获取/解密微信小程序用户信息的info接口
      当微信小程序前端获取到用户授权可以获取用户信息时,微信小程序前端将加密的用户信息发送到业务后台,业务后台请求微信服务器将用户信息解密并保存到我们的第三方用户登录表内。
    /**
     * 获取用户信息接口
     */
    @ApiOperation(value = "小程序获取用户信息接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "socialKey", value = "加密的登录key,用于绑定用户", required = true, dataType="String", paramType = "query"),
            @ApiImplicitParam(name = "signature", value = "使用 sha1( rawData + sessionkey ) 得到字符串,用于校验用户信息", required = true, dataType="String", paramType = "query"),
            @ApiImplicitParam(name = "rawData", value = "不包括敏感信息的原始数据字符串,用于计算签名", required = true, dataType="String", paramType = "query"),
            @ApiImplicitParam(name = "encryptedData", value = "包括敏感数据在内的完整用户信息的加密数据", required = true, dataType="String", paramType = "query"),
            @ApiImplicitParam(name = "iv", value = "加密算法的初始向量", required = true, dataType="String", paramType = "query")
    })
    @GetMapping("/info")
    public Result<?> info(@PathVariable String appid, String socialKey,
                       String signature, String rawData, String encryptedData, String iv) {
        if (!wxMaService.switchover(appid)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
        }
    
        // 查询第三方用户信息
        JustAuthSocial justAuthSocial = this.getJustAuthSocial(socialKey);
        if (StringUtils.isBlank(justAuthSocial.getAccessCode()))
        {
            throw new BusinessException("登录状态失效,请尝试重新进入小程序");
        }
        // 用户信息校验
        if (!wxMaService.getUserService().checkUserInfo(justAuthSocial.getAccessCode(), rawData, signature)) {
            WxMaConfigHolder.remove();//清理ThreadLocal
            return Result.error("user check fAIled");
        }

        // 解密用户信息
        WxMaUserInfo userInfo = wxMaService.getUserService().getUserInfo(justAuthSocial.getAccessCode(), encryptedData, iv);
        WxMaConfigHolder.remove();//清理ThreadLocal
        justAuthSocial.setAvatar(userInfo.getAvatarUrl());
        justAuthSocial.setUnionId(userInfo.getUnionId());
        justAuthSocial.setNickname(userInfo.getNickName());
        justAuthSocialService.updateById(justAuthSocial);
        return Result.data(userInfo);
    }
  • 当在小程序前端绑定或注册账号时,可以在用户允许的前提下获取微信用户的手机号,同样,手机号和用户信息都是需要传到业务后台,然后再请求微信服务器进行解密。获取到手机号之后,业务后台根据手机号和系统用户进行匹配,如果存在,那么直接将微信账号绑定到我们业务系统的当前手机号用户。如果不存在,那么返回微信小程序不存在绑定用户的信息,由小程序前端继续进行绑定或者注册操作。
    /**
     * 获取用户绑定手机号信息
     */
    @ApiOperation(value = "小程序获取用户绑定手机号信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "socialKey", value = "加密的登录key,用于绑定用户", required = true, dataType="String", paramType = "query"),
            @ApiImplicitParam(name = "encryptedData", value = "包括敏感数据在内的完整用户信息的加密数据", required = true, dataType="String", paramType = "query"),
            @ApiImplicitParam(name = "iv", value = "加密算法的初始向量", required = true, dataType="String", paramType = "query")
    })
    @GetMapping("/phone")
    public Result<?> phone(@PathVariable String appid, String socialKey, String encryptedData, String iv) {
        if (!wxMaService.switchover(appid)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
        }
        // 查询第三方用户信息
        JustAuthSocial justAuthSocial = this.getJustAuthSocial(socialKey);
        if (StringUtils.isBlank(justAuthSocial.getAccessCode()))
        {
            throw new BusinessException("登录状态失效,请尝试重新进入小程序");
        }

        // 解密
        WxMaPhoneNumberInfo phoneNoInfo = wxMaService.getUserService().getPhoneNoInfo(justAuthSocial.getAccessCode(), encryptedData, iv);
        WxMaConfigHolder.remove();//清理ThreadLocal
        
        // 不带区号的手机,国外的手机会带区号
        String phoneNumber = phoneNoInfo.getPurePhoneNumber();
        // 查询用户是否存在,如果存在,那么直接调用绑定接口
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(User::getMobile, phoneNumber);
        User userInfo = userService.getOne(lambdaQueryWrapper);
        Long userId;
        // 判断返回信息
        if (null != userInfo && null != userInfo.getId()) {
            userId = userInfo.getId();
        }
        else {
            // 如果用户不存在,那么调用新建用户接口,并绑定
            CreateUserDTO createUserDTO = new CreateUserDTO();
            createUserDTO.setAccount(phoneNumber);
            createUserDTO.setMobile(phoneNumber);
            createUserDTO.setNickname(StringUtils.isBlank(justAuthSocial.getNickname()) ? phoneNumber : justAuthSocial.getNickname());
            createUserDTO.setPassword(StringUtils.isBlank(justAuthSocial.getUnionId()) ? justAuthSocial.getOpenId() : justAuthSocial.getUnionId());
            createUserDTO.setStatus(GitEggConstant.UserStatus.ENABLE);
            createUserDTO.setAvatar(justAuthSocial.getAvatar());
            createUserDTO.setEmail(justAuthSocial.getEmail());
            createUserDTO.setStreet(justAuthSocial.getLocation());
            createUserDTO.setComments(justAuthSocial.getRemark());
            CreateUserDTO resultUserAdd = userService.createUser(createUserDTO);
            if (null != resultUserAdd && null != resultUserAdd.getId()) {
                userId = resultUserAdd.getId();
            } else {
                // 如果添加失败,则返回失败信息
                return Result.data(resultUserAdd);
            }
        }
        // 执行绑定操作
        justAuthService.userBind(justAuthSocial.getId(), userId);
        return Result.success("账号绑定成功");
    }
  • 提供绑定当前登录账号接口,由微信小程序前端进行调用绑定
    /**
     * 绑定当前登录账号
     */
    @ApiOperation(value = "绑定当前登录账号")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "socialKey", value = "加密的登录key,用于绑定用户", required = true, dataType="String", paramType = "query")
    })
    @GetMapping("/bind")
    public Result<?> bind(@PathVariable String appid, @NotBlank String socialKey, @CurrentUser GitEggUser user) {
        if (!wxMaService.switchover(appid)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
        }
        if (null == user || (null != user && null == user.getId())) {
            throw new BusinessException("用户未登录");
        }
        // 查询第三方用户信息
        JustAuthSocial justAuthSocial = this.getJustAuthSocial(socialKey);
        if (StringUtils.isBlank(justAuthSocial.getAccessCode()))
        {
            throw new BusinessException("账号绑定失败,请尝试重新进入小程序");
        }
        // 执行绑定操作
        justAuthService.userBind(justAuthSocial.getId(), user.getId());
        return Result.success("账号绑定成功");
    }
  • 提供解绑接口,除了绑定接口外,我们系统服务应提供微信小程序解绑功能,这里实现解绑接口
    /**
     * 解绑当前登录账号
     */
    @ApiOperation(value = "解绑当前登录账号")
    @GetMapping("/unbind")
    public Result<?> unbind(@PathVariable String appid, @CurrentUser GitEggUser user) {
        if (!wxMaService.switchover(appid)) {
            throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid));
        }
        if (null == user || (null != user && null == user.getId())) {
            throw new BusinessException("用户未登录");
        }
        LambdaQueryWrapper<JustAuthSocialUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(JustAuthSocialUser::getUserId, user.getId());
        justAuthSocialUserService.remove(queryWrapper);
        return Result.success("账号解绑成功");
    }

  通过以上接口的功能,基本实现了微信小程序前端进行绑定、注册以及获取用户信息、用户手机号所需要的接口,下面来实现小程序前端具体的业务实现。

三、微信小程序授权登录、注册、绑定小程序前端功能实现。

  微信小程序前端开发有多种方式,可以使用微信小程序官方开发方式,也可以使用第三方的开发方式。因为大多数前端都会使用Vue.js开发,而mpvue可以使用开发Vue.js的方式来开发微信小程序,所以这里我们选择使用mpvue来开发微信小程序。这里不详细讲解mpvue框架的搭建过程,只详细说明微信小程序授权登录相关功能,有需要的可以参考mpvue官方文档。

1、定义微信小程序授权登录相关接口文件login.js,将我们业务后台实现的接口统一管理和调用。

  因为我们的开发框架是支持多租户的,同时也是支持多个小程序的,为了同一套后台可以支持多个微信小程序,这里选择在发布的微信小程序中配置appId,由微信小程序前端参数来确定具体的微信小程序。

import fly from '@/utils/requestWx'

// 获取用户信息
export function getOpenId (params) {
  return fly.get(`/wx/user/${params.appId}/login`, params)
}

// 获取用户信息
export function getUserInfo (params) {
  return fly.get(`/wx/user/${params.appId}/info`, params)
}

// 获取用户手机号
export function getUserPhone (params) {
  return fly.get(`/wx/user/${params.appId}/phone`, params)
}

// 绑定微信账号
export function bindWeChatUser (params) {
  return fly.get(`/wx/user/${params.appId}/bind`, params)
}

// 解绑微信账号
export function unbindWeChatUser (params) {
  return fly.get(`/wx/user/${params.appId}/unbind`)
}

// 登录
export function postToken (params) {
  return fly.post(`/oauth/token`, params)
}

// 退出登录
export function logout () {
  return fly.post(`/oauth/logout`)
}

// 获取登录用户信息
export function getLoginUserInfo () {
  return fly.get(`/system/account/user/info`)
}

2、新增login.vue授权登录页面,实现微信小程序具体授权登录、绑定、注册的操作界面。

  • 增加微信授权登录按钮
    <div class="login-btn" v-show="!showAccountLogin">
      <van-button color="#1aad19"  block open-type="getUserInfo" @getuserinfo="bindGetUserInfo" >微信授权登录</van-button>
    </div>
  • 增加微信小程序获取微信用户绑定手机号的弹出框,应微信官方要求,必须由用户点击授权之后,才能够获取用户绑定的手机号。
    <van-dialog 
      title="授权验证"
      @getphonenumber="bindGetUserPhone"
      confirm-button-open-type="getPhoneNumber"
      message="微信一键登录需要绑定您的手机号"
      :show="showUserPhoneVisible">
    </van-dialog>
  • 增加账号绑定弹出框,同样微信官方要求,获取微信用户信息,必须由用户点击授权允许,所以这里弹出框里的按钮也是微信用户同意授权获取用户信息的按钮。
    <van-dialog 
      title="账号绑定"
      @getuserinfo="bindUserInfo"
      confirm-button-open-type="getUserInfo"
      message="登录成功,是否将账号绑定到当前微信?"
      :show="showUserInfoVisible">
    </van-dialog>

3、在methods中新增微信绑定相关方法来具体实现微信小程序授权登录、绑定、注册等操作接口的调用。

  • 通过wx.login拿到code,在后台通过openId判断是否已经绑定用户,如果已绑定用户,则不需要再进行用户授权操作,直接登录.
wxLogin () {
      var that = this
      wx.login({
        success (res) {
          that.code = res.code
          const params = {
            appId: appId,
            code: res.code
          }
          getOpenId(params).then(res => {
            if (res.code === 200 && res.data) {
              const result = res.data
              mpvue.setStorageSync('openid', result.openid)
              mpvue.setStorageSync('unionid', result.unionid)
              mpvue.setStorageSync('bindKey', result.bindKey)
              mpvue.setStorageSync('userBindAlready', result.userBindAlready)
              // 1、如果绑定过,那么直接使用绑定用户登录
              // 2、如果没有绑定过,那弹出获取用户信息和获取手机号信息进行绑定
              if (result.userBindAlready) {
                const loginParams = {
                  grant_type: 'social',
                  social_key: mpvue.getStorageSync('bindKey')
                }
                postToken(loginParams).then(res => {
                  if (res.code === 200) {
                    console.log(res)
                    const data = res.data
                    mpvue.setStorageSync('token', data.token)
                    mpvue.setStorageSync('refreshToken', data.refreshToken)
                    // 获取用户信息
                    that.loginSuccess()
                  } else {
                    Toast(res.msg)
                  }
                })
              }
            } else {
              Toast(res.msg)
            }
          })
        }
      })
    },
  • 获取微信用户信息实现登陆,微信小程序接口,只允许点击按钮,用户同意后才能获取用户信息,不要直接使用wx.getUserInfo,此接口已过期,微信不再支持。
    bindGetUserInfo: function (res) {
      var that = this
      if (res.mp.detail.errMsg === 'getUserInfo:ok') {
        const userParams = {
          appId: appId,
          socialKey: mpvue.getStorageSync('bindKey'),
          signature: res.mp.detail.signature,
          rawData: res.mp.detail.rawData,
          encryptedData: res.mp.detail.encryptedData,
          iv: res.mp.detail.iv
        }
        getUserInfo(userParams).then(response => {
          const userBindAlready = mpvue.getStorageSync('userBindAlready')
          // 1、如果绑定过,那么直接使用绑定用户登录
          // 2、如果没有绑定过,那弹出获取用户信息和获取手机号信息进行绑定
          if (userBindAlready) {
            const loginParams = {
              grant_type: 'social',
              social_key: mpvue.getStorageSync('bindKey')
            }
            postToken(loginParams).then(res => {
              if (res.code === 200) {
                console.log(res)
                const data = res.data
                mpvue.setStorageSync('token', data.token)
                mpvue.setStorageSync('refreshToken', data.refreshToken)
                // 获取用户信息
                that.loginSuccess()
              } else {
                // 弹出获取手机号授权按钮
                that.showUserPhoneVisible = true
              }
            })
          } else {
            // 弹出获取手机号授权按钮
            that.showUserPhoneVisible = true
          }
        })
      } else {
        console.log('点击了拒绝')
      }
    },
  • 微信通过用户点击授权获取手机号来实现账号绑定操作,如果用户点击拒绝,那么提示用户无法绑定当前用户微信绑定的手机号,请用户继续授权。
    bindGetUserPhone (e) {
      const that = this
      if (e.mp.detail.errMsg === 'getPhoneNumber:ok') {
        console.log(e.mp.detail)
        // 写入store
        const params = {
          appId: appId,
          socialKey: mpvue.getStorageSync('bindKey'),
          encryptedData: e.mp.detail.encryptedData,
          iv: e.mp.detail.iv
        }
        getUserPhone(params).then(res => {
          if (res.code === 200) {
            console.log(res)
            const loginParams = {
              grant_type: 'social',
              social_key: mpvue.getStorageSync('bindKey')
            }
            postToken(loginParams).then(res => {
              if (res.code === 200) {
                console.log(res)
                const data = res.data
                mpvue.setStorageSync('token', data.token)
                mpvue.setStorageSync('refreshToken', data.refreshToken)
                // 获取用户信息
                that.loginSuccess()
              } else {

              }
            })
          } else {
            that.showUserPhoneVisible = false
            // 获取用户信息
            that.loginSuccess()
            Toast(res.msg)
          }
        })
      } else {
        that.showUserPhoneVisible = false
        Toast('当前拒绝授权手机号登陆,请使用账号密码登录')
      }
    },

  通过以上开发基本实现了微信小程序授权登录第三方业务系统的功能,在此基础上,注册的功能可以根据业务需求来扩展,大多数互联网业务,都会是微信小程序授权登录之后就自动注册用户。但是有些传统行业的业务,比如只有某些公司或组织内部的用户才能登录,那么是不允许微信授权登录就自助注册成系统用户的。微信小程序前端框架也可以归根据自己的需求,及擅长的开发方式来选择,但是微信授权登录的流程是不变的,可以在此基础上根据业务需求修改优化。



Tags:微信小程序   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
2024年微信小程序分账全攻略:对接流程详解,轻松实现资金分配
在微信小程序运营中,分账功能对于实现多方收益分配、优化资金流转至关重要。那么,微信小程序如何分账?又有哪些对接流程呢?跟着小编去看看吧!一、微信小程序分账概述微信小程序分...【详细内容】
2024-03-15  Search: 微信小程序  点击:(17)  评论:(0)  加入收藏
一段微信小程序前端与后端连接的代码,带注解
微信小程序的前端和后端连接通常涉及到使用微信小程序提供的网络请求API与后端服务器进行通信。以下是一个简单的示例,展示如何使用微信小程序的前端代码向后端发送请求并处...【详细内容】
2024-01-24  Search: 微信小程序  点击:(55)  评论:(0)  加入收藏
一文了解什么是微信小程序
如果您无需下载和管理即可获得像原生 iOS 或 Android APP 一样流畅的体验会怎样?腾讯通过微信小程序实现了这一替代方案。一、什么是微信小程序?它们与原生应用程序和 H5 迷你...【详细内容】
2023-12-26  Search: 微信小程序  点击:(90)  评论:(0)  加入收藏
微信小程序的编译原理
2021年来,随着科技的进步,人们的生活水平也在不断提高。现在,微信小程序已经成为了现代人生活中不可或缺的一部分,它可以帮助我们更方便地查找信息,购物,预订机票和酒店,进行社交等...【详细内容】
2023-12-06  Search: 微信小程序  点击:(126)  评论:(0)  加入收藏
微信小程序怎么开发?
微信小程序是一种基于微信平台的轻量级应用程序,它具有无需下载安装、即用即走的特点,为用户提供了更加便捷的使用体验。作为专业人士,我认为微信小程序的开发具有很大的潜力和...【详细内容】
2023-11-15  Search: 微信小程序  点击:(313)  评论:(0)  加入收藏
16个优秀的开源微信小程序项目,接单赚钱利器!
对于国内互联网ToC应用来说,微信小程序是一个能够快速上线,又便于运营的平台。所以很多创业项目一开始都喜欢先支持小程序。本文主要收集了一些评价比较好的开源小程序,包括:框...【详细内容】
2023-11-10  Search: 微信小程序  点击:(272)  评论:(0)  加入收藏
想要微信小程序+Uniapp?XBoot开源项目助你快速开发!
大家好,我是墨林,今天给大家推荐一款基于Spring Boot 2.x开发的微信小程序平台项目:XBoot。前言随着当前互联网技术的不断发展,前后端分离的开发模式越来越受到大多数开发者的欢...【详细内容】
2023-11-08  Search: 微信小程序  点击:(259)  评论:(0)  加入收藏
微信小程序排名优化,从这几点做起
微信小程序作为一个新兴的移动平台,受到越来越多用户和开发者的关注。但由于小程序的数量激增,想要在竞争激烈的市场占有一席之地,提高小程序的曝光量和转化率就成为每一个...【详细内容】
2023-10-30  Search: 微信小程序  点击:(282)  评论:(0)  加入收藏
涵盖微信小程序、百度小程序等,首批26家应用程序分发平台公布
2022年8月1日《移动互联网应用程序信息服务管理规定》正式实施以来,国家互联网信息办公室依法依规组织开展应用程序分发平台备案管理工作。现公开发布第一批26家应用程序分发...【详细内容】
2023-09-27  Search: 微信小程序  点击:(111)  评论:(0)  加入收藏
微信小程序推出 snapshot 生成海报组件,不用再手动绘制画布了
IT之家 9 月 14 日消息,制作过微信小程序生成海报功能的小伙伴都知道,这一功能一般是通过 canvas 画布绘制与服务端绘制 2 种方式实现,不过都需要手动编写脚本,制作起来也不是很...【详细内容】
2023-09-15  Search: 微信小程序  点击:(170)  评论:(0)  加入收藏
▌简易百科推荐
京东小程序数据中心架构设计与最佳实践
一、京东小程序是什么京东小程序平台能够提供开放、安全的产品,成为品牌开发者链接京东内部核心产品的桥梁,致力于服务每一个信任我们的外部开发者,为不同开发能力的品牌商家提...【详细内容】
2024-03-27  dbaplus社群    Tags:小程序   点击:(10)  评论:(0)  加入收藏
我们一起解锁小程序开发新姿势
如今,鸿蒙开发日益受到广大开发者的关注,而小程序开发也早已成为互联网领域的热门话题。那么,我们不禁要问:是否有可能将这两者融为一体,将小程序开发的便捷与高效带入鸿蒙生态中...【详细内容】
2024-03-20  前端充电宝  微信公众号  Tags:小程序   点击:(13)  评论:(0)  加入收藏
一段微信小程序前端与后端连接的代码,带注解
微信小程序的前端和后端连接通常涉及到使用微信小程序提供的网络请求API与后端服务器进行通信。以下是一个简单的示例,展示如何使用微信小程序的前端代码向后端发送请求并处...【详细内容】
2024-01-24    简易百科  Tags:代码   点击:(55)  评论:(0)  加入收藏
小程序必须要安装部署SSL证书吗?
自2017年9月21日,微信发布一则《关于公众平台接口不再支持HTTP方式调用的公告》。明确表示,为保证数据传输安全,提高业务安全性,公众平台不再支持HTTP方式调用。应避免影响正常...【详细内容】
2024-01-02  云诏    Tags:小程序   点击:(70)  评论:(0)  加入收藏
一文了解什么是微信小程序
如果您无需下载和管理即可获得像原生 iOS 或 Android APP 一样流畅的体验会怎样?腾讯通过微信小程序实现了这一替代方案。一、什么是微信小程序?它们与原生应用程序和 H5 迷你...【详细内容】
2023-12-26  小文智能    Tags:微信小程序   点击:(90)  评论:(0)  加入收藏
小程序开发需要多少钱?小程序开发的真实成本:报价案例、费用价格表与开发周期解析
分享一个上海客户的微信小程序定制开发的需求,销售课程与相关商品。项目分为后台管理系统和小程序前端,功能不是太复杂,周期大概1个月,费用3万。大家可能比较关心几个地方,比如一...【详细内容】
2023-12-11  久码小程序开发  今日头条  Tags:小程序   点击:(113)  评论:(0)  加入收藏
小程序技术分享:安全机制与运行机制
小程序凭借其高曝光率、开发成本低、运行更流畅等优势和特点,一经推出就被广泛使用,面对小程序的火爆,自然而然地,就有很多开发者转战小程序领域,本文主要带大家了解下小程序运行...【详细内容】
2023-12-07  前端实习生Findan    Tags:小程序   点击:(138)  评论:(0)  加入收藏
微信小程序的编译原理
2021年来,随着科技的进步,人们的生活水平也在不断提高。现在,微信小程序已经成为了现代人生活中不可或缺的一部分,它可以帮助我们更方便地查找信息,购物,预订机票和酒店,进行社交等...【详细内容】
2023-12-06  前端实习生Findan    Tags:小程序   点击:(126)  评论:(0)  加入收藏
模板小程序和订制开发小程序的区别?
相比外卖APP,外卖小程序是不用下载到手机的,所以对于用户来说更方便一点。简单方便的程序用户才更愿意使用。现在不少商家越来越重视外卖小程序开发,想通过外卖小程序冲进这片...【详细内容】
2023-11-24  重庆洺宸传媒    Tags:小程序   点击:(232)  评论:(0)  加入收藏
一分钟学会用宝塔面板搭建小程序
宝塔面板搭建小程序怎样用?想要使用宝塔面板搭建小程序?这里是实用教程,帮助您快速上手。在本教程中,我们将扼要了解宝塔面板的基础知识,并一步步演示怎么搭建一个小程序。第一步...【详细内容】
2023-11-15    网络  Tags:小程序   点击:(193)  评论:(0)  加入收藏
站内最新
站内热门
站内头条