知識(shí)
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營(yíng)銷的便利,運(yùn)營(yíng)的高效,讓網(wǎng)站成為營(yíng)銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!
您當(dāng)前位置>首頁(yè) » 新聞資訊 » 小程序相關(guān) >
支付寶小程序MQTT數(shù)據(jù)Base64錯(cuò)誤
發(fā)表時(shí)間:2021-1-5
發(fā)布人:葵宇科技
瀏覽次數(shù):107
微信小程序的模擬器和真機(jī)、支付寶小程序的模擬器接受到數(shù)據(jù)解析都是正常的,但是支付寶小程序的真機(jī)卻報(bào)錯(cuò) AMQJS0007E Socket error:未能完成操作。(OSStatus錯(cuò)誤-9807。)
。
結(jié)論
支付寶小程序返回的數(shù)據(jù)為Base64格式,并且 帶有換行符 。所以導(dǎo)致在解析的時(shí)候出現(xiàn)錯(cuò)誤。 解決方案: 字符串去掉換行符。
data = data.replace(/[\r\n]/g,"");
復(fù)制代碼
現(xiàn)象
測(cè)試人員反饋說(shuō)在支付寶小程序上沒有軌跡。一臉懵逼的反應(yīng)說(shuō),不可能吧。微信都是好的,模擬器也自測(cè)了,沒有問(wèn)題啊。查看現(xiàn)象果然有問(wèn)題啊,啥都不顯示。 因?yàn)檐壽E使用的是MQTT的推送,不能通過(guò)charles抓包獲取并查看數(shù)據(jù),也沒法通過(guò)控制臺(tái)查看日志。也不像微信小程序可以打開調(diào)試模板。才疏學(xué)淺的我,只能通過(guò)toast內(nèi)容來(lái)判斷是否出錯(cuò)。!_! 有好方案請(qǐng)多多指教。
MQTT不支持支付寶小程序的真機(jī)?
第一反應(yīng)就是難道不支持嗎? 打開了mqtt.js看了看。前輩們已經(jīng)編寫好兼容支付寶小程序,那么也就是說(shuō)方案是沒有問(wèn)題的啊。著手添加日志,將出錯(cuò)的信息打印出來(lái)。在使用到mqtt的地方,所有的failure和catch中都添加日志并打印。
AMQJS0005E Internal error. Error Message: AMQJS0009E malformed UTF data:93 -3d.,Stack trace: No Error Stack Available
Base64格式問(wèn)題?
看到錯(cuò)誤日志后,問(wèn)了下度娘“啥原因啊,度娘?!? "要先看廣告哦,不然不告訴你"。看了一些廣告后,說(shuō)“是不是包含中文了啊”。 這有可能哦。找到后臺(tái)開發(fā)人員,提供了登錄的手機(jī)號(hào)碼,幫忙打印下發(fā)送的原文是啥。千辛萬(wàn)苦的找啊找啊,說(shuō)登錄后馬上就下線了,沒有發(fā)送內(nèi)容。這。。。 也就是說(shuō)上上下下。還是說(shuō)沒有添加打印日志的代碼。(誰(shuí)知道呢)
查找出錯(cuò)的位置
將mqtt中所有的代碼看一遍,順著報(bào)錯(cuò)的調(diào)用棧,在每一個(gè)錯(cuò)誤分支添加日志。等查看到最小單元的代碼塊后,按行進(jìn)行try-catch,找到指定的行。
var ERROR = {
OK: { code: 0, text: "AMQJSC0000I OK." },
CONNECT_TIMEOUT: { code: 1, text: "AMQJSC0001E Connect timed out." },
SUBSCRIBE_TIMEOUT: { code: 2, text: "AMQJS0002E Subscribe timed out." },
UNSUBSCRIBE_TIMEOUT: { code: 3, text: "AMQJS0003E Unsubscribe timed out." },
PING_TIMEOUT: { code: 4, text: "AMQJS0004E Ping timed out." },
INTERNAL_ERROR: { code: 5, text: "AMQJS0005E Internal error. Error Message: {0}, Stack trace: {1}" },
CONNACK_RETURNCODE: { code: 6, text: "AMQJS0006E Bad Connack return code:{0} {1}." },
SOCKET_ERROR: { code: 7, text: "AMQJS0007E Socket error:{0}." },
SOCKET_CLOSE: { code: 8, text: "AMQJS0008I Socket closed." },
MALFORMED_UTF: { code: 9, text: "AMQJS0009E Malformed UTF data:{0} {1} {2}." },
UNSUPPORTED: { code: 10, text: "AMQJS0010E {0} is not supported by this browser." },
INVALID_STATE: { code: 11, text: "AMQJS0011E Invalid state {0}." },
INVALID_TYPE: { code: 12, text: "AMQJS0012E Invalid type {0} for {1}." },
INVALID_ARGUMENT: { code: 13, text: "AMQJS0013E Invalid argument {0} for {1}." },
UNSUPPORTED_OPERATION: { code: 14, text: "AMQJS0014E Unsupported operation." },
INVALID_STORED_DATA: { code: 15, text: "AMQJS0015E Invalid data in local storage key={0} value=http://www.wxapp-union.com/{1}." },
INVALID_MQTT_MESSAGE_TYPE: { code: 16, text: "AMQJS0016E Invalid MQTT message type {0}." },
MALFORMED_UNICODE: { code: 17, text: "AMQJS0017E Malformed Unicode string:{0} {1}." },
BUFFER_FULL: { code: 18, text: "AMQJS0018E Message buffer is full, maximum buffer size: {0}." },
};
復(fù)制代碼
首先看到的報(bào)錯(cuò)的內(nèi)容來(lái)源,原來(lái)錯(cuò)誤的日志是mqtt報(bào)的。報(bào)錯(cuò)的代碼為
function parseUTF8(input, offset, length) {
var output = "";
var utf16;
var pos = offset;
while (pos < offset + length) {
var byte1 = input[pos++];
if (byte1 < 128)
utf16 = byte1;
else {
var byte2 = input[pos++] - 128;
if (byte2 < 0)
throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), ""]));
if (byte1 < 0xE0) // 2 byte character
utf16 = 64 * (byte1 - 0xC0) + byte2;
else {
var byte3 = input[pos++] - 128;
if (byte3 < 0)
throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), byte3.toString(16)]));
if (byte1 < 0xF0) // 3 byte character
utf16 = 4096 * (byte1 - 0xE0) + 64 * byte2 + byte3;
else {
var byte4 = input[pos++] - 128;
if (byte4 < 0)
throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), byte3.toString(16), byte4.toString(16)]));
if (byte1 < 0xF8) // 4 byte character
utf16 = 262144 * (byte1 - 0xF0) + 4096 * byte2 + 64 * byte3 + byte4;
else // longer encodings are not supported
throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), byte3.toString(16), byte4.toString(16)]));
}
}
}
if (utf16 > 0xFFFF) // 4 byte character - express as a surrogate pair
{
utf16 -= 0x10000;
output += String.fromCharCode(0xD800 + (utf16 >> 10)); // lead character
utf16 = 0xDC00 + (utf16 & 0x3FF); // trail character
}
output += String.fromCharCode(utf16);
}
return output;
}
復(fù)制代碼
在位置 throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), ""]));
拋出了異常??梢院艽_切的判斷因?yàn)锽ase64轉(zhuǎn)ArrayBuffer后,進(jìn)行數(shù)據(jù)內(nèi)容的判斷出錯(cuò)了。
分析ArrayBuffer
要進(jìn)行判斷數(shù)據(jù)是否有問(wèn)題,那么將模擬器和真機(jī)的數(shù)據(jù)都打印出來(lái),然后進(jìn)行比對(duì)。

發(fā)現(xiàn)固定相同位置的值不一致,那么也就是說(shuō)其中一定是添加或刪除了一些字符。
查看Base64字符串
再向上查看小程序直接返回的字符串是否就出現(xiàn)了問(wèn)題,如果有問(wèn)題,那么一定是后臺(tái)針對(duì)真機(jī)做了特殊的處理!或者真機(jī)的arm平臺(tái)針對(duì)某個(gè)方法有不同的處理邏輯!。。。

查看Base64字符串也很正常,將字符串使用Base64標(biāo)準(zhǔn)格式進(jìn)行解碼后發(fā)現(xiàn)有亂碼。好興奮啊,那一定是這個(gè)問(wèn)題了。興沖沖的就找后臺(tái)開發(fā)人員,一定是你們的數(shù)據(jù)有問(wèn)題。但是...打臉來(lái)的很快。從后臺(tái)的日志中看到返回的數(shù)據(jù)都是一樣的,根本不區(qū)分平臺(tái)。 再次核對(duì)base64的字符串后,發(fā)現(xiàn)其中的"l"和"I"寫錯(cuò)了。一個(gè)是小寫的L,一個(gè)是大寫的i??梢源_認(rèn)后臺(tái)發(fā)送過(guò)來(lái)的base64也是正確的。那么真相只有一個(gè):Base64轉(zhuǎn)ArrayBuffer出錯(cuò)了。
Base64轉(zhuǎn)ArrayBuffer
發(fā)現(xiàn)微信小程序是有提供方法進(jìn)行base64轉(zhuǎn)ArrayBuffer,base64轉(zhuǎn)string等。但是支付寶小程序卻什么都沒有,難倒是我沒找到嗎?。。。ㄖ赖?,請(qǐng)?zhí)砑酉略u(píng)論,讓我摩拜下) 找了很久也沒找到啥靠譜的,最后曲線救國(guó)。先將base64轉(zhuǎn)為string,再將string轉(zhuǎn)為ArrayBuffer。結(jié)果還是失敗了。
猜想
如果真機(jī)和模擬器出現(xiàn)問(wèn)題,那么直接用相同的字符串,也一樣會(huì)出現(xiàn)問(wèn)題。 將data直接hard code。然后進(jìn)行模擬器和真機(jī)的測(cè)試。發(fā)現(xiàn)。。。驚喜啊。都成功了,沒有報(bào)錯(cuò)啊。666 可以得出最后的結(jié)論了,真機(jī)返回的字符串一定有特殊字符并不可見。 馬上拿就想到了 空格和換行符 。
成功
將字符串進(jìn)行去除換行和空格后,一切都那么完美了。 最后多次測(cè)試發(fā)現(xiàn)是多了換行符。^ _ ^ 將mqtt.js代碼都看了一遍,還是收貨很多?。?/p>
相關(guān)案例查看更多
相關(guān)閱讀
- 昆明網(wǎng)站制作
- python開發(fā)小程序
- 保險(xiǎn)網(wǎng)站建設(shè)公司
- 云南網(wǎng)站建設(shè)費(fèi)用
- 百度人工排名
- 報(bào)廢車拆解管理系統(tǒng)
- 云南小程序商城
- 昆明網(wǎng)站開發(fā)
- 網(wǎng)站建設(shè)列表網(wǎng)
- 旅游網(wǎng)站建設(shè)
- 云南網(wǎng)站建設(shè)方案 doc
- 網(wǎng)絡(luò)公司哪家好
- 網(wǎng)站建設(shè)特性
- 網(wǎng)頁(yè)制作
- 昆明小程序開發(fā)聯(lián)系方式
- 大理網(wǎng)站建設(shè)公司
- 報(bào)廢車管理系統(tǒng)
- 云南省住房建設(shè)廳網(wǎng)站
- 云南網(wǎng)站建設(shè)首選公司
- 北京小程序制作
- 云南小程序開發(fā)公司推薦
- web
- 昆明小程序哪家好
- 云南小程序開發(fā)課程
- 智慧農(nóng)貿(mào)市場(chǎng)
- 云南網(wǎng)站開發(fā)
- 百度自然排名
- 云南建站公司
- 網(wǎng)站排名
- 手機(jī)網(wǎng)站建設(shè)