Subscriptions

RSS for tag

Give users access to content, services, or premium features in your app on an ongoing basis with subscriptions, a type of in-app purchase.

Subscriptions Documentation

Posts under Subscriptions tag

355 Posts
Sort by:
Post not yet marked as solved
6 Replies
1.5k Views
We have an App Store Server Notification endpoint. Our app offers an in app subscription. Most notifications have all of the expected fields, but in a small number of cases the decoded signedTransactionInfo and signedRenewalInfo fields are empty. I can't see anything about these fields being optional in the documentation, and without the transaction information I can't get the transaction id of the user, so I can't tell how this notification relates to others for the same original transaction id. Are these notifications expected? Should I be handling them in a special way? Or should I just ignore them? For example, a normal transaction will have the following fields: responseBodyV2DecodedPayload (     [notificationType] => DID_RENEW     [notificationUUID] => …     [version] => 2.0     [signedDate] => 1660947328849     [data] => (             [bundleId] => com.playpokpok.playroom             [bundleVersion] => 9             [environment] => Sandbox             [signedTransactionInfo] => JWSTransactionInfo             [signedRenewalInfo] => JWSRenewalInfo         ) ) But one of these unexpected requests will have the following form: responseBodyV2DecodedPayload (     [notificationType] => EXPIRED     [subtype] => VOLUNTARY     [notificationUUID] => …     [version] => 2.0     [signedDate] => 1662661854606     [data] => (             [appAppleId] => 1550204730             [bundleId] => com.playpokpok.playroom             [bundleVersion] => 6             [environment] => Production         ) )
Posted
by
Post not yet marked as solved
2 Replies
672 Views
Hello, In our B2C app our business customers need to offer one or more premium content channels customers can subscribe to. Each with a monthly and a yearly payment option. Having to create a unique subscription group specific to every possible premium content channel is simply not feasible and unmaintainable. I recognize we can't programmatically add subscription groups/subscriptions, so I am trying to instead use generic subscription groups/subscriptions to represent the possible price points and then mapping transactions to the relevant content channel(s) on the backend. We presently have 7 levels of premium content pricing options available for businesses to offer, each with a monthly and a yearly pricing option. I was encouraged to see a response from an App Store Commerce Engineer to a very similar question where it was suggested that we can use generic subscription groups and subscriptions as a generic price point mechanism and not have to have a subscription group for each individual channel for each individual business (https://developer.apple.com/forums/thread/698168). As such, creating 7 subscription groups, each with a monthly and a yearly subscription option is an acceptable solution and tests fine in the sandbox but I am concerned that once we roll to production it will not work because of not allowing a user to subscribe to multiple subscriptions in the same group, perhaps even at the same monthly option or whatever and will say 'You are already subscribed' or similar. So for example, let's say business A wants to offer two separate premium content channels, each at the L1 subscription level. Even if we are mapping it on the backend on our own, I suspect that the app store will reject the 2nd subscription request by the customer as they have already subscribed to a subscription in that group. Same if business A offers one L2 subscription channel of premium content and then business B also wants to offer subscriptions to their different premium channel content as an L2 subscription, the user could only sub to one or the other, not both because technically in the same sub-group and same subscription IAP. So where the App Store Commerce Engineer in the other post said, "Or you can create generic groups that dynamically represent the business a customer subscribes to. So this requires mapping the purchase Original_transaction_ID to your business identifier - and our product_ID is effectively a generic price point to represent pricing offerings your businesses choose from." as much as I want this to work, I'm not confident at all that it will given what I am reading on subscription group restrictions. Looking for confirmation advice here. Thanks so much for any help. BTW I did try to respond to the original question at the link above but appears to be locked. Thank you again for your time and consideration.
Posted
by
Post not yet marked as solved
1 Replies
1.9k Views
Hi Everyone, When you create Auto Renewable subscription price through App Store Connect site - you are able to set only 1 price (say for USA in USD) - and all the rest prices for 175 countries will set automatically. How to set same logic through using request with App Store Connect API? My current logic is: I'm using List All Price Points for a Subscription GET request to get all price points for specific subscriptionID (Docs: https://developer.apple.com/documentation/appstoreconnectapi/list_all_price_points_for_a_subscription) In the response I'm searching for specific price for USA (say $0.99) and getting it's price point ID Then using POST request to Create a Subscription Price Change (Docs: https://developer.apple.com/documentation/appstoreconnectapi/create_a_subscription_price_change) with pricePointID from the previous step. And it's setting the price indeed, BUT for USA only, so I'm not getting this automatically applied 175 countries list for free. Please let me know if there a way to set it automatically somehow, or should I manually calculate all 175 countries for myself somehow and to use 175 requests for each plan (I doubt it)
Posted
by
Post not yet marked as solved
11 Replies
2.2k Views
Hi community: When I try to access subscription settings, after filling in my sandbox user's password, a message "cannot connect" appears, just like below. Does someone know about a workaround to cancel or reset the subscription from the iPhone? Thanks in advance
Posted
by
Post marked as solved
5 Replies
3.6k Views
Dear all, This is my first post in this forum - and, in fact, my first app, too! I'm glad to be here, and thanks in advance for your help. I'm looking to offer an app for a one-time payment. I'd also like people to be able to try the app for a week. It seems that the "Pricing and Availability" section in App Store Connect is not the right place to configure this kind of offer. It does allow me to set a one-time price, but I cannot find a trial-period there (or am I missing something?) Two different strategies seem possible here: Using in-app-purchases: make the actual app free, but ask users after a week to buy a non-consumable IAP. The problem with that: I need to verify that the app has been installed for seven days ... even if it has been uninstalled at some point. Using subscriptions: There is a "free trial" option for subscriptions. But after that free trial, subscriptions are being payed periodically. I'd rather have the user only pay once for lifetime-access. Some apps seem to use strategy 1 - I believe the "Lap swim" app does. But still it seems like a bit of a hack - is there a more elegant way to achieve this?
Posted
by
Post not yet marked as solved
2 Replies
782 Views
Hi all, This is my first app. Its status is "Pending Developer's Release", so I assume that means it's ready. But my subscriptions have red exclamation marks and say "A subscription has been returned and is highlighted in the table below." I messaged Apple and was told - "I have escalated this information to the appropriate internal team. They'll follow up with you directly if they need anything." So...I'm not sure what to do. Do I just wait? Should I release it? It was approved a few days ago, so I assumed they had checked everything, but now I'm not sure. Any ideas or experience with this? Thanks!
Posted
by
Post not yet marked as solved
1 Replies
895 Views
As per the display in "App Store Connect > Sales and Trends > Subscriptions > Summary", I'm wanting to understand how to calculate the 'Active paid subscriptions' figure for a particular period using only the subscription event data. This is for further analysis and calculation outside of App Store Connect. For example, if at the start of April I have 500 active paid subscriptions, then at the end of April I have 550 active paid subscriptions, what are the calculation of Subscription events that would make up this figure? I'd presume the formula would be: End of period subscriptions = start of period subscriptions + activations (includes trials) + conversions to standard price + reactivations - refunds - trial only activations - cancellations However when I compare the above calculation against what is reported by 'Active paid subscriptions' at the start and end of a period in App Store Connect it is not the same. What is the calculation of events across a period that determines the current 'Active paid subscriptions' figure?
Posted
by
Post not yet marked as solved
11 Replies
5.9k Views
Hi, thanks for reading my question. I need help with some odd behaviour with product.purchase() not triggering a confirmation dialog after a subscription has expired and trying to purchase it again. Seeing this in iOS 16.2 and 15.7.2 (haven't tried any other versions) on actual devices, not in simulator. I'm using a sandbox user on the sandbox environment (not using the local store kit config file testing option). Using a newly created sandbox user, first subscription purchase goes through just fine, dialog box pops up, login with sandbox user, get confirmation of purchase and then Transaction.currentEntitlements has one item as expected. It auto renews for 12 times (each time Transaction.currentEntitlements contains the correct results) and then expires, as expected for sandbox. Transaction.currentEntitlements is then also empty, as expected. All good so far. Now I want to test purchasing it again...Call product.purchase() again to renew/start a new subscription and nothing happens, no confirm purchase dialog box pops up at all. The purchase function simply exits BUT returns success (as in the following gets called) but in self.updatePurchasedProducts(), Transaction.currentEntitlements is empty. case let .success(.verified(transaction)):      // Successful purchase       await transaction.finish()      await self.updatePurchasedProducts() if I instead go to Settings->App Store->Sandbox User-> Manage Subscriptions and renew the subscription there, instead of in my app, then Transaction.currentEntitlements has a new entry and all is good again. Alternatively, if I create yet another new sandbox user and logout of the old one I was using, I am once again able to purchase from within the app, so .purchase() once again works as normal. Is there something I am missing about expired subscriptions and trying to purchase them again in the app? Is this a sandbox issue and in production I'll have no problem? The sandbox user has purchasing enabled in Settings->App Store. I've also tried calling AppStore.sync() (which is in my "Restore Purchase" button) before calling product.purchase() after the subscription stops renewing, expires and this issue comes up, doesn't resolve it. Also have a less important question, the initial call to product.purchase(), the one that works as expected, has a bit of a delay before the confirmation dialog pops up, a few seconds, which will probably result in the user clicking the buy button again thinking it didn't work. Is a bit of a delay normal for sandbox? Will it be ok in production? When it fails, and I have to renew in Settings->AppStore->Sandbox user, there's also a bit of a delay after I return to my app, 5-15 or so seconds, before the transaction observer fires and currentEntitlements is checked again, is there a way to reduce this delay? Thank you! Colin @MainActor class IAPManager: NSObject, ObservableObject {  // removed other functions.....   func purchase(_ product: Product) async throws {    let result = try await product.purchase()     switch result {    case let .success(.verified(transaction)):      // Successful purchase       await transaction.finish()      await self.updatePurchasedProducts()    case let .success(.unverified(_, error)):       break     case .pending:       break     case .userCancelled:       break     @unknown default:       break   } }  func updatePurchasedProducts() async {     for await result in Transaction.currentEntitlements {       guard case .verified(let transaction) = result else {         continue       }       if transaction.revocationDate == nil {         self.purchasedProductIDs.insert(transaction.productID)       } else {         self.purchasedProductIDs.remove(transaction.productID)       }     }   } }
Posted
by
Post not yet marked as solved
4 Replies
1.4k Views
Hey, in our app we show post-purchase flow when a user purchases a subscription and its appearance should depend on the type of purchase: upgrade, downgrade or crossgrade. I found a way how to get this type on the backend side but can not figure out how to get this within the app. I see that Transaction has isUpgraded property but it is always false even if I move from a lower service plan to a higher one. So, I have two questions: Is this actually possible to know on the client when the user upgrades, downgrades or crossgrades? If yes, then how? Thanks
Posted
by
Post not yet marked as solved
2 Replies
787 Views
When performing StoreKit 2 operations in my Mac app, even very simple ones like AppStore.sync() a small but steady percentage of users experiences the following error: systemError(Error Domain=NSCocoaErrorDomain Code=4097 \"connection to service named com.apple.storekitagent\" UserInfo={NSDebugDescription=connection to service named com.apple.storekitagent}) Rebooting or re-downloading the App from the Mac App Store, as well as signing out and in again on the Mac App Store does not solve the issue. Strangely enough all of the affected users I'm aware of were initially able to perform In-App purchases via the said app. Without any updates or anything else however suddenly after a restart of the app the above error gets thrown by the system. As I have not found any way to solve this issue yet and the said customers are consequently left without service even though they are paying customers, I am desperate to find help with this issue. Given the simplicity of the AppStore.sync() method for example I can't imagine the solution to lie in code, but I might of course be wrong. Thank you, Bastian
Posted
by
Post marked as solved
7 Replies
1.5k Views
Hi I'm using presentCodeRedemptionSheet() method to display a sheet that enables users to redeem subscription offer codes. When calling the SKPaymentQueue.default().presentCodeRedemptionSheet() method on real app store app it will present redemption sheet and after entering the offer code in it is displaying screen where Cancel and Redeem buttons do not work. As seen in the attached picture. What could be the reason for this and what solutions can be found to solve the problem? Please someone help it is really frustrating. Environment: iOS 16.3
Posted
by
Post not yet marked as solved
2 Replies
1.3k Views
The sample code provided in https://developer.apple.com/wwdc21/10114 doesn't appear to call finish() on unverified transactions, and I haven't been able to find any documentation regarding what to do with unfinished transactions. However, Apple has always emphasized the importance of finishing transactions, and since a transaction object is provided even with the unverified state, I'd love some guidance!
Posted
by
Post not yet marked as solved
1 Replies
587 Views
Hi everyone! I recently launched a hard paywall in my app and have had a fair few people each day sign up to the 3 day free trial. Around 55% of users remain after the 3 day trial but I am finding that when it ends around 20-25% of the users are running into 'billing errors' meaning they end up not paying at the end of the trial despite never cancelling. The information coming through from Apple ranges from 'insufficient credit', 'incorrect details' and 'unknown' - but the % is way higher than Has anyone come across this issue before at such a high % and if so, is there anything we can do to try and improve this number? Thank you!
Post marked as solved
7 Replies
2.0k Views
We have implemented an auto-renewing subscription as an in-app-purchase for our iOS application. We are consuming the App Store Server Notifications for subscription transactions in order to update the user's account (and thereby maintain their 'Pro' access to our application). Sometimes those notifications never come to our server, and there is no evidence that they were even attempted to be sent to us. We have had some users report to our Customer Support team that they have successfully made a purchase of the subscription, but that they were not granted 'Pro' access. For the large majority of users this is not happening and all is well, but for some users the notifications just never come from the App Store Server API. We keep a record of all notifications that we receive from the App Store, and for these users we never received the "SUBSCRIBED" event. We have checked the Notification History API and there are no reports of any failure to send notifications to our server. We have checked our server logs for any sign of failure to receive incoming web requests, and there is no sign of these missing notifications. We have verified that our server supports ATS. We are keeping the transaction.originalID for all our users who are subscribed to the auto-renewing subscription. We have used this value to do some lookups into the transaction history and subscription status of the users who are being affected. Here is an example of our findings from those lookups: From the transaction history endpoint, we received an error: “Invalid transaction identifier”. From the subscription status endpoint, we received a response with the information for that user's active, valid subscription. We never received any App Store Server Notifications about this user’s subscription, and the transaction history API tells us it is an invalid transaction ID. We believe that the fact that the subscription status API returned the information showing that this user’s subscription is active and valid, and that the notification history API shows no sign of a failure to send us notifications about that subscription, shows that the App Store Server API never attempted to send us any notification for this user’s subscription. The same is true for a significant number of other users of our service. Can anyone help us determine what is going on, and how to best support these customers? It seems as though there was never an attempt to send these notifications to our server, but our users provide proof that they do in fact have an active subscription, for which they have paid (receipt email from Apple with a valid order ID).
Posted
by
Post not yet marked as solved
0 Replies
239 Views
Hello, I have developed an app that I would like to share via TestFlight. I would like to let my users beta test the app before adding credential and billing processes. When completed, the app will be a subscription based app, but I do not want to incorporate billing into the TestFlight version. Can I submit an app to TestFlight and, when rolling into production, change it to a subscription based app?
Posted
by
Post not yet marked as solved
4 Replies
679 Views
Hello, I require assistance urgently. My Apple Developer membership has expired and I am unable to renew it. Upon logging in to the Developer website, I was directed to use the Developer app to renew the membership. However, I cannot locate the renew button on the app. I have attempted to log in and out multiple times, as well as signing in from other devices, but to no avail. This situation is highly frustrating, and I feel let down by Apple's poor service.
Posted
by
Post not yet marked as solved
1 Replies
259 Views
Hi, I am building an app for my client which will be listed on my app store. The app has IAP built in. I know that the monies will be transferred to my bank account (the one associated with my Apple Account). However, this money belongs to my client and I don't want to have to transfer to them each month. How can I set up my app, so that the monies is deposited into client Bank Account (not my App Account bank account)?
Posted
by
Post not yet marked as solved
2 Replies
829 Views
Hello there, we have added url in App Store account in app information tan it is used for renewing user subscription after it is over. but at that time when user subscription is over, this url needs to be called to auto renew the user subscription but currently this url is not called by app store. can anyone have faced this issue before or any suggestion for this issue ?
Posted
by
Post not yet marked as solved
0 Replies
430 Views
Able to show the promotional offer, but after going through the payment process, inputting my password, and confirming the purchase, I get an error popup that says "Unable to Purchase. Contact the developer for more information." In the logs, I get the following errors: SKErrorDomain Code=12 "(null)" ASDServerErrorDomain Code=3903 "Unable to Purchase" Here are the example parameter values I am passing to the combined string appBundleId + '\u2063' + keyIdentifier + '\u2063' + productIdentifier + '\u2063' + offerIdentifier + '\u2063' + appAccountToken + '\u2063' + nonce + '\u2063' + timestamp appBundleId: com.app.myapp keyIdentifier: copied the key ID from the App Store Connect productIdentifier: product_identifier offerIdentifier: offer_identifier appAccountToken: tried both a UUID and an empty string nonce: a UUID to lowercase timestamp: UNIX timestamp How I'm generating the signature (Java) /* promotionalOfferKey = value between "-----BEGIN PRIVATE KEY-----" and "-----END PRIVATE KEY-----" from the downloaded p8 file from App Store Connect associated with the keyIdentifier parameter above */ // stringToSign = the combined string above byte[] encoded = Base64.getDecoder().decode(promotionalOfferKey); KeyFactory keyFactory = KeyFactory.getInstance("EC"); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded); Signature ecdsaSign = Signature.getInstance("SHA256withECDSA"); ecdsaSign.initSign(keyFactory.generatePrivate(keySpec)); ecdsaSign.update(stringToSign.getBytes(StandardCharsets.UTF_8)); byte[] signature = ecdsaSign.sign(); signatureToReturn = Base64.getEncoder().encodeToString(signature); What am I doing wrong? Thank you in advance.
Posted
by