문제

나는 며칠 동안 앱 구매에서 놀았습니다. 앱 스토어로 영수증을 검증하려고 할 때까지 모든 것이 잘 작동합니다.

영수증 데이터를 내 PHP 서버로 전달한 다음 거기에서 App Store로 전달하고 유효한 응답을 얻으면 영수증 데이터를 데이터베이스에 추가하려고합니다.

Store Kit 프로그래밍 안내서와 클래스 참조는이 특정 영역에 대해 쓸모가 없어서 실제로 어떤 종류의 예전도 제공하지 않기 때문에 유용한 것을 찾았습니다. 기사 그것은 나를 조금 도왔지만 여전히 뭔가 잘못되었습니다.

기본적으로 나는 영수증 검증을받은 사람이 내가 아무데도 없을 때 자신의 코드를 기꺼이 공유 할 것인지 궁금합니다.

감사

도움이 되었습니까?

해결책

먼저 게시 된 코드에 몇 가지 오타가 있습니다. 이 시도. (면책 조항 : Refactoring et. Al은 독자의 운동으로 남겨 둡니다!)

- (BOOL)verifyReceipt:(SKPaymentTransaction *)transaction {
    NSString *jsonObjectString = [self encode:(uint8_t *)transaction.transactionReceipt.bytes length:transaction.transactionReceipt.length];      
    NSString *completeString = [NSString stringWithFormat:@"http://url-for-your-php?receipt=%@", jsonObjectString];               
    NSURL *urlForValidation = [NSURL URLWithString:completeString];       
    NSMutableURLRequest *validationRequest = [[NSMutableURLRequest alloc] initWithURL:urlForValidation];              
    [validationRequest setHTTPMethod:@"GET"];         
    NSData *responseData = [NSURLConnection sendSynchronousRequest:validationRequest returningResponse:nil error:nil];  
    [validationRequest release];
    NSString *responseString = [[NSString alloc] initWithData:responseData encoding: NSUTF8StringEncoding];
    NSInteger response = [responseString integerValue];
    [responseString release];
    return (response == 0);
}

- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length {
    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    NSMutableData *data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t *output = (uint8_t *)data.mutableBytes;

    for (NSInteger i = 0; i < length; i += 3) {
        NSInteger value = 0;
        for (NSInteger j = i; j < (i + 3); j++) {
            value <<= 8;

            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }

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

    return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
}

당신은 당신의 내부 방법을 당신의 skpaymenttransactionObserver 메시지 :

@interface YourStoreClass (Internal)
- (BOOL)verifyReceipt:(SKPaymentTransaction *)transaction;
- (NSString *)encode:(const uint8_t *)input length:(NSInteger)length;
@end

참고 : 당신 ~할 수 있었다 같은 것을 사용하십시오 Libcrypto Base64 인코딩을 처리하려면 앱 승인 시간에서 내보내기 제한 및 추가 단계를보고 있습니다. 하지만 나는 멍청이 ...

그런 다음 원격 서버에서 트랜잭션 녹음을 시작하려는 곳마다 verifyreceipt : 거래를 통해 긍정적 인 거래를 다시 확인하십시오.

한편, 서버에서는 다음을 처리 할 수있는 수퍼 스트리핑 PHP가 있습니다.

$receipt = json_encode(array("receipt-data" => $_GET["receipt"]));
// NOTE: use "buy" vs "sandbox" in production.
$url = "https://sandbox.itunes.apple.com/verifyReceipt";
$response_json = call-your-http-post-here($url, $receipt);
$response = json_decode($response_json);

// Save the data here!

echo $response->status;

어디에 콜-http-post-here 가장 좋아하는 HTTP Post 메커니즘입니다. (곱슬 곱슬하다 가능한 선택입니다. ymmv. php.net에는 특종이 있습니다!)

약간 걱정하는 한 가지는 앱에서 서버로 이동하는 URL의 페이로드 길이입니다 (GET). RFC에 따라 길이 문제가 있는지 잊어 버립니다. 어쩌면 괜찮거나 서버 특정 일 수도 있습니다. (독자 :이 부분에 대한 조언을 환영합니다!)

이것을 동기 요청으로 만들 때 약간의 욕설이있을 수 있습니다. 당신은 그것을 비동기 적으로 게시하고 ol '을 올릴 수 있습니다. uiactivityindicatorview 또는 다른 HUD. 적절한 경우 : 그 InitwithData : 인코딩 : 전화는 나를 위해 loooooong 시간이 걸립니다. 몇 초, iPhone Land의 작은 영원 (또는 그 문제에 대한 다른 온라인). 어떤 종류의 불확실한 진행률 표시기를 보여주는 것이 좋습니다.

다른 팁

PHP 구현의 호스팅 된 예제뿐만 아니라 전체 소스 코드는 다음에서 사용할 수 있습니다. https://github.com/chrismaddern/ios-receipt-validator-php

도움이되기를 바랍니다!

인앱 구매 서버 모델을 사용할 때 발생할 수있는 연결 또는 검증 오류를 처리하는 방법이 궁금한 사람이라면 누구나. 영수증 검증은 거래가 완전하고 성공할 수 있도록합니다. 사용자의 전화를 실제로 믿을 수 없기 때문에 iPhone에서 그렇게하고 싶지 않습니다.

  1. 사용자는 인앱 구매를 시작합니다
  2. 완료되면 앱은 서버에게 유효성 검사를 요청합니다.
  3. Apple과의 영수증을 확인하십시오. 유효한 경우 구매에 연결된 모든 조치를 수행 할 수 있습니다 (콘텐츠 잠금 해제/제공, 구독 등록 ...)
  4. 앱은 큐에서 트랜잭션을 제거합니다 (FinishTransaction)

서버가 다운되면 트랜잭션을 완료하지 않지만 사용자에게 "사용할 수없는 메시지"를 표시해야합니다.

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions

나중에 다시 호출됩니다.

하지만 영수증이 유효하지 않다는 것을 알게되면 관련 거래를 완료해야합니다. 그렇지 않다면, 거래 대기열에서 영원히 살아가는 교도소가있을 수 있습니다. 즉, 앱이 실행될 때마다 PaymentQueue : UpdatedTransaction : 거래 당 한 번 호출됩니다 ...

내 앱에서 영수증 유효성 검사는 웹 서비스를 통해 수행되며 유효하지 않은 영수증의 경우 오류 코드를 반환합니다. 그렇기 때문에 외부 서버가 필요한 이유입니다. 사용자가 어떻게 든 영수증 유효성 검사를 건너 뛰는 경우 (웹 서비스 "성공"응답을 위조하여) 서버에 구매 추적이 없기 때문에 콘텐츠 / 액세스 기능을 잠금 해제 할 수 없습니다.

잠시 동안 이것으로 싸운 후 마침내 Apple의 문서에서 상태 코드 목록을 찾았습니다. 포함 끔찍한 21002 ( "영수증 데이터 속성의 데이터는 기본적으로"). 이 목록에 포함되지 않은 다른 상태 코드에 대한 보고서를 보았지만 지금은 Apple이 문서화 한 것 이상으로 보지 못했습니다. 이 코드는 다른 종류의 인앱 구매가 아닌 자동 갱신 구독에만 유효합니다 (또는 문서에 표시).

문제의 문서를 찾을 수 있습니다 여기.

나는 여기에서 Ray Wenderlich의 튜토리얼을 발견하지 못한 것에 놀랐습니다. 방금 내 생명을 구했습니다. 서버없이 영수증 검증을 겪습니다 (권장 솔루션이 아니라 어쨌든 심하게 수행).

http://www.raywenderlich.com/23266/in-apppurchases-in-ios-6-tutorial-consumables 및 receipt-validation

당신은 보내야합니다 영수증 PHP 서버의 파일로 PHP 측 에서이 스크립트를 사용하여 다음을 확인할 수 있습니다.

<?php

$path = 'receipt'; // $_FILE['receipt-data']["tmp_name"];
$receipt = file_get_contents($path);

$json['receipt-data'] = base64_encode($receipt);

$post = json_encode($json);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"https://buy.itunes.apple.com/verifyReceipt");
curl_setopt($ch, CURLOPT_POST,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$result=curl_exec ($ch);

curl_close ($ch);

?>

https://gist.github.com/eduardo22i/9adc2191f71ea612a7d071342e1e4a6f

이것을 다시 열고 정보를 위해이 양식을 검색하는 대가로 2 센트를 추가하십시오.

방금 앱에서 IAP 서비스를 설정하고 동일한 21002 오류에 부딪쳤다. 21002는 PHP 서버에 대한 게시물이 비어있을 때 (따라서 앱 스토어에 대한 HTTP 요청이 비어 있음) 부적절하게 형식화 될 때 발생했습니다. 우리의 작업을 수행하기 위해 iPhone 측에서 Base64 인코딩 된 NSString에서 게시물 데이터를 설정 한 다음 HTTP 요청으로 서버로 보냈습니다.

그런 다음 서버에서 우리는 그것을 붙잡고 배열과 JSON을 사용했습니다. 이와 같이:

$receipt = json_encode(array("receipt-data"=>$_POST['receipt-data']));

Get 대신 게시물을 사용하는 것을 제외하고는 위와 동일하다는 것을 알 수 있습니다. 개인적인 취향.

그런 다음 Curl을 사용하여 샌드 박스에 게시하고 응답에 JSON_DECODE를 사용했습니다.

이것은이 주제에 대해 누구나 필요로하는 훌륭한 도서관입니다.

https://github.com/aporat/store-receipt-validator

그 이상을 넘어 검증합니다.

  • iTunes
  • 플레이 스토어
  • 아마존 앱 스토어

더 좋아하는 사람이 나를 돕는 데 도움이되기를 바랍니다.

NULL 응답 또는 오류 코드를받는 경우 21002를 사용하는 경우이 줄을 추가하십시오. CURL 오류 코드를 확인한 경우 SSL 인증서 오류입니다 ...

curl_setopt ($curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt ($curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top