內(nèi)購最新流程:僅限使用swift:https://juejin.cn/post/6974733392260644895
1、第一步:調(diào)用蘋果支付
#pragma mark -- 蘋果支付
- (void)ApplePay {
if ([SKPaymentQueue canMakePayments]) {
// 6.請求蘋果后臺商品
[self getRequestAppleProduct];
}
}
// 請求蘋果商品
- (void)getRequestAppleProduct {
// 7. 這里的com.czchat.CZChat01就對應(yīng)著蘋果后臺的商品ID思灌,他們是通過這個ID進行聯(lián)系的。
NSArray *product = [[NSArray alloc] initWithObjects:self.BuyID, nil];
NSSet *nsset = [NSSet setWithArray:product];
// 8.初始化請求
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate = self;
[SVProgressHUD showWithStatus:@"正在加載"];
// 9.開始請求
[request start];
}
// 10.接收到產(chǎn)品的返回信息,然后用返回的商品信息進行發(fā)起購買請求
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray *products = response.products;
// 如果服務(wù)器沒有產(chǎn)品
if (products.count == 0) {
NSLog(@"nothing");
return;
}
SKProduct *requestProduct = nil;
for (SKProduct *pro in products) {
NSLog(@"%@", [pro description]);
NSLog(@"%@", [pro localizedTitle]);
NSLog(@"%@", [pro localizedDescription]);
NSLog(@"%@", [pro price]);
NSLog(@"%@", [pro productIdentifier]);
// 11. 如果后臺消費條目的ID與我這里需要的請求的一樣(用于確保訂單的正確性)
if ([pro.productIdentifier isEqualToString:self.BuyID]) {
requestProduct = pro;
}
}
NSLog(@"%@", requestProduct);
//12. 發(fā)送購買請求
NSArray *transactions = [SKPaymentQueue defaultQueue].transactions;
if (transactions.count > 0) {
// 檢測是否有未完成的交易
SKPaymentTransaction *transaction = [transactions firstObject];
if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
return;
} else {
SKPayment *payment = [SKPayment paymentWithProduct:requestProduct];
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
} else {
SKPayment *payment = [SKPayment paymentWithProduct:requestProduct];
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
}
// 請求失敗
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
NSLog(@"%@", error);
[SVProgressHUD dismiss];
}
// 反饋請求的產(chǎn)品信息結(jié)束后
- (void)requestDidFinish:(SKRequest *)request {
NSLog(@"信息反饋結(jié)束");
}
// 13.購買監(jiān)聽結(jié)果
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
NSLog(@"------");
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchased:
NSLog(@"交易完成");
NSLog(@"購買完成啃炸,向自己的服務(wù)器驗證------ %@", transaction.payment.applicationUsername);
NSLog(@"購買完成,向自己的服務(wù)器驗證------ %@", transaction.payment.hyb_toJsonString);
// 將交易從交易隊列中刪除
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
if (transaction.originalTransaction) { // 訂閱特殊處理
// 如果是自動續(xù)費的訂單originalTransaction會有內(nèi)容
} else {
//普通購買卓舵,以及 第一次購買 自動訂閱
// [self completedTransaction:transaction]; // 本地校驗交易憑據(jù)
[self getApplePayDataToServerRequsetWith:transaction]; // 后臺服務(wù)器校驗App Store交易憑據(jù)
}
break;
case SKPaymentTransactionStatePurchasing:
NSLog(@"商品添加進列表");
break;
case SKPaymentTransactionStateRestored:
NSLog(@"已經(jīng)購買過商品");
[SVProgressHUD dismiss];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateFailed:
if (transaction.error.code == SKErrorPaymentCancelled) {
NSLog(@"用戶取消了購買請求");
} else if (transaction.error.code == SKErrorCloudServiceNetworkConnectionFailed) {
NSLog(@"設(shè)備無法鏈接到網(wǎng)絡(luò)");
}
else {
NSLog(@"交易失斈嫌谩!L屯濉裹虫!");
}
[SVProgressHUD dismiss];
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateDeferred:
NSLog(@"已在隊列中,等待外部操作");
break;
default:
break;
}
}
}
2融击、第二步:后臺服務(wù)器端驗證App Store票據(jù)(為了安全筑公,需要自己服務(wù)器驗證App Store票據(jù))
注意:字符串:@"{"receipt-data" : "%@"}",服務(wù)器解碼時尊浪,帶上“receipt-data”字段匣屡,不然base64解碼失敗
蘋果返回的訂單中in_app
是一個數(shù)組,要想獲取到對應(yīng)的某一個訂單信息拇涤,就如下這樣:
特別說明:如果你需要當(dāng)前票據(jù)的唯一號捣作,取in_app
中最后一個票據(jù)的transaction_id
就行,即transaction.transactionIdentifier
工育,這個transaction_id
和蘋果返回的訂單中的transaction_id
比較虾宇,獲取對應(yīng)的訂單,改變數(shù)據(jù)庫用戶的交易記錄如绸。
#pragma mark -- -- 后臺服務(wù)器端驗證App Store票據(jù) -- --
/** 注意:這里之后可以不用自己去驗證嘱朽,直接調(diào)用自己服務(wù)器接口旭贬,讓后臺去APP Store 驗證*/
/** 將App Store返回的交易憑據(jù)發(fā)送到后臺服務(wù)器,由后臺服務(wù)器驗證搪泳,code==200稀轨,提示成功 */
// (14.): 交易結(jié)束,當(dāng)交易結(jié)束后還要后臺服務(wù)器端去App Store上驗證支付信息是否都正確岸军,只有所有都正確后奋刽,我們就可以給用戶發(fā)放我們的虛擬產(chǎn)品了。
- (void)getApplePayDataToServerRequsetWith:(SKPaymentTransaction *)transaction {
// 唯一transaction_id
NSString *transaction_id = transaction.transactionIdentifier;
NSString *str = [[NSString alloc] initWithData:transaction.transactionReceipt encoding:NSUTF8StringEncoding];
NSLog(@"------ 完成交易調(diào)用的方法getApplePayDataToServerRequsetWith 1----------");
// 獲取設(shè)備端app的交易收據(jù)數(shù)據(jù)艰赞,使用NSBundle的方法定位app的收據(jù)佣谐,并用Base64編碼。將此 Base64 編碼數(shù)據(jù)發(fā)送到您的服務(wù)器方妖。
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
if (!receiptData) {
NSLog(@"沒有交易收據(jù), NO receipt");
} else {
// 獲取編碼格式的收據(jù)
NSString *encodedReceipt = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
// 注意:字符串:@"{\"receipt-data\" : \"%@\"}"狭魂,服務(wù)器解碼時,帶上“receipt-data”字段党觅,不然base64解碼失敗
// NSString *sendString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodedReceipt];
// server解析json字符串和端上一樣雌澄,不帶轉(zhuǎn)義字符“\”根本解析不出來
// 先將憑據(jù)轉(zhuǎn)成字典,在將字典轉(zhuǎn)成json字符串(添加了receipt-data)
NSDictionary *sendDic = @{@"receipt-data" : encodedReceipt};
NSData *data = [NSJSONSerialization dataWithJSONObject:sendDic options:NSJSONWritingPrettyPrinted error:nil];
NSString *sendString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[self getApplePayDataToServerRequestString:sendString withTransaction:transaction];
}
}
//(15.):發(fā)送到服務(wù)器杯瞻,由服務(wù)器判斷交易收據(jù)(生成預(yù)訂單镐牺,成功后在發(fā)送到服務(wù)器校驗App Store憑據(jù))
- (void)getApplePayDataToServerRequestString:(NSString *)receiptString withTransaction:(SKPaymentTransaction *)transaction {
if(user_uuid == nil)
{
LoginViewCTRL *loginViewCTRL = [[LoginViewCTRL alloc] init];
loginViewCTRL.loginVieCTRLBlock = ^{
};
[self.navigationController pushViewController:loginViewCTRL animated:YES];
return;
}
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
NSString *pay_member_id = @"";
if ([self.BuyID isEqualToString:@"1MonthMember"]) {
pay_member_id = @"21";
}else if ([self.BuyID isEqualToString:@"6MontherMember"])
{
pay_member_id = @"23";
}else if ([self.BuyID isEqualToString:@"12MonthMember"])
{
pay_member_id = @"24";
}else if ([self.BuyID isEqualToString:@"buyMember03"])
{
pay_member_id = @"45";
}
NSDictionary *dic = @{
@"user_uuid":wy_user_uuid?:@"",
@"app_version":app_Version,
@"pay_method":@"3",
@"pay_source":@"6",
@"pay_for":self.normalMemberBut.selected?@"1":@"11",
@"client_type":@"2",
@"pay_member_id":[NSString stringWithFormat:@"%@", pay_member_id]
};
NSArray *keyArray = [dic allKeys]; // 將dic中的全部key取出,并放到數(shù)組
// 根據(jù)ASCII碼,將參數(shù)key從小到大排序(升序)
NSStringCompareOptions comparisonOptions =NSCaseInsensitiveSearch|NSNumericSearch|NSWidthInsensitiveSearch|NSForcedOrderingSearch;
NSComparator sort = ^(NSString *obj1, NSString *obj2) {
NSRange range = NSMakeRange(0, obj1.length);
return [obj1 compare:obj2 options:comparisonOptions range:range];
};
NSArray *resultArr = [keyArray sortedArrayUsingComparator:sort];
// NSLog(@"字符串?dāng)?shù)組排序結(jié)果%@",resultArr);
NSMutableArray *paramValueArr = [NSMutableArray arrayWithCapacity:resultArr.count];
for (NSString *str in resultArr) {
// 將key對應(yīng)的value魁莉,存到數(shù)組睬涧,用“7500KM”組成字符串
NSString *tokenStr = [dic objectForKey:[NSString stringWithFormat:@"%@", str]];
if (tokenStr.length > 0) {
[paramValueArr addObject:tokenStr];
}
}
// NSLog(@"字符串?dāng)?shù)組Value排序結(jié)果%@",paramValueArr);
NSString *token = [paramValueArr componentsJoinedByString:@"7500KM"];
token = [JXUtilTool md5HexDigest:token];
NSDictionary *params = @{
@"user_uuid":wy_user_uuid?:@"",
@"app_version":app_Version,
@"pay_method":@"3", // 支付方式 1:阿里 2:微信 3:蘋果
@"pay_source":@"6",// 1.二維碼支付 2.H5支付 3.支付寶手機網(wǎng)站支付 4.支付寶電腦網(wǎng)站支付 5.微信JSAPI 6.APP
@"pay_for":self.normalMemberBut.selected?@"1":@"11",// 1: 會員 2:金幣 3:禮品卡 4:商城 10其它(自定義生成的訂單)11閱讀會員
@"client_type":@"2", // 1.安卓 2ios 3.pc
@"pay_member_id":[NSString stringWithFormat:@"%@", pay_member_id], // 會員類型:1月、6月沛厨、12月宙地、一年
@"token":[NSString stringWithFormat:@"%@", token]
};
__weak typeof(self)weakSelf = self;
[[AFShareManager sharedManager] POST:[AFShareManager LFT_UrlString:@"/pay/member"] parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"%@", task.currentRequest.URL);
NSInteger reCode = [[responseObject objectForKey:@"reCode"] integerValue];
if (reCode == 200) {
// responseObject = [Tool Handle7500kmresponseObject:responseObject]; // 解碼
NSDictionary *dataDic = [NSDictionary dictionary];
dataDic = [responseObject objectForKey:@"data"];
[self getApplePayDataToServerRequestString:receiptString withBookingOrderDictionary:dataDic withTransaction:transaction];
} else {
NSString *message = [responseObject objectForKey:@"reMessage"];
[KAlertViewFactory showToastWithMessage:message];
[SVProgressHUD dismiss];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@", task.currentRequest.URL);
NSLog(@"error ---->>>> %@", error);
[SVProgressHUD dismiss];
}];
}
// (16.)發(fā)送到后臺服務(wù)器,校驗App Store憑據(jù)
- (void)getApplePayDataToServerRequestString:(NSString *)receiptString withBookingOrderDictionary:(NSDictionary *)bookingOrderDic withTransaction:(SKPaymentTransaction *)transaction {
NSDictionary *params = @{
@"base64Receipt":receiptString,
@"out_trade_no":[NSString stringWithFormat:@"%@", bookingOrderDic[@"out_trade_no"]],
@"price":[NSString stringWithFormat:@"%@", bookingOrderDic[@"price"]],
@"user_uuid":[NSString stringWithFormat:@"%@", bookingOrderDic[@"user_uuid"]]
};
[[AFShareManager sharedManager] POST:[AFShareManager LFT_UrlString:@"/member/verifyReceipt"] parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"%@", task.currentRequest.URL);
NSInteger reCode = [[responseObject objectForKey:@"reCode"] integerValue];
if (reCode == 200) { // 驗證完成逆皮,改變展示的信息
[self GainPersonInfo];
[[WL_Tool getInstance] GainUserInfo:self];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"購買成功" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles: nil];
[alert show];
} else {
NSString *message = [NSString stringWithFormat:@"%@",[responseObject valueForKey:@"reMessage"]];
// [KAlertViewFactory showToastWithMessage:message];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:nil cancelButtonTitle:@"確定" otherButtonTitles: nil];
[alert show];
}
[SVProgressHUD dismiss];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@", task.currentRequest.URL);
NSLog(@"error ---->>>> %@", error);
[SVProgressHUD dismiss];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}];
}
2、第二步:(第二種参袱,不需要服務(wù)器驗證电谣,自己在客戶端驗證,不安全抹蚀,容易被破解剿牺,導(dǎo)致賺錢少哦)
#pragma mark -- 方法(completedTransaction:)和方法(SubmitDataTrade_no: memberType: Transaction:)
// 14. 交易結(jié)束,當(dāng)交易結(jié)束后還要去App Store上驗證支付信息是否都正確环壤,只有所有都正確后晒来,我們就可以給用戶發(fā)放我們的虛擬產(chǎn)品了。
- (void)completedTransaction:(SKPaymentTransaction *)transaction {
NSString *str = [[NSString alloc] initWithData:transaction.transactionReceipt encoding:NSUTF8StringEncoding];
NSString *environment = [self environmentForReceipt:str];
NSLog(@"------ 完成交易調(diào)用的方法completedTransaction 1----------%@", environment);
// 驗證憑據(jù)郑现,獲取到蘋果返回的交易憑據(jù)
// appStoreReceiptURL iOS 7.0 增加的湃崩,購買交易完成后荧降,會將憑據(jù)存放在該地址
NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
// 從沙盒中獲取到購買憑據(jù)
NSData *receiptData = [NSData dataWithContentsOfURL:receiptURL];
/**
20 BASE64 常用的編碼方案,通常用于數(shù)據(jù)傳輸攒读,以及加密算法的基礎(chǔ)算法朵诫,傳輸過程中能夠保證數(shù)據(jù)傳輸?shù)姆€(wěn)定性
21 BASE64 是可以解密的
22 */
NSString *encodeStr = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
NSString *sendString = [NSString stringWithFormat:@"{\"receipt-data\" : \"%@\"}", encodeStr];
NSLog(@"______%@", sendString);
/** 注意:這里之后可以不用自己去驗證,直接調(diào)用自己服務(wù)器接口薄扁,讓后臺去APP Store 驗證*/
NSURL *storeUrl = nil;
if ([environment isEqualToString:@"environment=Sandbox"]) {
storeUrl = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
} else {
storeUrl = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"];
}
// 這個二進制數(shù)據(jù)由服務(wù)器進行驗證:zl
NSData *postData = [NSData dataWithBytes:[sendString UTF8String] length:[sendString length]];
NSLog(@"++++++%@", postData);
NSMutableURLRequest *connectionRequest = [NSMutableURLRequest requestWithURL:storeUrl];
[connectionRequest setHTTPMethod:@"POST"];
[connectionRequest setTimeoutInterval:50.0]; // 120.0 ----50.0zl
[connectionRequest setCachePolicy:NSURLRequestUseProtocolCachePolicy];
[connectionRequest setHTTPBody:postData];
// 開始請求
NSError *error = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:connectionRequest returningResponse:nil error:&error];
if (error) {
NSLog(@"驗證購買過程中發(fā)生的錯誤剪返,錯誤信息:%@", error.localizedDescription);
return;
}
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"請求成功后的數(shù)據(jù):%@",dic);
//這里可以等待上面請求的數(shù)據(jù)完成后并且state = 0 驗證憑據(jù)成功來判斷后進入自己服務(wù)器邏輯的判斷,也可以直接進行服務(wù)器邏輯的判斷,驗證憑據(jù)也就是一個安全的問題。樓主這里沒有用state = 0 來判斷邓梅。
// [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
NSString *product = transaction.payment.productIdentifier;
NSLog(@"transaction.payment.productIdentifier++++%@",product);
if ([product length] > 0)
{
NSArray *tt = [product componentsSeparatedByString:@"."];
NSString *bookid = [tt lastObject];
if([bookid length] > 0)
{
NSLog(@"打印bookid%@",bookid);
//這里可以做操作把用戶對應(yīng)的虛擬物品通過自己服務(wù)器進行下發(fā)操作,或者在這里通過判斷得到用戶將會得到多少虛擬物品,在后面([self getApplePayDataToServerRequsetWith:transaction];的地方)上傳上面自己的服務(wù)器脱盲。
NSDictionary *receipt = [dic valueForKey:@"receipt"];
NSArray *in_app = [receipt valueForKey:@"in_app"];
for (int i = 0; i<in_app.count; i++) {
NSDictionary *tempDic = [in_app objectAtIndex:i];
NSString *transaction_id = [tempDic valueForKey:@"transaction_id"];
NSString *product_id = [tempDic valueForKey:@"product_id"];
if ([product_id isEqualToString:@"wl_1MonthMember"]) {
[self SubmitDataTrade_no:transaction_id memberType:@"21" Transaction:transaction];
}else if ([product_id isEqualToString:@"wl_6MontherMember"])
{
[self SubmitDataTrade_no:transaction_id memberType:@"23" Transaction:transaction];
}else if ([product_id isEqualToString:@"wl_12MonthMember"])
{
[self SubmitDataTrade_no:transaction_id memberType:@"24" Transaction:transaction];
}else if ([product_id isEqualToString:@"buyMember03"])
{
[self SubmitDataTrade_no:transaction_id memberType:@"45" Transaction:transaction];
}
}
}
}
[SVProgressHUD dismiss];
//此方法為將這一次操作上傳給我本地服務(wù)器,記得在上傳成功過后一定要記得銷毀本次操作。調(diào)用[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
//[self getApplePayDataToServerRequsetWith:transaction];
}
-(void)SubmitDataTrade_no:(NSString *)trade_no memberType:(NSString *)memberType Transaction:(SKPaymentTransaction *)transaction
{
NSString *user_uuid = [[NSUserDefaults standardUserDefaults] objectForKey:@"user_uuid"];
if(user_uuid == nil)
{
LoginViewCTRL *loginViewCTRL = [[LoginViewCTRL alloc] init];
loginViewCTRL.loginVieCTRLBlock = ^{
};
[self.navigationController pushViewController:loginViewCTRL animated:YES];
}else
{
[SVProgressHUD showWithStatus:@"正在加載"];
NSString *url=[NSString stringWithFormat:@"%@%@",ServerOtherUrl,@"/pay/applepay.do"];
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *app_Version = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
NSString *token = [NSString stringWithFormat:@"%@%@%@%@%@",user_uuid,trade_no,memberType,app_Version,token_check_bit];
token = [JXUtilTool md5HexDigest:token];
NSLog(@"user_uuid=%@&trade_no=%@&memberType=%@&app_version=%@&token=%@",user_uuid,trade_no,memberType,app_Version,token);
NSDictionary *parameters=@{@"user_uuid":user_uuid,
@"trade_no":trade_no,
@"memberType":memberType,
@"app_version":app_Version,
@"token":token
};
//AFN管理者調(diào)用get請求方法
[[AFShareManager sharedManager] GET:url parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//請求成功返回數(shù)據(jù) 根據(jù)responseSerializer 返回不同的數(shù)據(jù)格式
NSLog(@"%@",task.currentRequest.URL);
NSInteger reCode = [[responseObject valueForKey:@"reCode"] integerValue];
if (reCode == 200)
{
[self GainPersonInfo];
[[WL_Tool getInstance] GainUserInfo:self];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"購買成功" delegate:nil cancelButtonTitle:@"確定" otherButtonTitles: nil];
[alert show];
}else
{
NSString *message = [NSString stringWithFormat:@"%@",[responseObject valueForKey:@"reMessage"]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:message delegate:nil cancelButtonTitle:@"確定" otherButtonTitles: nil];
[alert show];
}
[SVProgressHUD dismiss];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//請求失敗
NSLog(@"%@",task.currentRequest.URL);
NSLog(@"error-->%@",error);
[SVProgressHUD dismiss];
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}];
}
}
3日缨、第三步:
// 結(jié)束后钱反,一定要銷毀
- (void)dealloc {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
// 在第二步中調(diào)用(第二種,不安全的驗證票據(jù)方法中):
- (NSString *)environmentForReceipt:(NSString *)str {
str = [str stringByReplacingOccurrencesOfString:@"\r\n" withString:@""];
str = [str stringByReplacingOccurrencesOfString:@"\n" withString:@""];
str = [str stringByReplacingOccurrencesOfString:@"\t" withString:@""];
str = [str stringByReplacingOccurrencesOfString:@" " withString:@""];
str = [str stringByReplacingOccurrencesOfString:@"\"" withString:@""];
NSArray *arr = [str componentsSeparatedByString:@";"];
// 存儲收據(jù)環(huán)境的變量
NSString *environment = arr[2];
return environment;
}
4殿遂、漏訂單處理:
#pragma mark -- Apple內(nèi)購:漏單情況
- (void)appleRequest {
/** Apple內(nèi)購:漏單情況 */
//讀取用戶狀態(tài)和配置信息到單例中
if ([GWUserInfoContext sharedUserInfoContext].userInfo.token &&[GWUserInfoContext sharedUserInfoContext].userInfo.name.length !=0) {
// GWUserInfoModel *model = [GWUserInfoContext sharedUserInfoContext].userInfo;
NSString *user_id = [NSString stringWithFormat:@"%ld", [GWUserInfoContext sharedUserInfoContext].userInfo.userId];
if (user_id != nil) {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSArray *receiptArray = [userDefaults objectForKey:[NSString stringWithFormat:@"%@Apple_ReceiptData_MemberArray", user_id]];
if (receiptArray != nil) { // 本地有值
if (receiptArray.count > 0) {
NSMutableArray *receipt_MutableArray = [NSMutableArray arrayWithCapacity:0];
receipt_MutableArray = [receiptArray mutableCopy];
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 處理耗時操作的代碼塊...
for (NSDictionary *dic in receipt_MutableArray) {
[self getApplePayWithOrderDictionary:dic]; // 可以多次請求數(shù)據(jù)庫數(shù)據(jù)
}
//通知主線程刷新
dispatch_async(dispatch_get_main_queue(), ^{
//回調(diào)或者說是通知主線程刷新诈铛,(這里可以保存、刪除一下數(shù)據(jù))
});
});
}
}
[userDefaults synchronize];
}
}
}
// (11.)發(fā)送到后臺服務(wù)器墨礁,校驗App Store憑據(jù)
- (void)getApplePayWithOrderDictionary:(NSDictionary *)orderDic {
// [GWUserInfoContext sharedUserInfoContext].userInfo = [GWUtilities GetNSUserDefaults];
NSString *user_id = [NSString stringWithFormat:@"%ld", [GWUserInfoContext sharedUserInfoContext].userInfo.userId];
NSString *payloadStr = [NSString stringWithFormat:@"%@", orderDic[@"receipt-data"]];
NSDictionary *params = @{
@"payload":[NSString stringWithFormat:@"%@", payloadStr],
@"transactionId":[NSString stringWithFormat:@"%@", orderDic[@"transaction_id"]],
@"oid":[NSString stringWithFormat:@"%@", orderDic[@"order_id"]]
};
[BRNetworkHepler postWithUrl:@"/golf/vip/iosPay" params:params headers:nil success:^(GWHttpBaseResponseModel *responseObject, NSString *message) {
NSInteger code = responseObject.code;
if (code == 200) {
NSDictionary *dataDic = responseObject.data;
NSString *order_id = [NSString stringWithFormat:@"%@", dataDic[@"oid"]];
// 票據(jù)驗證成功:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSArray *receiptArray = [userDefaults objectForKey:[NSString stringWithFormat:@"%@Apple_ReceiptData_MemberArray", user_id]];
if (receiptArray != nil) { // 本地含有儲存 票據(jù)
NSMutableArray *receipt_MutableArray = [NSMutableArray arrayWithCapacity:0];
receipt_MutableArray = [receiptArray mutableCopy];
for (NSDictionary *dic in receipt_MutableArray) {
if ([[NSString stringWithFormat:@"%@", dic[@"order_id"]] isEqualToString:order_id]) {
[receipt_MutableArray removeObject:dic];
}
}
if (receipt_MutableArray.count > 0) {
NSArray *Apple_ReceiptData_MemberArray = [receipt_MutableArray copy];
[userDefaults setObject:Apple_ReceiptData_MemberArray forKey:[NSString stringWithFormat:@"%@Apple_ReceiptData_MemberArray", user_id]];
} else {
[userDefaults removeObjectForKey:[NSString stringWithFormat:@"%@Apple_ReceiptData_MemberArray", user_id]];
}
} else {
}
[userDefaults synchronize];
} else {
NSLog(@"message ===>>> %@", responseObject.msg);
}
} failure:^(NSError *error, NSString *message) {
NSLog(@"error ====>>>> %@", error);
NSLog(@"message ===>>> %@", message);
}];
}