错误 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)

反应原生 IAP:订阅总是返回状态:21002 a

如何使用 base64 对客户端“transaction.transactionReceipt”进行编码?

了解 iOS 中的收据验证和收据刷新