微信JSSDK,就是网页中通过微信提供的JS接口,调取微信客户端一些功能,比如位置、相机等等,我相信使用最多的还是分享了。
说个题外话,很多人看到朋友圈的链接,点进去有的是公众号,有的是网页,公众号自然不用说,自带分享分享的,而网页分享则必须自定义分享文字、图片了,而且网页分享必须通过扫码的形式进入页面,才能分享,如果是直接点击url链接进去的,是无法分享的(分享后也仅仅是一串链接)
首先公众号后台配置域名,很简单,根据文档来就行。
之后安装,因为我是ts项目,所以安装ts版本,版本中部分属性与现在微信sdk有一丢丢变化,所以实际开发中,发现类型不匹配,记得改一下接口类型就行。
npm i weixin-js-sdk-ts
官方文档可以看到,config中需要以下属性,其中debug和jsApiList应该直接在前端填入,根据实际情况写入需要调用的jsApiList接口,而其他几个属性应该由后端返回,因为涉及到获取access_token。
wx.config({
debug: true, //
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的 JS 接口列表
});
那么我们先实现后端,以下都是后端代码,nodejs实现
1,获取access_token,就根据appid和appsecret获取,本地建议建立缓存,不要每次都去微信请求
/**
* 获取access_token,如果超过缓存时间则从新请求微信api获取,否则直接返回缓存的数据
*/
export const getAccessToken = async () => {
const iat = global.CONFIG.WX.Access_Token_Iat
const express = global.CONFIG.WX.Access_Token_Expires_In
const access_token = global.CONFIG.WX.Access_Token
if (!iat || !express || !access_token || Date.now() > (iat + express * 1000)) {
const url = `https://api.weixin.qq.com/cgi-bin/token?
grant_type=client_credential
&appid=${global.CONFIG.WX.AppID}
&secret=${global.CONFIG.WX.AppSecret}`
const result: IAccessToken = (await axios.post(url)).data
global.CONFIG.WX.Access_Token_Expires_In = result.expires_in
global.CONFIG.WX.Access_Token_Iat = Date.now()
global.CONFIG.WX.Access_Token = result.access_token
return result.access_token
}
else {
return access_token
}
}
2,利用access_token换取jsapi_ticket凭证,同样建议本地缓存。
/**
* 获得jsapi_ticket凭证
* @param access_token
* @returns
*/
const getTicket = async (access_token: string) => {
const iat = global.CONFIG.WX.Jsapi_Ticket_Iat
const expires = global.CONFIG.WX.Jsapi_Ticket_Expires_In
const jsapi_ticket = global.CONFIG.WX.Jsapi_Ticket
if (!iat || !expires || !jsapi_ticket || Date.now() > (iat + expires * 1000)) {
const ticketurl = `https://api.weixin.qq.com/cgi-bin/ticket/getticket?
access_token=${access_token}&type=jsapi`
const result: IResponseTicket = (await axios.get(ticketurl)).data
global.CONFIG.WX.Jsapi_Ticket_Expires_In = result.expires_in
global.CONFIG.WX.Jsapi_Ticket_Iat = Date.now()
global.CONFIG.WX.Jsapi_Ticket = result.ticket
return result.ticket
}
else {
return jsapi_ticket
}
}
3,实现签名,通过sh1加密,此处加密需要前端传过来rul这个参数。
/**
* 实现签名
* @param jsapi_ticket
* @param url
* @returns
*/
const signature = (jsapi_ticket: string, url: string) => {
const config: JSApi_Config = {
appId: global.CONFIG.WX.AppID,
nonceStr: random(10),
timestamp: Date.now(),
signature:''
}
let string1 = `jsapi_ticket=${jsapi_ticket}`
string1 = string1 + `&noncestr=${config.nonceStr}`
string1 = string1 + `×tamp=${config.timestamp}`
string1 = string1 + `&url=${url}`
config.signature=sha1(string1)
return config
}
4,实现路由,前端请求此路由,并且需要post传递url这个参数即可。
export default async (req: IRequest, res: Response, next: NextFunction) => {
const access_token = await (getAccessToken())
const url = req.body.url
if (!url) {
return next(DataFail)
}
const ticket = await getTicket(access_token)
return next(signature(ticket,url))
}
最终后端返回的就是这样一个对象
/**
* 完成的ticketconfig
*/
export interface IJSApi_Config {
/**
* 必填,公众号的唯一标识
*/
appId: string,
/**
* 必填,生成签名的时间戳
*/
timestamp: number,
/**
* 必填,生成签名的随机串
*/
nonceStr: string,
/**
* 必填,签名必填
*/
signature: string
}
后端工作完成了,那么前端就简单多了
const result = await AJRequestTicketConfig(callback)
const config: IJSApi_Config = {
debug: false,
...result,
jsApiList: ['updateTimelineShareData', 'updateAppMessageShareData']
}
wx.config(config)
这样,前端就配置好了,然后根据实际情况,再配置updateAppMessageShareData和updateAppMessageShareData即可。