H5接入微信公众号方法(超详细)

微信官方文档

一、使用真实公众号并认证开发者,或者申请使用测试号

注意: 在微信开发者工具中调试,必须先成为公众号开发者,可以在微信公众号后台进行配置 位置: 公众号后台 > 设置与开发 > 开发者工具 > web开发者工具 > 绑定微信开发者微信号(必须先关注此公众号才能成为开发者)

二、在公众号后台配置相关信息,有两处需要填写

1. 接口配置信息

此处可不填写,这个地方的内容是发送消息时用的,如果仅是调用普通微信api,无需填写。

2. js安全域名

此处必须配置,只有此域名发出的请求才能获得微信权限

注意:域名不需要加http://或者https://,也不需要添加端口号,可以是ip地址

例:192.168.123.123;abcd.abcd.cn

三、获取微信api接口授权

为保证安全,建议获取access_token、jsapi_ticket、计算签名都由后端完成

提示:需要预先知道的数据

1. 获取access_token

使用get请求,参数有三个,分别是:grant_type、appid、secret

其中grant_type值固定为client_credential,其它两个分别为公众号的appID和appsecret

// 请求示例

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

注意:access_token有效期为7200秒

2. 获取jsapi_ticket

使用get请求,参数有两个,分别是:access_token、type

access_token是上一个接口返回的,type为固定值jsapi

// 请求示例

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

注意:jsapi_ticket有效期为7200秒

3. 签名算法

对指定字段进行sha1签名

字段分别为:jsapi_ticket(通过上面接口获取的)、noncestr(随机字符串)、timestamp(时间戳)、url(当前网页的URL,不包含#及其后面部分)

// 示例

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW×tamp=1414587457&url=http://mp.weixin.qq.com?params=value

附:sha1签名算法

export default {

methods: {

// 当前时间戳

timeStamp(data) {

return parseInt(new Date(data).getTime()) + "";

},

// 字符转义

encodeUTF8(s) {

let i,

r = [],

c,

x;

for (i = 0; i < s.length; i++)

if ((c = s.charCodeAt(i)) < 0x80) r.push(c);

else if (c < 0x800) r.push(0xc0 + ((c >> 6) & 0x1f), 0x80 + (c & 0x3f));

else {

if ((x = c ^ 0xd800) >> 10 == 0)

//对四字节UTF-16转换为Unicode

(c = (x << 10) + (s.charCodeAt(++i) ^ 0xdc00) + 0x10000), r.push(0xf0 + ((c >> 18) & 0x7), 0x80 + ((c >> 12) & 0x3f));

else r.push(0xe0 + ((c >> 12) & 0xf));

r.push(0x80 + ((c >> 6) & 0x3f), 0x80 + (c & 0x3f));

}

return r;

},

// sha1签名算法

sha1(s) {

let data = new Uint8Array(this.encodeUTF8(s));

let i, j, t;

let l = (((data.length + 8) >>> 6) << 4) + 16,

s = new Uint8Array(l << 2);

s.set(new Uint8Array(data.buffer)), (s = new Uint32Array(s.buffer));

for (t = new DataView(s.buffer), i = 0; i < l; i++) s[i] = t.getUint32(i << 2);

s[data.length >> 2] |= 0x80 << (24 - (data.length & 3) * 8);

s[l - 1] = data.length << 3;

let w = [],

f = [

function () {

return (m[1] & m[2]) | (~m[1] & m[3]);

},

function () {

return m[1] ^ m[2] ^ m[3];

},

function () {

return (m[1] & m[2]) | (m[1] & m[3]) | (m[2] & m[3]);

},

function () {

return m[1] ^ m[2] ^ m[3];

},

],

rol = function (n, c) {

return (n << c) | (n >>> (32 - c));

},

k = [1518500249, 1859775393, -1894007588, -899497514],

m = [1732584193, -271733879, null, null, -1009589776];

(m[2] = ~m[0]), (m[3] = ~m[1]);

for (i = 0; i < s.length; i += 16) {

let o = m.slice(0);

for (j = 0; j < 80; j++)

(w[j] = j < 16 ? s[i + j] : rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1)),

(t = (rol(m[0], 5) + f[(j / 20) | 0]() + m[4] + w[j] + k[(j / 20) | 0]) | 0),

(m[1] = rol(m[1], 30)),

m.pop(),

m.unshift(t);

for (j = 0; j < 5; j++) m[j] = (m[j] + o[j]) | 0;

}

t = new DataView(new Uint32Array(m).buffer);

for (let i = 0; i < 5; i++) m[i] = t.getUint32(i << 2);

let sign = Array.prototype.map

.call(new Uint8Array(new Uint32Array(m).buffer), function (e) {

return (e < 16 ? "0" : "") + e.toString(16);

})

.join("");

return sign;

},

},

};

4. 获取微信api权限

wx.config({

debug: true, // 开启调试模式

appId: '', // 必填,公众号的唯一标识

timestamp: , // 必填,生成签名的时间戳

nonceStr: '', // 必填,生成签名的随机串

signature: '',// 必填,签名

jsApiList: [] // 必填,需要使用的JS接口列表

});

5. 通过ready接口处理成功验证 注意: config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。

wx.ready(function(){

});

微信JS-SDK说明文档

6. 调用已授权的api 这一步很简单,照着微信官方文档调用就可以了

示例:

wx.ready(function(){

wx.getLocation({

type: 'wgs84', // 默认为wgs84的gps坐标,如果要返回直接给openLocation用的火星坐标,可传入'gcj02'

success: function (res) {

var latitude = res.latitude; // 纬度,浮点数,范围为90 ~ -90

var longitude = res.longitude; // 经度,浮点数,范围为180 ~ -180。

var speed = res.speed; // 速度,以米/每秒计

var accuracy = res.accuracy; // 位置精度

}

});

});