七仔的博客

七仔的博客GithubPages分博

0%

针对微信获取小程序码scene参数的数据压缩算法

针对微信小程序码获取接口B的scene参数对输入参数做压缩处理放入scene参数中

针对微信获取小程序码scene参数的数据压缩算法

一、前言

微信小程序现在有四个获取小程序码的接口,分别是:

  • 接口 A: 适用于需要的码数量较少的业务场景

生成小程序码,可接受 path 参数较长,生成个数受限,请谨慎使用。

  • 接口 B:适用于需要的码数量极多的业务场景

生成小程序码,可接受页面参数较短,生成个数不受限。

  • 接口 C:适用于需要的码数量较少的业务场景(不推荐使用)

生成二维码,可接受 path 参数较长,生成个数受限。

  • 接口 D:适用于“一物一码”的业务场景

微信一物一码 支持生成小程序码。微信通过“一物一码”接口发放的二维码相比较普通链接二维码更安全、支持更小的印刷面积,支持跳转到指定小程序页面,且无数量限制

二、问题

需要生成的小程序码数量要求很大,接口D的场景不一致,不考虑,接口A和接口C的生成数量加起来不超过十万,剩下的选择只有接口B,但是接口B的要求scene参数为(最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&’()+,/:;=?@-._~,其它字符请自行编码为合法字符)
算起来的话数字10个,大小写英文有26
2=52个,加上特殊字符共有82个字符,业务要求将两个信息放入32个字符内,不考虑别的手段,两个信息一个信息的数量小,但是另一个信息为数字和英文组成的36进制编码。
经过计算后可以发现将特殊字符中的一个作为分隔符,将32位信息36进制压缩进81进制中可以缩短到27位,一个做分隔,还有4位保存另一个信息!可以做!

三、接口B文档

1
POST https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN
属性 类型 默认值 必填 说明
access_token string 接口调用凭证
scene string 最大32个可见字符,只支持数字,大小写英文以及部分特殊字符:!#$&’()*+,/:;=?@-._~,其它字符请自行编码为合法字符(因不支持%,中文无法使用 urlencode 处理,请使用其他编码方式)
page string 主页 必须是已经发布的小程序存在的页面(否则报错),例如 pages/index/index, 根路径前不要填加 /,不能携带参数(参数请放在scene字段里),如果不填写这个字段,默认跳主页面
width number 430 二维码的宽度,单位 px,最小 280px,最大 1280px
auto_color boolean false 自动配置线条颜色,如果颜色依然是黑色,则说明不建议配置主色调,默认 false
line_color Object {“r”:0,”g”:0,”b”:0} auto_color 为 false 时生效,使用 rgb 设置颜色 例如 {“r”:”xxx”,”g”:”xxx”,”b”:”xxx”} 十进制表示
is_hyaline boolean false 是否需要透明底色,为 true 时,生成透明底色的小程序

返回值为图片的Buffer

四、操作

将82个字符中的“-”拿出来做分隔符,剩下81个字符做为81进制,将36进制转为10进制,再将10进制转为81进制。

五、工具类

我写好了工具类,直接拿来用就可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import org.apache.commons.lang.StringUtils;
import java.math.BigInteger;

/**
* 小程序码加密解密(进制转换)
*/
public class MiniCodeUtil {

/**八十一进制*/
private static String chars =
"0123456789" +
"ABCDEFGHIJ" +
"KLMNOPQRST" +
"UVWXYZabcd" +
"efghijklmn" +
"opqrstuvwx" +
"yz!#$&'()*" +
"+,/:;=?@._" +
"~";
private static int scale = 81;
private static int minLength = 4;

/**
* 加密
* @param str 字符串
* @return
*/
public static String encode(String str) {
BigInteger num = new BigInteger(str, 36);
StringBuilder sb = new StringBuilder();
int remainder;
while (num.compareTo(BigInteger.valueOf(scale - 1)) > 0) {
remainder = num.mod(BigInteger.valueOf(scale)).intValue();
sb.append(chars.charAt(remainder));
/**除以进制数,获取下一个末尾数*/
num = num.divide(BigInteger.valueOf(scale));
}
sb.append(chars.charAt(num.intValue()));
String value = sb.reverse().toString();
return StringUtils.leftPad(value, minLength, '0');
}

/**
* 解密
* @param str 字符串
* @return
*/
public static String decode(String str) {
/**将 0 开头的字符串进行替换*/
str = str.replace("^0*", "");
BigInteger value = BigInteger.ZERO;
char tempChar;
BigInteger tempCharValue;
for (int i = 0; i < str.length(); i++) {
/**获取字符*/
tempChar = str.charAt(i);
/**单字符值*/
tempCharValue = BigInteger.valueOf(chars.indexOf(tempChar));
/**单字符值在进制规则下表示的值*/
BigInteger item = BigInteger.valueOf(scale).pow(str.length() - i - 1);
value = value.add(tempCharValue.multiply(item));
}
return addZeroForNum(value.toString(36), 32);
}



/**
* 补零
* str 原字符串
* strLength 字符串总长
* */
private static String addZeroForNum(String str, int strLength) {
int strLen = str.length();
if (strLen < strLength) {
while (strLen < strLength) {
StringBuffer sb = new StringBuffer();
sb.append("0").append(str);// 左补0
// sb.append(str).append("0");//右补0
str = sb.toString();
strLen = str.length();
}
}
return str;
}
}

六、调用方式

1
System.out.println(MiniCodeUtil.decode(MiniCodeUtil.encode("995587e102064d47b670f5b81253dd58")));

七、Javascript函数(未做大数处理)

写了个javascript的解密函数,但是javascript对大于9007199254740992的数处理出现错误,所以该函数只能对位数比较短的数做处理,例如处理32位数会出现问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
var Stack = (function(){
var items = new WeakMap();
//先入后出,后入先出
class Stack{
constructor(){
items.set(this,[]);
}
push(ele){
//入栈
var ls = items.get(this);
ls.push(ele);
}
pop(){
//出栈
var ls = items.get(this);
return ls.pop();
}
size(){
//获取栈的长度
var ls = items.get(this);
return ls.length;
}
print(){
//打印栈
var ls = items.get(this);
return ls.toString();
}
}
return Stack;
})();

/**
* num 需要转化的数字
* base 转化的进制,默认为 2
* */
function devide(num,base){
base = Math.floor(base) || 2;
if(typeof num != "number" || num < 0 || base > 36 || base < 2){
throw new Error("参数错误");
return '';
}
num = Math.floor(num);

var code = "0123456789abcdefghijklmnopqrstuvwxyz";
var stack = new Stack();
var res = '';
var rem;
while(num > 0){
rem = num % base;
stack.push(rem);
num = Math.floor(num/base);
}

while(stack.size() > 0){
res += code[stack.pop()];
}

return res;
}
function transfrom(num,base){
//任意进制转十进制
var bases = [
"0","1","2","3","4","5","6","7","8","9",
"A","B","C","D","E","F","G","H","I","J",
"K","L","M","N","O","P","Q","R","S","T",
"U","V","W","X","Y","Z","a","b","c","d",
"e","f","g","h","i","j","k","l","m","n",
"o","p","q","r","s","t","u","v","w","x",
"y","z","!","#","$","&","'","(",")","*",
"+",",","/",":",";","=","?","@",".","_",
"~"];
var config = {};
for(var k = 0; k < base; k++){
config[bases[k]] = k;
}
num = String(num);
var count = 0;
var res = 0;
var i;
while(num.length > 0){
i = num[num.length - 1];
i = config[i];
res = res + i * Math.pow(base,count);
num = num.substr(0,num.length-1);
count++;
}
return res;
}




/**字符串*/
var str = '1f/@*WYzW(Bq:yJSWqguXPJSf1W'
var str_res = devide(transfrom(str,81),36);
console.log("str_res :" + str_res )

此为博主副博客,留言请去主博客,转载请注明出处:https://www.baby7blog.com/myBlog/67.html

欢迎关注我的其它发布渠道