[iOS]關(guān)于支付寶支付返回值的坑

關(guān)于支付寶支付寶的返回值問題, 再一次踩到深坑里, 無論是從返回值的格式上, 還是使用在線的格式化工具驗(yàn)證, 都像是JSON字符串, 理論上一定能夠轉(zhuǎn)換為字典類型. 但事實(shí)卻總是不盡如人意.
返回值整體是一個字典, 但使用json格式化工具檢查會發(fā)現(xiàn), 格式不對:

支付寶支付結(jié)果

這是因?yàn)樽詈笠粋€鍵值對不完整, 后面加個"", 即"memo": ""

補(bǔ)充完整后的結(jié)果

雖然json格式不對, 但是可以正確的獲取狀態(tài)碼, 即"resultStatus" 字段是可以正常獲取到的, 問題就出在獲取結(jié)果內(nèi)容時, 即: "result" 字段對應(yīng)的內(nèi)容, 看結(jié)構(gòu)也應(yīng)該是一個字典, 其內(nèi)容如下:

result字段內(nèi)容

怎么看怎么都是個字典, 但是使用如下方式轉(zhuǎn)換的時候:

guard let result: Dictionary<String, Any> = resultDic?["result"] as? Dictionary<String, Any> else {
       printLog(message: "error  return")
       return
}

其結(jié)果總是nil, 怎么都不能轉(zhuǎn)換為字典. 后來查了一些資料, 說這個字段對應(yīng)的是一個字符串, 需要自己分割去獲取相應(yīng)的結(jié)果. 嘗試轉(zhuǎn)成字符串試試:

let obj = resultDic?["result"]
let obj1 = obj as? String

obj1 正確轉(zhuǎn)換為一個字符串, 不過這個字符串是這樣的:

{\"alipay_trade_app_pay_response\":{\"code\":\"10000\",\"msg\":\"Success\",\"app_id\":\"2017012354656320\",\"auth_app_id\":\"2017098762379652\",\"charset\":\"UTF-8\",\"timestamp\":\"2017-07-26 15:27:39\",\"total_amount\":\"0.01\",\"trade_no\":\"2017080531001004110233498754\",\"seller_id\":\"2088376896937865\",\"out_trade_no\":\"2017080417556432152031721246532\"},\"sign\":\"XWwmxNraskQcaXx/8YL+lf6yWy0/Ws+hAIXxSznZfLM9C1kmcWcQ00PLteIctdI35yF3N4HdkVbGI697qMQbJiPZ+1yHGe1e3UXfqX7LUrVUN5M4hgXnPDf8ekHdPlLVnPeDrTKD3IcPXq5SU5d9U7kytGYQjx6LeHUuG/Oa3N/5pQXmr8xIf5z/kOiHCrXYEW7Eq4FVobliGRfKF2pSaB00Dt9zHTUSMPjw5KVfcM9D/ecniLbu8NtQ1y/mRalUIkDQ1HMNYAhinhUcxB6SHIkeenbeS67/TsrDYTIZoNKpMfY/8jqY+Yc8wwfkZFJYjjZCPuM8tvjCWOTMy/kcXA==\",\"sign_type\":\"RSA2\"}

繞了一大圈, 卻只能獲得一個字符串, 看到這個結(jié)果, 我是懵逼的, 這怎么搞? 沒辦法, 不能搞也得搞, 硬著頭皮上吧;

接下來就需要我們手動去處理這個字符串, 來獲取我們需要的信息.
一般我們想到的都是最好能轉(zhuǎn)換成一個字典, 這樣也方便我們?nèi)ナ褂? 那到底能不能轉(zhuǎn)換成字典呢? 直接轉(zhuǎn)換是不行的, 下面我使用兩種方式來處理這個結(jié)果:

方式一: 分割字符串

分割字符串后保存成字典時可以的.
回頭看看這個字符串的格式:

  1. 有一些多余的字符: \" { } ;
  2. 看似是鍵值對的之間都是以逗號(,)分割, 可以先以逗號(,)分割字符串, 得到都是鍵值對的字符數(shù)組;
  3. 鍵和值之間是以冒號分割, 然后再以冒號(:)分割, 得到鍵和值的數(shù)組, 再去取值即可;

注意: 此處的分割依據(jù), 不同的后臺寫的編碼格式, 可能會有不同, 根據(jù)自己獲取到支付結(jié)果來分割即可.

知道了這些就可以去手動分割處理這個字符串了:

  1. 去除多余字符串, 這里是以空字符串替換的形式
//1. 去除字符串內(nèi)的 \" 
        let str1 = str.replacingOccurrences(of: "\"", with: "")
        // 2. 去除字符串內(nèi)的 {
        let str2 = str1.replacingOccurrences(of: "{", with: "")
        // 3. 去除字符串內(nèi)的 }
        let str3 = str2.replacingOccurrences(of: "}", with: "")
  1. 以逗號(,)分割字符串, 得到的是一個鍵值對的字符串?dāng)?shù)組
// 4. 以逗號(,)分割字符串, 獲取到一個數(shù)組
        let arr = str3.components(separatedBy: ",")
  1. 然后遍歷這個數(shù)組, 對每一個字符串以冒號(:)進(jìn)行分割, 得到鍵和值的數(shù)組
for tmp in arr {
            let tmpArr = tmp.components(separatedBy: ":")
}

這時的結(jié)果數(shù)組里就包含鍵值兩個字符串, 仔細(xì)觀察會發(fā)現(xiàn), 這些小數(shù)組中有一個(第一個)是包含了三個元素的, 其余的都是2個元素, 然后, 以字典的形式來重新保存這些鍵值對:

for tmp in arr {
            let tmpArr = tmp.components(separatedBy: ":")
            // 這時的結(jié)果
            if tmpArr.count == 2 {
                let key = tmpArr[0]
                let value = tmpArr[1]
                dic[key] = value
            } else if tmpArr.count == 3 {
                let key = tmpArr[1]
                let value = tmpArr[2]
                dic[key] = value
            }
        }

完整的代碼如下, 最后返回一個正常的字典:

class func changeStringResultToDic(_ str: String) -> Dictionary<String, String> {
        //1. 去除字符串內(nèi)的 \" , 這里是以空字符串替換的形式
        let str1 = str.replacingOccurrences(of: "\"", with: "")
        // 2. 去除字符串內(nèi)的 {
        let str2 = str1.replacingOccurrences(of: "{", with: "")
        // 3. 去除字符串內(nèi)的 }
        let str3 = str2.replacingOccurrences(of: "}", with: "")
        // 4. 以逗號(,)分割字符串, 獲取到一個數(shù)組
        let arr = str3.components(separatedBy: ",")
        
        var dic: [String: String] = [:]
        // 5. 遍歷這個數(shù)組, 然后再以 : 來分割子字符串
        for tmp in arr {
            let tmpArr = tmp.components(separatedBy: ":")
            // 這時的結(jié)果
            if tmpArr.count == 2 {
                let key = tmpArr[0]
                let value = tmpArr[1]
                dic[key] = value
            } else if tmpArr.count == 3 {
                let key = tmpArr[1]
                let value = tmpArr[2]
                dic[key] = value
            }
        }
        
        return dic
    }
方式二: 先轉(zhuǎn)成Data, 然后再去解析為Dictionary

最簡單的方式是使用下面的方法先轉(zhuǎn)換為utf8編碼的Data數(shù)據(jù), 然后再使用JSONSerialization的方法來解析這個JSON數(shù)據(jù)為字典對象:

if let data = str.data(using: String.Encoding.utf8) {
            
            if let dic1 = try? JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: Any] {
                
                print(dic1)
                
                print(dic1!["alipay_trade_app_pay_response"]["out_trade_no"])
                
            }
        }

不過, 這種方式解析出來的字典不是以[String: String]方式的鍵值對, 而是[String: Any], 最好在這里處理成[String: String]以方便使用.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容