微信签名--前端实现

2020 年 07 月 24 日

admin
js

最近,在开发中遇到一个问题,需要做微信签名。但是,后端资源有限,需要前端自己实现签名算法相关逻辑,于是,将这个过程记录下来。由于是测试公众号,不保证生产上一定可以用,还需要多多测试。

公众平台测试账号

首先,注册一个公众号,个人的,企业的都可以。注册登录地址

然后,在 开发 --> 开发者工具 --> 公众平台测试账号,开通测试账号:

然后,注册或者扫码登录,进入测试号管理页面:

然后,配置 JS接口安全域名。因为,我们大多数是通过本地调试微信api接口的,所以,这里我们将本地 ip 加入进去;

然后,还需要关注测试公众号:

最后,开启相应的接口权限。微信,默认开启了大部分的权限,个别接口权限,需要单独开启:

前端签名

首先,获取 access_token。需要 appidsecret

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

结果如下:

{
    "access_token": "35_PwB3tILi1TiLCBOwh4QG3ysUOcP8HE5cluT4KCNQPOLyi5fWaahZXcRNUY6f81XYAozoXA-xXPOXOcdVdYnIbq-OWiMy_SXrSq9JZiAa5Z0BNLO5pjrAc95YQt9s7FpqmBQ8DXbnNFoTgObGRKBjACAIBS",
    "expires_in": 7200
}

然后,获取 ticket。需要上一步的 access_token

https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=35_PwB3tILi1TiLCBOwh4QG3ysUOcP8HE5cluT4KCNQPOLyi5fWaahZXcRNUY6f81XYAozoXA-xXPOXOcdVdYnIbq-OWiMy_SXrSq9JZiAa5Z0BNLO5pjrAc95YQt9s7FpqmBQ8DXbnNFoTgObGRKBjACAIBS

结果如下:

{
    "errcode": 0,
    "errmsg": "ok",
    "ticket": "LIKLckvwlJT9cWIhEQTwfJD7cCZkfgt_i8dz_EsCUpWBLqMG5-KyRVH7xnihf2-bV7SpdzHgBTzcimj8fUMGYg",
    "expires_in": 7200
}

然后,签名算法:

function sign() {
  var data = {
    noncestr: 'Wm3WZYTPz0wzccnW',
    jsapi_ticket: '',
    timestamp: '1595235986',
    url: window.location.href.split('#')[0],
  }
  data = this.objKeySort(data)
  var sha1 = this.sha1(data)
  return sha1
}

function objKeySort(arys) {
  var newkey = Object.keys(arys).sort()
  var newObj = '';
  for (var i = 0; i < newkey.length; i++)  {
    newObj += [newkey[i]] + '=' + arys[newkey[i]] + '&'
  }
  return newObj.substring(0, newObj.length - 1)
}

function encodeUTF8(s) {
  var 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
}

function sha1(s) {
  var data = new Uint8Array(this.encodeUTF8(s))
  var i, j, t
  var 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
  var 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) {
    var 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 (var i = 0; i < 5; i++) m[i] = t.getUint32(i << 2)

  var hex = Array.prototype.map
    .call(new Uint8Array(new Uint32Array(m).buffer), function (e) {
      return (e < 16 ? '0' : '') + e.toString(16)
    })
    .join('')
  return hex
}

最后,微信配置:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://cdn.bootcss.com/vConsole/3.3.4/vconsole.min.js"></script>
  <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
  <script>签名方法...</script>
</head>
<body>
  <script>
  window.onload = function () {
    wx.config({
      debug: true,
      appId: '',
      timestamp: 1595235986,
      nonceStr: '',
      signature: this.sign(),
      jsApiList: ['scanQRCode'],
      openTagList: ['wx-open-launch-weapp'], 
    })
    wx.ready(function (res) {
      ...
    }
  </script>
</body>
</html>

测试

起服务 serve ./your/path,然后通过浏览器访问,或者微信开发者访问

0 / 500

微信签名--前端实现

2020 年 07 月 24 日

1

Like

0

Download

273

Viewed

技术是第一生产力