8 Replies
      Latest reply on Jan 15, 2020 4:24 PM by rich
      asedfasfydsfaq Level 1 Level 1 (0 points)

        Hello Devs,


        our app uses auto-renewable subscription. Under "Features" App-Store-Connect allows to create a "Promotional Offer". At creating you are asked to type-in a "Product Code". "The code that customers will enter to redeem this promotional offer. This code is case sensitive."


        So I am asking you where users should type this code in? As these codes are not unique (you can freely create them) they do not work in the App-Store- App.


        We implemented the offer as documented: https://developer.apple.com/documentation/storekit/in-app_purchase/implementing_subscription_offers_in_your_app

        This documentation does not say anything about the product code at all. So we created a textfield where users can type-in the code and then we pass this right to the request for possible and eligible offers. Although it was really difficult to deal with the gaps of information, we finally got it working.

         

        The App- Store- Review- Team rejected our app by telling us, we would use different mechanisms as StoreKit API, which is not the case. We are only trying to implement the feature that is offered.

         

        Also they are referring to App-Store-Guidelines 3.1.1: "Apps may not use their own mechanisms to unlock content or functionality, such as license keys, augmented reality markers, ..." After multiple attempts to ask, they first ignored to enter on the product code and suggested to use other features instead. Finally they adviced us to ask here in the forum to get any clarification or experience. The App-Store-Review- Team did not know this feature.


        So does anybody ever tried to use that Product Codes? is this feature not usable at all or at this time? Or is the App-Store-Review-Team not up-to-date?

         

        I would be interested in any experience or observations you made on this topic.

         

        Thanks in advance!

        • Re: Rejection: Promotional Offer Product Code
          KMT Level 9 Level 9 (15,405 points)

               > rejected our app by telling us,

           

          Rather than simply paraphrase that rejection, it can help to quote it directly, thanks. Quote them all, so we can see the exhange, pls.

           

          I can't explain why app review doesn't know what's going on, but it sounds like you and they are talking past each other since IAP promo codes aren't new...if that means review has their head up, err, in the sand on this one, it's a sad day when we have to do their job yet again.

           

          In the mean time - this SO thread talks about both dev and user side IAP promo code use:

          • Dev side: https://stackoverflow.com/questions/50732606/ios-how-can-we-offer-discount-through-promo-code-for-in-app-purchase

           

          This thread illustrates user side:

          • User side: h ttps://support.crookneckapps.com/hc/en-us/articles/115000054666-Redeeming-in-app-purchase-promo-codes

            • Re: Rejection: Promotional Offer Product Code
              asedfasfydsfaq Level 1 Level 1 (0 points)

              Thanks for the quick answer. Here are a few quotes of the rejections (tried several times):

              - "We found that your app enables users to enter a promotional code to receive a free trial by means other than the StoreKit API. To resolve this issue please revise your app to remove this feature of your app, and make a free trail of your app's premium services available via the StoreKit API only."

               

              - "Your app unlocks or enables additional functionality with mechanisms such as promo codes, data transfer codes, license keys, augmented reality markers, or QR codes, which is not appropriate for the App Store."

               

              Also thanks for the links, but in these threads they are talking about auto-generated codes, which should work in the App Store, as they are all unique.

               

              So we try to use these "product codes" that you can customly create in App-Store-Connect, but cannot be redeemed in the App Store (not unique). App Store Connect asks to type-in a "product code, customers can enter to redeem the offer. This code is case sensitive." We want to use that one.

               

              Thanks you!

                • Re: Rejection: Promotional Offer Product Code
                  KMT Level 9 Level 9 (15,405 points)

                       >We want to use that one.

                   

                  Got it now, thanks.

                   

                  Suggest you confirm your process by, and point App Review to, ASC Help...

                   

                   

                  Promotional Offers:

                  A discounted price you can set for your auto-renewable subscriptions for a specific duration and type (pay as you go, pay up front, free) for existing and previously subscribed customers. Offers can be used to help win back subscribers who have canceled their subscriptions or promote an upgrade to a higher-ranked subscription at a special price. Keep in mind that:

                  • You determine when to present the offers through StoreKit APIs
                  • Customers that have completed an introductory offer are still eligible to get a promotional offer
                  • You must generate a subscription key in Users and Access to validate your offers
                  • You can have up to 10 active offers per subscription
                  • Offers don't display on your App Store product page
                  • Customers running iOS 12.2, macOS 10.14.4, and tvOS 12.2 can accept these offers.

                  Promotional Offer Reference Name:

                  An internal name for a promotional offer that you can reference.

                  Promotional Offer Product Code:

                  A code that you create. This code is case sensitive and must be unique for each offer you create. You won't be able to re-use an offer code, even if it's been deleted.

                    • Re: Rejection: Promotional Offer Product Code
                      asedfasfydsfaq Level 1 Level 1 (0 points)

                      Okay, so we are going to submit the app again. We will provide more information like links to documentation and ASC Help from the beginning.

                      You posted these definitions about Promotional Offers. Do you have a link to the source? I can't find it in the documentations nor ASC Help anymore. That would be really helpful!

                       

                      Thanks again!

                        • Re: Rejection: Promotional Offer Product Code
                          KMT Level 9 Level 9 (15,405 points)

                               > Do you have a link to the source?

                           

                          Yes - I effort to always supply links (we're discouraged from paraphasing, etc). Use the link in my reply above....those items are on that ASC Help page.

                          • Re: Rejection: Promotional Offer Product Code
                            jdawg69 Level 1 Level 1 (0 points)

                            What happened when you submitted the app again? We would like to add promotional offers to our app but can't find any information on how the user activates the promotion.

                             

                            Thanks

                            J

                              • Re: Rejection: Promotional Offer Product Code
                                asedfasfydsfaq Level 1 Level 1 (0 points)

                                Hi J,

                                I attached an explaining text with the links posted here and the link the this thread. After then the app had been approved for a few months! But a few weeks ago an update has been rejected for the same old reason. After a lot of discussions and phone-calls with the App-Store-Review-Team we finally gave up. They referred to the guidelines, but they could not quote the reason. They said we created our "own mechanisms" to unlock paid features. There is a gap of information how to use Apples own feature and the review-team do not really know how things have to be implemented, they just judge on what they see.

                                My guess is that they are afraid of being deceived so they reject the app. So this is still unsolved and not impossible, but it will cost you a lot of time arguing with the review, designing, coding and (re-)creating marketing-plans for nothing.

                                  • Re: Rejection: Promotional Offer Product Code
                                    rich Apple Staff Apple Staff (265 points)

                                    If I understand your promo code mechanism, you want to make it possible for the user to go to some View Controller and enter some code in a text field - which the app can then validate and results in access to content that can also be accessed via In-App Purchase. Such a mechanism is outside of the control of the App Store as a means for providing content and is considered a different mechanism to StoreKit.

                                     

                                    If you want to implement promo codes, then what KMT described is correct. However, the supported promo code support is not redeemed in the app, but in the App Store app. One copies the promo code, opens the App Store app, presses the Redeem button and pastes in the promo code. The App Store will now create a transaction item for the app's transaction queue. When the app's transactionObserver is next activated, it will detect the new transaction and process in a manner similar to the user having just purchased the item and been charged for the In-App Purchase transaction.  In this way, the App Store is involved with the In-App Purchase promo code process. Promo codes are available from AppStoreConnect.

                                     

                                    Here's a more complete description of the promo code process.

                                     

                                    BEGIN

                                    The promo code process functions as follows.

                                     

                                    First, the promo code redemption process, to date, only works in the production environment. After the promo code is redeemed, it is the responsibility of the app to detect that the promo code was redeemed.

                                     

                                    The process begins with the user entering the App Store application to redeem the promo code. After the promo code is redeemed,

                                    1. the App Store verifies the promo code,

                                    2. determines which application bundle ID it is for and what the associated In-App Purchase identifier the code is for,

                                    3. records a charge to the iTunes user account and sets up an incompleteTransaction record for the application / iTunes user account.

                                     

                                    Note, there is no push notification or auto-launch of the corresponding app after the App Store processes the promo code. It's the responsibility of the app, the next time it is launched to detect the incompleteTransaction.

                                     

                                    At some point after the promo code redemption, the user launches the application. Assuming that the application correctly installs the transactionObserver at application launch time, the transactionObserver queries the App Store for any incompleteTransaction using the current iTunes User account and the application bundle ID. In this case, the transactionObserver detects the matching incompleteTransaction. iOS presents the user with an authentication dialog, which the user uses to validate themselves, then the App Store issues a successful SKPaymentTransactionStatePurchased indication to the applications updatedTransactions delegate method. The behavior is similar to that where the user has just pressed the “Buy” button for the In-App Purchase item. The application processes the transaction and makes the associated content available to the user, then finishes the process by calling finishTransaction to acknowledge the App Store that the application received and processed the transaction.

                                     

                                    If you install the app via Xcode or TestFlight, the app always operates in the sandbox. This is also true for the App Review process. Until the sandbox supports promo code redemption, App Review will not review promo code redemption as it will not work in the sandbox.

                                     

                                    If the app is using In-App Purchase identifiers for the first time in a version of the app, promo codes will not work in the production version of the app until the app is officially released on the App Store. For example, if you define In-App Purchase identifier "my company.myapp.myinapp_purchase_item5" for the first time in app revision v2.0, and App Review approves the app, you must approve the app for App Store use to verify that a promo code for "my company.myapp.myinapp_purchase_item5" works. If the app is in the "pending developer release" state, the promo code for "my company.myapp.myinapp_purchase_item5" will not work. However, once the identifier is released in an app, then in v2.1 of the app, you can verify the promo code for "my company.myapp.myinapp_purchase_item5" while the app is in "pending developer release state".

                                     

                                    If you are looking for a means to test the promo code process in the sandbox environment, there is an alternative means to do so. Consider that a promo code results in an incompleteTransaction being registered for a user on the App Store Server. When you make a purchase using the addPayment method, this results in an incompleteTransaction being created. If the app never makes the finishTransaction call after being notified of the .purchased transaction, the next use of the transactionObserver should detect it. Try following these instructions.

                                     

                                    1. In the StoreKit implementation in your application, comment out the use of the finishTransaction call. Prevent the app from making this call - also add a log statement to indicate that the finishTransaction call would have been made, but wasn't.

                                    2. Install the app to your device (this won't work in the simulator) and make the test purchase with your test user account. Make sure that you see the log statement indicating that the finishTransaction call was not made. Since the finishTransaction call is not being made, the App Store Server will not clear the purchase from the test user record.

                                    3. Stop the app. If you are launching the app within Xcode, you might want to set a breakpoint on the entry to the updatedTransactions delegate method.

                                    4. Restart the app. After the call is made to addTransactionObserver, the incompleteTransaction should be detected and iOS should prompt you to authenticate the purchase. After authenticating your test user account, you should see the updatedTransactions delegate method entered with the .purchased indication. If your app can process this incompleteTransaction - it will handle a promo code in the production environment.

                                    5. One more thing to test - move the app to the background, then to the foreground, if the app never makes the call to finishTransaction, the transaction remains incomplete. You should again be presented with the Authentication dialog - note, the transactionObserver fires in the following three cases

                                    - when the addTransactionObserver is called

                                    - when the app calls addPayment AND

                                    - when the app with active transactionObserver transitions from the background to the foreground.

                                     

                                    Reminder - make sure to restore the call to finishTransaction, otherwise, the app will never complete the incompleteTransaction.

                                    END

                                     

                                    rich kubota - rkubota@apple.com

                                    developer technical support CoreOS/Hardware/MFI