【问题标题】:Status 21002 While Verifying Transaction Receipt验证交易收据时的状态 21002
【发布时间】:2012-10-18 22:27:44
【问题描述】:

我尝试查看所有其他问题,但似乎没有任何解决此问题的方法。我已经缩小范围,所以来自https://sandbox.itunes.apple.com/verifyReceipt 的响应只是{"status":21002}。任何帮助将不胜感激,我已经复制了下面的相关代码。

NSString *completeString = @"http://www.mysite.com/verify.php";

NSURL *urlForValidation = [NSURL URLWithString:completeString];

NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation];

[validationRequest setHTTPMethod:@"POST"];

NSString *strTest = [NSString stringWithFormat:@"receipt=%@", [self createEncodedString:transaction.transactionReceipt]];

[validationRequest setHTTPBody:[NSData dataFromBase64String:strTest]];

NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil];

NSString *response = [[NSString alloc] initWithData: responseData encoding: NSUTF8StringEncoding];

NSLog(@"%@", response);

- (NSString*) createEncodedString:(NSData*)data {
    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    const int size = ((data.length + 2)/3)*4;
    uint8_t output[size];

    const uint8_t* input = (const uint8_t*)[data bytes];
    for (int i = 0; i < data.length; i += 3)
    {
        int value = 0;
        for (int j = i; j < (i + 3); j++)
        {
            value <<= 8;
            if (j < data.length)
                value |= (0xFF & input[j]);
        }

        const int index = (i / 3) * 4;
        output[index + 0] =  table[(value >> 18) & 0x3F];
        output[index + 1] =  table[(value >> 12) & 0x3F];
        output[index + 2] = (i + 1) < data.length ? table[(value >> 6)  & 0x3F] : '=';
        output[index + 3] = (i + 2) < data.length ? table[(value >> 0)  & 0x3F] : '=';
    }

    return  [[NSString alloc] initWithBytes:output length:size encoding:NSASCIIStringEncoding];
}

最后这是使用的PHP代码:

$url = 'https://sandbox.itunes.apple.com/verifyReceipt';

$receipt = "{%s}" % $_POST["receipt"];

$purchase_encoded = base64_encode( $receipt );

$encodedData = json_encode( Array( 
    'receipt-data' => $purchase_encoded 
) );

//Open a Connection using POST method, as it is required to use POST method.
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $encodedData);
$encodedResponse = curl_exec($ch);
curl_close($ch);


//Decode response data using json_decode method to get an object.

echo $encodedResponse;

$response = json_decode( $encodedResponse );

echo $response;

【问题讨论】:

    标签: php objective-c ios in-app-purchase


    【解决方案1】:

    经过一番折腾,我终于弄明白了。我相信最大的错误在于我如何设置 HTTP 正文。最终代码如下,希望这可以帮助其他人!

    目标-C:

    NSString *completeString = @"http://www.mysite.com/verify.php";
    
    NSURL *urlForValidation = [NSURL URLWithString:completeString];
    
    NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation];
    
    [validationRequest setHTTPMethod:@"POST"];
    
    NSString *strTest = [NSString stringWithFormat:@"receipt=%@", [self base64forData:transaction.transactionReceipt]];
    
    [validationRequest setHTTPBody:[strTest dataUsingEncoding:NSUTF8StringEncoding]];
    
    NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil];
    
    NSString *response = [[NSString alloc] initWithData: responseData encoding: NSUTF8StringEncoding];
    
    NSLog(@"%@", response);
    

    PHP:

    $url = 'https://sandbox.itunes.apple.com/verifyReceipt';
    
    $encodedData = json_encode( Array( 
        'receipt-data' => $_POST["receipt"] 
    ) );
    
    
    //Open a Connection using POST method, as it is required to use POST method.
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $encodedData);
    $encodedResponse = curl_exec($ch);
    curl_close($ch);
    
    $response = json_decode( $encodedResponse );
    
    /*
    echo "Status Code:";
    
    echo $response->{'status'};
    */
    
    if ($response->{'status'} != 0) {
        echo "FAIL";
    } else {
        echo "SUCCESS";
    }
    

    【讨论】:

      【解决方案2】:

      nlutterman 的回答是正确的!它对我帮助很大。 如果有人试图让他的解决方案发挥作用,那么只有使用以下方法将收据数据编码为 base64(应用内),它才会起作用。

      - (NSString*)base64forData:(NSData*)theData {
      const uint8_t* input = (const uint8_t*)[theData bytes];
      NSInteger length = [theData length];
      
      static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
      
      NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
      uint8_t* output = (uint8_t*)data.mutableBytes;
      
      NSInteger i;
      for (i=0; i < length; i += 3) {
          NSInteger value = 0;
          NSInteger j;
          for (j = i; j < (i + 3); j++) {
              value <<= 8;
      
              if (j < length) {
                  value |= (0xFF & input[j]);
              }
          }
      
          NSInteger theIndex = (i / 3) * 4;
          output[theIndex + 0] =                    table[(value >> 18) & 0x3F];
          output[theIndex + 1] =                    table[(value >> 12) & 0x3F];
          output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
          output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
      }
      
      return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; }
      

      正常的base64EncodedStringWithOptions: 不起作用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-11-16
        • 2015-12-26
        • 2021-01-10
        • 2017-01-11
        • 2019-12-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多