在开发小程序的过程中,需要从H5页面携带参数打开小程序,通过微信开发者文档得知可以使用明文URL Scheme打开小程序。但是根据文档要求拼接好明文URL Scheme之后,发现无法打开小程序;经过排查后得知是因为明文URL Scheme的参数不支持中文所导致,即使通过url_encode也不行。
使用Base64编码
微信小程序的明文URL Scheme对参数的要求是最大512个字符,只支持数字,大小写英文以及部分特殊字符:!#$&'()*+,/:;=?@-._~%`,需要url_encode。
既然是这样,那只需将中文编码为上述要求的字符,在使用时再解码就可以了;而Base64编码完美适配上述要求。
// 将字符串转换为 UTF-16 编码的 Uint16Array
function stringToUTF16Array(str) {
var utf16 = new Uint16Array(str.length);
for (var i = 0; i < str.length; i++) {
utf16[i] = str.charCodeAt(i);
}
return utf16;
}
// 将 Uint16Array 转换为字符串
function utf16ArrayToString(utf16Array) {
return String.fromCharCode.apply(null, utf16Array);
}
// 将 Uint16Array 转换为 Base64 编码的字符串
function base64EncodeUTF16(str) {
var utf16Array = stringToUTF16Array(str);
var binary = '';
for (var i = 0; i < utf16Array.length; i++) {
// 将 Uint16Array 转换为二进制字符串
var char = utf16Array[i];
binary += String.fromCharCode(char & 0xFF);
binary += String.fromCharCode(char >> 8);
}
return btoa(binary);
}
// 将 Base64 编码的字符串解码为 Uint16Array
function base64DecodeUTF16(base64Str) {
var binary = atob(base64Str);
var utf16Array = new Uint16Array(binary.length / 2);
for (var i = 0; i < utf16Array.length; i++) {
utf16Array[i] = binary.charCodeAt(i * 2) + (binary.charCodeAt(i * 2 + 1) << 8);
}
return utf16ArrayToString(utf16Array);
}
// 示例
var originalString = "你好,世界!";
var base64String = base64EncodeUTF16(originalString);
console.log(base64String); // 输出: YE99WQz/Fk5MdQH/
var decodedString = base64DecodeUTF16(base64String);
console.log(decodedString); // 输出: 你好,世界!
代码解析
-
stringToUTF16Array 函数:将字符串转换为 UTF-16 编码的
Uint16Array。每个字符的 Unicode 值被存储在数组中。 -
utf16ArrayToString 函数:将
Uint16Array转换回字符串。使用String.fromCharCode.apply(null, utf16Array)方法将Uint16Array转换为字符串。 -
base64EncodeUTF16 函数:
- 将 UTF-16 编码的
Uint16Array转换为二进制字符串。对于每个 16 位字符,提取低 8 位和高 8 位,将其转换为两个字符。 - 使用
btoa函数将二进制字符串编码为 Base64 字符串。
- 将 UTF-16 编码的
-
base64DecodeUTF16 函数:
- 使用
atob函数将 Base64 字符串解码为二进制字符串。 - 将二进制字符串转换为
Uint16Array。每两个字符合并为一个 16 位字符的 Unicode 值。 - 将
Uint16Array转换回原始字符串。
- 使用
通过以上方法,你可以将任意包含中文字符的字符串转换为使用 UTF-16 编码的 Base64 字符串,并且可以解码回原始字符串。
小程序问题
Base64编码问题
因为微信小程序是不支持btoa和atob函数,因此需要在小程序自己实现 Base64 编码与解码或者引入第三方库。
本文的小程序使用Taro框架进行开发,该框架提供base64ToArrayBuffer和arrayBufferToBase64函数。使用这两个函数对base64EncodeUTF16与base64DecodeUTF16进行改造即可。
解码问题
打开小程序的方式有很多种,如明文URL Scheme、推送消息等,但是明文URL Scheme的参数不支持中文,其他打开小程序的方式并没有这样的限制,因此需要使用小程序的场景值加以判断。(明文 URL Scheme 打开小程序的场景值为 1286)
即使用明文URL Scheme打开小程序时,对中文参数进行 Base64 解码,通过其他方式打开小程序时,不需要对中文参数进行 Base64 解码。