How to test SKPaymentTransactionStateDeferred?
iOS 8 will be rolling out soon. We have Xcode beta 6 atm, but still cannot find any docs on how to properly test Family Sharing (or did I miss something?). My question is how to properly setup Sandbox with parent/child? I tried to make it work in beta 1 without joy.
Any hints guys?
Two related stories on Apple Developer Forum:
- How to create a children sandbox account on iTunes Connect?(https://devforums.apple.com/message/1030357#1030357)
- Testing “Ask to Buy” in sandbox (https://devforums.apple.com/message/1005569#1005569)
5 Solutions Collect From Internet About “How to test SKPaymentTransactionStateDeferred?”
I’ve made a little headway on this topic, so thought I’d report in. Plus, I’ve found an apparent bug, which I’ve reported to Apple.
What I’ve done is the following:
1) Create a parent test (sandbox) account in iTunes Connect, and create a child test account. These are really just two test accounts in iTunes Connect. Call them P and C for parent and child.
2) With both accounts, go to https://appleid.apple.com and change their year for their age. iTunes Connect doesn’t let you do this. For some reason, the process with family sharing doesn’t work unless ages do have a year. I’ve found that you have to do the selection twice on the year list at https://appleid.apple.com. Odd. I set my P as older (some adult age) and my C as younger.
3) On one apple device (my iPhone, running iOS8), I setup family sharing under Settings > iCloud for the P account. I’m signed into iTunes on this device with my real iTunes Apple Id (which has my payment info).
4) I then invite my C apple id to be part of my family, under Settings > iCloud.
5) I accept the invitation from P (on my iPad, also running iOS8), which involves signing into the iCloud on that other device as C.
6) On my iPhone, I turn on “Ask To Buy” for the C family member.
Now, I’m ready to try a test purchase as C on my sandboxed app. After I go through the regular process in my app’s store I get the following alert:
when I tap on “Ask”, I get the next alert:
Now, I’ve tried two options, with separate purchases. I’ve tried the “OK” option, which should send a notification to the P account. I have yet to receive such a notification on my P account (still signed into iCloud as that on my iPad).
I’ve also tried the “Approve in Person” option on the “child”s iPad. I use the P account, and I enter in that if on the next alert:
I get no error after that, so it would seem the Approve In Person worked, but I have yet to have that purchase convert to SKPaymentTransactionStatePurchased state. All of the deferred purchases are still in the payment queue of the app, each with the state SKPaymentTransactionStateDeferred. When I restart the app, the state of each purchase, still in the queue, is deferred.
Next, I wondered if there was some problem with the particular test iTunes account for C, so I made a second child account, call that C2, and tried to establish it as a child under P on my iPhone. However, I run into a further problem there. I get the alert (on the iPad), when I try to accept the invitation to be a family member under P for C2:
To me, this limitation on iCloud account shouldn’t apply to test accounts. This is the apparent bug I’ve reported to Apple.
So, in summary, I’m not yet 100% convinced that my SKPaymentTransactionStateDeferred implementation is working. We shall see if Apple gets back to me.
From iOS 8.3 there is a new flag available for SKPayment:
So in case you need to test SKPaymentTransactionStateDeferred state you initialize
SKMutablePayment and set
simulatesAskToBuyInSandbox = YES.
PS. WARNING: folks complain that this API doesn’t work properly (see comments)
iOS 9.2.1, Xcode 7.2.1, ARC enabled
simulatesAskToBuyInSandbox property does not cause the payment queue observer to register the
SKPaymentTransactionStateDeferred state. Instead, it just process the payment and the observer registers the
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:productUserRequested]; payment.simulatesAskToBuyInSandbox = true; [[SKPaymentQueue defaultQueue] addPayment:payment];
The only test I was able to perform was to call my method for the deferred payment when the observer registered the
SKPaymentTransactionStatePurchased state instead of my usual method and not call:
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
This persists the transaction upon app. termination, and gives you the ability to test the user not completing the purchase (e.g. loss of reception during final stages of purchasing) and deferred purchase. This is assuming your purchasing method passes a deferred parameter, as described in Listing 4-2 Responding to transaction statuses in In App Purchasing Guide: Delivering Products. Here is what the method would look like:
To simulate hung up purchasing:
[self showTransactionAsInProgress:transaction deferred:NO];
To simulate deferred:
[self showTransactionAsInProgress:transaction deferred:YES];
Note: Upon app. restart, the Apple in app. purchase mechanism will ask for your credentials if you did not process any other payments for the credentials, uninstalled the app., or signed out of “iTunes and App Stores” in “Settings”. Also, if you tap “Cancel” here, then the transaction will not fail, because the payment queue observer will keep registering the
I found this suggestion from Apple which might prove to be helpful, it is a fancy way of doing what I suggested:
Test an Interrupted Transaction
Set a breakpoint in your transaction queue observer’s
paymentQueue:updatedTransactions: method so you can control whether it
delivers the product. Then make a purchase as usual in the test
environment, and use the breakpoint to temporarily ignore the
transaction—for example, by returning from the method immediately
using the thread return command in LLDB.
Terminate and relaunch your app. Store Kit calls the
paymentQueue:updatedTransactions: method again shortly after launch;
this time, let your app respond normally. Verify that your app
correctly delivers the product and completes the transaction.
Hope this helps! Cheers.
When creating child account according to Chris Prince answer, make sure you set it’s “age” between 13 and 18 years old. If you set it to be less than 13, you can’t verify it’s age (even if you add credit card to your P account). If it’s above 18 – option to enable Ask to buy is gone. Spent hours trying to find out what i’m doing wrong.
Also you need to create C account via itunes connect not via “Creat child’s account” option in family sharing screen.
Wish I could comment, but since I don’t have 50 reputation points, I have to create a separate answer.
As it turns out it would appear that the sandbox environment does not support the parent child relationship so the messages will not be sent when the accounts in question are setup as mentioned in the answer by @ChrisPrince.
The article I dug up can be found here: https://forums.developer.apple.com/thread/38561#117143
The snippet of importance from the answer by the apple staff member is
With regards to Ask-To-Buy support, there is no support for this function in the Sandbox. “Ask to Buy” is not an API implementation, but a support process implemented by iTunesConnect which requires StoreKit interaction with a specific iTunes account. This support only exists in the production environment. For this process to work in the sandbox environement, ITC would need to implement for test accounts to refer to other accounts to grant approval for purchases.
The rest of the article highlights the guidelines and flows for Ask to Buy support but testing must be done in the production environment where the child/parent account relationship is active.
- Login flow failing after upgrading to iOS9
- AVcapture session slow launch after session restart
- xcode iOS getting a list of all localizations
- iOS Screenshot part of the screen
- Number of threads created by GCD?
- How to add a CocoaPod framework to Xcode 8 Playground
- iOS – How can I schedule something once a day?
- How to swizzle a method of a private class
- Objective-C ARC and passing C arrays of objects
- How to use dispatch_async_f?
- Animate MapKit annotation coordinate change in Swift?
- Cannot call value of non-function type '((success: Bool, error: NSError?) throws -> Void)?)
- UIAlertView Buttons(subviews) is not Showing in iOS 7
- iPhone apps: Webapps or native?
- iOS Universal storyboard on iPhone 5 & 5s issue