123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- //
- // IAPManager.m
- // jiaPei
- //
- // Created by 张嵘 on 2022/9/21.
- // Copyright © 2022 JCZ. All rights reserved.
- //
- #import "IAPManager.h"
- #import <Foundation/Foundation.h>
- #import <StoreKit/StoreKit.h>
- @interface IAPManager()<SKPaymentTransactionObserver,SKProductsRequestDelegate>{
- NSString *_currentPurchasedID;
- IAPCompletionHandle _iAPCompletionHandle;
- }
- @end
- @implementation IAPManager
-
- + (instancetype)shareIAPManager {
-
- static IAPManager *iAPManager = nil;
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken,^{
- iAPManager = [[IAPManager alloc] init];
- });
- return iAPManager;
- }
- - (instancetype)init{
- self = [super init];
- if (self) {
- [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
- }
- return self;
- }
-
- - (void)dealloc{
- [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
- }
-
-
- - (void)startPurchaseWithID:(NSString *)purchID completeHandle:(IAPCompletionHandle)handle{
- if (purchID) {
- if ([SKPaymentQueue canMakePayments]) {
- _currentPurchasedID = purchID;
- _iAPCompletionHandle = handle;
-
- //从App Store中检索关于指定产品列表的本地化信息
- NSSet *nsset = [NSSet setWithArray:@[purchID]];
- SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
- request.delegate = self;
- [request start];
- }else{
- [self handleActionWithType:IAPPurchNotArrow data:nil transactionIdentifier:nil isTest:NO];
- }
- }
- }
- - (void)handleActionWithType:(IAPPurchType)type data:(NSData *)data transactionIdentifier:(NSString *)transactionIdentifier isTest:(BOOL)isTest {
- #if DEBUG
- switch (type) {
- case IAPPurchSuccess:
- NSLog(@"购买成功");
- break;
- case IAPPurchFailed:
- NSLog(@"购买失败");
- break;
- case IAPPurchCancel:
- NSLog(@"用户取消购买");
- break;
- case IAPPurchVerFailed:
- NSLog(@"订单校验失败");
- break;
- case IAPPurchVerSuccess:
- NSLog(@"订单校验成功");
- break;
- case IAPPurchNotArrow:
- NSLog(@"不允许程序内付费");
- break;
- default:
- break;
- }
- #endif
- if(_iAPCompletionHandle){
- _iAPCompletionHandle(type,data,transactionIdentifier,isTest);
- }
- }
-
- - (void)verifyPurchaseWithPaymentTransaction:(SKPaymentTransaction *)transaction isTestServer:(BOOL)isTestServer {
- //交易验证
- NSURL *recepitURL = [[NSBundle mainBundle] appStoreReceiptURL];
- NSData *receipt = [NSData dataWithContentsOfURL:recepitURL];
-
- if(!receipt){
- // 交易凭证为空验证失败
- [self handleActionWithType:IAPPurchVerFailed data:nil transactionIdentifier:nil isTest:isTestServer];
- return;
- }
- // 购买成功将交易凭证发送给服务端进行再次校验
- [self handleActionWithType:IAPPurchSuccess data:receipt transactionIdentifier:transaction.transactionIdentifier isTest:isTestServer];
-
- NSError *error;
- NSDictionary *requestContents = @{
- @"receipt-data": [receipt base64EncodedStringWithOptions:0]
- };
- NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents
- options:0
- error:&error];
-
- if (!requestData) { // 交易凭证为空验证失败
- [self handleActionWithType:IAPPurchVerFailed data:nil transactionIdentifier:nil isTest:isTestServer];
- return;
- }
-
- NSString *serverString = @"https://buy.itunes.apple.com/verifyReceipt";
- if (isTestServer) {
- serverString = @"https://sandbox.itunes.apple.com/verifyReceipt";
- }
- NSURL *storeURL = [NSURL URLWithString:serverString];
- NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];
- [storeRequest setHTTPMethod:@"POST"];
- [storeRequest setHTTPBody:requestData];
-
- [[NSURLSession sharedSession] dataTaskWithRequest:storeRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
- if (error) {
- // 无法连接服务器,购买校验失败
- [self handleActionWithType:IAPPurchVerFailed data:nil transactionIdentifier:nil isTest:isTestServer];
- } else {
- NSError *error;
- NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
- if (!jsonResponse) {
- // 服务器校验数据返回为空校验失败
- [self handleActionWithType:IAPPurchVerFailed data:nil transactionIdentifier:nil isTest:isTestServer];
- }
-
- NSString *status = [NSString stringWithFormat:@"%@",jsonResponse[@"status"]];
- if(status && [status isEqualToString:@"0"]){
- [self handleActionWithType:IAPPurchVerSuccess data:nil transactionIdentifier:nil isTest:isTestServer];
- } else if (status && [status isEqualToString:@"21007"]) {
- [self verifyPurchaseWithPaymentTransaction:transaction isTestServer:YES];
- } else {
- [self handleActionWithType:IAPPurchVerFailed data:nil transactionIdentifier:nil isTest:isTestServer];
- }
- #if DEBUG
- NSLog(@"----验证结果 %@",jsonResponse);
- #endif
- }
- }];
-
- // 验证成功与否都注销交易,否则会出现虚假凭证信息一直验证不通过,每次进程序都得输入苹果账号
- [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
- }
-
- #pragma mark - SKProductsRequestDelegate
- - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
- NSArray *product = response.products;
- if([product count] <= 0){
- #if DEBUG
- NSLog(@"--------------没有商品------------------");
- #endif
- return;
- }
-
- SKProduct *p = nil;
- for(SKProduct *pro in product){
- if([pro.productIdentifier isEqualToString:_currentPurchasedID]){
- p = pro;
- break;
- }
- }
-
- #if DEBUG
- NSLog(@"productID:%@", response.invalidProductIdentifiers);
- NSLog(@"产品付费数量:%lu",(unsigned long)[product count]);
- NSLog(@"产品描述:%@",[p description]);
- NSLog(@"产品标题%@",[p localizedTitle]);
- NSLog(@"产品本地化描述%@",[p localizedDescription]);
- NSLog(@"产品价格:%@",[p price]);
- NSLog(@"产品productIdentifier:%@",[p productIdentifier]);
- #endif
-
- SKPayment *payment = [SKPayment paymentWithProduct:p];
- [[SKPaymentQueue defaultQueue] addPayment:payment];
- }
-
- //请求失败
- - (void)request:(SKRequest *)request didFailWithError:(NSError *)error{
- #if DEBUG
- NSLog(@"------------------从App Store中检索关于指定产品列表的本地化信息错误-----------------:%@", error);
- #endif
- }
-
- - (void)requestDidFinish:(SKRequest *)request{
- #if DEBUG
- NSLog(@"------------requestDidFinish-----------------");
- #endif
- }
-
- #pragma mark - SKPaymentTransactionObserver
- - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
- for (SKPaymentTransaction *tran in transactions) {
- switch (tran.transactionState) {
- case SKPaymentTransactionStatePurchased:
- [self verifyPurchaseWithPaymentTransaction:tran isTestServer:NO];
- break;
- case SKPaymentTransactionStatePurchasing:
- #if DEBUG
- NSLog(@"商品添加进列表");
- #endif
- break;
- case SKPaymentTransactionStateRestored:
- #if DEBUG
- NSLog(@"已经购买过商品");
- #endif
- // 消耗型不支持恢复购买
- [[SKPaymentQueue defaultQueue] finishTransaction:tran];
- break;
- case SKPaymentTransactionStateFailed:
- [self failedTransaction:tran];
- break;
- default:
- break;
- }
- }
- }
- // 交易失败
- - (void)failedTransaction:(SKPaymentTransaction *)transaction{
- if (transaction.error.code != SKErrorPaymentCancelled) {
- [self handleActionWithType:IAPPurchFailed data:nil transactionIdentifier:nil isTest:NO];
- }else{
- [self handleActionWithType:IAPPurchCancel data:nil transactionIdentifier:nil isTest:NO];
- }
-
- [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
- }
- @end
- /* 调用支付方法
- - (void)purchaseWithProductID:(NSString *)productID{
-
- [[IAPManager shareIAPManager] startPurchaseWithID:productID completeHandle:^(IAPPurchType type,NSData *data) {
-
- }];
- }
- */
|