【01】针对客户详细信息开发苹果客户端object-c语言完整详细包含产品查询,购买,交易验证和恢复购买功能的完整实例-优雅草卓伊凡引言 此前由于卓伊凡我发布过关于苹果ios上架中 in -purchase 苹果内购问题 得到客户咨询来处理,苹果内购相关问题,现在讲demo写出如下,客户是采用object-c 开发的苹果客户端。 实战目前已经配置好的后台 目前已经配置的积分,对应的商品金额 以下是一个详细的 Objective-C 内购实现示例,包含产品查询、购买、交易验证和恢复购买功能: // InAppPurchaseManager.h#import <Foundation/Foundation.h>#import <StoreKit/StoreKit.h>NS_ASSUME_NONNULL_BEGINextern NSString *const IAPManagerProductPurchasedNotification;extern NSString *const IAPManagerProductPurchaseFailedNotification;extern NSString *const IAPManagerProductsLoadedNotification;@interface InAppPurchaseManager : NSObject <SKProductsRequestDelegate, SKPaymentTransactionObserver>+ (instancetype)sharedManager;// 查询产品信息- (void)requestProductsWithIdentifiers:(NSSet *)productIdentifiers;// 购买产品- (void)purchaseProduct:(SKProduct *)product;// 恢复购买- (void)restorePurchases;// 验证交易凭证- (void)verifyReceipt:(NSData *)receiptData;@property (nonatomic, strong) NSArray *products;@property (nonatomic, strong) NSSet *productIdentifiers;@property (nonatomic, strong) NSMutableSet *purchasedProductIdentifiers;@endNS_ASSUME_NONNULL_END// InAppPurchaseManager.m#import "InAppPurchaseManager.h"NSString *const IAPManagerProductPurchasedNotification = @"IAPManagerProductPurchasedNotification";NSString *const IAPManagerProductPurchaseFailedNotification = @"IAPManagerProductPurchaseFailedNotification";NSString *const IAPManagerProductsLoadedNotification = @"IAPManagerProductsLoadedNotification";@interface InAppPurchaseManager ()@property (nonatomic, strong) SKProductsRequest *productsRequest;@end@implementation InAppPurchaseManager+ (instancetype)sharedManager { static InAppPurchaseManager *sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance;}- (instancetype)init { if (self = [super init]) { // 初始化产品标识符 _productIdentifiers = [NSSet setWithArray:@[@"001Liu", @"002Liu", @"003Liu"]]; _purchasedProductIdentifiers = [NSMutableSet set]; // 检查之前的购买记录 for (NSString *productIdentifier in _productIdentifiers) { BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productIdentifier]; if (productPurchased) { [_purchasedProductIdentifiers addObject:productIdentifier]; } } // 添加支付观察者 [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; } return self;}#pragma mark - 产品请求- (void)requestProductsWithIdentifiers:(NSSet *)productIdentifiers { self.productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers]; self.productsRequest.delegate = self; [self.productsRequest start];}#pragma mark - SKProductsRequestDelegate- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { self.products = response.products; // 输出无效产品ID(用于调试) for (NSString *invalidIdentifier in response.invalidProductIdentifiers) { NSLog(@"无效产品ID: %@", invalidIdentifier); } // 通知产品已加载 [[NSNotificationCenter defaultCenter] postNotificationName:IAPManagerProductsLoadedNotification object:nil]; self.productsRequest = nil;}- (void)request:(SKRequest *)request didFailWithError:(NSError *)error { NSLog(@"产品请求失败: %@", error.localizedDescription); self.productsRequest = nil;}#pragma mark - 购买功能- (void)purchaseProduct:(SKProduct *)product { if (![SKPaymentQueue canMakePayments]) { UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"无法购买" message:@"您的设备禁止应用内购买" preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]]; [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alert animated:YES completion:nil]; return; } SKPayment *payment = [SKPayment paymentWithProduct:product]; [[SKPaymentQueue defaultQueue] addPayment:payment];}#pragma mark - SKPaymentTransactionObserver- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions { for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: [self completeTransaction:transaction]; break; case SKPaymentTransactionStateFailed: [self failedTransaction:transaction]; break; case SKPaymentTransactionStateRestored: [self restoreTransaction:transaction]; break; default: break; } }}- (void)completeTransaction:(SKPaymentTransaction *)transaction { [self provideContentForProductIdentifier:transaction.payment.productIdentifier]; [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; // 验证交易凭证(可选但推荐) [self verifyReceipt:transaction.transactionReceipt];}- (void)restoreTransaction:(SKPaymentTransaction *)transaction { [self provideContentForProductIdentifier:transaction.originalTransaction.payment.productIdentifier]; [[SKPaymentQueue defaultQueue] finishTransaction:transaction];}- (void)failedTransaction:(SKPaymentTransaction *)transaction { if (transaction.error.code != SKErrorPaymentCancelled) { NSLog(@"交易失败: %@", transaction.error.localizedDescription); // 发送失败通知 [[NSNotificationCenter defaultCenter] postNotificationName:IAPManagerProductPurchaseFailedNotification object:transaction.error]; } [[SKPaymentQueue defaultQueue] finishTransaction:transaction];}- (void)provideContentForProductIdentifier:(NSString *)productIdentifier { [_purchasedProductIdentifiers addObject:productIdentifier]; [[NSUserDefaults standardUserDefaults] setBool:YES forKey:productIdentifier]; [[NSUserDefaults standardUserDefaults] synchronize]; // 发送购买成功通知 [[NSNotificationCenter defaultCenter] postNotificationName:IAPManagerProductPurchasedNotification object:productIdentifier];}#pragma mark - 恢复购买- (void)restorePurchases { [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];}- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { NSLog(@"恢复购买完成");}- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error { NSLog(@"恢复购买失败: %@", error.localizedDescription);}#pragma mark - 凭证验证(示例)- (void)verifyReceipt:(NSData *)receiptData { // 这里应该将凭证发送到你的服务器进行验证 // 以下是示例代码 NSURL *url = [NSURL URLWithString:@"https://your-server.com/verify_receipt"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"POST"; // 构建请求体 NSDictionary *requestBody = @{@"receipt-data": [receiptData base64EncodedStringWithOptions:0], @"password": @"your_shared_secret"}; // 如果有的话 NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:requestBody options:0 error:&error]; if (!error) { request.HTTPBody = jsonData; NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { NSLog(@"验证失败: %@", error.localizedDescription); return; } // 解析服务器响应 NSError *jsonError; NSDictionary *responseJSON = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError]; if (!jsonError) { NSLog(@"验证结果: %@", responseJSON); // 根据验证结果处理业务逻辑 } }]; [task resume]; }}- (void)dealloc { [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];}@end// 使用示例 - 在ViewController中#import "ViewController.h"#import "InAppPurchaseManager.h"@interface ViewController () <SKProductsRequestDelegate>@property (weak, nonatomic) IBOutlet UIButton *purchaseButton1;@property (weak, nonatomic) IBOutlet UIButton *purchaseButton2;@property (weak, nonatomic) IBOutlet UIButton *purchaseButton3;@property (weak, nonatomic) IBOutlet UIButton *restoreButton;@property (nonatomic, strong) SKProduct *product1;@property (nonatomic, strong) SKProduct *product2;@property (nonatomic, strong) SKProduct *product3;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // 注册通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productsLoaded:) name:IAPManagerProductsLoadedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productPurchased:) name:IAPManagerProductPurchasedNotification object:nil]; // 请求产品信息 NSSet *productIdentifiers = [NSSet setWithArray:@[@"001Liu", @"002Liu", @"003Liu"]]; [[InAppPurchaseManager sharedManager] requestProductsWithIdentifiers:productIdentifiers];}- (void)productsLoaded:(NSNotification *)notification { // 更新UI显示产品信息 for (SKProduct *product in [InAppPurchaseManager sharedManager].products) { if ([product.productIdentifier isEqualToString:@"001Liu"]) { self.product1 = product; [self.purchaseButton1 setTitle:[NSString stringWithFormat:@"购买 - %@", product.price] forState:UIControlStateNormal]; } else if ([product.productIdentifier isEqualToString:@"002Liu"]) { self.product2 = product; [self.purchaseButton2 setTitle:[NSString stringWithFormat:@"购买 - %@", product.price] forState:UIControlStateNormal]; } else if ([product.productIdentifier isEqualToString:@"003Liu"]) { self.product3 = product; [self.purchaseButton3 setTitle:[NSString stringWithFormat:@"购买 - %@", product.price] forState:UIControlStateNormal]; } }}- (void)productPurchased:(NSNotification *)notification { NSString *productIdentifier = notification.object; NSLog(@"购买成功: %@", productIdentifier); // 更新UI,例如禁用已购买产品的按钮 if ([productIdentifier isEqualToString:@"001Liu"]) { self.purchaseButton1.enabled = NO; [self.purchaseButton1 setTitle:@"已购买" forState:UIControlStateNormal]; } // 类似处理其他产品...}- (IBAction)purchaseProduct1:(id)sender { if (self.product1) { [[InAppPurchaseManager sharedManager] purchaseProduct:self.product1]; }}- (IBAction)purchaseProduct2:(id)sender { if (self.product2) { [[InAppPurchaseManager sharedManager] purchaseProduct:self.product2]; }}- (IBAction)purchaseProduct3:(id)sender { if (self.product3) { [[InAppPurchaseManager sharedManager] purchaseProduct:self.product3]; }}- (IBAction)restorePurchases:(id)sender { [[InAppPurchaseManager sharedManager] restorePurchases];}- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self];}@end
|