IOS应用内支付返回新旧Receipt适配

作者: 48d585b6cf69 | 来源:发表于2017-12-20 15:48 被阅读179次

    ios7.0后ios支付成功返回的票据Receipt的获取方式有了新的方式,

    原来的SKPaymentTransaction中的transactionReceipt属性获取票据的方式已经过期,虽然还能使用,但是苹果官方建议使用新的

    新版的获取Receipt的方式是通过新接口如下

    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData  *receipt = [NSData dataWithContentsOfURL:receiptURL];
    

    当然,低于ios7.0的还是需要使用老版本接口,对两种版本进行适配的代码如下:

    NSData*receipt= nil;
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")){
    //ios after 7.0
        NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
        receipt = [NSData dataWithContentsOfURL:receiptURL];
        NSString *receiptURLStr = [receiptURL absoluteString];
        NSRange rangeSandbox = [receiptURLStr rangeOfString:@"sandbox"];
        if (rangeSandbox.location != NSNotFound){
            record[kIAPEnvironment] = [NSNumber numberWithInt:1];
        }
    }else{
    //ios 3.0~7.0
        receipt = transaction.transactionReceipt;
        NSDictionary *dict = [NSDictionary dictionaryWithContentsOfData:receipt];
        if (dict){
            NSString *env = [dict objectForKey:@"environment"];
            if ([env isEqualToString:@"Sandbox"]) {
                record[kIAPEnvironment] = [NSNumber numberWithInt:1];
            }
      }
    }
    

    判断是否是沙盒支付,新版本可以直接判断receiptURL中是否存在“sandbox“

    老版本receipt可以解析NSData 查看environment是否为Sandbox来判断

    + (NSDictionary *)dictionaryWithContentsOfData: (NSData *)data{
        CFPropertyListRef plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, (__bridge CFDataRef)data,
        kCFPropertyListImmutable, NULL);
        if(plist == nil) return nil;
        if ([(__bridge id)plist isKindOfClass:[NSDictionary class]]){
        return (__bridge NSDictionary *)plist;
        }else{
        CFRelease(plist);
        return nil;
        }
    }
    

    客户端receipt验证方式:

    NSError *error;
    NSDictionary *requestContents = @{
    @"receipt-data": [receipt base64EncodedString]
    };
    NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
    options:0
    error:&error];
    if (!requestData) {
        return;
    }
    // Create a POST request with the receipt data.
    NSURL *storeURL = [NSURL URLWithString:@"https://sandbox.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 ... */
        }
    }];
    

    老版本返回格式:

    {
    
    bid = "com.coodezhang.test";
    
    bvrs = "1.0";
    
    "item_id" = 892617314;
    
    "original_purchase_date" = "2017-12-14 07:43:14 Etc/GMT";
    
    "original_purchase_date_ms" = 1626147394550;
    
    "original_purchase_date_pst" = "2017-12-14 12:43:14 America/Los_Angeles";
    
    "original_transaction_id" = 1000001127239959;
    
    "product_id" = "com.coodezhang.test_coins99M_Tier1";
    
    "purchase_date" = "2017-12-14 07:43:14 Etc/GMT";
    
    "purchase_date_ms" = 1626147394550;
    
    "purchase_date_pst" = "2017-12-14 12:43:14 America/Los_Angeles";
    
    quantity = 1;
    
    "transaction_id" = 1000001127239959;
    
    "unique_identifier" = 0000b0124819;
    
    "unique_vendor_identifier" = "ASDGF2DB-DSAD-5A21-9611-642A4B9CASDE7";
    
    };
    
    status = 0;
    
    }
    

    新版本返回格式官方文档:官方文档

    新版本返回格式:

    {
    
    environment = Sandbox;
    
    receipt =     {
    
    "adam_id" = 0;
    
    "app_item_id" = 0;
    
    "application_version" = 1;
    
    "bundle_id" = "com.coodezhang.test";
    
    "download_id" = 0;
    
    "in_app" =         (
    
    {
    
    "is_trial_period" = false;
    
    "original_purchase_date" = "2017-12-14 07:18:56 Etc/GMT";
    
    "original_purchase_date_ms" = 1513235936000;
    
    "original_purchase_date_pst" = "2017-12-13 23:18:56 America/Los_Angeles";
    
    "original_transaction_id" = 1000000359369424;
    
    "product_id" = "com.coodezhang.test_coins99M_Tier1";
    
    "purchase_date" = "2017-12-14 07:18:56 Etc/GMT";
    
    "purchase_date_ms" = 1513235936000;
    
    "purchase_date_pst" = "2017-12-13 23:18:56 America/Los_Angeles";
    
    quantity = 1;
    
    "transaction_id" = 1000000359369424;
    
    }
    
    ...... 可能存在多条
    
    );
    
    "original_application_version" = "1.0";
    
    "original_purchase_date" = "2013-08-01 07:00:00 Etc/GMT";
    
    "original_purchase_date_ms" = 1375340400000;
    
    "original_purchase_date_pst" = "2013-08-01 00:00:00 America/Los_Angeles";
    
    "receipt_creation_date" = "2017-12-14 07:18:56 Etc/GMT";
    
    "receipt_creation_date_ms" = 1513235936000;
    
    "receipt_creation_date_pst" = "2017-12-13 23:18:56 America/Los_Angeles";
    
    "receipt_type" = ProductionSandbox;
    
    "request_date" = "2017-12-14 07:19:23 Etc/GMT";
    
    "request_date_ms" = 1513235963829;
    
    "request_date_pst" = "2017-12-13 23:19:23 America/Los_Angeles";
    
    "version_external_identifier" = 0;
    
    };
    
    status = 0;
    
    }
    

    值得注意的是,新版中数据结构中的in_app字段,可能包含多个transaction的receipt。当完成transaction后,还没有成功调用读取过receipt的接口,那下一次读取recept时会把所有的都读取出来,从而出现多条数据。

    一般开发商app支付都有自己的支付系统,可能每次下单之前都会创建自己的订单号,需要与ios支付后返回的receipt一一对应,这种情况下如何处理还需要注意。

    相关文章

      网友评论

        本文标题:IOS应用内支付返回新旧Receipt适配

        本文链接:https://www.haomeiwen.com/subject/elbgwxtx.html