How to test app store purchase receipt to obtain original application version
我想在应用启动时加载应用购买收据。如何模拟应用购买(不是应用内购买,而是实际应用购买),以便获得收据? (我正在尝试从付费转为免费增值)。
我正在使用此代码加载收据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | (BOOL)isAppPreviouslyPurchased { BOOL wasPreviouslyPurchased = false; // Load the receipt from the app bundle. NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL]; NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL]; if (receiptData) { //read purchase version from receipt NSDictionary *receipt = [NSJSONSerialization JSONObjectWithData:receiptData options:0 error:nil]; NSString *oldVersion = receipt[@"original_application_version"]; float vFloat = [oldVersion floatValue]; if (vFloat < 1.6) { wasPreviouslyPurchased = true; } } return wasPreviouslyPurchased; } |
首先:刷新收据
1 2 3 | SKReceiptRefreshRequest *request = [[SKReceiptRefreshRequest alloc] init]; request.delegate = self; [request start]; |
添加
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { // Call the appropriate custom method for the transaction state. case SKPaymentTransactionStatePurchasing: [self showTransactionAsInProgress:transaction deferred:NO]; break; case SKPaymentTransactionStateDeferred: [self showTransactionAsInProgress:transaction deferred:YES]; break; case SKPaymentTransactionStateFailed: [self failedTransaction:transaction]; break; case SKPaymentTransactionStatePurchased: [self completeTransaction:transaction]; break; case SKPaymentTransactionStateRestored: [self restoreTransaction:transaction]; break; default: // For debugging NSLog(@"Unexpected transaction state %@", @(transaction.transactionState)); break; } } } |
然后,当此方法被调用时,您的收据将被刷新;)
其次:您必须解密收据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | NSData *receipt; // Sent to the server by the device // Create the JSON object that describes the request NSError *error; NSDictionary *requestContents = @{ @"receipt-data": [receipt base64EncodedStringWithOptions:0] }; NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents options:0 error:&error]; if (!requestData) { /* ... Handle error ... */ } // Create a POST request with the receipt data. NSURL *storeURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"]; NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL]; [storeRequest setHTTPMethod:@"POST"]; [storeRequest setHTTPBody:requestData]; // Make a connection to the iTunes Store on a background queue. NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if (connectionError) { /* ... Handle error ... */ } else { NSError *error; NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; if (!jsonResponse) { /* ... Handle error ...*/ } /* ... Send a response back to the device ... */ } }]; |
您可以使用此代码对其进行解密,但是Apple并没有真正建议使用。您应该从服务器呼叫iTunes。
然后,您可以使用Apple服务器返回的响应来调用您的方法。
就像这样(使用本地验证,就像苹果所说的那样不好)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | NSData *receipt; // Sent to the server by the device // Create the JSON object that describes the request NSError *error; NSDictionary *requestContents = @{ @"receipt-data": [receipt base64EncodedStringWithOptions:0] }; NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents options:0 error:&error]; if (!requestData) { /* ... Handle error ... */ } // Create a POST request with the receipt data. NSURL *storeURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"]; NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL]; [storeRequest setHTTPMethod:@"POST"]; [storeRequest setHTTPBody:requestData]; // Make a connection to the iTunes Store on a background queue. NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [NSURLConnection sendAsynchronousRequest:storeRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if (connectionError) { /* ... Handle error ... */ } else { NSError *error; NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; if (!jsonResponse) { /* ... Handle error ...*/ } [self isAppPreviouslyPurchased:jsonResponse]; } }]; -(BOOL)isAppPreviouslyPurchased:(NSDictionary *)receipt { BOOL wasPreviouslyPurchased = false; NSString *oldVersion = receipt[@"original_application_version"]; float vFloat = [oldVersion floatValue]; if (vFloat < 1.6) { wasPreviouslyPurchased = true; } return wasPreviouslyPurchased; } |