【02】针对客户详细信息开发苹果客户端object-c语言完整详细包含产品查询,购买,交易验证和恢复购买功能的完整目录文件结构-优雅草卓伊凡引言 上一篇已经写了具体的代码,本篇详细了代码的目录结构,完整的demo实例, 实战文件目录结构YourProjectName/├── Supporting Files/│ ├── YourProjectName-Info.plist│ └── YourProjectName-Prefix.pch├── InAppPurchase/│ ├── InAppPurchaseManager.h│ ├── InAppPurchaseManager.m│ └── InAppPurchaseConstants.h (可选)├── ViewControllers/│ ├── IAPStoreViewController.h│ ├── IAPStoreViewController.m│ └── IAPStoreViewController.xib (或.storyboard)└── Resources/ └── IAPProducts.plist (可选,用于存储产品信息)文件详细说明1. InAppPurchaseManager.h位置: YourProjectName/InAppPurchase/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_END2. InAppPurchaseManager.m位置: YourProjectName/InAppPurchase/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// 实现代码与之前提供的相同// ...@end3. IAPStoreViewController.h位置: YourProjectName/ViewControllers/IAPStoreViewController.h #import <UIKit/UIKit.h>#import <StoreKit/StoreKit.h>NS_ASSUME_NONNULL_BEGIN@interface IAPStoreViewController : UIViewController@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 (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingIndicator;@property (nonatomic, strong) SKProduct *product1;@property (nonatomic, strong) SKProduct *product2;@property (nonatomic, strong) SKProduct *product3;- (IBAction)purchaseProduct1:(id)sender;- (IBAction)purchaseProduct2:(id)sender;- (IBAction)purchaseProduct3:(id)sender;- (IBAction)restorePurchases:(id)sender;@endNS_ASSUME_NONNULL_END4. IAPStoreViewController.m位置: YourProjectName/ViewControllers/IAPStoreViewController.m #import "IAPStoreViewController.h"#import "InAppPurchaseManager.h"@interface IAPStoreViewController ()@end@implementation IAPStoreViewController- (void)viewDidLoad { [super viewDidLoad]; [self setupUI]; [self setupNotifications]; [self loadProducts];}- (void)setupUI { // 初始化UI状态 self.purchaseButton1.enabled = NO; self.purchaseButton2.enabled = NO; self.purchaseButton3.enabled = NO; [self.loadingIndicator startAnimating];}- (void)setupNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productsLoaded:) name:IAPManagerProductsLoadedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productPurchased:) name:IAPManagerProductPurchasedNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(productPurchaseFailed:) name:IAPManagerProductPurchaseFailedNotification object:nil];}- (void)loadProducts { NSSet *productIdentifiers = [NSSet setWithArray:@[@"001Liu", @"002Liu", @"003Liu"]]; [[InAppPurchaseManager sharedManager] requestProductsWithIdentifiers:productIdentifiers];}// 通知处理方法- (void)productsLoaded:(NSNotification *)notification { [self.loadingIndicator stopAnimating]; for (SKProduct *product in [InAppPurchaseManager sharedManager].products) { if ([product.productIdentifier isEqualToString:@"001Liu"]) { self.product1 = product; [self.purchaseButton1 setTitle:[NSString stringWithFormat:@"购买 - %@", product.price] forState:UIControlStateNormal]; self.purchaseButton1.enabled = YES; } else if ([product.productIdentifier isEqualToString:@"002Liu"]) { self.product2 = product; [self.purchaseButton2 setTitle:[NSString stringWithFormat:@"购买 - %@", product.price] forState:UIControlStateNormal]; self.purchaseButton2.enabled = YES; } else if ([product.productIdentifier isEqualToString:@"003Liu"]) { self.product3 = product; [self.purchaseButton3 setTitle:[NSString stringWithFormat:@"购买 - %@", product.price] forState:UIControlStateNormal]; self.purchaseButton3.enabled = YES; } }}- (void)productPurchased:(NSNotification *)notification { NSString *productIdentifier = notification.object; [self showAlertWithTitle:@"购买成功" message:[NSString stringWithFormat:@"已成功购买: %@", productIdentifier]]; // 更新UI [self updatePurchaseStatus];}- (void)productPurchaseFailed:(NSNotification *)notification { NSError *error = notification.object; if (error.code != SKErrorPaymentCancelled) { [self showAlertWithTitle:@"购买失败" message:error.localizedDescription]; }}// Action方法- (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]; [self.loadingIndicator startAnimating];}// 辅助方法- (void)updatePurchaseStatus { // 检查购买状态并更新UI InAppPurchaseManager *iapManager = [InAppPurchaseManager sharedManager]; if ([iapManager.purchasedProductIdentifiers containsObject:@"001Liu"]) { self.purchaseButton1.enabled = NO; [self.purchaseButton1 setTitle:@"已购买" forState:UIControlStateNormal]; } if ([iapManager.purchasedProductIdentifiers containsObject:@"002Liu"]) { self.purchaseButton2.enabled = NO; [self.purchaseButton2 setTitle:@"已购买" forState:UIControlStateNormal]; } if ([iapManager.purchasedProductIdentifiers containsObject:@"003Liu"]) { self.purchaseButton3.enabled = NO; [self.purchaseButton3 setTitle:@"已购买" forState:UIControlStateNormal]; }}- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message { UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil]]; [self presentViewController:alert animated:YES completion:nil];}- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self];}@end5. 配置文件 (可选)IAPProducts.plist (位置: YourProjectName/Resources/IAPProducts.plist) <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict> <key>Products</key> <array> <string>001Liu</string> <string>002Liu</string> <string>003Liu</string> </array> <key>SharedSecret</key> <string>your_shared_secret_here</string></dict></plist>项目配置要求在Xcode中配置: - 开启In-App Purchase capability
- 确保Bundle Identifier与开发者后台一致
在Info.plist中添加: <key>SKPaymentQueue</key><dict> <key>merchant.liu1</key> <string>Merchant Identifier for In-App Purchase</string></dict>
|