Ios 获取应用内购买的订阅过期日期-从appStoreReceiptURL开始

Ios 获取应用内购买的订阅过期日期-从appStoreReceiptURL开始,ios,objective-c,in-app-purchase,Ios,Objective C,In App Purchase,我有一个应用内购买,是一个自动续费订阅。从已完成的应用内购买中,我需要能够检索订阅到期日期,以便知道订阅何时不再有效。我的理解是,这意味着(从iOS 7开始)从appStoreReceiptURL开始,获取其背后的数据,然后以某种方式从那里我可以访问有关应用内购买的元素 但是从那里开始就很模糊,我在网上找到的代码示例似乎都不起作用。它们中的很多都已经过时了。它们中的大多数根本不涉及订阅。我真正需要的是一些从appStoreReceiptURL到订阅到期日期的直线示例代码,中间的代码行最少。出于某

我有一个应用内购买,是一个自动续费订阅。从已完成的应用内购买中,我需要能够检索订阅到期日期,以便知道订阅何时不再有效。我的理解是,这意味着(从iOS 7开始)从appStoreReceiptURL开始,获取其背后的数据,然后以某种方式从那里我可以访问有关应用内购买的元素

但是从那里开始就很模糊,我在网上找到的代码示例似乎都不起作用。它们中的很多都已经过时了。它们中的大多数根本不涉及订阅。我真正需要的是一些从appStoreReceiptURL到订阅到期日期的直线示例代码,中间的代码行最少。出于某种原因,这似乎非常困难,但我不明白为什么。通常情况下,人们会将收据验证纳入其中,这似乎是一个好主意,但它也增加了另一个巨大的复杂性,这模糊了我的主要目标,而且收据验证代码似乎总是不起作用。而我似乎总是遇到麻烦的地方是我获取NSData并对其进行base64编码。看起来应该是这样的:

NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSLog(@"receiptURL:%@", receiptURL);

NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
NSLog(@"receiptData:%@", receiptData);

NSString *receiptString = [self base64forData:receiptData];
NSLog(@"receiptString:%@", receiptString);
// from http://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];
}
其中base64forData方法如下所示:

NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSLog(@"receiptURL:%@", receiptURL);

NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
NSLog(@"receiptData:%@", receiptData);

NSString *receiptString = [self base64forData:receiptData];
NSLog(@"receiptString:%@", receiptString);
// from http://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];
}
//来自http://stackoverflow.com/questions/2197362/converting-nsdata-to-base64
+(NSString*)base64forData:(NSData*)数据{
常量uint8_t*输入=(常量uint8_t*)[数据字节];
NSInteger长度=[数据长度];
静态字符表[]=“abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzo123456789+/=”;
NSMutableData*数据=[NSMutableData数据长度:((长度+2)/3)*4];
uint8_t*输出=(uint8_t*)data.mutableBytes;
恩森特格尔一世;
对于(i=0;i>12)&0x3F];
输出[索引+2]=(i+1)>6)和0x3F]:'=';
输出[索引+3]=(i+2)>0)和0x3F]:'=';
}
return[[NSString alloc]initWithData:数据编码:NSASCIIStringEncoding];
}
在输出中,我返回一个有效的receiptURL,但只有在我在应用程序委托中执行代码时才返回。如果我尝试在像store observer这样的子类中执行它,它总是返回nil。我现在忽略它,只是在应用程序委托中执行它。然后,如果receiptURL有效,我将获得一个有效的receiptData块,然后是receiptString所以看起来base64forData方法不起作用,或者整个方法都是错误的


从iOS 7中未被弃用的已完成SKPaymentTransaction中获取订阅到期日的最简单方法是什么?

我们使用苹果的app store收据验证服务。Tom Kincaid对这个问题的回答中有很好的示例代码:-


嗨,John,你解决了这个问题吗?我也有同样的问题,搜索了很长时间,但一直没有找到答案。使用Apple itunes收据验证服务-请参阅中的注释。如果能看到这些日志行的输出,并与我自己的数据进行比较,以了解我是否有正确的数据开始,那就太好了。