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

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

雖然json格式不對, 但是可以正確的獲取狀態(tài)碼, 即"resultStatus" 字段是可以正常獲取到的, 問題就出在獲取結(jié)果內(nèi)容時, 即: "result" 字段對應(yīng)的內(nèi)容, 看結(jié)構(gòu)也應(yīng)該是一個字典, 其內(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é)果:
方式一: 分割字符串
分割字符串后保存成字典時可以的.
回頭看看這個字符串的格式:
- 有一些多余的字符: \" { } ;
- 看似是鍵值對的之間都是以逗號(,)分割, 可以先以逗號(,)分割字符串, 得到都是鍵值對的字符數(shù)組;
- 鍵和值之間是以冒號分割, 然后再以冒號(:)分割, 得到鍵和值的數(shù)組, 再去取值即可;
注意: 此處的分割依據(jù), 不同的后臺寫的編碼格式, 可能會有不同, 根據(jù)自己獲取到支付結(jié)果來分割即可.
知道了這些就可以去手動分割處理這個字符串了:
- 去除多余字符串, 這里是以空字符串替換的形式
//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: "")
- 以逗號(,)分割字符串, 得到的是一個鍵值對的字符串?dāng)?shù)組
// 4. 以逗號(,)分割字符串, 獲取到一個數(shù)組
let arr = str3.components(separatedBy: ",")
- 然后遍歷這個數(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]以方便使用.