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

2020-01-21 03:37:50王冬梅

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://www.easck.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 ... */
  }
}];