wxjssdk 前端自己搞签名

88 阅读3分钟

引言:由于时间问题,后端拒绝配合,只给提供 ticket,所以没有办法,前端卑微只能靠自己,找了好多办法,终于搞定,虽然最后也没用上

注:强烈不推荐使用,这玩意都是后端搞得,前端搞那不是开玩笑嘛

框架:vue3+ts+vite+vant+pinia, 打包 h5 内嵌微信小程序

  1. 排序对象的属性名数组
const objKeySort = (arys: any) => {
  //先用Object内置类的keys方法获取要排序对象的属性名数组,再利用Array的sort方法进行排序
  const newkey = Object.keys(arys).sort();
  // console.log('newkey=' + newkey);
  let newObj = ''; //创建一个新的对象,用于存放排好序的键值对
  for (let i = 0; i < newkey.length; i++) {
    //遍历newkey数组
    newObj += [newkey[i]] + '=' + arys[newkey[i]] + '&';
  }
  return newObj.substring(0, newObj.length - 1);
};

2.生成指定长度的随机字符串,作为nonceStr

const randomString = (length: any) => {
  // 定义字符串中的字符
  const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  let result = '';
  // 循环指定长度
  for (let i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
  // 返回生成的字符串
  return result;
};

  1. 获取 ticket,这个必须要后端了,前端真的搞不了

  2. 获取签名,使用 sha1 加密

    首先 排序

   const sortStr = objKeySort({
    // eslint-disable-next-line camelcase
    jsapi_ticket: res.data,
    noncestr: nonceStr, // nocestr必须全部小写,当初为了省事,直接用的大写 S,结果踩坑,找了好久才发现问题,差点崩溃了。
    timestamp,
    url: window.location.href.split('#')[0],
  });
pnpm install js-sha1
import { sha1 } from 'js-sha1';
const signature = sha1(sortStr);
  1. 配置 wx jssdk
export const wxSetConfig = async (debug: boolean = false) => {
  const nonceStr = randomString(16);
  const timestamp = Math.round(new Date().getTime() / 1000);
  _wx.config({
    debug: debug, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp, // 必填,生成签名的时间戳
    nonceStr, // 必填,生成签名的随机串
    signature, // 必填,签名
    jsApiList: ['scanQRCode'], // 必填,需要使用的JS接口列表
  });
};

完整代码如下

import _wx from 'weixin-js-sdk';
import Request from './request/';
import { sha1 } from 'js-sha1';

const http = new Request();

const objKeySort = (arys: any) => {
  //先用Object内置类的keys方法获取要排序对象的属性名数组,再利用Array的sort方法进行排序
  const newkey = Object.keys(arys).sort();
  // console.log('newkey=' + newkey);
  let newObj = ''; //创建一个新的对象,用于存放排好序的键值对
  for (let i = 0; i < newkey.length; i++) {
    //遍历newkey数组
    newObj += [newkey[i]] + '=' + arys[newkey[i]] + '&';
  }
  return newObj.substring(0, newObj.length - 1);
};

// 生成指定长度的随机字符串
const randomString = (length: any) => {
  // 定义字符串中的字符
  const chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  let result = '';
  // 循环指定长度
  for (let i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
  // 返回生成的字符串
  return result;
};

/** 获取wx-ticket配置信息 */
export const getPolicy = () => {
  return http.post('');
};

export const wxSetConfig = async (debug: boolean = false) => {
  const res = await getPolicy();
  const nonceStr = randomString(16);
  const timestamp = Math.round(new Date().getTime() / 1000);
  const sortStr = objKeySort({
    jsapi_ticket: res.data,
    noncestr: nonceStr,
    timestamp,
    url: window.location.href.split('#')[0], // 域名需在微信公众号 js 安全接口内配置
  });

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