错误 21002:使用服务器的 IOS 收据验证
Posted
技术标签:
【中文标题】错误 21002:使用服务器的 IOS 收据验证【英文标题】:error 21002 : receipt validation for IOS using server 【发布时间】:2019-12-18 02:28:21 【问题描述】:我正在尝试通过我的服务器使用收据验证。但我收到 21002 错误“receipt-data 属性中的数据格式错误或丢失。”
我尝试了所有找到的 php 代码,但没有一个能工作。我尝试直接连接到沙箱,它工作正常,但是当我将它更改为我的服务器时,会出现此错误。
private func validateReceipt(completion : @escaping (_ status : Bool) -> ())
// Get receipt if available
if let appStoreReceiptURL = Bundle.main.appStoreReceiptURL,
FileManager.default.fileExists(atPath: appStoreReceiptURL.path)
do
let receiptData = try Data(contentsOf: appStoreReceiptURL, options: .alwaysMapped)
print(receiptData)
let receiptdata = receiptData.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 00))
let dict = ["receipt-data" : receiptdata]
let jsonData = try! JSONSerialization.data(withJSONObject: dict, options: JSONSerialization.WritingOptions(rawValue: 0))
let request = NSMutableURLRequest(url: NSURL(string: ReceiptURL.myServer.rawValue)! as URL)
let session = URLSession.shared
request.httpMethod = "POST"
request.httpBody = jsonData
let task = session.dataTask(with: request as URLRequest, completionHandler: data, response, error in
if let dataR = data
self.handleData(responseDatas: dataR as NSData, completion: status in
completion(status)
)
else
completion(false)
)
task.resume()
catch print("Couldn't read receipt data with error: " + error.localizedDescription)
private func handleData(responseDatas : NSData, completion : (_ status : Bool) -> ())
do
if let json = try JSONSerialization.jsonObject(with: responseDatas as Data, options: JSONSerialization.ReadingOptions.mutableLeaves) as? NSDictionary
if let value = json.value(forKeyPath: "status") as? Int
if value == 0
completion(true)
else
completion(false)
else
completion(false)
catch
print(error.localizedDescription)
PHP 代码端
<?php
function getReceiptData($receipt)
$fh = fopen('showme.txt',w);
fwrite($fh,$receipt);
fclose($fh);
$endpoint = 'https://sandbox.itunes.apple.com/verifyReceipt';
$ch = curl_init($endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $receipt);
$response = curl_exec($ch);
$errno = curl_errno($ch);
$errmsg = curl_error($ch);
curl_close($ch);
$msg = $response.' - '.$errno.' - '.$errmsg;
echo $response;
foreach ($_POST as $key=>$value)
$newcontent .= $key.' '.$value;
$new = trim($newcontent);
$new = trim($newcontent);
$new = str_replace('_','+',$new);
$new = str_replace(' =','==',$new);
if (substr_count($new,'=') == 0)
if (strpos('=',$new) === false)
$new .= '=';
$new = '"receipt-data":"'.$new.'"';
$info = getReceiptData($new);
?>
有什么建议吗? 为什么这段代码不起作用?
编辑 1:
我尝试使用邮递员并连接到 sandbox.itunes.com,但我得到了同样的错误
Postman Pic
我认为现在问题出在这行代码上
let receiptdata = receiptData.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 00))
我正在尝试解决它。有什么建议吗?
【问题讨论】:
How to ask a good question & What topics can I ask about here? 【参考方案1】:有php代码,参考my answer。
使用post,只需使用json格式的原始post数据。
在你的 php 代码中,你不应该做 str_replace
的工作,数据已经很好地 base64 编码,只需使用它。
在您的邮递员中,您应该使用 json 原始邮递数据。参考What is the difference between form-data, x-www-form-urlencoded and raw in the Postman Chrome application?
【讨论】:
以上是关于错误 21002:使用服务器的 IOS 收据验证的主要内容,如果未能解决你的问题,请参考以下文章
在使用 Swift 的应用程序收据验证中返回代码 21002
Firebase Firestore +云功能服务器端验证应用内购买收据(Swift + NodeJS)
Firebase Firestore + Cloud Function 服务器端验证应用内购买收据(Swift + NodeJS)