我正在使用MKStoreKit,并且在我的应用程序中观察了几个月的异常情况。一些用户开始向我发送消息,说他们的购买未完成。但是我做销售。
自4月以来,purchase_error_7
和purchase_error_6
都被调用了624次以上。
purchase_error_7
在这里:
- (void)startValidatingReceiptsAndUpdateLocalStore {
[self startValidatingAppStoreReceiptWithCompletionHandler:^(NSArray *receipts, NSError *error) {
if (error) {
NSLog(@"Receipt validation failed with error: %@", error);
[[NSNotificationCenter defaultCenter] postNotificationName:kMKStoreKitReceiptValidationFailedNotification object:error];
NSUInteger characterCount = [error.localizedDescription length];
if (characterCount > 80) {
characterCount = 80;
}
[FIRAnalytics logEventWithName:@"purchase_error_7"
parameters:@{
@"name": [error.localizedDescription substringToIndex:characterCount],
@"full_text": [[NSUserDefaults standardUserDefaults] stringForKey:@"UserDefaultID"]
}];
} else {
__block BOOL purchaseRecordDirty = NO;
[receipts enumerateObjectsUsingBlock:^(NSDictionary *receiptDictionary, NSUInteger idx, BOOL *stop) {
NSString *productIdentifier = receiptDictionary[@"product_id"];
NSNumber *expiresDateMs = receiptDictionary[@"expires_date_ms"];
if (expiresDateMs) { // renewable subscription
NSNumber *previouslyStoredExpiresDateMs = self.purchaseRecord[productIdentifier];
if (!previouslyStoredExpiresDateMs ||
[previouslyStoredExpiresDateMs isKindOfClass:NSNull.class]) {
self.purchaseRecord[productIdentifier] = expiresDateMs;
purchaseRecordDirty = YES;
} else {
if ([expiresDateMs doubleValue] > [previouslyStoredExpiresDateMs doubleValue]) {
self.purchaseRecord[productIdentifier] = expiresDateMs;
purchaseRecordDirty = YES;
}
}
}
}];
if (purchaseRecordDirty) {
[self savePurchaseRecord];
}
[self.purchaseRecord enumerateKeysAndObjectsUsingBlock:^(NSString *productIdentifier, NSNumber *expiresDateMs, BOOL *stop) {
if (![expiresDateMs isKindOfClass: [NSNull class]]) {
if ([[NSDate date] timeIntervalSince1970] > [expiresDateMs doubleValue]) {
[[NSNotificationCenter defaultCenter] postNotificationName:kMKStoreKitSubscriptionExpiredNotification object:productIdentifier];
}
}
}];
}
}];
}
purchase_error_6
在这里:
- (void)startValidatingAppStoreReceiptWithCompletionHandler:(void (^)(NSArray *receipts, NSError *error)) completionHandler {
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSError *receiptError;
BOOL isPresent = [receiptURL checkResourceIsReachableAndReturnError:&receiptError];
if (!isPresent) {
// No receipt - In App Purchase was never initiated
completionHandler(nil, nil);
return;
}
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
if (!receiptData) {
// Validation fails
NSLog(@"Receipt exists but there is no data available. Try refreshing the reciept payload and then checking again.");
completionHandler(nil, nil);
return;
}
NSError *error;
NSMutableDictionary *requestContents = [NSMutableDictionary dictionaryWithObject:
[receiptData base64EncodedStringWithOptions:0] forKey:@"receipt-data"];
NSString *sharedSecret = [MKStoreKit configs][@"SharedSecret"];
if (sharedSecret) requestContents[@"password"] = sharedSecret;
NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents options:0 error:&error];
#ifdef DEBUG
NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:kSandboxServer]];
#else
NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:kLiveServer]];
#endif
[storeRequest setHTTPMethod:@"POST"];
[storeRequest setHTTPBody:requestData];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:storeRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSInteger status = [jsonResponse[@"status"] integerValue];
if (jsonResponse[@"receipt"] != [NSNull null]) {
NSString *originalAppVersion = jsonResponse[@"receipt"][@"original_application_version"];
if (nil != originalAppVersion) {
[self.purchaseRecord setObject:originalAppVersion forKey:kOriginalAppVersionKey];
[self savePurchaseRecord];
}
else {
completionHandler(nil, nil);
}
}
else {
completionHandler(nil, nil);
}
if (status != 0) {
NSError *error = [NSError errorWithDomain:@"com.mugunthkumar.mkstorekit" code:status
userInfo:@{NSLocalizedDescriptionKey : errorDictionary[@(status)]}];
completionHandler(nil, error);
} else {
NSMutableArray *receipts = [jsonResponse[@"latest_receipt_info"] mutableCopy];
if (jsonResponse[@"receipt"] != [NSNull null]) {
NSArray *inAppReceipts = jsonResponse[@"receipt"][@"in_app"];
[receipts addObjectsFromArray:inAppReceipts];
completionHandler(receipts, nil);
} else {
completionHandler(nil, nil);
}
}
} else {
NSUInteger characterCount = [error.localizedDescription length];
if (characterCount > 80) {
characterCount = 80;
}
[FIRAnalytics logEventWithName:@"purchase_error_6"
parameters:@{
@"name": [error.localizedDescription substringToIndex:characterCount],
@"full_text": [[NSUserDefaults standardUserDefaults] stringForKey:@"UserDefaultID"]
}];
completionHandler(nil, error);
}
}] resume];
}