起步

首先创建一个项目,我们采用uni-app来作为我们的前端框架

vue-cli
npm install -g @vue/cli

使用正式版(对应HBuilderX最新正式版)

vue create -p dcloudio/uni-preset-vue my-project

在安装过程中选择默认版本即可

启动

安装完成后按照提示进入我们的项目根目录下执行启动命令

npm run serve

启动成功图

申请测试号

官方文档

申请测试公众号

这里我们本地学习,所以可以申请一个测试哈,方便我们快速了解微信相关配置。在实际开发中我们会将我们的网站配置在真正的公众号中。

1.首先登录微信公众平台,选择一个公众号登录,第一次登录时可能没有公众号,我们可以申请注册一个订阅号即可。

登录进来后点击下图标示菜单可以申请一个测试号

点击之后我要求我们登录,我们扫码登录一下即可,然后可以看到如下界面

appIDappsecret接口配置信息S接口安全域名

配置授权回调页面域名

在测试号管理页面往下滑可以看到下面的配置项

设置我们项目的启动地址,由于是测试号,所以这里可以配置IP地址

注意:测试号可以配置ip地址,正式号只能配置域名

给测试号配置菜单 

安装axiox

npm install axios --save

获取AccessToken

AccessToken
GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

请求如下接口获取Access token,这个Access token有7200秒的有效期,并且接口每天限制2000次请求,所以一般由后端去请求该接口并保存起来,并且设置定时刷新。但是由于现在学习阶段,所以我们前端可以直接请求

src\util\getTonken.js
import http from "axios"
const APPID = "这里替换成测试号的APPID"
const APPSECRET = "这里替换成测试号的APPSECRET"


// 更新tonken
function updateToken() {
    return new Promise((resolve, reject) => {
        http.get(`/weixin/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${APPSECRET}`).then(res => {
            resolve(res.data.access_token)
        }).catch(err => {
            reject(err)
        })
    })
}

// 获取Tonken
export function getToKen() {
    return new Promise(async (resolve, reject) => {
        // 从缓存中读取token
        let stroagetoken = uni.getStorageSync('accessToken')
        // 如果缓存中有token,则直接返回缓存中的token
        if (stroagetoken) {
            console.log('缓存获取的token');
            // 返回结果
            resolve(stroagetoken)
        } else {
            // 如果缓存没有token,则走接口重新获取新的token
            let token = await updateToken()
            // 存入到缓存中
            uni.setStorageSync('accessToken', token)
            // 设置定时任务,每隔7000秒更新一次tonken
            setInterval(async () => {
                // 获取新的token
                let token = await updateToken()
                // 存入到缓存中
                uni.setStorageSync('accessToken', token)
            }, 7000000);
            console.log('接口获取的token');
            // 返回结果
            resolve(token)
        }
    })
}

请求微信地址的跨域问题

/weixinhttps://api.weixin.qq.com
vue.config.js
公众号H5页面接入微信登录流程module.exports = {
    publicPath: "./",
    devServer: {
        disableHostCheck: true, //禁用主机检查 
        proxy: {
            "/weixin": {
                target: "https://api.weixin.qq.com/",
                ws: true,
                secure: true, // 使用的是http协议则设置为false,https协议则设置为true
                changOrigin: true, //开启代理
                pathRewrite: {
                    "^/weixin": "",
                },
            }
        },
    },
};
/weixinhttps://api.weixin.qq.com/

创建菜单

接口地址

POST(请使用https协议) https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN

接口参数见官网文档

下面代码即可为测试号创建一个普通菜单

const ACCESS_TOKEN = uni.getStorageSync("accessToken");
const menuObj = {
    button: [
        {
            type: "view",
            name: "测试项目",
            url: "http://192.168.60.230:8080/",
        },
    ],
};
// 创建菜单
http.post(`/weixin/cgi-bin/menu/create?access_token=${ACCESS_TOKEN}`, menuObj).then((res) => {
    console.log(res, "创建菜单");
});

代码执行后,我们扫描测试号的二维码,即可看到配置的菜单。这里要保证我们的手机和电脑在同一个局域网下,通俗点就是连着同一个WiFi,这样我们才能在手机端点击菜单进入到我们的项目中

微信网页授权

授权步骤

引导关注者开发授权页面

redirect_uri/?code=CODE&state=STATE。

授权地址

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

参数说明

参数是否必须说明
appid公众号的唯一标识
redirect_uri授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理
response_type返回类型,请填写code
scope应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 )
state重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节
#wechat_redirect无论直接打开还是做页面302重定向时候,必须带此参数

开始编码

<view>
    <button type="info" @click="getUserInfo">获取授权</button>
</view>
data() {
    return {
        homeUrl:"http://192.168.60.230:8080/",
    };
},
methods: {
    // 点击授权按钮
    getUserInfo() {
        // 获取当前页面地址作为回调地址,并且对地址进行urlEncode处理
        let local = encodeURIComponent(this.homeUrl);
        // 获取公众号appid
        let appid = "wx2188729b190d357d";
        // 跳转到授权页面
        window.location.href =
            "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
            appid +
            "&redirect_uri=" +
            local +
            "&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
    },
}
access token

通过路径上的code获取网页授权token

获取token的接口地址

GET https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

首先我们封装一个获取路径参数的方法

getUrlCode(name) {
    return (
        decodeURIComponent(
            (new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec(
                location.href
            ) || [, ""])[1].replace(/\+/g, "%20")
        ) || null
    );
}
codetokenAPPIDAPPSECRETdata
data() {
    return {
        APPID: "wx2188729b190d357d",
        APPSECRET: "d976b0e6262b829ba003e9a24032447c",
    };
},
// 根据code获取网站授权token
getTokenFormCode(code) {
    http.get(
        `/weixin/sns/oauth2/access_tokenappid=${this.APPID}&secret=${this.APPSECRET}&code=${code}&grant_type=authorization_code`
    ).then((res) => {
        console.log(res.data.access_token,'根据code获取网站授权token');
        console.log(res.data.openid,'获取到的用户openid'); 
    });
},
onLoad
onLoad() {
    // 判断是否有code
    let weixinCode = this.getUrlCode("code");
    // 当获取到code后再调用获取token的方法
    weixinCode && this.getTokenFormCode(weixinCode);
},

拉取用户信息

scopesnsapi_userinfo

接口地址

GET https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

编写方法

// 根据网页授权token和openid获取用户基础信息
getAuthorizationInfo(token, openid) {
    http.get(`/weixin/sns/userinfo?access_token=${token}&openid=${openid}&lang=zh_CN`).then((res) => {
        console.log(res, "用户基础信息");
    });
},
getTokenFormCodetokenopenidgetAuthorizationInfo
// 根据code获取网站授权token
getTokenFormCode(code) {
    http.get(
        `/weixin/sns/oauth2/access_tokenappid=${this.APPID}&secret=${this.APPSECRET}&code=${code}&grant_type=authorization_code`
    ).then((res) => {
        const { access_token, openid } = res.data;
        this.getAuthorizationInfo(access_token, openid); 
    });
},

接口返回结果

根据接口数据展示头像和昵称

getAuthorizationInfo
// 根据code获取网站授权token
getAuthorizationInfo(token, openid) {
    http.get(`/weixin/sns/userinfo?access_token=${token}&openid=${openid}&lang=zh_CN`).then((res) => {
        // 解构赋值
        const { headimgurl, nickname } = res.data;
        this.userInfo = {
            // 用户头像
            headimgurl: headimgurl,
            // 用户微信昵称
            nickname: nickname,
        };
    });
},

在页面上展示用户信息

<view class="userInfo">
    <view>
        <image :src="userInfo.headimgurl"></image>
    </view>
    <view>{{ userInfo.nickname }}</view>
</view>

效果展示