支付寶小程序MQTT數據Base64錯誤 - 新聞資(zī)訊 - 雲南小程序開發|雲南軟件開發|雲南網站(zhàn)建設-西山區知普網絡科技工作室

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不管是網站(zhàn),軟件還是小程序,都要直接或間接能為您産生價值,我們在追求其視覺表現的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網站(zhàn)成為營銷工具,讓軟件能切實提升企業(yè)内部管理水平和(hé)效率。優秀的程序為後期升級提供便捷的支持!

支付寶小程序MQTT數據Base64錯誤

發表時間:2021-1-5

發布人:葵宇科技

浏覽次數:83

微信小程序的模拟器(qì)和(hé)真機、支付寶小程序的模拟器(qì)接受到數據解析都是正常的,但是支付寶小程序的真機卻報錯 AMQJS0007E Socket error:未能完成操作。(OSStatus錯誤-9807。)

結論

支付寶小程序返回的數據為Base64格式,并且 帶有換行符 。所以導緻在解析的時候出現錯誤。 解決方案: 字符串去掉換行符。

data = data.replace(/[\r\n]/g,"");
複制代碼

現象

測試人員反饋說在支付寶小程序上沒有軌迹。一臉懵逼的反應說,不可(kě)能吧。微信都是好的,模拟器(qì)也自測了,沒有問(wèn)題啊。查看現象果然有問(wèn)題啊,啥都不顯示。 因為軌迹使用的是MQTT的推送,不能通(tōng)過charles抓包獲取并查看數據,也沒法通(tōng)過控制台查看日志。也不像微信小程序可(kě)以打開調試模闆。才疏學淺的我,隻能通(tōng)過toast内容來判斷是否出錯。!_! 有好方案請多多指教。

MQTT不支持支付寶小程序的真機?

第一反應就是難道不支持嗎? 打開了mqtt.js看了看。前輩們已經編寫好兼容支付寶小程序,那麼也就是說方案是沒有問(wèn)題的啊。着手添加日志,将出錯的信息打印出來。在使用到mqtt的地方,所有的failure和(hé)catch中(zhōng)都添加日志并打印。

AMQJS0005E Internal error. Error Message: AMQJS0009E malformed UTF data:93 -3d.,Stack trace: No Error Stack Available

Base64格式問(wèn)題?

看到錯誤日志後,問(wèn)了下(xià)度娘“啥原因啊,度娘。”, "要先看廣告哦,不然不告訴你(nǐ)"。看了一些廣告後,說“是不是包含中(zhōng)文(wén)了啊”。 這有可(kě)能哦。找到後台開發人員,提供了登錄的手機号碼,幫忙打印下(xià)發送的原文(wén)是啥。千辛萬苦的找啊找啊,說登錄後馬上就下(xià)線了,沒有發送内容。這。。。 也就是說上上下(xià)下(xià)。還是說沒有添加打印日志的代碼。(誰知道呢(ne))

查找出錯的位置

将mqtt中(zhōng)所有的代碼看一遍,順着報錯的調用棧,在每一個(gè)錯誤分支添加日志。等查看到最小單元的代碼塊後,按行進行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}." },
    };
複制代碼

首先看到的報錯的内容來源,原來錯誤的日志是mqtt報的。報錯的代碼為

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;
    }
複制代碼

在位置 throw new Error(format(ERROR.MALFORMED_UTF, [byte1.toString(16), byte2.toString(16), ""])); 抛出了異常。可(kě)以很确切的判斷因為Base64轉ArrayBuffer後,進行數據内容的判斷出錯了。

分析ArrayBuffer

要進行判斷數據是否有問(wèn)題,那麼将模拟器(qì)和(hé)真機的數據都打印出來,然後進行比對。

發現固定相同位置的值不一緻,那麼也就是說其中(zhōng)一定是添加或删除了一些字符。

查看Base64字符串

再向上查看小程序直接返回的字符串是否就出現了問(wèn)題,如(rú)果有問(wèn)題,那麼一定是後台針對真機做了特殊的處理!或者真機的arm平台針對某個(gè)方法有不同的處理邏輯!。。。

查看Base64字符串也很正常,将字符串使用Base64标準格式進行解碼後發現有亂碼。好興奮啊,那一定是這個(gè)問(wèn)題了。興沖沖的就找後台開發人員,一定是你(nǐ)們的數據有問(wèn)題。但是...打臉來的很快。從後台的日志中(zhōng)看到返回的數據都是一樣的,根本不區分平台。 再次核對base64的字符串後,發現其中(zhōng)的"l"和(hé)"I"寫錯了。一個(gè)是小寫的L,一個(gè)是大寫的i。可(kě)以确認後台發送過來的base64也是正确的。那麼真相隻有一個(gè):Base64轉ArrayBuffer出錯了。

Base64轉ArrayBuffer

發現微信小程序是有提供方法進行base64轉ArrayBuffer,base64轉string等。但是支付寶小程序卻什麼都沒有,難倒是我沒找到嗎!!!(知道的,請添加下(xià)評論,讓我摩拜下(xià)) 找了很久也沒找到啥靠譜的,最後曲線救國。先将base64轉為string,再将string轉為ArrayBuffer。結果還是失敗了。

猜想

如(rú)果真機和(hé)模拟器(qì)出現問(wèn)題,那麼直接用相同的字符串,也一樣會出現問(wèn)題。 将data直接hard code。然後進行模拟器(qì)和(hé)真機的測試。發現。。。驚喜啊。都成功了,沒有報錯啊。666 可(kě)以得出最後的結論了,真機返回的字符串一定有特殊字符并不可(kě)見。 馬上拿就想到了 空格和(hé)換行符

成功

将字符串進行去除換行和(hé)空格後,一切都那麼完美了。 最後多次測試發現是多了換行符。^ _ ^ 将mqtt.js代碼都看了一遍,還是收貨很多啊!

相關(guān)案例查看更多