分享 微信 JS API 集成

hiveer · 2021年10月24日 · 236 次阅读

集成微信 JSSDK(使用微信分享的 API)

最近有个需求,就是在微信分享官网的时候,需要能定制标题,描述和 logo。

经过调查发现,微信现在不再支持通过在页面上设置图片的形式来设置 logo(亲测,经过验证),而是只能通过绑定公众号,然后通过微信的公众平台的 API 来定制这些内容。

下面就展示如何一步一步的实现这个集成:

域名绑定

首先我们需要有个域名,然后将这个域名绑定到微信公众号。这里要分两种情况:

  • 如果您使用微信提供的测试公众号进行测试

入口:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

直接用你自己的微信扫码登录即可。登录之后你会看到这样一个配置:

在这里你需要把你的域名填入,需要特别强调的是,这里需要填入的是域名而非 URL。所以,请把http://, https://以及一般在 URL 最后的反斜杠/都去掉。

特别强调,在测试账号下,域名可以没有备案,所以你可以看到我给的例子中使用的是ngrok生成的测试链接。同时测试账号下,这个域名对应的服务也不需要经过微信网页授权验证。

  • 如果是正常的公众号 你需要保证您的域名是经过备案的域名,以及您的域名对应的站点经过了微信网页授权(将微信提供的文件:MP_verify_<*>.txt 上传到域名对应的服务器,并且保证能通过域名访问到这个文件)。其余的同上!

引入 JS 文件

在需要调用 JS 接口的页面引入如下 JS 文件,(支持 https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js

引入这个文件之后,来自微信的 JS 对象wx将会全局可用,下面会看到如何使用。

权限验证

这里需要先明白我们为什么需要权限验证,以及背后的原理是怎么回事。

我们回过头看第一步所做的事情,我们把网站的域名绑定到了一个公众号。那么我们在分享这个网页的时候,如果微信发现这个网页调用了微信的 API,那么微信就需要验证,这个网页是不是跟其绑定的公众号所配置的 JS 安全与名对应的网站。如果是,微信才会响应 API 的调用,否则拒绝。

下面我们来看看权限验证的接口wx.config

wx.config({
  debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  appId: '', // 必填,公众号的唯一标识
  timestamp: , // 必填,生成签名的时间戳
  nonceStr: '', // 必填,生成签名的随机串
  signature: '',// 必填,签名
  jsApiList: [] // 必填,需要使用的JS接口列表
});

debug: true,这个只能在测试的时候开启,如果上线,请务必关掉

timestamp 这个就是一个数字字符串格式的时间戳,没有什么特别的要求,但是请务必保证和生成签名时候使用的是一致的。

nonceStr 这个就是一个随机的字符串,没有什么特别的要求,但是请务必保证和生成签名的时候使用的是一致的。

signature 这个就是签名,这里需要特别强调的是这个签名是不能在前端代码完成的,否则微信会认为其无效,具体微信怎么实现的不清楚。所以这里要分两种情况,如果你是一个正常的 web 应用,那么在后端生成签名,通过适合你的方式传递到前端,然后再调用这个接口认证。如果是静态网站,那么你只能通过一个后端的 API 来返回这个签名,然后前端通过 ajax 来调用这个 API,获取签名。我的情况就是第二种。

真正的去调用微信的 API

上一步我们只是在做权限验证,相当于找微信确认我们是否有资格调用 API,如果通过了验证,我们才会被允许调用 API。这里我们将看到如何调用 API。

微信提供了一个认证成功之后会执行的钩子函数wx.ready()

wx.ready(function(){
  // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});

所有的对 API 的调用都必须放在这个钩子函数中,否则因为权限认证接口是异步的,API 调用可能不会成功。

认证失败的处理

微信提供了一个认证失败之后会执行的钩子函数wx.error()

wx.error(function(res){
  // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});

下面我们来看看如何生成签名

生成签名,就像上面说到的,需要在后端完成。具体算法是怎么样的,我们继续看。

参与签名的字段包括 noncestr(随机字符串), 有效的 jsapi_ticket, timestamp(时间戳), url(当前网页的 URL,不包含#及其后面部分)

这里面有一个新字段我们没有聊过jsapi_ticket,这个是什么呢?它类似于一个我们日常生活中,使用到的票,火车票,电影票等。微信将jsapi_ticket视作调用微信 JS API 的票据,只有你拥有了票,你才能调用。

那么怎么获取这个票呢?

方法如下:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi,这里又多了一个新的参数access_token

access_token又是什么呢?

access_token 是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用 access_token。

这里我们可以这样理解,你去游乐园玩,你需要一个入场的票,这个就是access_token,你可以通过它玩游乐场的一些项目。但是某些特别的项目你需要单独再买票,这个就是jsapi_ticket

你可以通过下面的链接获取access_token

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

至此我们拿到了生成签名的所有参数,接下来我们需要把这些签名排个序,这个排序的规则是根据参数名字的 ASCII 码从小到大排序,就像这样:

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

最后对这个字符串进行 sha1 签名:

0f9de62fce790f9a083d5c99e95740ceb90c27ed

最后我附上完整的代码供对照理解:

function registerWechatSharingApi() {
  var url=window.location.href.split('#')[0]
  $.ajax({
    method: "get",
    url: "<后端接口返回signature>?current_site_url="+url,
    dataType: "json",
    success: function(data){
      wx.config({
        debug: false,
        appId: data.appId,
        timestamp: data.timestamp,
        nonceStr: data.noncestr,
        signature: data.signature,
        jsApiList: [
          "onMenuShareTimeline",
          "onMenuShareAppMessage",
          "onMenuShareWeibo",
          "onMenuShareQZone"
        ]
      });
    },
    error:function(data){
      console.log("Fetch WX signature failed")
    }
  });
  wx.ready(function (){
    console.log("WX config verify success")
    var shareData = {
      title: document.querySelector('title').innerText.replace(/\n|\r/g, ""),
      desc: document.querySelector("meta[name='description']").getAttribute('content'),
      link: window.location.href,
      imgUrl: "<图片的地址>"
    };
    wx.onMenuShareAppMessage(shareData);
    wx.onMenuShareTimeline(shareData);
    wx.onMenuShareWeibo(shareData);
    wx.onMenuShareQZone(shareData);
  });
  wx.error(function(res){
    console.log("WX config verify failed");
  });
}

registerWechatSharingApi()

参考文档:

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请 注册新账号