我正在尝试通过服务器使用收据验证。但出现21002错误“ receiving-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连接,但遇到了相同的错误
我认为现在问题出在这行代码上
let receiptdata = receiptData.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 00))
我正在尝试解决它。有什么建议吗?
答案 0 :(得分:0)
有关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?