Apple からのメッセージを確認する
「あなたのアプリは領収書の検証を正しく実装していないことがわかりました。そのため、レビュー (サンドボックス) 環境と本番環境を適切に区別していません。これにより、サンドボックスの領収書チェックではなく、本番サーバーへの検証クエリが発生し、.あなたのアプリを審査することを妨げています。」
私たちの質問: 私たちはアプリケーションでローカルにレシートを確認しています。号を購読すると、領収書を受け取ります。アプリケーションは、レシートがサンドボックスに属しているか本番環境に属しているかを知りません。したがって、アプリは最初に領収書を本番サーバーに送信します。運用サーバーは、領収書がサンドボックス環境に属していることを示す 21007 を返します。その後、同じものをサンドボックス環境に送信します。この手順が間違っていたかどうかを明確にしていただけますか?
サブスクリプション成功後 領収書の取得:
-(void)checkReceipt:(NSData *)receipt forProdictId:(NSString *) productid
{
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
[appDel showProgressViewWithText:@“Please wait...”];
[ReceiptCheck validateReceiptWithData:receipt completionHandler:^(BOOL success,NSString *response)
{
if(success==YES)
{
[self updateReceipt:receipt withResponse:response];
}
else
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate hideProgressView];
}
}
}
----------------------------領収書の検証-------------------- --------------
#import "ReceiptCheck.h"
#import "NSString+Base64.h"
#import "SBJSON.h"
#define SHARED_SECRET @"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
#define RECEIPT_URL_SANDBOX @"https://sandbox.itunes.apple.com/verifyReceipt"
#define RECEIPT_URL_PRODUCTION @"https://buy.itunes.apple.com/verifyReceipt"
@implementation ReceiptCheck
@synthesize receiptData,completionBlock;
+(ReceiptCheck *)validateReceiptWithData:(NSData *)_receiptData completionHandler:(void(^)(BOOL,NSString *))handler {
ReceiptCheck *checker = [[ReceiptCheck alloc] init];
checker.receiptData=_receiptData;
checker.completionBlock=handler;
[checker checkReceipt];
return checker;
}
-(void)checkReceipt {
// verifies receipt with Apple
NSError *jsonError = nil;
NSString *receiptBase64 = [NSString base64StringFromData:receiptData length:[receiptData length]];
// NSLog(@"Receipt Base64: %@",receiptBase64);
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithObjectsAndKeys: receiptBase64,@"receipt-data", SHARED_SECRET,@"password", nil] options:NSJSONWritingPrettyPrinted error:&jsonError];
if(jsonError)
{
completionBlock(NO,[jsonError localizedDescription]);
return;
}
NSURL *requestURL = [NSURL URLWithString:RECEIPT_URL_PRODUCTION];
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:requestURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:150];
[req setHTTPMethod:@"POST"];
[req setHTTPBody:jsonData];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if(conn)
{
receivedData = [[NSMutableData alloc] init];
} else
{
completionBlock(NO,@"Cannot create connection.");
}
}
-(void)checkReceiptSandBox {
// verifies receipt with Apple
NSError *jsonError = nil;
NSString *receiptBase64 = [NSString base64StringFromData:receiptData length:[receiptData length]];
// NSLog(@"Receipt Base64: %@",receiptBase64);
//NSString *jsonRequest=[NSString stringWithFormat:@"{\"receipt-data\":\"%@\"}",receiptBase64];
//NSLog(@"Sending this JSON: %@",jsonRequest);
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:[NSDictionary dictionaryWithObjectsAndKeys: receiptBase64,@"receipt-data", SHARED_SECRET,@"password", nil] options:NSJSONWritingPrettyPrinted error:&jsonError];
//NSLog(@"JSON: %@",[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding] );
if(jsonError)
{
completionBlock(NO,[jsonError localizedDescription]);
return;
}
NSURL *requestURL = [NSURL URLWithString:RECEIPT_URL_SANDBOX];
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:requestURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:150];
[req setHTTPMethod:@"POST"];
[req setHTTPBody:jsonData];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:req delegate:self];
if(conn)
{
receivedData = [[NSMutableData alloc] init];
} else
{
completionBlock(NO,@"Cannot create connection.");
}
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
completionBlock(NO,[error localizedDescription]);
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[receivedData appendData:data];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *response = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
NSData* data = [response dataUsingEncoding:NSUTF8StringEncoding];
NSString *json_string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
SBJSON *parser = [[SBJSON alloc] init];
NSDictionary *values = [parser objectWithString:json_string error:nil];
if([values valueForKey:@"status"])
{
if([[values valueForKey:@"status"] integerValue] == 21007)
{ // SAND BOX RECEIPT
[self checkReceiptSandBox];
return;
}
}
completionBlock(YES,response);
}
@end
更新受領後:
- (void) updateReceipt:(NSData *)receipt withResponse:(NSString *)response
{
NSData* data = [response dataUsingEncoding:NSUTF8StringEncoding];
NSString *json_string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
SBJSON *parser = [[SBJSON alloc] init];
NSDictionary *values = [parser objectWithString:json_string error:nil];
NSLog(@"%@",values);
if([[values valueForKey:@"status"] integerValue] == 0)
{
NSString *strReceipt=@"";
if([values valueForKey:@"latest_receipt"])
{
strReceipt = [values valueForKey:@"latest_receipt"];
if([values valueForKey:@"latest_receipt_info"])
{
[self saveReceiptDetailsWithReceipt:strReceipt andReceiptInfo:values];
NSString *strProductID = [[values valueForKey:@"latest_receipt_info"] valueForKey:@"product_id"];
NSLog(@"%@",strProductID);
WebServices *webService = [[WebServices alloc] init];
webService.delegate=self;
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
[appDel showProgressViewWithText:@"Please wait..."];
webService.strSubscriptionProductID=strProductID;
[webService afterSubscription:values andSubscriptionId:[self getSubscriptionIDForProductID:strProductID] receipt:strReceipt];
}
}
}
else if([[values valueForKey:@"status"] integerValue] == 21006)
{
NSString *strReceipt=[NSString base64StringFromData:receipt length:[receipt length]];
if([values valueForKey:@"latest_expired_receipt_info"])
{
[self saveReceiptDetailsWithReceipt:strReceipt andReceiptInfo:values];
}
}
else if([[values valueForKey:@"status"] integerValue] == 21000)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"JSON Error" message:[NSString stringWithFormat:@"The App Store could not read the JSON object you provided."] delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
}
else if([[values valueForKey:@"status"] integerValue] == 21002)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Data Error" message:[NSString stringWithFormat:@"The data in the receipt-data property was malformed."] delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
}
else if([[values valueForKey:@"status"] integerValue] == 21003)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Receipt Authentication Error" message:[NSString stringWithFormat:@"The receipt could not be authenticated."] delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
}
else if([[values valueForKey:@"status"] integerValue] == 21004)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Shared Secret Error" message:[NSString stringWithFormat:@"The shared secret you provided does not match the shared secret on file for your account."] delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
}
else if([[values valueForKey:@"status"] integerValue] == 21005)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Server Error" message:[NSString stringWithFormat:@"The receipt server is not currently available."] delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
}
else if([[values valueForKey:@"status"] integerValue] == 21007)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Receipt Error" message:[NSString stringWithFormat:@"This receipt is a sandbox receipt, but it was sent to the production service for verification."] delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
}
else if([[values valueForKey:@"status"] integerValue] == 21008)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Receipt Error" message:[NSString stringWithFormat:@"This receipt is a production receipt, but it was sent to the sandbox service for verification."] delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
[alert show];
}
}