为测试用户清除 iOS 应用内购买沙箱中的购买

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7747457/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:50:33  来源:igfitidea点击:

Clearing purchases from iOS in-app purchase sandbox for a test user

iphoneiosin-app-purchase

提问by RandomIOSDeveloper

Does anyone have any ideas on how to reset and/or clear the iOS in-app purchase sandbox?

有没有人对如何重置和/或清除 iOS 应用内购买沙箱有任何想法?

I have an app that I'm testing with the sandbox, and I'd like to test new purchases without having to create a new test user every time I purchase something.

我有一个正在使用沙盒测试的应用程序,我想测试新购买的东西,而不必每次购买东西时都创建新的测试用户。

If I don't do this, then I (of course) always get a message that the in-app purchase item has already been purchased when I click on my app's buy button.

如果我不这样做,那么当我点击我的应用程序的购买按钮时,我(当然)总是会收到一条消息,表明应用程序内购买项目已经被购买。

回答by Roberto Canogar

IMO there are 3 things you can do to make testing non-consumables bearable:

IMO 您可以做 3 件事来使测试非消耗品变得可以忍受:

  1. You can have many test accounts associated to one email. Gmail for example lets you add a "plus" string to the email to create aliases for an address: so [email protected]and [email protected]both really just go to [email protected]. Probably other email hosts do the same. When you create a test account you need to introduce: first name, last name, email address, password, secret question, secret answer, date of birth, and iTunes store country. You can put exactly the same data (including password) for [email protected]and [email protected]and you will have two test accounts. Finally, in your [email protected]inbox you will receive two verification emails from Apple to confirm both test accounts.

  2. Say that you have a non-consumable with product ID @"Extra_Levels". Instead of writing @"Extra_Levels" in all methods (requestProduct, purchaseProduct, ...), just write PRODUCT_ID1and at some header file put #define PRODUCT_ID1 @"Extra_Levels"(with no semicolon!), then the preprocessor will search PRODUCT_ID1 and substitute it for @"Extra_Levels". Then creating a new non-consumable called @"Extra_Levels_01" and changing the #define will be as good as resetting the purchases for all your test users.

  3. As appsmatics pointed out, you can test the correct behavior of your code when you buy a non-consumable IAP by first using a consumable IAP (so that test user can make as many purchases as needed) to get rid of some bugs. Of course, you should also test the code with the real non-consumable IAP after that.

  1. 您可以将多个测试帐户关联到一封电子邮件。例如,Gmail 允许您向电子邮件添加“加号”字符串以创建地址的别名:因此[email protected][email protected]两者实际上都只需转到[email protected]. 可能其他电子邮件主机也会这样做。创建测试帐户时,您需要介绍:名字、姓氏、电子邮件地址、密码、秘密问题、秘密答案、出生日期和 iTunes 商店国家/地区。您可以为[email protected]和 输入 完全相同的数据(包括密码)[email protected],您将拥有两个测试帐户。最后,在您的[email protected]收件箱中,您将收到来自 Apple 的两封验证电子邮件,以确认两个测试帐户。

  2. 假设您有一个产品 ID 为 @"Extra_Levels" 的非消耗品。不要在所有方法(requestProduct、purchaseProduct、...)中写入@"Extra_Levels",只需写入PRODUCT_ID1并在某些头文件中放置#define PRODUCT_ID1 @"Extra_Levels"(不带分号!),然后预处理器将搜索 PRODUCT_ID1 并将其替换为@"Extra_Levels"。然后创建一个名为 @"Extra_Levels_01" 的新非消耗品并更改 #define 将与重置所有测试用户的购买一样好。

  3. 正如appsmatics 指出的那样,您可以在购买非消耗性IAP 时通过首先使用消耗性IAP(以便测试用户可以根据需要进行尽可能多的购买)来消除一些错误来测试代码的正确行为。当然,之后您还应该使用真正的非消耗性 IAP 测试代码。

回答by Ben Zotto

You can't do this, as far as I know. The sandbox backend works like a real account-- once it's purchased, it's purchased (and thus you can test restore). You should do most of your development with the store stuff shimmed out, and then when you get to testing it for real, just expect to create several test accounts.

据我所知,你不能这样做。沙盒后端就像一个真实帐户一样工作——一旦购买,它就会被购买(因此您可以测试恢复)。你应该在商店里做大部分开发,然后当你真正测试它时,只需要创建几个测试帐户。

回答by user1105951

I have 2 in app purchase items. 1 for production. and the other for testing. when I need to "clear" I delete the in app item and create new one (15 seconds in itunes connect and 1 second to change the product id in code)

我有 2 个应用内购买项目。1 用于生产。另一个用于测试。当我需要“清除”时,我会删除应用内项目并创建新项目(iTunes 连接中 15 秒,代码中更改产品 ID 1 秒)

if i dont need to test "new user", i use the production in app item.

如果我不需要测试“新用户”,我会在应用项目中使用产品。

回答by bobobobo

Well, technically you don't need that.

好吧,从技术上讲,您不需要那个。

If you get SKPaymentTransactionStateRestored, it is 100% equivalent to the app store verifying the user and granting him the purchase. I have a switch like:

如果得到SKPaymentTransactionStateRestored,则 100% 相当于应用商店验证用户并授予他购买权。我有一个开关,如:

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
  for( SKPaymentTransaction *purch in transactions )
  {
    switch( purch.transactionState )
    {
      case SKPaymentTransactionStateRestored:
        info( "PURCHASE RESTORE" ) ;
        // fall thru
      case SKPaymentTransactionStatePurchased:
        [[SKPaymentQueue defaultQueue] finishTransaction:purch];
        // Do regular changes to app state for this purchase,
        // register in keychain, etc.
        break ;

       //.. other cases
     }
  }
}

The question of having your app logic / take back the purchase is simple: if you're caching purchases in keychain, delete your keychain. If you're doing it some other how, just change your local app state to pretend like the user never purchased it before. The request to purchase dialog is still exactly the same, the only difference is when you punch YES, it gives you SKPaymentTransactionStateRestoredinstead of SKPaymentTransactionStatePurchased.

让您的应用程序逻辑/收回购买的问题很简单:如果您在钥匙串中缓存购买,请删除您的钥匙串。如果您正在以其他方式执行此操作,只需更改本地应用程序状态以假装用户以前从未购买过它。购买对话框的请求仍然完全相同,唯一的区别是当您点击 YES 时,它给您SKPaymentTransactionStateRestored而不是SKPaymentTransactionStatePurchased.

回答by Christopher Larsen

Deleting your app and reinstalling works also for sandbox testing. Depends on the app obviously, but I'm testing a subscription based app that only purchases during sign up at the moment so it's been the easiest solution.

删除您的应用程序并重新安装也适用于沙盒测试。显然取决于应用程序,但我正在测试基于订阅的应用程序,该应用程序目前仅在注册期间购买,因此它是最简单的解决方案。

回答by Emile Cormier

Check out SimStoreKit. It's a "simulated version of the iPhone's StoreKit, for testing store UIs on the iPhone Simulator, or even on device without having to set up IAP in Connect."

查看SimStoreKit。它是“iPhone StoreKit 的模拟版本,用于在 iPhone 模拟器上甚至在设备上测试商店 UI,而无需在 Connect 中设置 IAP”。

SimStoreKit stores purchases in the user defaults under the key ILSimSKTransactions. So to clear all purchases you can do:

SimStoreKit 将购买存储在键下的用户默认值中ILSimSKTransactions。因此,要清除所有购买,您可以执行以下操作:

[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"ILSimSKTransactions"]

On the simulator, you can simply remove your app and install it again.

在模拟器上,您只需删除应用程序并重新安装即可。

I've successfully used SimStoreKit to debug my app's store front before testing with the sandbox. The beauty of this library is that it can be set-up to use the same class names as the real StoreKit framework (by doing #define ILSimReplaceRealStoreKit 1before doing #include <ILSimStoreKit.h>).

在使用沙箱进行测试之前,我已经成功地使用 SimStoreKit 调试了我的应用程序的店面。这个库的美妙之处在于它可以被设置为使用与真正的 StoreKit 框架相同的类名(通过在做#define ILSimReplaceRealStoreKit 1之前做#include <ILSimStoreKit.h>)。

In source files where I need to access StoreKit, I include this header file:

在我需要访问 StoreKit 的源文件中,我包含了这个头文件:

#import <TargetConditionals.h>

#if TARGET_IPHONE_SIMULATOR
    #define kILSimAllowSimulatedStoreKit 1
    #define ILSimReplaceRealStoreKit 1
    #import <ILSimStoreKit.h>
#else
    #import <StoreKit/StoreKit.h>
#endif

This has the effect of using SimStoreKit when I run on the simulator and the real StoreKit when I run on the device.

这具有在模拟器上运行时使用 SimStoreKit 和在设备上运行时使用真实 StoreKit 的效果。

回答by anorskdev

Not really an answer, but help in explaining.

不是真正的答案,但有助于解释。

Thought that since the file had to be downloaded, that just maybe it could be deleted. Simple function below tries that (Swift 3.0):

认为既然必须下载文件,那也许可以将其删除。下面的简单函数尝试(Swift 3.0):

func removeReceipt() {
    if let receiptURL = Bundle.main.appStoreReceiptURL {
        print("receipt URL: \(receiptURL)")
        do {
            try FileManager.default.removeItem(at: receiptURL)
            print("Success")
        } catch let error as NSError {
            print("ERROR: \(error.localizedDescription)")
        }
    }
}

Got following response:

得到以下回复:

receipt URL: file:///private/var/mobile/Containers/Data/Application/7A2-App-Related-Number-67/StoreKit/sandboxReceipt

收据网址:file:///private/var/mobile/Containers/Data/Application/7A2-App-Related-Number-67/StoreKit/sandboxReceipt

ERROR: “sandboxReceipt” couldn't be removed because you don't have permission to access it.

错误:“sandboxReceipt”无法删除,因为您无权访问它。

Though the code shows that it pulls the receipt out of the app bundle, had kind of thought that the bundle was static, and so the receipt might still be deletable. I'm sure there are safety reasons why this all works this way - so ended up having to delete app to (re)-test case of going from no receipt to new receipt downloaded.

尽管代码显示它从应用程序包中提取收据,但我认为该包是静态的,因此收据可能仍然可以删除。我确信这一切都以这种方式工作是有安全原因的 - 所以最终不得不删除应用程序到(重新)测试从没有收据到下载新收据的情况。

回答by Adobels

alternatively to create multiple test user solution you can create multiple test in app purchases in iTunes connect then you don't need to change a user account.

或者,要创建多个测试用户解决方案,您可以在 iTunes Connect 中的应用程序购买中创建多个测试,然后您无需更改用户帐户。

回答by ArthurVonBabylon

Just keep using the same test account, restoring purchases as opposed to completing new ones. After all, whether you start a new purchase or restore an old one, YOUR APP will do the same thing (at least initially, maybe the user interface will update differently upon completion). Apple are the folks handling things differently in those different situations - don't worry about it.

只需继续使用相同的测试帐户,恢复购买而不是完成新的购买。毕竟,无论您是开始新购买还是恢复旧产品,您的 APP 都会做同样的事情(至少在最初,用户界面可能会在完成后更新不同)。苹果是在这些不同情况下处理不同事情的人 - 不要担心。

Place your delivery logic in the SKPaymentTransactionStateRestored case within this method's implementation for testing:

将您的交付逻辑放在此方法的实现中的 SKPaymentTransactionStateRestored 案例中以进行测试:

- (void)paymentQueue:(SKPaymentQueue *)queue
 updatedTransactions:(NSArray *)transactions;

Then be sure to put that delivery logic into the SKPaymentTransactionStatePurchased case.

然后确保将该交付逻辑放入 SKPaymentTransactionStatePurchased 案例中。

At the end, because most of us are obsessive-compulsive to varying degrees, do a final test with a fresh account (not a big deal to make a second one for absolute certainty).

最后,因为我们大多数人都有不同程度的强迫症,所以用一个新的账户做最后的测试(绝对确定再做一个没什么大不了的)。

The final thing to note: consider apple's position. If there was a problem with developers having to waste time creating tens or hundreds of accounts to test IAP thoroughly, they would have solved the problem. There is no problem.

最后要注意的是:考虑苹果的立场。如果开发人员不得不浪费时间创建数十或数百个帐户来彻底测试 IAP,他们就会解决问题。没有问题。