我在应用程序委托中调用收据验证方法来检查可续订过程。它在开发模式下工作正常,但在从应用商店发布后,即使用户尚未购买该产品,它总是返回是。请建议我做错了什么。在沙盒模式下它工作正常,但在发布后我发现它总是返回 true 的问题。为了验证收据,我使用以下代码
验证收据
+(BOOL ) getStoreReceipt:(BOOL)sandbox andTrasaction:(SKPaymentTransaction *)tractaion{
NSArray *objects;
NSArray *keys;
NSDictionary *dictionary;
BOOL gotreceipt = false;
@try {
NSURL *receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
if ([[NSFileManager defaultManager] fileExistsAtPath:[receiptUrl path]]) {
NSData *receiptData = [NSData dataWithContentsOfURL:receiptUrl];
NSString *receiptString = [self base64forData:receiptData];
NSLog(@"receiptString Value---->= %@",receiptString);
NSString *encReceipt = [receiptData base64EncodedStringWithOptions:0];
NSLog(@"receiptString Value ======>= %@",encReceipt);
if (receiptString != nil) {
NSString *strSharedSecrect = @"MY_Secrect_Key";
objects = [[NSArray alloc] initWithObjects:receiptString,strSharedSecrect, nil];
keys = [[NSArray alloc] initWithObjects:@"receipt-data",@"password", nil];
dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
NSString *postData = [self getJsonStringFromDictionary:dictionary];
NSLog(@"postData Value---->= %@",receiptString);
NSString *urlSting = @"https://buy.itunes.apple.com/verifyReceipt";
// if (sandbox) urlSting = @"https://sandbox.itunes.apple.com/verifyReceipt";
dictionary = [self getJsonDictionaryWithPostFromUrlString:urlSting andDataString:postData];
NSLog(@"dictionary Value for receipt---->= %@",dictionary);
if ([dictionary objectForKey:@"status"] != nil) {
if ([[dictionary objectForKey:@"status"] intValue] == 0) {
gotreceipt = true;
}
}
}
}//623065
} @catch (NSException * e) {
gotreceipt = false;
return NO;
NSLog(@"NSException---->= %@",e);
}
if (!gotreceipt) {
NSLog(@"Not gotreceipt---->=");
objects = [[NSArray alloc] initWithObjects:@"-1", nil];
keys = [[NSArray alloc] initWithObjects:@"status", nil];
dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];
return NO;
}else{
BOOL isPurchased = [self PurchasedSubscriptionStatues:dictionary];
return isPurchased;
}
return NO;
}
检查是否有待更新...
+(BOOL)PurchasedSubscriptionStatues:(NSDictionary *)transactionReceipt
{
if ([[transactionReceipt allKeys] containsObject:@"pending_renewal_info"]) {
NSArray *arrData = [transactionReceipt objectForKey:@"pending_renewal_info"];
NSDictionary *dicPendinRenew = [arrData objectAtIndex:0];
if ([[dicPendinRenew allKeys] containsObject:@"expiration_intent"] || [[dicPendinRenew objectForKey:@"auto_renew_status"] integerValue]==0) {
return NO;
}else if ([[dicPendinRenew objectForKey:@"auto_renew_status"] integerValue]==1) {
return YES;
}else{
return NO;
}
}else{
return YES;
}
return NO;
}
将字符串转换为字典
+(NSString *)getJsonStringFromDictionary:(NSDictionary *)dicVal
{
NSError *error = nil;
NSData *postData = [NSJSONSerialization dataWithJSONObject:dicVal options:NSJSONWritingPrettyPrinted error:&error];
NSString *postString = @"";
if (! postData) {
NSLog(@"Got an error: %@", error);
return nil;
}
else { postString = [[NSString alloc] initWithData:postData encoding:NSUTF8StringEncoding];
return postString;
}
}
Convert Dictionary to string
+(NSDictionary *) getJsonDictionaryWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
NSString *jsonString = [self getStringWithPostFromUrlString:urlString andDataString:dataString];
NSLog(@"getJsonDictionaryWithPostFromUrlString-->%@", jsonString); // see what the response looks like
return [self getDictionaryFromJsonString:jsonString];
}
+ (NSDictionary *) getDictionaryFromJsonString:(NSString *)jsonstring {
NSError *jsonError;
NSDictionary *dictionary = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:[jsonstring dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&jsonError];
if (jsonError) {
dictionary = [[NSDictionary alloc] init];
}
return dictionary;
}
请求发布方法以获取回复
+ (NSString *) getStringWithPostFromUrlString:(NSString *)urlString andDataString:(NSString *)dataString {
NSString *s = @"";
@try {
NSData *postdata = [dataString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postlength = [NSString stringWithFormat:@"%d", [postdata length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setTimeoutInterval:60];
[request setHTTPMethod:@"POST"];
[request setValue:postlength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postdata];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
if (data != nil) {
s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
}
@catch (NSException *exception) {
s = @"";
}
return s;
}
// from https://stackoverflow.com/questions/2197362/converting-nsdata-to-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];
}
------------------------------------------------------------------------
我认为您的PurchasedSubscriptionStatues
方法有错误:如果收据不包含pending_renewal_info
密钥,则返回YES
.尝试创建一个新的沙盒用户,并查看收据是否包含此密钥,如果没有 - 在这种情况下,此方法应返回NO
。
此外,您可以尝试使用一些可以管理应用内购买的库,例如 RMStore,以简化收据验证。