小兔鲜儿 - 微信登录

2023-10-30

目录

微信登录​

登录方式

静态结构​

获取登录凭证​

获取手机号码​

微信登录接口(生产环境) 

模拟手机登录(开发环境)

用户信息持久化存储​


涉及知识点:微信授权登录,文件上传,Store 状态管理等。

微信登录

微信小程序的开放能力,允许开发者获取微信用户的基本信息(昵称、性别、手机号码等),开发者常用来实现注册/登录的功能。

登录方式

常见登录/注册方式:

  1. 用户名/手机号 + 密码
  2. 手机号 + 验证码
  3. 授权登录

实际开发过程中常常需要实现以上的一种或多种方式,我们的项目主要实现授权登录

微信授权登录

用户在使用小程序时,其实已登录微信,其本质上就是:微信授权给小程序读取微信用户信息

开放接口 / 登录 / wx.login (qq.com)icon-default.png?t=N7T8https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html

开放能力 / 用户信息 / 手机号快速验证组件 (qq.com)icon-default.png?t=N7T8https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html

传统登录方式

传统登录方式,一般是通过输入密码或者手机验证码实现登录。

 温馨提示:接口文档中提供练习使用的登录接口,大家可在课后自行完成。

静态结构

登录页

// src/pages/login/login.vue

<script setup lang="ts">
//
</script>

<template>
  <view class="viewport">
    <view class="logo">
      <image
        src="https://pcapi-xiaotuxian-front-devtest.itheima.net/miniapp/images/logo_icon.png"
      ></image>
    </view>
    <view class="login">
      <!-- 网页端表单登录 -->
      <!-- <input class="input" type="text" placeholder="请输入用户名/手机号码" /> -->
      <!-- <input class="input" type="text" password placeholder="请输入密码" /> -->
      <!-- <button class="button phone">登录</button> -->

      <!-- 小程序端授权登录 -->
      <button class="button phone">
        <text class="icon icon-phone"></text>
        手机号快捷登录
      </button>
      <view class="extra">
        <view class="caption">
          <text>其他登录方式</text>
        </view>
        <view class="options">
          <!-- 通用模拟登录 -->
          <button>
            <text class="icon icon-phone">模拟快捷登录</text>
          </button>
        </view>
      </view>
      <view class="tips">登录/注册即视为你同意《服务条款》和《小兔鲜儿隐私协议》</view>
    </view>
  </view>
</template>

<style lang="scss">
page {
  height: 100%;
}

.viewport {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 20rpx 40rpx;
}

.logo {
  flex: 1;
  text-align: center;
  image {
    width: 220rpx;
    height: 220rpx;
    margin-top: 15vh;
  }
}

.login {
  display: flex;
  flex-direction: column;
  height: 60vh;
  padding: 40rpx 20rpx 20rpx;

  .input {
    width: 100%;
    height: 80rpx;
    font-size: 28rpx;
    border-radius: 72rpx;
    border: 1px solid #ddd;
    padding-left: 30rpx;
    margin-bottom: 20rpx;
  }

  .button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 80rpx;
    font-size: 28rpx;
    border-radius: 72rpx;
    color: #fff;
    .icon {
      font-size: 40rpx;
      margin-right: 6rpx;
    }
  }

  .phone {
    background-color: #28bb9c;
  }

  .wechat {
    background-color: #06c05f;
  }

  .extra {
    flex: 1;
    padding: 70rpx 70rpx 0;
    .caption {
      width: 440rpx;
      line-height: 1;
      border-top: 1rpx solid #ddd;
      font-size: 26rpx;
      color: #999;
      position: relative;
      text {
        transform: translate(-40%);
        background-color: #fff;
        position: absolute;
        top: -12rpx;
        left: 50%;
      }
    }

    .options {
      display: flex;
      justify-content: center;
      align-items: center;
      margin-top: 70rpx;
      button {
        padding: 0;
        background-color: transparent;
      }
    }

    .icon {
      font-size: 24rpx;
      color: #444;
      display: flex;
      flex-direction: column;
      align-items: center;

      &::before {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 80rpx;
        height: 80rpx;
        margin-bottom: 6rpx;
        font-size: 40rpx;
        border: 1rpx solid #444;
        border-radius: 50%;
      }
    }
    .icon-weixin::before {
      border-color: #06c05f;
      color: #06c05f;
    }
  }
}

.tips {
  position: absolute;
  bottom: 80rpx;
  left: 20rpx;
  right: 20rpx;
  font-size: 22rpx;
  color: #999;
  text-align: center;
}
</style>

获取登录凭证

前端:调用 wx.login() 接口获取登录凭证(code)。

后端:通过凭证(code)向微信服务器换取用户登录态信息。

<script setup lang="ts">
import { onLoad } from '@dcloudio/uni-app'

// 获取 code 登录凭证
let code = ''
onLoad(async () => {
  const res = await wx.login()
  code = res.code
})
</script>

注意

code 的获取不要在 getphonenumber 事件回调函数调用,否则可能会出现错误!!!

温馨提示

用户登录态信息,不包含用户昵称、性别、手机号码等信息,作用是用于后端服务器与微信服务器通讯

获取手机号码

出于安全限制,小程序【规定】想获取用户的手机号,必须由用户主动【点击按钮】并【允许申请】才可获取加密的手机号信息。

前端:提供 open-type 按钮,在事件处理函数中获取加密的手机号信息。

后端:解密手机号信息,把手机号和用户登录态关联在一起。

<script setup lang="ts">
// 获取用户手机号码
const onGetphonenumber: UniHelper.ButtonOnGetphonenumber = (ev) => {
  console.log(ev)
}
</script>

<template>
  <view class="viewport">
    <view class="login">
      <button class="button phone" open-type="getPhoneNumber" @getphonenumber="onGetphonenumber">
        <text class="icon icon-phone"></text>
        手机号快捷登录
      </button>
    </view>
  </view>
</template>

常见问题:

Q:为什么我无法唤起获取手机号的界面?

A:获取手机号功能目前针对非个人开发者,所以个人开发者无法唤起获取手机号界面,详见文档

为方便开发者开发和体验小程序、小游戏的各种能力,开发者可以申请小程序或小游戏的 测试号,并使用此帐号在开发者工具创建项目进行开发测试,以及真机预览体验。申请测试号的过程非常简单。只需访问 申请地址 ,并使用微信扫描二维码,即可获得为自己分配好的小程序和小游戏测试账号。

项目提供了模拟登录 API 用于练习。

微信登录接口(生产环境) 

接口调用

接口地址:/login/wxMin

请求方式:POST

请求参数:

Body

字段名称 是否必须 默认值 备注
code wx.login 获取
iv getphonenumber 事件回调获取
encryptedData getphonenumber 事件回调获取
// src/services/login.ts

import type { LoginResult } from '@/types/member'
import { http } from '@/utils/http'

type LoginParams = {
  code: string
  encryptedData: string
  iv: string
}
/**
 * 小程序登录
 * @param data 请求参数
 */
export const postLoginWxMinAPI = (data: LoginParams) => {
  return http<LoginResult>({
    method: 'POST',
    url: '/login/wxMin',
    data,
  })
}

 类型声明

// src/types/member.d.ts

/** 小程序登录 登录用户信息 */
export type LoginResult = {
  /** 用户ID */
  id: number
  /** 头像  */
  avatar: string
  /** 账户名  */
  account: string
  /** 昵称 */
  nickname?: string
  /** 手机号 */
  mobile: string
  /** 登录凭证 */
  token: string
}

参考代码

小兔鲜儿项目采用常见的 登录凭证 + 手机号 实现授权登录。

// src/pages/login/login.vue

<script setup lang="ts">
import { postLoginWxMinAPI } from '@/services/login'
import { onLoad } from '@dcloudio/uni-app'

// 获取 code 登录凭证
let code = ''
onLoad(async () => {
  const res = await wx.login()
  code = res.code
})

// 获取用户手机号码
const onGetphonenumber: UniHelper.ButtonOnGetphonenumber = async (ev) => {
  // 获取参数
  const encryptedData = ev.detail.encryptedData!
  const iv = ev.detail.iv!
  // 登录请求
  await postLoginWxMinAPI({ code, encryptedData, iv })
  // 成功提示
  uni.showToast({ icon: 'none', title: '登录成功' })
}
</script>

<template>
  <view class="viewport">
    <view class="login">
      <button class="button phone" open-type="getPhoneNumber" @getphonenumber="onGetphonenumber">
        <text class="icon icon-phone"></text>
        手机号快捷登录
      </button>
    </view>
  </view>
</template>

模拟手机登录(开发环境)

获取手机号功能,目前针对非个人开发者,且完成了认证的小程序开放详见文档

温馨提示

为了更好实现登录后续的业务,后端提供了一个内部测试用的接口,只需要传手机号即可实现快捷登录。

请求接口

接口地址:/login/wxMin/simple

请求方式:POST

请求参数:

Body

字段名称 是否必须 默认值 备注
phoneNumber 模拟的手机号

该接口跟微信登录接口返回的数据格式是相同的。

/**
 * 小程序登录_内测版
 * @param phoneNumber 模拟手机号码
 */
export const postLoginWxMinSimpleAPI = (phoneNumber: string) => {
  return http<LoginResult>({
    method: 'POST',
    url: '/login/wxMin/simple',
    data: {
      phoneNumber,
    },
  })
}

 参考代码

 <button @tap="onGetphonenumberSimple">
   <text class="icon icon-phone">模拟快捷登录</text>
 </button>
const onGetphonenumberSimple = async () => {
  const res = await postLoginWxMinSimpleAPI("13123456789");
  console.log(res);
  uni.showToast({ icon: "success", title: "登录成功" });
};

用户信息持久化存储

Pinia 的持久化存储插件在 项目起步 模块已经搭建完成,现在只需要在用户登录成功后,补充 TS 类型声明并保存用户信息即可。

参考代码

Store

// src/stores/modules/member.ts

import type { LoginResult } from '@/types/member'
import { defineStore } from 'pinia'
import { ref } from 'vue'

// 定义 Store
export const useMemberStore = defineStore(
  'member',
  () => {
    // 会员信息
    const profile = ref<LoginResult>() 

    // 保存会员信息,登录时使用
    const setProfile = (val: LoginResult) => {
      profile.value = val
    }

    // 清理会员信息,退出时使用
    const clearProfile = () => {
      profile.value = undefined
    }

    // 记得 return
    return { profile, setProfile, clearProfile }
  },
  {
    // 小程序端配置
    persist: {
      storage: {
        getItem(key) {
          return uni.getStorageSync(key)
        },
        setItem(key, value) {
          uni.setStorageSync(key, value)
        },
      },
    },
  },
)

 登录页

<script setup lang="ts">
import { postLoginWxMinAPI, postLoginWxMinSimpleAPI } from '@/services/login'
import { useMemberStore } from '@/stores'
import type { LoginResult } from '@/types/member'
import { onLoad } from '@dcloudio/uni-app'

// 获取 code 登录凭证
let code = ''
onLoad(async () => {
  const res = await wx.login()
  code = res.code
})

// 获取用户手机号码(企业中写法)
const onGetphonenumber: UniHelper.ButtonOnGetphonenumber = async (ev) => {
  const encryptedData = ev.detail.encryptedData!
  const iv = ev.detail.iv!
  const res = await postLoginWxMinAPI({ code, encryptedData, iv })
  loginSuccess(res.result)
}

// 模拟手机号码快捷登录(开发练习)
const onGetphonenumberSimple = async () => {
  const res = await postLoginWxMinSimpleAPI('13123456789')
  loginSuccess(res.result)
}

const loginSuccess = (profile: LoginResult) => {
  // 保存会员信息
  const memberStore = useMemberStore() 
  memberStore.setProfile(profile) 
  // 成功提示
  uni.showToast({ icon: 'success', title: '登录成功' })
  setTimeout(() => {
    // 页面跳转
    uni.switchTab({ url: '/pages/my/my' })
  }, 500)
}
</script>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

小兔鲜儿 - 微信登录 的相关文章

  • 微信小游戏使用three.js开发总结2023.9.12

    微信小程序开发总结 1技术选择 我这里使用的是three js 进行的开发 目前开发了 酒馆卡牌 3D决对 两款微信小游戏 其中 酒馆卡牌 模仿的是iphone 美区的游戏 注重看在游戏没有复杂的战斗 在没有服务器的情况下依旧可以运行 由于
  • 微信收付通V3支付

  • 手把手接入【微信测试公众号】,不会还有人不会调试公众号吧?

    仅使用微信的测试公众号 Java开发内容 遇错与参考 Java接入测试微信公众号调试流程 前提 创建并配置测试号 登陆注册微信测试公众号 沙箱 微信验签 免登授权获取用户信息 微信接口调试工具的使用 创建服务号菜单 常见错误 invalid
  • 微信接口开发报错invalid credential, access_token is invalid or not latest hint

    微信接口凭证access token一定要全局管理 我们的查酒后台集成了微信公众平台的客服API接口 不用登录微信公众号的后台就可以直接给用户发送消息 最近 运营的同事反馈 通过微信查酒 后台无法直接给用户推送微信消息了 起初 我也没在意
  • 小程序跳转:云开发H5跳转小程序的坑,微信可跳,H5无法跳

    目录 问题描述 原因分析 解决方案 更多前端知识 问题描述 本文适合小白交流 首次利用小程序云开发 将遇到的坑记录一下 我也是在论坛搜到很些人遇到类似问题 但是并没有正解 连官方的人都不知道开发者错在哪一步 其实是小白开发者进入了误区 后续
  • 微信小程序--苹果机型日期格式错误new Date(日期)显示Invina Date

    开发小程序有关日历显示的时候 在使用 new Date 2023 02 15 的页面上 安卓和开发者工具可以正常显示 但是苹果系统无法正常显示 看了一下真机调试 显示Invina Date 于是去看了一下这个 new Date 这个api在
  • 微信小程序open-data组件功能调整

    这里我开源了一个微信小程序的案例 https gitee com xiaoshixiaoran wechat applet 相关后台接口我会有空用SSM重写一遍再挂上去 由于微信小程序官网在2021 12 27号发布了组件功能调整 原来的获
  • vue3 + router-view + keepalive parentComponent.ctx.deactivate is not a function

    vue3中keepAlive的用法与vue2中存在区别 vue3中的用法
  • 微信公众号实现微信支付(含前后端完整代码)

    刚做完公众号微信支付 记录一下 获取微信支付之前 要先获取用户的基本信息哦 前端使用uniapp开发的H5 小伙伴们可以照着改一下对应语法 首先来个微信支付的工具类 wxApi js 这里我放到了项目下的common目录下 代码如下 微信
  • H5微信分享记录

    最近做H5微信分享 用的微信jssdk来做 现记录下一些过程和遇到的问题 一 公众号配置 微信官方文档 已经说明了使用步骤 公众号配置比较模糊 主要是要配置ip白名单和绑定js接口安全域名 1 检查分享接口权限是否已获得 在微信公众号的 设
  • 微信支付商家转账到零钱功能使用教程

    之前的 企业付款到零钱 功能 微信支付已下架 以后用 商家转账到零钱 功能取代 下面介绍如何开通并使用该功能 从运营账户支出 首先需要先去了解一下微信支付的这3个账户的关系 商家转账到零钱 功能 是从运营账户转账给用户的 开通 商家转账到零
  • 小程序实现微信登录Java后端(一)--前端实现

    目录 一 概述 二 登录流程 三 前端代码 四 解读前端代码 1 登录部分 2 检查当前用户是否已登录 3 小程序启动时校验登录 五 阶段性小结 一 概述 最近终于有时间去搞一下准备参加比赛的小程序 小程序一开始设计的是使用邮箱登录 老师建
  • 微信扫码登录修改二维码的样式

    默认是这个样子二维码都没有展示全 微信的了的 js 对象是这个样子 既然大家看到我这篇文章 想必里面的属性已经知道了 这里不做赘述 let href data text css base64 LmltcG93ZXJCb3ggLnFyY29k
  • 测试用例:微信发红包测试用例(最新版)

    测试 核心 重点 功能 界面 安全性 易用性 兼容性 性能 一 功能测试 1 一对一红包 一对一发出去的红包自己不能领取 一对一红包金额 最多200 2 群发红包 1 拼手气红包 1 是否可以正常选择拼手气红包 2 红包个数 只能是数字 且
  • 【计算机毕设文章】微信点餐小程序

    微信点餐小程序 摘 要 随着社会的发展 社会的方方面面都在利用信息化时代的优势 互联网的优势和普及使得各种系统的开发成为必需 本文以实际运用为开发背景 运用软件工程原理和开发方法 它主要是采用java语言技术和mysql数据库来完成对系统的
  • 微信支付 二维码生成 域名穿透 封装 如何实现 看这篇就够了!

    微信支付 扫码支付 微信扫码支付介绍 具体参考 官方文档 微信扫码支付流程 总结我们接下来要做的事情 调用下单接口 获取code url 根据code url生成二维码 查询订单的支付状态 统一下单 核心对象创建 1 添加依赖
  • 办公自动化-邮件通知和微信通知

    在工作中 或者学习中或者生活上等 需要定时提醒自己或其他人 处理一些待办任务事项 需要发邮件通知下 同时可能会要求发送文件之类的事情 由于现在大家微信使用频率最高 所以能发送微信通知消息 效果更好 同时开通下微信通知功能 第一步 邮件通知工
  • 微信getAccessToken限制问题

    微信getAccessToken限制问题 错误代码 45009 错误信息 调用分钟频率受限 https developers weixin qq com miniprogram dev OpenApiDoc mp access token
  • 1-创建小程序项目

    注册 打开https mp weixin qq com 点击 立即注册 选择小程序 获取APPID 登录小程序在 开发管理 gt 开发设置 获取 APPID 开发工具 登录小程序在 开发工具 gt 开发者工具 获取 微信开发者工具 创建小程
  • 微信怎么申请小程序商城?一步步教你完成

    随着移动互联网的发展 越来越多的企业和个人开始关注微信小程序 微信小程序是一种不需要下载安装即可使用的应用 它实现了应用 触手可及 的梦想 用户扫一扫或者搜一下就能打开应用 其中 小程序商城因其便捷性和实用性 受到了众多商家的青睐 那么 如

随机推荐

  • comsol 多物理场仿真流程-以开关柜为例

    1 主要方法 在SolidWorks中对于开关柜的内部与外部结构进行建模 生成能够导入软件计算的3D模型 将SolidWorks中的模型导入comsol软件中 设置参数进行多物理场耦合仿真 1 具体步骤 删除高压开关柜中对其内部电磁环境无较
  • 如何使用Qt软件实现一个圆形按钮

    要使用Qt软件实现一个圆形按钮 可以按照以下步骤进行操作 使用以上步骤 你就可以在Qt软件中实现一个圆形按钮 记得根据自己的需要调整按钮的样式和布局 在Qt的项目中创建一个新的QPushButton控件 或者使用现有的QPushButton
  • JAVA实现CSV文件转List

    首先来说说解决问题的思路 先创建一个类Test来接收csv文件中的内容 然后通过解析csv文件 讲内容转换为List
  • 今天给一个shopify网站修改了一下

    今天的客户是浙江的 他们没有设计稿 给了我一个需要模仿的网站 要求是把自己的商品详情页搞成和对标网站一样的 这个事情两天给搞定了 他们很满意 对标网站是一个卖狗粮的 他们是卖玩具的 哈哈 但是因为没有设计稿 修修补补了很多地方 还要求在页面
  • 装载问题(回溯法)

    1 具体问题 一批集装箱共n个要装上2艘载重量分别为c1和c2的轮船 其中集装箱i的重量为Wi且W1 W2 Wn lt c1 c2 试确定一个合理的装载方案使这n个集装箱装上这两艘轮船 2 问题分析 容易去证明 如果一个装载问题有解 则采用
  • 什么软件做可视化大屏最简单、最快?

    做可视化大屏的工具有很多 但要说什么软件做可视化大屏最简单 最快 那必然是BI系统 特别是国产BI系统奥威BI 奥威BI系统能提供大量的模板功能 精简操作 提高效率 而且采用的是零编程 即点击 拖拉拽这样的方式来制作报表 使用门槛低 即使是
  • ros1 bag to ros2 bag play

    有个问题是 ros1格式的bag需要转到ros2格式的bag 怎么弄 需要注意的是 这里只能提供标准信息的rosbag转换 如果带有自定义msg的rosbag 应该是不可以的 请注意一下 解决办法 安装依赖 sudo apt install
  • 【IDEA】对于IDEA出现程序包无法找到或者js代码无法加载问题的6种解决方案

    前言 在平时做项目时 我们有时候会出现各种奇奇怪怪的bug 标题所列举的这两种情况我都遇到过 搜的博客解决方案也很多都是一样的 今天我就给大家汇总一下解决方案 一 如果你是使用maven管理项目 在idea右上角能够看到Maven 点击Ma
  • java 比较两个类_Java 中有没有直接可以判断两个类是否相同的方法?

    展开全部 java没有直接判e5a48de588b662616964757a686964616f31333337623436断两个雷是否相同 但提供了如下方法 1 如果说两个对象的判断可以使用 equals 或者 2 如果判断对象是否某个类
  • JVM知识点(二)

    1 G1垃圾收集器 XX MaxGCPauseMillis 10 G1的参数 表示在任意1s时间内 停顿时间不能超过10ms G1将堆切分成很多小堆区 Region 每一个Region可以是Eden Survivor或Old区 这些区在内存
  • 三种memcached的JAVA客户端比较

    Memcached客户端程序 Memcached的java客户端已经存在三种了 官方提供的基于传统阻塞io由Greg Whalin维护的客户端 DustinSallings实现的基于java nio的Spymemcached XMemcac
  • Python3,我用这种方式讲解python模块,80岁的奶奶都说能理解。建议收藏 ~ ~

    Python模块讲解 1 引言 2 python模块详解 2 1 含义 2 2 代码示例 2 3 进阶 3 总结 1 引言 小屌丝 鱼哥 你看天上的月亮越来越圆了 小鱼 唉 又是一年团圆夜 又是一年中秋节 小屌丝 嘿嘿 可不滴 这个中秋 你
  • GIT error: object file is empty?

    how to fix GIT error object file is empty 前几天在使用git status 产生了一个错误 经过多方搜索 找到一篇文章 现简述一下大意 原文 开始 当我尝试提交一个修改时 我得到了一个错误 erro
  • Servlet 规范和 Servlet 容器

    如果大家觉得文章有错误内容 欢迎留言或者私信讨论 前引 通过之前的学习我们知道浏览器发给服务器的 HTTP 请求在服务器端需要调用服务端的程序来处理 也就是我们写的 Java 类 一般来说不同请求对应不同的 Java 类 那么问题来了 HT
  • 解决vue中样式不起作用:样式穿透/深度选择器(/deep/)

    项目场景 提示 这里简述项目相关背景 解决vue中样式不起作用 样式穿透 深度选择器 deep 原因分析 提示 这里填写问题的分析 原因1 组件内部使用组件 添加了scoped属性 原因2 动态引入html 也添加了scoped属性 原因3
  • 工作中PTO和OOO是什么意思?

    PTO paid time off 带薪休假 其实就是我们所说的请年假 OOO out of office 就是字面意思 不在办公室 推荐一篇商务英文缩写介绍 ASAP OOO FYI 你都看得懂嗎 步入職場 一定要會的50個 商用縮寫
  • UE4(一)- 源码分析起点

    06 21 2020 UE4源码分析的起点 UE4文件结构 UE4 Editor UE4 C 项目文件夹结构 UE4 源码分析的起点 项目中的main函数 UObject 继承树 1 Gameplay类 Objects Actors Com
  • Nodejs开发(二)-项目打包和运行

    在Nodejs开发 一 Windows搭建Node环境搭建nodejs环境之后 接着进行项目的打包和运行 1 npm run build prod 首先管理员方式打开cmd 然后cd到项目所在文件夹 执行命令npm run build pr
  • NOKIA 刷机 6680

    使用NOKIA最新的PC套件6 82版可以在线刷机了 必须为6 82版 下载地址 http nds1 nokia com files support global phones software Nokia PC Suite 682 rel
  • 小兔鲜儿 - 微信登录

    目录 微信登录 登录方式 静态结构 获取登录凭证 获取手机号码 微信登录接口 生产环境 模拟手机登录 开发环境 用户信息持久化存储 涉及知识点 微信授权登录 文件上传 Store 状态管理等 微信登录 微信小程序的开放能力 允许开发者获取微