用戶
 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

掃一掃,登錄網站

小程序社區 首頁 教程 實戰教程 查看內容

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

Rolan 2020-9-10 10:33

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

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

結論

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

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

現象

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

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

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

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

Base64格式問題?

看到錯誤日志后,問了下度娘“啥原因啊,度娘。”, "要先看廣告哦,不然不告訴你"。看了一些廣告后,說“是不是包含中文了啊”。 這有可能哦。找到后臺開發人員,提供了登錄的手機號碼,幫忙打印下發送的原文是啥。千辛萬苦的找啊找啊,說登錄后馬上就下線了,沒有發送內容。這。。。 也就是說上上下下。還是說沒有添加打印日志的代碼。(誰知道呢)

查找出錯的位置

將mqtt中所有的代碼看一遍,順著報錯的調用棧,在每一個錯誤分支添加日志。等查看到最小單元的代碼塊后,按行進行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={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), ""])); 拋出了異常。可以很確切的判斷因為Base64轉ArrayBuffer后,進行數據內容的判斷出錯了。

分析ArrayBuffer

要進行判斷數據是否有問題,那么將模擬器和真機的數據都打印出來,然后進行比對。

發現固定相同位置的值不一致,那么也就是說其中一定是添加或刪除了一些字符。

查看Base64字符串

再向上查看小程序直接返回的字符串是否就出現了問題,如果有問題,那么一定是后臺針對真機做了特殊的處理!或者真機的arm平臺針對某個方法有不同的處理邏輯!。。。

查看Base64字符串也很正常,將字符串使用Base64標準格式進行解碼后發現有亂碼。好興奮啊,那一定是這個問題了。興沖沖的就找后臺開發人員,一定是你們的數據有問題。但是...打臉來的很快。從后臺的日志中看到返回的數據都是一樣的,根本不區分平臺。 再次核對base64的字符串后,發現其中的"l"和"I"寫錯了。一個是小寫的L,一個是大寫的i。可以確認后臺發送過來的base64也是正確的。那么真相只有一個:Base64轉ArrayBuffer出錯了。

Base64轉ArrayBuffer

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

猜想

如果真機和模擬器出現問題,那么直接用相同的字符串,也一樣會出現問題。 將data直接hard code。然后進行模擬器和真機的測試。發現。。。驚喜啊。都成功了,沒有報錯啊。666 可以得出最后的結論了,真機返回的字符串一定有特殊字符并不可見。 馬上拿就想到了 空格和換行符

成功

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

鮮花
鮮花
雞蛋
雞蛋
分享至 : QQ空間
收藏
河北20选5大星走势图 有梦pc蛋蛋 股市行情分析软件 稀土股票 吉林十一选五遗漏爱乐彩 河南快三走势一定牛 江西多乐彩基本走势图 百度 重庆时时人工计划软件 山东11选5 五连号遗漏 1万炒股一年最多挣多少最牛散户从5万到20亿 银行基金配资业务 十一选五前三组万能码 宁夏十一选五投注网站 三分赛车计划六码 江西时时彩倍投 极速时时彩有什么漏洞 二六三股票