微信小程序明文URL Scheme跳转失败问题

3,249 阅读3分钟

在开发小程序的过程中,需要从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); // 输出: 你好,世界!

代码解析

  1. stringToUTF16Array 函数:将字符串转换为 UTF-16 编码的 Uint16Array。每个字符的 Unicode 值被存储在数组中。

  2. utf16ArrayToString 函数:将 Uint16Array 转换回字符串。使用 String.fromCharCode.apply(null, utf16Array) 方法将 Uint16Array 转换为字符串。

  3. base64EncodeUTF16 函数

    • 将 UTF-16 编码的 Uint16Array 转换为二进制字符串。对于每个 16 位字符,提取低 8 位和高 8 位,将其转换为两个字符。
    • 使用 btoa 函数将二进制字符串编码为 Base64 字符串。
  4. base64DecodeUTF16 函数

    • 使用 atob 函数将 Base64 字符串解码为二进制字符串。
    • 将二进制字符串转换为 Uint16Array。每两个字符合并为一个 16 位字符的 Unicode 值。
    • Uint16Array 转换回原始字符串。

通过以上方法,你可以将任意包含中文字符的字符串转换为使用 UTF-16 编码的 Base64 字符串,并且可以解码回原始字符串。

小程序问题

Base64编码问题

因为微信小程序是不支持btoaatob函数,因此需要在小程序自己实现 Base64 编码与解码或者引入第三方库。

本文的小程序使用Taro框架进行开发,该框架提供base64ToArrayBufferarrayBufferToBase64函数。使用这两个函数对base64EncodeUTF16base64DecodeUTF16进行改造即可。

解码问题

打开小程序的方式有很多种,如明文URL Scheme、推送消息等,但是明文URL Scheme的参数不支持中文,其他打开小程序的方式并没有这样的限制,因此需要使用小程序的场景值加以判断。(明文 URL Scheme 打开小程序的场景值为 1286)

即使用明文URL Scheme打开小程序时,对中文参数进行 Base64 解码,通过其他方式打开小程序时,不需要对中文参数进行 Base64 解码。