首先,在我上一次發(fā)的這篇文章里http://www.reibang.com/p/d2b3f297ba9e 存在幾個(gè)容易出現(xiàn)問題的點(diǎn)吃度,在實(shí)際的運(yùn)營中確實(shí)也出現(xiàn)過匹涮,所以針對出現(xiàn)的問題也做了一下優(yōu)化,希望對大家有幫助。
問題一
在前一篇內(nèi)購的代碼中坞生,在實(shí)際運(yùn)營中仔役,出現(xiàn)過獲取不到平臺訂單號,也就是applicationUsername為nil的情況 恨胚,這種情況是因?yàn)樘O果返回參數(shù)為nil導(dǎo)致的漏單骂因,所以說這個(gè)參數(shù)并不是完全的可靠。所以赃泡,有必要在這個(gè)參數(shù)返回為nil 的時(shí)候做一下處理寒波。首先有兩種方案:
一、可以在本地進(jìn)行存儲升熊,先去判斷蘋果返回的這個(gè)applicationUsername是否為nil 如果為nil,去判斷傳入的這個(gè)平臺訂單號是否有值俄烁,如果有,直接使用這個(gè)值(一般走購買流程级野,這個(gè)值都是有的即可页屠,如果是走的漏單流程,applicationUsername 為nil 且此時(shí)是不傳入平臺訂單號的蓖柔,這時(shí)候就應(yīng)該在發(fā)起購買的之后存儲這個(gè)訂單號辰企,具體存儲可以將拉起購買傳進(jìn)來的平臺order作為值,然后transaction.transactionIdentifier作為key(注:實(shí)測當(dāng)憑證為key 存儲的話况鸣,在有訂閱類型商品的收會(huì)出現(xiàn)同一個(gè)商品不同時(shí)段憑證不一樣的情況牢贸,導(dǎo)致取不到存儲的order,因此通過transaction.transactionIdentifier(唯一事務(wù)id)來進(jìn)行存儲,這個(gè)實(shí)測確保是唯一的)存儲到某個(gè)目錄下,文件名可以用:平臺訂單號.plist的格式保存。所以在下次走漏單的流程時(shí)候蘋果返回applicatonUsername為nil 的 镐捧,可以去遍歷存儲的plist,然后將鍵為該憑證的值取出來潜索,這就是與購買憑證匹配的平臺訂單號了。
二懂酱、第二種方法需要跟服務(wù)端交互 竹习,也就是在拉起內(nèi)購的時(shí)候,在獲取到憑證的時(shí)候列牺,將憑證和傳進(jìn)來的平臺訂單號一起post到你們家后臺整陌,當(dāng)在獲取蘋果返回的applicationUsername為nil 的時(shí)候 ,通過憑證去后臺將這個(gè)平臺訂單號取回來就可以了瞎领。第二種方法需要進(jìn)行兩部交互有點(diǎn)繁瑣蔓榄。
問題二
在此前的文章中的這一段代碼,在實(shí)際運(yùn)營中出現(xiàn)過因?yàn)橛唵翁枮閚il 而無法刪除已經(jīng)成功的憑證默刚,不停向服務(wù)器發(fā)起訪問的問題,部分代碼如下:
-(void)checkIAPFiles:(SKPaymentTransaction *)transaction{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
NSArray *cacheFileNameArray = [fileManager contentsOfDirectoryAtPath:[SandBoxHelper iapReceiptPath] error:&error];
if (error == nil) {
for (NSString *name in cacheFileNameArray) {
if ([name hasSuffix:@".plist"]){
//如果有plist后綴的文件逃魄,說明就是存儲的購買憑證
NSString *filePath = [NSString stringWithFormat:@"%@/%@", [SandBoxHelper iapReceiptPath], name];
[self sendAppStoreRequestBuyPlist:filePath trans:transaction];
}
}
} else {
[RRHUD hide];
}
}
#pragma mark -- 根據(jù)訂單號來移除本地憑證的方法
-(void)successConsumptionOfGoodsWithOrder:(NSString * )cpOrder{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError * error;
if ([fileManager fileExistsAtPath:[SandBoxHelper iapReceiptPath]]) {
NSArray * cacheFileNameArray = [fileManager contentsOfDirectoryAtPath:[SandBoxHelper iapReceiptPath] error:&error];
if (error == nil) {
for (NSString * name in cacheFileNameArray) {
NSString * filePath = [NSString stringWithFormat:@"%@/%@", [SandBoxHelper iapReceiptPath], name];
[self removeReceiptWithPlistPath:filePath ByCpOrder:cpOrder];
}
}
}
}
#pragma mark -- 根據(jù)訂單號來刪除 存儲的憑證
-(void)removeReceiptWithPlistPath:(NSString *)plistPath ByCpOrder:(NSString *)cpOrder{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError * error;
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
NSString * order = [dic objectForKey:@"order"];
if ([cpOrder isEqualToString:order]) {
//移除與游戲cp訂單號一樣的plist 文件
BOOL ifRemove = [fileManager removeItemAtPath:plistPath error:&error];
if (ifRemove) {
NSLog(@"成功訂單移除成功");
}else{
NSLog(@"成功訂單移除失敗");
}
}else{
NSLog(@"本地?zé)o與之匹配的訂單");
}
}
以上代碼的話會(huì)在獲取不到訂單號的時(shí)候刪除不了本地的已經(jīng)成功的訂單荤西。會(huì)導(dǎo)致 -(void)checkIAPFiles:(SKPaymentTransaction *)transaction這個(gè)方法始終判斷這個(gè)目錄下有文件。在購買的時(shí)候不停地向服務(wù)端發(fā)起訪問,加劇服務(wù)器壓力邪锌。
針對以上的問題勉躺,我簡化了一些流程,考慮到蘋果內(nèi)購有獨(dú)有的漏單操作觅丰。其實(shí)不必要存儲憑證也可以實(shí)現(xiàn)補(bǔ)單流程 饵溅。優(yōu)化代碼我貼出來,具體關(guān)于applicationUsername為nil 的處理妇萄,大家可以根據(jù)需求從中選擇一個(gè)來進(jìn)行處理 蜕企。至于文件我也會(huì)更新到github ,鏈接請看評論,有需要大家可以下載使用冠句。至于該文件中的一些block 或者你們看不懂的回調(diào)其實(shí)跟我的業(yè)務(wù)有關(guān)轻掩,因?yàn)槲沂菍慡DK給別人用的所以要回調(diào)購買的結(jié)果給研發(fā)做判斷進(jìn)行發(fā)貨操作。不關(guān)乎你們的內(nèi)購邏輯懦底。一下是優(yōu)化之后的內(nèi)購代碼 :
IPAPurchase.h
IPAPurchase.h
#import <Foundation/Foundation.h>
/**
block
@param isSuccess 是否支付成功
@param certificate 支付成功得到的憑證(用于在 自己服務(wù)器驗(yàn)證)
@param errorMsg 錯(cuò)誤信息
*/
typedef void(^PayResult)(BOOL isSuccess,NSString *certificate,NSString *errorMsg);
@interface IPAPurchase : NSObject
@property (nonatomic, copy)PayResult payResultBlock;
內(nèi)購支付
@param productID 內(nèi)購商品ID
@param payResult 結(jié)果
*/
-(void)buyProductWithProductID:(NSString *)productID payResult:(PayResult)payResult;
@end
IPAPurchase.m
// IPAPurchase.m
// iOS_Purchase
// Created by zhanfeng on 2017/6/6.
// Copyright ? 2017年 unlock_liujia. All rights reserved.
#import "IPAPurchase.h"
#import "ULSDKConfig.h"
#import <StoreKit/StoreKit.h>
#import <StoreKit/SKPaymentTransaction.h>
static NSString * const receiptKey = @"receipt_key";
dispatch_queue_t iap_queue(){
static dispatch_queue_t as_iap_queue;
static dispatch_once_t onceToken_iap_queue;
dispatch_once(&onceToken_iap_queue, ^{
as_iap_queue = dispatch_queue_create("com.iap.queue", DISPATCH_QUEUE_CONCURRENT);
});
return as_iap_queue;
}
@interface IPAPurchase()<SKPaymentTransactionObserver,
SKProductsRequestDelegate>
{
SKProductsRequest *request;
}
//購買憑證
@property (nonatomic,copy)NSString *receipt;//存儲base64編碼的交易憑證
//產(chǎn)品ID
@property (nonnull,copy)NSString * profductId;
@end
static IPAPurchase * manager = nil;
@implementation IPAPurchase
#pragma mark -- 單例方法
+ (instancetype)manager{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!manager) {
manager = [[IPAPurchase alloc] init];
}
});
return manager;
}
#pragma mark -- 添加內(nèi)購監(jiān)聽者
-(void)startManager{
dispatch_sync(iap_queue(), ^{
[[SKPaymentQueue defaultQueue] addTransactionObserver:manager];
});
}
#pragma mark -- 移除內(nèi)購監(jiān)聽者
-(void)stopManager{
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
});
}
#pragma mark -- 發(fā)起購買的方法
-(void)buyProductWithProductID:(NSString *)productID payResult:(PayResult)payResult{
[self removeAllUncompleteTransactionsBeforeNewPurchase];
self.payResultBlock = payResult;
[RRHUD showWithContainerView:RR_keyWindow status:NSLocalizedString(@"Buying...", @"")];
self.profductId = productID;
if (!self.profductId.length) {
UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"Warm prompt" message:@"There is no corresponding product." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alertView show];
}
if ([SKPaymentQueue canMakePayments]) {
[self requestProductInfo:self.profductId];
}else{
UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"Warm prompt" message:@"Please turn on the in-app paid purchase function first." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alertView show];
}
}
#pragma mark -- 結(jié)束上次未完成的交易
-(void)removeAllUncompleteTransactionsBeforeNewPurchase{
NSArray* transactions = [SKPaymentQueue defaultQueue].transactions;
if (transactions.count >= 1) {
for (NSInteger count = transactions.count; count > 0; count--) {
SKPaymentTransaction* transaction = [transactions objectAtIndex:count-1];
if (transaction.transactionState == SKPaymentTransactionStatePurchased||transaction.transactionState == SKPaymentTransactionStateRestored) {
[[SKPaymentQueue defaultQueue]finishTransaction:transaction];
}
}
}else{
NSLog(@"沒有歷史未消耗訂單");
}
}
#pragma mark -- 發(fā)起購買請求
-(void)requestProductInfo:(NSString *)productID{
NSArray * productArray = [[NSArray alloc]initWithObjects:productID,nil];
NSSet * IDSet = [NSSet setWithArray:productArray];
request = [[SKProductsRequest alloc]initWithProductIdentifiers:IDSet];
request.delegate = self;
[request start];
}
#pragma mark -- SKProductsRequestDelegate 查詢成功后的回調(diào)
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
NSArray *myProduct = response.products;
if (myProduct.count == 0) {
[RRHUD hide];
[RRHUD showErrorWithContainerView:UL_rootVC.view status:NSLocalizedString(@"No Product Info", @"")];
if (self.payResultBlock) {
self.payResultBlock(NO, nil, @"無法獲取產(chǎn)品信息唇牧,購買失敗");
}
return;
}
SKProduct * product = nil;
for(SKProduct * pro in myProduct){
NSLog(@"SKProduct 描述信息%@", [pro description]);
NSLog(@"產(chǎn)品標(biāo)題 %@" , pro.localizedTitle);
NSLog(@"產(chǎn)品描述信息: %@" , pro.localizedDescription);
NSLog(@"價(jià)格: %@" , pro.price);
NSLog(@"Product id: %@" , pro.productIdentifier);
if ([pro.productIdentifier isEqualToString:self.profductId]) {
product = pro;
break;
}
}
if (product) {
SKMutablePayment * payment = [SKMutablePayment paymentWithProduct:product];
//使用蘋果提供的屬性,將平臺訂單號復(fù)制給這個(gè)屬性作為透傳參數(shù)
payment.applicationUsername = self.order;
[[SKPaymentQueue defaultQueue] addPayment:payment];
}else{
NSLog(@"沒有此商品信息");
}
}
//查詢失敗后的回調(diào)
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
if (self.payResultBlock) {
self.payResultBlock(NO, nil, [error localizedDescription]);
}
}
//如果沒有設(shè)置監(jiān)聽購買結(jié)果將直接跳至反饋結(jié)束;
-(void)requestDidFinish:(SKRequest *)request{
}
#pragma mark -- 監(jiān)聽結(jié)果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
//當(dāng)用戶購買的操作有結(jié)果時(shí)聚唐,就會(huì)觸發(fā)下面的回調(diào)函數(shù)丐重,
for (SKPaymentTransaction * transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:{
[self completeTransaction:transaction];
}break;
case SKPaymentTransactionStateFailed:{
[self failedTransaction:transaction];
}break;
case SKPaymentTransactionStateRestored:{//已經(jīng)購買過該商品
[self restoreTransaction:transaction];
}break;
case SKPaymentTransactionStatePurchasing:{
NSLog(@"正在購買中...");
}break;
case SKPaymentTransactionStateDeferred:{
NSLog(@"最終狀態(tài)未確定");
}break;
default:
break;
}
}
}
//完成交易
#pragma mark -- 交易完成的回調(diào)
- (void)completeTransaction:(SKPaymentTransaction *)transaction
{
[self getAndSaveReceipt:transaction]; //獲取交易成功后的購買憑證
}
#pragma mark -- 處理交易失敗回調(diào)
- (void)failedTransaction:(SKPaymentTransaction *)transaction{
[RRHUD hide];
NSString * error = nil;
if(transaction.error.code != SKErrorPaymentCancelled) {
[RRHUD showInfoWithContainerView:UL_rootVC.view status:NSLocalizedString(@"Buy Failed", @"")];
error = [NSString stringWithFormat:@"%ld",transaction.error.code];
} else {
[RRHUD showInfoWithContainerView:UL_rootVC.view status:NSLocalizedString(@"Buy Canceled", @"")];
error = [NSString stringWithFormat:@"%ld",transaction.error.code];
}
if (self.payResultBlock) {
self.payResultBlock(NO, nil, error);
}
[[SKPaymentQueue defaultQueue]finishTransaction:transaction];
}
- (void)restoreTransaction:(SKPaymentTransaction *)transaction{
[RRHUD hide];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
#pragma mark -- 獲取購買憑證
-(void)getAndSaveReceipt:(SKPaymentTransaction *)transaction{
//獲取交易憑證
NSURL * receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
NSData * receiptData = [NSData dataWithContentsOfURL:receiptUrl];
NSString * base64String = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
//初始化字典
NSMutableDictionary * dic = [[NSMutableDictionary alloc]init];
NSString * order = transaction.payment.applicationUsername;
//如果這個(gè)返回為nil
NSLog(@"后臺訂單號為訂單號為%@",order);
[dic setValue: base64String forKey:receiptKey];
[dic setValue: order forKey:@"order"];
[dic setValue:[self getCurrentZoneTime] forKey:@"time"];
NSString * userId;
if (self.userid) {
userId = self.userid;
[[NSUserDefaults standardUserDefaults]setObject:userId forKey:@"unlock_iap_userId"];
}else{
userId = [[NSUserDefaults standardUserDefaults]
objectForKey:@"unlock_iap_userId"];
}
if (userId == nil||[userId length] == 0) {
userId = @"走漏單流程未傳入userId";
}
if (order == nil||[order length] == 0) {
order = @"蘋果返回透傳參數(shù)為nil";
}
[[ULSDKAPI shareAPI]sendLineWithPayOrder:order UserId:userId Receipt:base64String LineNumber:@"IPAPurchase.m 337"];
NSString *fileName = [NSString UUID];
NSString *savedPath = [NSString stringWithFormat:@"%@/%@.plist", [SandBoxHelper iapReceiptPath], fileName];
[dic setValue: userId forKey:@"user_id"];
//這個(gè)存儲成功與否其實(shí)無關(guān)緊要
BOOL ifWriteSuccess = [dic writeToFile:savedPath atomically:YES];
if (ifWriteSuccess){
NSLog(@"購買憑據(jù)存儲成功!");
}else{
NSLog(@"購買憑據(jù)存儲失敗");
}
[self sendAppStoreRequestBuyWithReceipt:base64String userId:userId paltFormOrder:order trans:transaction];
}
-(void)getPlatformAmountInfoWithOrder:(NSString *)transOrcer{
[[ULSDKAPI shareAPI]getPlatformAmountWithOrder:transOrcer success:^(id responseObject) {
if (RequestSuccess) {
_platformAmount = [[responseObject objectForKey:@"data"]objectForKey:@"amount"];
_amount_type = [[responseObject objectForKey:@"data"]objectForKey:@"amount_type"];
_third_goods_id = [[responseObject objectForKey:@"data"]objectForKey:@"third_goods_id"];
[FBSDKAppEvents logEvent:@"pay_in_sdk" valueToSum:[_platformAmount doubleValue] parameters:@{@"fb_currency":@"USD",@"amount":_platformAmount,@"amount_type":_amount_type,@"third_goods_id":_third_goods_id}];
}else{
NSLog(@"%@",[responseObject objectForKey:@"message"]);
}
} failure:^(NSString *failure) {
}];
}
#pragma mark -- 存儲成功訂單
-(void)SaveIapSuccessReceiptDataWithReceipt:(NSString *)receipt Order:(NSString *)order UserId:(NSString *)userId{
NSMutableDictionary * mdic = [[NSMutableDictionary alloc]init];
[mdic setValue:[self getCurrentZoneTime] forKey:@"time"];
[mdic setValue: order forKey:@"order"];
[mdic setValue: userId forKey:@"userid"];
[mdic setValue: receipt forKey:receiptKey];
NSString *fileName = [NSString UUID];
NSString * successReceiptPath = [NSString stringWithFormat:@"%@/%@.plist", [SandBoxHelper SuccessIapPath], fileName];
//存儲購買成功的憑證
[self insertReceiptWithReceiptByReceipt:receipt withDic:mdic inReceiptPath:successReceiptPath];
}
-(void)insertReceiptWithReceiptByReceipt:(NSString *)receipt withDic:(NSDictionary *)dic inReceiptPath:(NSString *)receiptfilePath{
BOOL isContain = NO;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError * error;
NSArray * cacheFileNameArray = [fileManager contentsOfDirectoryAtPath:[SandBoxHelper SuccessIapPath] error:&error];
if (cacheFileNameArray.count == 0) {
[dic writeToFile:receiptfilePath atomically:YES];
if ([dic writeToFile:receiptfilePath atomically:YES]) {
NSLog(@"寫入購買憑據(jù)成功");
}
}else{
if (error == nil) {
for (NSString * name in cacheFileNameArray) {
NSString * filePath = [NSString stringWithFormat:@"%@/%@", [SandBoxHelper SuccessIapPath], name];
NSMutableDictionary *localdic = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
if ([localdic.allValues containsObject:receipt]) {
isContain = YES;
}else{
continue;
}
}
}else{
NSLog(@"讀取本文存儲憑據(jù)失敗");
}
}
if (isContain == NO) {
BOOL results = [dic writeToFile:receiptfilePath atomically:YES];
if (results) {
NSLog(@"寫入憑證成功");
}else{
NSLog(@"寫入憑證失敗");
}
}else{
NSLog(@"已經(jīng)存在憑證請勿重復(fù)寫入");
}
}
#pragma mark -- 獲取系統(tǒng)時(shí)間的方法
-(NSString *)getCurrentZoneTime{
NSDate * date = [NSDate date];
NSDateFormatter*formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString*dateTime = [formatter stringFromDate:date];
return dateTime;
}
#pragma mark -- 去服務(wù)器驗(yàn)證購買
-(void)sendAppStoreRequestBuyWithReceipt:(NSString *)receipt userId:(NSString *)userId paltFormOrder:(NSString * )order trans:(SKPaymentTransaction *)transaction{
[[ULSDKAPI shareAPI]sendLineWithPayOrder:order UserId:userId Receipt:receipt LineNumber:@"IPAPurchase.m 474"];
#pragma mark -- 發(fā)送信息去驗(yàn)證是否成功
[[ULSDKAPI shareAPI] sendVertifyWithReceipt:receipt order:order userId:userId success:^(ULSDKAPI *api, id responseObject) {
if (RequestSuccess) {
[RRHUD hide];
[RRHUD showSuccessWithContainerView:UL_rootVC.view status:NSLocalizedString(@"Buy Success", @"")];
//結(jié)束交易方法
[[SKPaymentQueue defaultQueue]finishTransaction:transaction];
[self getPlatformAmountInfoWithOrder:order];
NSData * data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] appStoreReceiptURL] path]];
NSString *result = [data base64EncodedStringWithOptions:0];
if (self.payResultBlock) {
self.payResultBlock(YES, result, nil);
}
//這里將成功但存儲起來
[self SaveIapSuccessReceiptDataWithReceipt:receipt Order:order UserId:userId];
[self successConsumptionOfGoodsWithReceipt:receipt];
}else{
#pragma mark -- callBack 回調(diào)
[api sendVertifyWithReceipt:receipt order:order userId:userId success:^(ULSDKAPI *api, id responseObject) {
if (RequestSuccess) {
[RRHUD hide];
[RRHUD showSuccessWithContainerView:UL_rootVC.view status:NSLocalizedString(@"Buy Success", @"")];
[[SKPaymentQueue defaultQueue]finishTransaction:transaction];
[self getPlatformAmountInfoWithOrder:order];
NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] appStoreReceiptURL] path]];
NSString *result = [data base64EncodedStringWithOptions:0];
if (self.payResultBlock) {
self.payResultBlock(YES, result, nil);
}
//存儲成功訂單
[self SaveIapSuccessReceiptDataWithReceipt:receipt Order:order UserId:userId];
//刪除已成功訂單
[self successConsumptionOfGoodsWithReceipt:receipt];
}
#pragma 校驗(yàn)發(fā)貨失敗 1
} failure:^(ULSDKAPI *api, NSString *failure) {
[RRHUD hide];
[RRHUD showErrorWithContainerView:UL_rootVC.view status:NSLocalizedString(@"Request Error", @"")];
}];
}else{
[RRHUD hide];
#pragma mark --發(fā)送錯(cuò)誤報(bào)告
[api sendFailureReoprtWithReceipt:receipt order:order success:^(ULSDKAPI *api, id responseObject) {
} failure:^(ULSDKAPI *api, NSString *failure) {
[RRHUD hide];
}];
}
} failure:^(ULSDKAPI *api, NSString *failure) {
[RRHUD hide];
}];
}
} failure:^(ULSDKAPI *api, NSString *failure) {
[RRHUD hide];
[api VertfyFailedRePostWithUserId:userId Order:order jsonStr:failure];
}];
}
#pragma mark -- 根據(jù)訂單號來移除本地憑證的方法
-(void)successConsumptionOfGoodsWithReceipt:(NSString * )receipt{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError * error;
if ([fileManager fileExistsAtPath:[SandBoxHelper iapReceiptPath]]) {
NSArray * cacheFileNameArray = [fileManager contentsOfDirectoryAtPath:[SandBoxHelper iapReceiptPath] error:&error];
if (error == nil) {
for (NSString * name in cacheFileNameArray) {
NSString * filePath = [NSString stringWithFormat:@"%@/%@", [SandBoxHelper iapReceiptPath], name];
[self removeReceiptWithPlistPath:filePath ByReceipt:receipt];
}
}
}
}
#pragma mark -- 根據(jù)訂單號來刪除 存儲的憑證
-(void)removeReceiptWithPlistPath:(NSString *)plistPath ByReceipt:(NSString *)receipt{
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError * error;
NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
NSString * localReceipt = [dic objectForKey:@"receipt_key"];
//通過憑證進(jìn)行對比
if ([receipt isEqualToString:localReceipt]) {
BOOL ifRemove = [fileManager removeItemAtPath:plistPath error:&error];
if (ifRemove) {
NSLog(@"成功訂單移除成功");
}else{
NSLog(@"成功訂單移除失敗");
}
}else{
NSLog(@"本地?zé)o與之匹配的訂單");
}
}
@end
代碼可能粘貼不齊,細(xì)節(jié)調(diào)整之后和最新的單例類內(nèi)購文件已經(jīng)同步到GitHub 了杆查,如有需要可以去gitHud 直接下載源文件扮惦,建議自己揣摩清楚之后再參考或者引入自己的項(xiàng)目,之所謂知其所以也要知其所以然根灯。另外在-(void)getAndSaveReceipt:(SKPaymentTransaction *)transaction径缅;方法里面沒有對applicationUsername為nil 做處理,大家可以跟我說的哪兩種思路進(jìn)行解決烙肺,我在這里就不代碼演示了纳猪。大家多動(dòng)腦~ github鏈接如下:https://github.com/jiajiaailaras/ULIPAPurchase