SCPStoreKitManager 1.1.2

SCPStoreKitManager 1.1.2

测试已测试
语言语言 Obj-CObjective C
许可 MIT
发布最后发布2014 年 12 月

Ste Prescott 维护。



基于 Block 的 iOS7 内购收据验证存储库管理器。请注意,您必须已正确设置 iTunes Connect,已有一些内购项目。示例应用没有用户可视反馈,但您可以通过控制台跟踪其进度。该应用只能在 iDevice 上运行,并且 不能 在模拟器中运行。

所需框架

  • StoreKit

安装

Pod

SCPStoreKitManager 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile

pod 'SCPStoreKitManager'
子模块
  1. 将此存储库作为子模块添加,或下载为 .zip 文件
  2. 在名为 src 的文件夹中,包含了 SCPStoreKitManager 文件夹中的所需文件。如果不想验证收据,则只需将 Categories 文件夹和 SCPStoreKitManager.h + .m 复制到您的项目中。
  3. 在您的项目导航器中,右键单击 SCPStoreKitManager 文件夹,然后单击 在 Finder 中显示。这应在新的 Finder 窗口中打开保存框架的位置。
  4. 转到您项目的项目构建设置,在 搜索路径 部分,您需要添加头文件和库的路径。为此,双击 头文件搜索路径 项。这应弹出一个窗口。回到我们之前在第 3 步打开的 finder 窗口中,按住旁边的文件夹并拖动到 头文件搜索路径 窗口。
  5. 您应该看到类似 "$(SRCROOT)/ExampleProject/SCPStoreKitManager" 的内容。现在,必须将最后一列中的下拉值从 non-recursive 更改为 recursive。点击保存。
  6. 现在双击 库搜索路径,应显示类似的弹出窗口。回到第 3 步中我们打开的 finder 窗口中,导航到 SCPStoreKitReceiptValidator > openSSL > lib。同样,当选择 lib 文件夹时,按住旁边的文件夹并拖动到 库搜索路径 窗口。
  7. 就像我们在第5步中做的那样,你应该会看到一个类似于 "$(SRCROOT)/ExampleProject/SCPStoreKitManager/SCPStoreKitReceiptValidator/openSSL/lib" 的路径。点击保存。

注意:如果你想使用自己的OpenSSL实现,请将这些搜索路径链接到你的实现。

现在你应该能够构建项目并且不出现错误。如果你的项目确实有错误,请确保两个搜索路径都设置为 recursive

用法

框架分为两部分。第一部分是从iTunes检索应用内购买项目并处理它们的购买。第二部分是接收验证。你不需要使用接收验证,但是建议保护你的应用内购买(IAPs)。

SCPStoreKitManager

这是一个基于块封装StoreKit委托方法的包装。

有四个实例方法可以通过共享实例访问。

- (void)requestProductsWithIdentifiers:(NSSet *)productsSet productsReturnedSuccessfully:(ProductsReturnedSuccessfully)productsReturnedSuccessfullyBlock invalidProducts:(InvalidProducts)invalidProductsBlock failure:(Failure)failureBlock;

这个方法接收一组产品标识符(NSSet)。这些产品标识符应与你在iTunes Connect中设置的应用内购买(IAP)的产品ID相匹配。如有需要,请参考Apple文档以获取帮助。

这将请求你所请求的每个产品的IAP详情,在成功请求后,将调用success块,返回一个包含SKProductNSArray。如果你请求了不在iTunes Connect上的产品,这些标识符将作为一个包含失败标识符的NSStringNSArray返回。

失败块将捕捉其他错误,如无法连接到iTunes。

示例
//Request the product details from iTunes
[[SCPStoreKitManager sharedInstance] requestProductsWithIdentifiers:productIdentifiers
                                   productsReturnedSuccessfully:^(NSArray *products) {
                                       NSLog(@"Products : %@", products);
                                   }
                                                    invalidProducts:^(NSArray *invalidProducts) {
                                                        NSLog(@"Invalid Products : %@", invalidProducts);
                                                    }
                                                            failure:^(NSError *error) {
                                                                NSLog(@"Error : %@", [error localizedDescription]);
                                                            }];

- (void)requestPaymentForProduct:(SKProduct *)product paymentTransactionStatePurchasing:(PaymentTransactionStatePurchasing)paymentTransactionStatePurchasingBlock paymentTransactionStatePurchased:(PaymentTransactionStatePurchased)paymentTransactionStatePurchasedBlock paymentTransactionStateFailed:(PaymentTransactionStateFailed)paymentTransactionStateFailedBlock paymentTransactionStateRestored:(PaymentTransactionStateRestored)paymentTransactionStateRestoredBlock failure:(Failure)failureBlock;

此方法接收你希望能够请求支付的SKProduct。根据SKProduct事务的状态,将调用四个不同的块。使用这些块是为了在支付过程中更新你的UI。除了失败块之外,每个块都将返回一个包含SKPaymentTransactionNSArray。当调用到paymentTransactionStatePurchased块时,Apple已经为在事务数组中返回的产品支付了款项。此时,你应该解锁所需的内容或添加所需的内容以完成购买。

示例
//Request payment for product
[[SCPStoreKitManager sharedInstance] requestPaymentForProduct:_products[indexPath.row]
                            paymentTransactionStatePurchasing:^(NSArray *transactions) {
                                  NSLog(@"Purchasing products : %@", transactions);
                              }
                             paymentTransactionStatePurchased:^(NSArray *transactions) {
                                 NSLog(@"Purchased products : %@", transactions);
                             }
                                paymentTransactionStateFailed:^(NSArray *transactions) {
                                    NSLog(@"Failed products : %@", transactions);
                                }
                              paymentTransactionStateRestored:^(NSArray *transactions) {
                                  NSLog(@"Restored products : %@", transactions);
                              }
                                                      failure:^(NSError *error) {
                                                          NSLog(@"Failure : %@", [error localizedDescription]);
                                                      }];

- (void)restorePurchasesPaymentTransactionStateRestored:(PaymentTransactionStateRestored)paymentTransactionStateRestoredBlock paymentTransactionStateFailed:(PaymentTransactionStateFailed)paymentTransactionStateFailedBlock failure:(Failure)failureBlock;

如果你提供应用内购买(IAP),你必须提供一个方法来恢复任何已执行的IAP。有关更多信息,请参阅更多资讯。要实现此目的,请在共享实例上调用此方法,所有先前的交易都将返回一个包含SKPaymentTransactionNSArrayPaymentTransactionStateRestored块中。

示例
//Request to restore previous purchases
[[SCPStoreKitManager sharedInstance] restorePurchasesPaymentTransactionStateRestored:^(NSArray *transactions) {
      NSLog(@"Restored transactions : %@", transactions);
}
                                                       paymentTransactionStateFailed:^(NSArray *transactions) {
                                                           NSLog(@"Failed to restore transactions : %@", transactions);
                                                       }
                                                                             failure:^(NSError *error) {
                                                                                 NSLog(@"Failure : %@", [error localizedDescription]);
                                                                             }];

- (NSString *)localizedPriceForProduct:(SKProduct *)product;

接收一个SKProduct并返回一个价格字符串的产品该方法,该价格与手机的区域设置相匹配。

示例
[productPriceLabel setText:[[SCPStoreKitManager sharedInstance] localizedPriceForProduct:product]];

SCPStoreKitReceiptValidator
- (void)validateReceiptWithBundleIdentifier:(NSString *)bundleIdentifier bundleVersion:(NSString *)bundleVersion tryAgain:(BOOL)tryAgain showReceiptAlert:(BOOL)showReceiptAlert alertViewTitle:(NSString *)alertViewTitle alertViewMessage:(NSString *)alertViewMessage success:(Success)successBlock failure:(Failure)failureBlock;

有一个方法可以验证应用程序发票未被苹果公司篡改。此方法确实需要几个参数,但它们我认为它们是有用的。

参数说明

  • (NSString *)bundleIdentifier

    这应该与您应用的包标识符匹配。这个值是在应用程序中以硬编码方式设置的,而不是从info.plist中检索得到的。这样做的原因是为了防止任何人通过编辑plist文件来匹配任何已购买的所有IAP的收据。

  • bundleVersion:(NSString *)bundleVersion

    您不仅要知道收据是否为正确的应用程序,还要知道是正确的版本。同样地,为了避免编辑plist,这个值也是硬编码的。

  • (BOOL)tryAgain

    当一个App首次安装时,没有收据。这个BOOL值用来确定验证器是否应该尝试从Apple请求新的/更新的收据。这样做可能会显得有些奇怪,因为为此用户必须输入他们的Apple ID详细信息。如果将其设置为NO,则不会尝试刷新或从Apple请求收据,而只验证设备上已存在的任何收据。

  • (BOOL)showReceiptAlert

    如果设置为YES,则会显示UIAlertView,告知用户在显示输入Apple ID细节的警示之前,为什么会被要求输入Apple ID。这可以给用户提供信心,因为它可能会让人感到担忧,如果在没有任何预先通知或背景的情况下,一打开应用就要求输入Apple ID细节。在显示警示时,用户会得到一个选项来请求收据。

  • (NSString *)alertViewTitle and (NSString *)alertViewMessage

    这两个参数允许您为警示视图提供自定义的标题和消息。

  • (Success)successBlock

    一旦收据被验证,您可以确信收据是真实的。当这个block被调用时,您会接收到一个SCPStoreKitReceipt。关于SCPStoreKitReceipt的详细信息请参见以下内容。

  • (Failure)failureBlock

    如果将要验证的收据是无效的,您可以在失败的块中处理它。

示例
//Validate the Apps receipt
[[SCPStoreKitReceiptValidator sharedInstance] validateReceiptWithBundleIdentifier:@"me.ste.SCPStoreKitManager"
                                                                    bundleVersion:@"1.0"
                                                                         tryAgain:YES
                                                                 showReceiptAlert:YES
                                                                   alertViewTitle:nil
                                                                 alertViewMessage:nil
                                                                          success:^(SCPStoreKitReceipt *receipt) {
                                                                              //Here you would do some further checks such as :
                                                                                //Validate that the number of coins/tokens the user has does not exceed the number they have paid for
                                                                                //Unlock any non-consumable items

                                                                              NSLog(@"App receipt : %@", [receipt fullDescription]);

                                                                              //Enumerate through the IAPs and unlock their features
                                                                              [[receipt inAppPurchases] enumerateObjectsUsingBlock:^(SCPStoreKitIAPReceipt *iapReceipt, NSUInteger idx, BOOL *stop) {
                                                                                  NSLog(@"Previous purchase of '%@' on %@", [iapReceipt productIdentifier], [iapReceipt purchaseDate]);
                                                                              }];

                                                                          } failure:^(NSError *error) {
                                                                              NSLog(@"%@", [error fullDescription]);
                                                                          }];

收据

有两大类收据:SCPStoreKitReceiptSCPStoreKitIAPReceipt。每一类都包含非常有用的数据。您不需要对任何这些收据进行init操作,您将它们从SCPStoreKitReceiptValidator方法中获得。

所有收据都有相同的辅助方法。

- (NSDictionary *)fullDescription;

这个方法仅仅将收据输出为一个NSDictionary

SCPStoreKitReceipt

这个收据包含了我们可以用来验证App收据是否为这个App和这个设备的一些数据。

属性包括

@property (nonatomic, strong, readonly) NSString *bundleIdentifier;
@property (nonatomic, strong, readonly) NSData *bundleIdentifierData;
@property (nonatomic, strong, readonly) NSData *hash;
@property (nonatomic, strong, readonly) NSData *opaqueValue;
@property (nonatomic, strong, readonly) NSString *originalVersion;
@property (nonatomic, strong, readonly) NSString *version;

@property (nonatomic, strong, readonly) NSMutableArray *inAppPurchases;

关于这些属性的更多信息,请查阅WWDC13会议。两点值得注意是

  • NSString *originalVersion 如果您将应用从付费应用更改为增值付费应用,您不希望让现有客户感到不悦,在他们为应用付费之后再让他们为IAP付费。利用这个属性,您可以检查应用的原始购买版本,如果它在您的增值付费更改之前,那么您就知道您需要解锁他们在原始购买时应用的全部功能。

  • 这个数组包含了为App收据创建的所有IAP。有关属性及其如何用于验证购买,请参阅以下内容。

SCPStoreKitIAPReceipt

这个收据包含了单个IAP的所有详情。在这个收据中也有一些有用的属性,它们包括

@property (nonatomic, strong, readonly) NSString *productIdentifier;
@property (nonatomic, strong, readonly) NSNumber *quantity;
@property (nonatomic, strong, readonly) NSDate *cancellationDate;
@property (nonatomic, strong, readonly) NSDate *originalPurchaseDate;
@property (nonatomic, strong, readonly) NSDate *purchaseDate;
@property (nonatomic, strong, readonly) NSString *transactionIdentifier;
@property (nonatomic, strong, readonly) NSString *originalTransactionIdentifier;
@property (nonatomic, strong, readonly) NSDate *subscriptionExpiryDate;
@property (nonatomic, strong, readonly) NSNumber *webItemId;

使用这些属性的一些方法包括

  • NSString *productIdentifier

    这个用于确定购买的产品是什么,以及需要解锁哪些功能和产品。

  • NSNumber *quantity

    如果这是一件消耗品,例如硬币或代币,你可以计算购买了多少件此类物品,然后将这个数量与用户的余额进行比较,以检查余额是否被篡改。(.plist编辑。)如果此产品给用户10个代币,并且他们购买了两次,那么他们应该最多有20个代币。如果他们拥有更多,那么你知道有人篡改了,需要处理这个问题。

联系方式

twitter:@ste_prescott

许可证

本项目按照MIT许可证提供。

版权所有 (C) 2014 Ste Prescott

在此特此无条件地授予任何获得此软件及其相关文档副本(以下简称“软件”)的人员在此软件上毫无限制地处理、包括但不限于使用、复制、修改、合并、发布、分发、再许可以及/或出售软件副本的权利,并允许软件接受人进行此操作,但需遵守以下条件

以上版权声明和本许可声明应包含在软件的副本或实质部分中。

软件按“原样”提供,不提供任何形式的保证,无论是明示的、暗示的,包括但不限于对适销性、特定用途适用性和非侵权的保证。在任何情况下,作者或版权所有者均不对任何索赔、损害或其他责任承担责任,无论该责任是否在合同之诉、侵权或其他责任中产生,几乎所有与软件或其使用或其他操作有关或由此产生的。