欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

支付寶小程序MQTT數(shù)據(jù)Base64錯(cuò)誤 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識(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)案例查看更多