评论

微信多端应用接入华为账号登录教程

多端应用实现华为账号登录解决方案

写在前面

原生微信小程序利用多端框架生成鸿蒙APP,做了一堆的各种APP的适配,满是期待的去提审APP,初次提交鸿蒙官方审核是不会管你是否接入华为登录,但是如果你想再次提交APP更新版本,就会检查你是否接入华为账号登录,并且会引导你接入APP原生的登录能力。

目前为止多端框架还不支持鸿蒙原生插件,也没有做一键登录华为账号的适配(因为多端框架官方确实有点忙)。为了满足华为账号登录的条件,可以借助WebView + 华为账号 Web 端授权方案就能轻松搞定,这也是当前适配微信生态且能满足华为 APP 审核要求的最优实现方式,此外,即便后续微信团队推出华为账号原生登录,其配置和开发流程大概率会像苹果登录一样繁琐,而 WebView 方案轻量、易维护,现网使用完全无压力,后续也可灵活切换,是兼顾当下需求和长期维护的优选。今天就给大家带来一步到位的实操教程。


核心实现逻辑

整体流程围绕 微信多端应用跳转 WebView→加载华为账号官方授权页面→用户授权→获取授权码 code→回传微信端→服务端兑换凭证 展开,需关注华为账号登录的底层交互(不管用户是 手机号输入、一键授权、密码验证等),只需做好页面跳转和 code 的传递、解析工作,如果做过微信公众号网页授权登录就会轻松很多。逻辑如下:

  1. 微信多端应用 在用户登录页面,点击华为账号登录 跳转到 WebView 页面并加载华为账号 Web 端标准授权链接;
  2. 用户在 WebView 中完成华为 / 鸿蒙账号的登录 / 授权操作(全程由华为官方页面处理,开发者无需干预);
  3. 授权成功后,华为 OAuth 服务通过预设回调地址将授权码 code拼接在 URL 中返回至 WebView,我们需要自己再写一个接收code的页面;
  4. WebView 从回调 URL 中解析出 code,通过微信通信 API 回传至微信多端应用主程序;
  5. 微信应用将 code 传递至自身服务端,由服务端调用华为官方接口完成 code 兑换,获取 Access Token、用户信息等;
  6. 服务端解析用户信息,完成微信多端应用的华为账号登录态创建。

核心步骤及相关代码

第一步:用户选择“华为帐号”来进行登录,拼接OAuth服务请求授权的链接,跳转到webview到该请求链接,访问华为OAuth服务。华为官方文档地址: https://developer.huawei.com/consumer/cn/doc/HMSCore-Guides/web-get-access-token-0000001050048946

第二步:休息一会

第三步:做一个华为授权登录回调的页面用来接收华为授权码code ,需引入微信jssdk,并涉及到在webview里边网页向小程序发送消息,小程序webview官方文档:https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html

第三点五步:在获取到华为账号授权码code后,再次请求OAuth服务,调用https://oauth-login.cloud.huawei.com/oauth2/v3/token,通过授权码code换取Access Token、Refresh Token以及ID Token。这部分内容就不展开细说了,详细看华为官方文档,写的已经很详细了。https://developer.huawei.com/consumer/cn/doc/HMSCore-Guides/web-get-access-token-0000001050048946


小程序端代码

// webview页面
<web-view src="{{url}}" bindmessage="bindMessage"></web-view>


// webview 的 js
bindMessage(e) {
    var eventChannel = this.getOpenerEventChannel()
    eventChannel.emit('hwLoginBack', e)
  },



网页代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <title>授权登录中...</title>
  
  <!-- 1. 引入微信 JS-SDK (必须) -->
  <script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.6.2.js"></script>
  
  <style>
    /* 基础样式重置与居中布局 */
    body {
      background-color: #fff;
      margin: 0;
      height: 100vh;
      display: flex;
      align-items: center;
      justify-content: center;
      font-family: -apple-system, sans-serif;
      color: #333;
    }
    .status-text {
      font-size: 16px;
      padding: 20px;
    }
  </style>
</head>


<body>
  <div id="reqStatus" class="status-text">登录中...</div>


  <script>
    // 更新页面状态文字
    function setReqStatus(text) {
      const el = document.getElementById('reqStatus');
      if (el) el.textContent = text;
    }


    /**
     * 简易 Ajax 封装
     * 兼容性优于 fetch,确保在各种 WebView 中稳定运行
     */
    function ajax(options) {
      const xhr = new XMLHttpRequest();
      xhr.open(options.method || 'GET', options.url, true);
      xhr.timeout = options.timeout || 10000;
      xhr.setRequestHeader('Content-Type', 'application/json');


      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status === 200) {
            try {
              const res = JSON.parse(xhr.responseText);
              options.success && options.success(res);
            } catch (e) {
              options.success && options.success(xhr.responseText);
            }
          } else {
            options.error && options.error(new Error('HTTP Status: ' + xhr.status));
          }
        }
      };


      xhr.onerror = () => options.error && options.error(new Error('Network Error'));
      xhr.send(JSON.stringify(options.data || {}));
    }


    // 页面加载完成后执行主逻辑
    document.addEventListener('DOMContentLoaded', function () {
      // 2. 获取 URL 中的 code 和 state 参数
      const params = new URLSearchParams(window.location.search);
      const code = params.get('code');
      const state = params.get('state');


      if (code && state) {
        setReqStatus('正在验证身份...');
        
        // 3. 调用后端接口换取登录态
        ajax({
          url: 'https://api.your-domain.com/login/callback', // 【替换】你的真实后端接口
          method: 'POST',
          data: { code: code, state: state },
          success: function (res) {
            setReqStatus('登录成功,正在跳转...');
            
            // 4. 关键:将后端返回的数据通过 postMessage 传回小程序
            // 小程序端需在 <web-view> 组件上绑定 bindmessage 事件接收
            wx.miniProgram.postMessage({ data: res });


            // 5. 返回小程序上一页(触发 bindmessage)
            // 注意:只有在 navigateBack / redirectTo 等页面销毁/切换操作时,小程序才会收到 message
            wx.miniProgram.navigateBack({ delta: 1 });
          },
          error: function (err) {
            setReqStatus('登录失败,请重试');
            console.error('Login Error:', err);
          }
        });
      } else {
        setReqStatus('参数缺失,无法登录');
      }
    });
  </script>
</body>
</html>



如果觉得对你有帮助,欢迎点赞收藏加关注~

最后一次编辑于  02-12  
点赞 4
收藏
评论
登录 后发表内容