18、实现应用内购买功能:从零开始创建一个简单的商店

实现应用内购买功能:从零开始创建一个简单的商店

1. 引言

随着移动应用市场的迅速发展,应用内购买(In-App Purchase, IAP)已经成为开发者提高收入的重要途径之一。通过应用内购买,用户可以在应用中购买虚拟商品、服务甚至订阅。本文将详细介绍如何使用 Store Kit 框架为 iOS 应用添加应用内购买功能,包括设置沙盒测试环境、创建简单的商店界面以及实现购买逻辑。

2. 设置沙盒测试环境

在将应用内购买功能集成到应用之前,必须先在 iTunes Connect 中设置产品和测试环境,以模拟支付处理过程而不实际收费。这有助于开发者测试购买流程,确保一切正常运作。

2.1 注册 iTunes Connect

首先,登录 iTunes Connect ,并按照以下步骤创建测试用户和产品:

  1. 创建测试用户
    - 导航到 iTunes Connect 的“用户与权限”部分。
    - 选择“测试用户”选项卡,点击“添加新用户”按钮。
    - 填写必要信息,确保使用不同于现有 iTunes 账户的邮箱地址(例如使用 Gmail 的别名功能)。
    - 创建的测试用户仅用于沙盒环境,不会对真实账户产生影响。

  2. 添加应用内购买产品
    - 从 iTunes Connect 主页选择“我的应用”,然后选择要添加应用内购买的应用。
    - 点击“功能”选项卡下的“应用内购买”,再点击“创建新应用内购买”。
    - 根据需要选择产品类型(消耗型、非消耗型或订阅型),并填写相关信息。
    - 提交产品以供苹果审核,但无需上传二进制文件。

2.2 产品类型

产品类型 描述
可消耗品 用户每次需要时购买的产品,如游戏中的增强道具。
非消耗品 用户只购买一次并永久拥有的产品,如可下载的歌曲或图像。
订阅 用户根据需要频繁续订的产品,可以是消耗型或非消耗型。

3. 创建简单的商店界面

接下来,我们将创建一个简单的商店界面,允许用户浏览和购买 iPhone 背景。商店将使用基于导航的应用程序模板,并在 UITableView 中显示产品列表。

3.1 添加 Store Kit 框架

  1. 打开 Xcode,创建一个新的基于导航的项目,命名为 WPStore
  2. 右键点击 Frameworks 文件夹,选择“添加现有框架”,然后添加 StoreKit.framework

3.2 实现 RootViewController

RootViewController.h 中声明必要的属性和方法:

#import <StoreKit/StoreKit.h>

@interface RootViewController : UITableViewController <SKProductsRequestDelegate, SKPaymentTransactionObserver> {
    NSMutableArray *products;
    NSMutableArray *transactionHistory;
}

@property (nonatomic, retain) NSMutableArray *transactionHistory;

- (void)requestProductData;
- (void)completeTransaction:(SKPaymentTransaction *)transaction;
- (void)restoreTransaction:(SKPaymentTransaction *)transaction;
- (void)failedTransaction:(SKPaymentTransaction *)transaction;
- (void)recordTransaction:(SKPaymentTransaction *)transaction;
- (void)provideContent:(NSString *)productIdentifier;

@end

3.3 实现 RootViewController.m

RootViewController.m 中实现以下方法:

#import "RootViewController.h"

@implementation RootViewController

@synthesize transactionHistory;

- (void)viewDidLoad {
    [super viewDidLoad];

    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
    products = [[NSMutableArray alloc] init];

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"history.plist"];

    self.transactionHistory = [NSMutableArray arrayWithContentsOfFile:path];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }

    SKProduct *product = [products objectAtIndex:indexPath.row];
    cell.textLabel.text = [NSString stringWithFormat:@"$%.2f %@", product.price.doubleValue, product.localizedTitle];
    cell.detailTextLabel.text = product.localizedDescription;
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    return cell;
}

3.4 实现产品选择逻辑

当用户点击表格中的一行时,显示墙纸预览界面。为此,我们需要实现 UITableView didSelectRowAtIndexPath 方法:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    SKProduct *product = [products objectAtIndex:indexPath.row];
    WallpaperViewController *wpViewController = [[WallpaperViewController alloc] initWithNibName:@"WallpaperViewController" bundle:[NSBundle mainBundle]];
    wpViewController.product = product;
    [self.navigationController pushViewController:wpViewController animated:YES];
    [wpViewController release];
}

4. 创建 WallPaperViewController

为了显示墙纸预览界面,我们需要创建一个新的 WallpaperViewController 类,并为其添加相应的视图和逻辑。

4.1 创建 WallPaperViewController.h

WallpaperViewController.h 中声明必要的属性和方法:

#import <UIKit/UIKit.h>
#import <StoreKit/StoreKit.h>

@interface WallpaperViewController : UIViewController {
    IBOutlet UIImageView *imageView;
    SKProduct *product;
}

@property (nonatomic, retain) IBOutlet UIImageView *imageView;
@property (nonatomic, retain) SKProduct *product;
- (IBAction)buttonClicked:(id)sender;

@end

4.2 实现 WallPaperViewController.m

WallpaperViewController.m 中实现以下方法:

#import "WallpaperViewController.h"

@implementation WallpaperViewController

@synthesize imageView, product;

- (void)viewDidLoad {
    [super viewDidLoad];

    // 设置墙纸图像
    imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"%@.jpeg", product.productIdentifier]];
}

- (IBAction)buttonClicked:(id)sender {
    // 实现购买逻辑
    SKPayment *payment = [SKPayment paymentWithProduct:product];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}

@end

以上内容介绍了如何设置沙盒测试环境和创建简单的商店界面。接下来,我们将深入探讨如何实现购买逻辑、处理交易以及提供购买内容。通过这些步骤,您可以为您的应用添加完整且功能强大的应用内购买系统。

5. 实现购买逻辑

为了确保应用内购买流程的顺利进行,我们需要实现购买逻辑、处理交易以及提供购买内容。以下是具体的实现步骤。

5.1 请求产品数据

首先,我们需要请求产品数据,以便在商店界面上显示可用的产品。这可以通过实现 requestProductData 方法来完成:

- (void)requestProductData {
    NSSet *productIdentifiers = [NSSet setWithObjects:@"com.rightsprite.wallpaper.01", @"com.rightsprite.wallpaper.02", @"com.rightsprite.wallpaper.03", nil];
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:productIdentifiers];
    request.delegate = self;
    [request start];
}

5.2 处理产品请求响应

当产品请求完成时, SKProductsRequestDelegate 协议会调用 productsRequest:didReceiveResponse: 方法。我们需要在此方法中处理响应并更新产品列表:

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
    products = [response.products mutableCopy];
    [self.tableView reloadData];
}

5.3 处理购买交易

当用户点击购买按钮时,我们会调用 SKPaymentQueue 来发起购买请求。接下来,我们需要实现 SKPaymentTransactionObserver 协议中的方法来处理交易结果。

5.3.1 完成交易

当购买成功时,调用 completeTransaction 方法来记录交易并向用户提供内容:

- (void)completeTransaction:(SKPaymentTransaction *)transaction {
    [self recordTransaction:transaction];
    [self provideContent:transaction.payment.productIdentifier];
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}
5.3.2 恢复交易

当用户恢复之前购买的产品时,调用 restoreTransaction 方法来处理恢复逻辑:

- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
    [self completeTransaction:transaction];
}
5.3.3 处理失败交易

如果交易失败,我们需要通知用户并记录错误:

- (void)failedTransaction:(SKPaymentTransaction *)transaction {
    if (transaction.error.code != SKErrorPaymentCancelled) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"购买失败" 
                                                        message:transaction.error.localizedDescription 
                                                       delegate:nil 
                                              cancelButtonTitle:@"确定" 
                                              otherButtonTitles:nil];
        [alert show];
        [alert release];
    }
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

5.4 记录交易

为了记录用户的购买历史,我们可以在磁盘上保存一个属性列表文件,其中包含每个购买的产品标识符:

- (void)recordTransaction:(SKPaymentTransaction *)transaction {
    if ([self.transactionHistory containsObject:transaction.payment.productIdentifier]) {
        return;
    }

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *path = [documentsDirectory stringByAppendingPathComponent:@"history.plist"];

    [self.transactionHistory addObject:transaction.payment.productIdentifier];
    [self.transactionHistory writeToFile:path atomically:YES];
}

5.5 提供购买内容

当用户成功购买某个产品时,我们需要将内容提供给用户。例如,如果是壁纸,则将其保存到用户的相机胶卷中:

- (void)provideContent:(NSString *)productIdentifier {
    UIImageWriteToSavedPhotosAlbum([UIImage imageNamed:[NSString stringWithFormat:@"%@.jpeg", productIdentifier]], self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}

- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"购买完成" 
                                                    message:@"壁纸已保存到您的相机胶卷。" 
                                                   delegate:nil 
                                          cancelButtonTitle:@"确定" 
                                          otherButtonTitles:nil];
    [alert show];
    [alert release];
}

6. 优化和注意事项

6.1 优化用户体验

确保商店界面简洁明了,用户可以轻松浏览和购买产品。同时,提供详细的购买确认信息,以增强用户的信任感。

6.2 注意事项

  • 开发时间 :在向应用添加商店时,始终考虑它将如何影响开发时间。确保在考虑应用内购买产品准备好后立即提交,以免审核过程拖慢部署进度。
  • 功能性 :不要让应用完全依赖于应用内购买。确保为那些下载应用但选择不购买产品的用户提供一定的价值。
  • 安全性 :确保所有交易通过 iTunes 安全处理,避免在应用中直接处理支付信息。

7. 结论

通过上述步骤,您可以为 iOS 应用添加一个完整且功能强大的应用内购买系统。从设置沙盒测试环境到实现购买逻辑,再到提供购买内容,每个环节都至关重要。希望本文能帮助您更好地理解和实现应用内购买功能,从而为您的应用带来更多收入。

表格:应用内购买产品类型对比

产品类型 描述
可消耗品 用户每次需要时购买的产品,如游戏中的增强道具。
非消耗品 用户只购买一次并永久拥有的产品,如可下载的歌曲或图像。
订阅 用户根据需要频繁续订的产品,可以是消耗型或非消耗型。

mermaid 流程图:应用内购买流程

graph TD;
    A[启动应用] --> B[请求产品数据];
    B --> C{产品请求完成?};
    C -- 是 --> D[更新产品列表];
    D --> E[用户选择产品];
    E --> F[发起购买请求];
    F --> G{交易成功?};
    G -- 是 --> H[记录交易];
    H --> I[提供购买内容];
    G -- 否 --> J{用户取消?};
    J -- 是 --> K[结束交易];
    J -- 否 --> L[显示错误信息];
    L --> K;

通过以上步骤,您可以为 iOS 应用添加一个完整且功能强大的应用内购买系统。希望本文能帮助您更好地理解和实现应用内购买功能,从而为您的应用带来更多收入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值