1. BackgroundAt WWDC 2021, a new StoreKit 2 library was launched on the iOS 15 system, which uses a completely new API to solve in-app purchase issues.
2. Materials3. Problems with StoreKit 11. Can I view the refunded order details in Apple backend? No. Apple can only send a notification to our server after processing the refund, informing us that a refund has occurred. 2. Can refunds for consumable, non-consumable, non-renewable subscriptions, and auto-renewal be tested in the sandbox environment? No. The system does not provide this kind of testing method. 3. Can the orderID in the Apple receipt provided by the user be associated with the specific transaction? cannot.
4. During the development process, it is impossible to directly associate the transaction with the orderID, although there is an applicationUserName field that can store information. However, this field is not 100% reliable and may lose stored data in some cases. 5. We cannot proactively go to Apple servers to obtain transaction history and refund information. We cannot proactively associate the order ID in the Apple receipt provided by the user with the orders we currently know. 6. Currently, sk1's skproduct cannot distinguish between consumables, non-consumables, subscription products, and non-continuous subscription products. 7. sk1 has queue monitoring. Each purchase needs to monitor the corresponding purchase status changes through the queue. All transaction callbacks are being monitored, and it is difficult to distinguish which are transactions for replenishing orders and normal purchases. IV. New features of StoreKit v2The new features of StoreKit 2 mainly include three parts:
StoreKit 2 APIThe main updates of StoreKit 2 are as follows:
5.1 Only supports Swift developmentStoreKit 2 was developed using the new features of Swift 5.5, which completely changed the implementation of APIs for obtaining products, initiating transactions, and managing transaction information. https://swift.org/blog/ For example, the syntax for obtaining products is different: Original way to obtain goods // 1. Request product New way to get products // Get the product 5.2 New API
5.2.1 ProductSome new product types and subscription information have been added. These fields are not available in StoreKit 1. Fields that are convenient for us to use:
For example: Some apps have membership subscription services, and those services will have automatic renewals for 1 month, 3 months, 12 months, etc. There will also be some first-time purchase discounts, and this first-time purchase discount is linked to the Apple ID and has nothing to do with the app's own account system. For example, Pony.com's products have their own account system of QQ number + WeChat number. So we couldn't simply judge whether your Apple ID had enjoyed the first-time purchase discount before. After all, users can have multiple QQ numbers or multiple WeChat numbers. Before Apple's purchase page pops up, we didn't know whether this Apple ID had enjoyed the first-time purchase discount, which would cause misunderstandings to users. On the previous page, I was told that the first month was only 18 yuan, but why did it cost 25 yuan when I actually paid? This has visibly reduced users' willingness to buy. Now we can use the isEligibleForIntroOffer property to easily and conveniently obtain this information in advance, and not display this offer to Apple ID accounts that have already enjoyed it. Provides a new interface for obtaining products public static func products ( for identifiers : Identifiers ) async throws - > A new purchase interface is provided. Some optional parameters PurchaseOption structure are added when purchasing goods. The structure contains a new and particularly important field appAccountToken, which is similar to the SKPayment.applicationUsername field, but the appAccountToken information will be permanently saved in the Transaction information. The appAccountToken field is created by the developer; it is associated with the user account in the App; it uses the UUID format; and it is permanently stored in the Transaction information. PS: Apple means that the appAccountToken field here is used to store user account information, but it can also be used to store orderID-related information. The orderID needs to be converted into UUID format and inserted into the Transaction information to facilitate operations such as order replenishment and refund. public func purchase ( options : Set < Product . PurchaseOption > = []) async throws - > Product . PurchaseResult Processing and verifying transactions. The system will verify whether it is a legitimate transaction. At this time, the system no longer provides base64 receipt string information. You only need to upload transaction.id and transaction.originalID. The server side selects the appropriate ID for verification as needed. func checkVerified < T > ( _ result : VerificationResult < T > ) throws - > T { Listening for Transaction Updates func listenForTransactions () - > Task < Void , Error > { For transaction updates, this listener allows us to listen:
5.2.2 Transaction HistoryProvides three new transaction-related APIs:
You can filter out purchased items based on available subscription items and non-consumable items. extension Transaction { Synchronize purchase records of different devices. This API can replace the restore purchase API in StoreKit 1. After calling this method, the system will pop up a prompt box to ask you to enter your AppleID account and password information. extension AppStore { 5.2.3 Subscription statusThe status of subscription-type items, such as actively obtaining the latest transaction, obtaining the status of updated subscriptions, obtaining the information of updated subscriptions, etc. Among them, obtaining the information of updated subscriptions can obtain the updated status, item ID, and if expired, the reason for expiration can be known. (For example, user cancellation, deduction failure, normal subscription expiration, etc.) All the data obtained is JWS format verification. 5.2.4 show manager subscriptionsYou can directly call up the Manage Subscriptions page in the App Store. extension AppStore { 5.2.5 Request refund APIA new refund API is provided, allowing users to apply for a refund directly in the developer's app. After the user applies for a refund, the app will receive a notification, and the Apple server will also notify the developer's server. (Refund testing can also be performed in the sandbox environment, but this feature has not yet been enabled in the App Store.) extension Transaction { 5.2.6 Summary:
6. Server to ServerBuilding a developer server can achieve the following functions:
6.1 Validate status with receiptsWhen the server verifies the receipt through the /verifyReceipt interface, the data structure of the new API has also changed. For example, the purchase time, expiration time, and original purchase time formats have been unified, and the appAcountToken field, in-app purchase type field, refund time, refund reason, promotional offer type, etc. have been added. For details, please refer to Manage in-app purchases on your server - WWDC21 - Videos - Apple Developer video, or Validating Receipts with the App Store | Apple Developer Documentation 6.2 Check status with APIsSome new APIs have been added to actively obtain subscription status, transaction history, etc. For details, please refer to this document: App Store Server API | Apple Developer Documentation
6.3 Track status with notificationsWhen the subscription status changes, Apple server will proactively notify our server of the changes. The functionality is the same as the previous version, but some statuses have been removed and some have been added. To facilitate testing refund notifications in the sandbox environment, the App Store can set up a separate server URL configuration for the sandbox environment. 6.4 Changes in purchasing processFor example, when you purchase a subscription product for the first time, after the purchase is successful, the Apple server will proactively notify our server of the status. At this point, our server does not need to verify with the Apple server again. Even if you want to verify later, you can also verify at any time through the /inApps/v1/subscriptions interface. In addition to accepting Apple's notifications for renewal, billing grace period, user refunds, etc., you can also actively request Apple's server to obtain the latest status. For example, when your own server is down or you do not receive Apple's notification for some reason, actively requesting Apple's server to obtain transaction history and transaction status information will play a huge role. 6.5 Server Migration and Upgrade to JWS FormatFor StoreKit 2, Apple has abandoned the receipt verification logic, and only needs to provide the originalTransactionId of the transaction to obtain complete transaction information. So how to upgrade from StoreKit 1 to StoreKit 2?
6.6 Manager family sharingManage family sharing. Currently, Apple supports family sharing for non-consumable and automatic subscription items. In addition, Apple will return a field inAppOwnershipType to indicate whether the current user is the primary user of the purchased item. It is more convenient to track the user's status 6.7 Sandbox test
6.8 Summary
7. Customer Support and Handle refundsSupport customers and handle refunds - WWDC21 - Videos - Apple Developer 7.1 How do I identify the in-app purchase made by this customer?How to identify the user's purchase items. When the user is charged but does not receive the product, the user will return the question and provide a screenshot of the charge information in the Apple mailbox. Then our server can use the invoice order ID in the screenshot to request the /inApps/v1/lookup/{customer_order_id} interface to find the corresponding transaction information. Then we can verify whether the purchase is successful, whether a refund has been applied, whether the goods need to be reissued, etc. https://developer.apple.com/documentation/appstoreserverapi/look_up_order_id/inApps/v1/lookup/{customer_order_id} 7.2 How do I lookup this customer's past refunds?How to check the user's past refund information? The current situation is that if our server is down or we don’t receive a refund notification, we don’t know whether the user has made a refund. Although StoreKit 2 provides an API for obtaining transaction records, it is not the best way to filter refund transactions through this API. Therefore, Apple has provided a new API to query all refund records of this user, and only needs any original_transaction_id. https://developer.apple.com/documentation/appstoreserverapi/get_refund_history/inApps/v1/refund/lookup/{original_transaction_id} 7.3 How do I compensate subscribers for a service issue?How are subscribers compensated for service issues? For example, when a server problem occurs, in order to retain users/attract more users, how to plan to compensate users. Developers can provide an in-app purchase redemption code (all types of in-app purchases are acceptable) and generate it in the Apple backend. Then let users redeem it in the App Store, or call the presentCodeRedemptionSheet() interface in the App to pop up the system redemption interface: 7.4 How do I appease customers for outages or canceled events?How to appease customers about interrupted or cancelled events? The main purpose is to give users some benefits and appease them. Similar to other apps where users can get a one-month membership for free after signing in for a month. However, the expiration time of this method is determined by the backend of the server. Apple also provides an interface that allows developers to give 90 days of free compensation to users who subscribe to in-app purchases twice a year. That is, for apps with automatic subscriptions, developers can proactively compensate users on the server (extend the order time for free), up to 90 days each time. ttps : //developer.apple.com/documentation/appstoreserverapi/extend_a_subscription_renewal_date/inApps/v1/subscription/extend/{original_transaction_id 7.5 How to manage subscriptions in the AppAs in 5.2.4 above, a showManageSubscriptions interface is provided to directly call up the subscription management page. extension AppStore { 7.6 How to apply for a refund in the APPSame as 5.2.5 request refund API above 8. New API Purchase ProcessOriginal API Purchase Process
New API Purchase ProcessThe entire payment purchase process is the same as the original API purchase process, except that when uploading transaction information in step 3.1, you no longer need to upload receipt/token information, but only upload transaction_id. The server can use transaction_id to get the transaction result from Apple server, and no longer need to use receipt/token to verify the ticket. IX. QA9.1 How to choose between the new API (StoreKit 2) and the original API (StoreKit 1)
If your app relies on any of the following features, you may want to use the original In-App Purchasing API:
Use the original API for existing and legacy applications.
Old App:
9.2 The client uses StoreKit 1, and the server upgrades to the StoreKit 2 API. Can it be used like this? Can. For the backend, both Apple Server API V1 and Apple Server API V2 can be used, regardless of whether the client is upgraded to StoreKit 2. 9.3 Will the interaction process change after Native SDK uses StoreKit 2? And will the communication process with the server change? You can refer to the new API purchase flow chart above. 9.4 Will there be order loss in StoreKit 2? How to solve the problem? It is still possible that an order may be lost, for example, the purchase is successful, but Apple fails to return the result due to network problems, but this will be easier to resolve. Solution:
9.5 If the purchase is successful but the transaction is not finished, will the transaction be reissued after the next cold start? Yes, it has the same functionality as StoreKit 1, but the APIs are different. 9.6 After upgrading from StoreKit 1 to StoreKit 2, can I see the items I purchased using StoreKit 1? As you can see, they are compatible with each other. 9.7 For apps using StoreKit1, can we give up reading the local receipt and pass it to the server for verification, and directly use the transaction_id of StoreKit2 to pass it to the Apple server for ticket verification? Can. 9.8 Regarding the transaction information returned by Apple, can we determine what type of product the transaction status information corresponds to? Yes, storekit2 will clearly tell us the current product type in the transaction return information. As the server has two different logics for consumables and subscription products, we can easily distinguish whether it is a subscription product and then request the corresponding interface through this field. |
<<: 9 decentralized, end-to-end, open-source alternatives to major social media platforms
>>: Android 13 introduces new restrictions, malware will not be able to use accessibility APIs
[[396442]] April 28 news With the release of iOS ...
Xiaomi and Midea got married without dating each ...
It is the 60th anniversary of Panzhihua's dev...
In order to ensure the country's food securit...
Sometimes in the workplace, we encounter products...
Yesterday was a very special day for people like ...
Meizu has been waiting for a long time for the op...
Recently, the "2020 World Intelligent Connec...
I once had the following conversation with a read...
The China Earthquake Networks Center officially d...
This month we planned a WeChat fan-raising activi...
The clothing category has always been a product w...
In the past year, To B has been very popular, and...
Recently, Foxconn Technology Group executives rev...
[[134520]] When Google Glass was first launched, ...