j3k0 / cordova-plugin-purchase

In-App Purchase for Cordova on iOS, Android and Windows
https://purchase.cordova.fovea.cc
1.29k stars 529 forks source link

iOS purchase popup trigger multiple times and unable to get transaction details #1513

Closed ragulbit closed 3 months ago

ragulbit commented 3 months ago

I've integrated version 13.10.0 of the cordova-plugin-purchase into my Ionic application. Additionally, I've set up a consumable product in the Apple App Store and created a dedicated sandbox user for testing purposes.

While I can successfully retrieve product details from the store and display them in the application template, I'm encountering an issue during the purchase process. After initiating the purchase, the popup appears prompting me to enter the sandbox user password, then the popup shows "done" and closes. However, approximately 10 seconds later, the purchase popup reappears. This repetitive behavior persists, occurring in a recurring manner.

Below are my logs in the Xcode.

What did I miss? I need to get the transaction details and send them to the backend through API for validation and future reference. How Can I achieve this?

I really appreciate any help you can provide.

⚡️  [log] - [CdvPurchase] INFO: initialize()
⚡️  [log] - [CdvPurchase.Adapters] INFO: Adding platforms: [{"platform":"ios-appstore"}]
⚡️  [log] - [CdvPurchase.Adapters] INFO: 
⚡️  [log] - [CdvPurchase.Adapters] INFO: AppStore initializing...
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: bridge.init
To Native Cordova ->  InAppPurchase debug InAppPurchase749584148 ["options": []]
To Native Cordova ->  InAppPurchase setup InAppPurchase749584149 ["options": []]
[CdvPurchase.AppleAppStore.objc] setup: OK
⚡️  [log] - [CdvPurchase.AppleAppStore.Bridge] DEBUG: setup ok
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: ready
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: bridge.init done
To Native Cordova ->  InAppPurchase canMakePayments InAppPurchase749584150 ["options": []]
[CdvPurchase.AppleAppStore.objc] canMakePayments: Device can make payments.
⚡️  [log] - [CdvPurchase.Adapters] INFO: AppStore initialized. 
⚡️  [log] - [CdvPurchase.Adapters] INFO: AppStore products: [{"id":"sample_consumable_product_01","type":"consumable","platform":"ios-appstore"}]
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: bridge.load
⚡️  [log] - [CdvPurchase.AppleAppStore.Bridge] DEBUG: load ["sample_consumable_product_01"]
To Native Cordova ->  InAppPurchase load InAppPurchase749584151 ["options": [<__NSArrayM 0x600000d458f0>(
sample_consumable_product_01
)
]]
[CdvPurchase.AppleAppStore.objc] load: Getting products data
[CdvPurchase.AppleAppStore.objc] load: Set has 1 elements
[CdvPurchase.AppleAppStore.objc] load:  - sample_consumable_product_01
[CdvPurchase.AppleAppStore.objc] load: Starting product request...
[CdvPurchase.AppleAppStore.objc] load: Product request started
To Native Cordova ->  ⚡️  [log] - [CdvPurchase.AppleAppStore.Bridge] DEBUG: processing pending transactions
InAppPurchase processPendingTransactions InAppPurchase749584152 ["options": []]
[CdvPurchase.AppleAppStore.objc] processPendingTransactionUpdates
[CdvPurchase.AppleAppStore.objc] BatchProductsRequestDelegate.productsRequest:didReceiveResponse:
[CdvPurchase.AppleAppStore.objc] BatchProductsRequestDelegate.productsRequest:didReceiveResponse: Has 1 validProducts
[CdvPurchase.AppleAppStore.objc] BatchProductsRequestDelegate.productsRequest:didReceiveResponse:  - sample_consumable_product_01: Sample consumable product
[CdvPurchase.AppleAppStore.objc] BatchProductsRequestDelegate.productsRequest:didReceiveResponse: sendPluginResult: (
        (
                {
            billingPeriod = 0;
            billingPeriodUnit = Day;
            countryCode = IN;
            currency = INR;
            description = "Sample consumable product for testing";
            discounts =             (
            );
            group = "<null>";
            id = "sample_consumable_product_01";
            introPrice = "<null>";
            introPriceMicros = "<null>";
            introPricePaymentMode = "<null>";
            introPricePeriod = "<null>";
            introPricePeriodUnit = "<null>";
            price = "\U20b9\U00a099.00";
            priceMicros = 99000000;
            title = "Sample consumable product";
        }
    ),
        (
    )
)
⚡️  [log] - [CdvPurchase.AppleAppStore.Bridge] DEBUG: load ok: { valid:[{"id":"sample_consumable_product_01","description":"Sample consumable product for testing","introPrice":null,"introPricePaymentMode":null,"billingPeriodUnit":"Day","countryCode":"IN","introPricePeriodUnit":null,"discounts":[],"title":"Sample consumable product","price":"₹ 99.00","billingPeriod":0,"group":null,"priceMicros":99000000,"currency":"INR","introPricePeriod":null,"introPriceMicros":null}] invalid:[] }
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: bridge.loaded: {"validProducts":[{"id":"sample_consumable_product_01","description":"Sample consumable product for testing","introPrice":null,"introPricePaymentMode":null,"billingPeriodUnit":"Day","countryCode":"IN","introPricePeriodUnit":null,"discounts":[],"title":"Sample consumable product","price":"₹ 99.00","billingPeriod":0,"group":null,"priceMicros":99000000,"currency":"INR","introPricePeriod":null,"introPriceMicros":null}],"invalidProducts":[]}
⚡️  [log] - [CdvPurchase.AppleAppStore] DEBUG: load eligibility: [{"id":"sample_consumable_product_01","description":"Sample consumable product for testing","introPrice":null,"introPricePaymentMode":null,"billingPeriodUnit":"Day","countryCode":"IN","introPricePeriodUnit":null,"discounts":[],"title":"Sample consumable product","price":"₹ 99.00","billingPeriod":0,"group":null,"priceMicros":99000000,"currency":"INR","introPricePeriod":null,"introPriceMicros":null}]
⚡️  [log] - [CdvPurchase.AppleAppStore] DEBUG: No discount eligibility determiner, skipping...
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: eligibilities ready: {"request":[],"response":[]}
⚡️  [log] - [CdvPurchase.AppleAppStore] DEBUG: sample_consumable_product_01 is valid: {"id":"sample_consumable_product_01","description":"Sample consumable product for testing","introPrice":null,"introPricePaymentMode":null,"billingPeriodUnit":"Day","countryCode":"IN","introPricePeriodUnit":null,"discounts":[],"title":"Sample consumable product","price":"₹ 99.00","billingPeriod":0,"group":null,"priceMicros":99000000,"currency":"INR","introPricePeriod":null,"introPriceMicros":null}
⚡️  [log] - [CdvPurchase.AppleAppStore] DEBUG: registering new product
⚡️  [log] - [CdvPurchase.AppleAppStore] DEBUG: Products loaded: [{"className":"Product","title":"Sample consumable product","description":"Sample consumable product for testing","platform":"ios-appstore","type":"consumable","id":"sample_consumable_product_01","offers":[{"className":"Offer","id":"$","pricingPhases":[{"price":"₹ 99.00","priceMicros":99000000,"currency":"INR","paymentMode":"UpFront","recurrenceMode":"NON_RECURRING"}],"productId":"sample_consumable_product_01","productType":"consumable","platform":"ios-appstore","offerType":"Default"}],"raw":{"id":"sample_consumable_product_01","description":"Sample consumable product for testing","introPrice":null,"introPricePaymentMode":null,"billingPeriodUnit":"Day","countryCode":"IN","introPricePeriodUnit":null,"discounts":[],"title":"Sample consumable product","price":"₹ 99.00","billingPeriod":0,"group":null,"priceMicros":99000000,"currency":"INR","introPricePeriod":null,"introPriceMicros":null},"countryCode":"IN"}]
⚡️  [log] - [CdvPurchase.AppleAppStore] DEBUG: loading appstore receipt...
⚡️  [log] - [CdvPurchase.AppleAppStore.Bridge] DEBUG: loading appStoreReceipt
To Native Cordova ->  InAppPurchase appStoreReceipt InAppPurchase749584153 ["options": []]
[CdvPurchase.AppleAppStore.objc] appStoreReceipt:
⚡️  [log] - [CdvPurchase.AppleAppStore.Bridge] DEBUG: infoPlist: com.appid.app,2.0,2030075904,null
⚡️  [log] - [CdvPurchase.AppleAppStore] DEBUG: appstore receipt loaded
⚡️  [log] - [CdvPurchase.AdapterListener] DEBUG: receiptsReady: ios-appstore (1/0)
⚡️  [warn] - [CdvPurchase.AppleAppStore] WARNING: no appStoreReceipt
⚡️  [log] - [CdvPurchase.Adapters] INFO: AppStore products loaded: [{"className":"Product","title":"Sample consumable product","description":"Sample consumable product for testing","platform":"ios-appstore","type":"consumable","id":"sample_consumable_product_01","offers":[{"className":"Offer","id":"$","pricingPhases":[{"price":"₹ 99.00","priceMicros":99000000,"currency":"INR","paymentMode":"UpFront","recurrenceMode":"NON_RECURRING"}],"productId":"sample_consumable_product_01","productType":"consumable","platform":"ios-appstore","offerType":"Default"}],"raw":{"id":"sample_consumable_product_01","description":"Sample consumable product for testing","introPrice":null,"introPricePaymentMode":null,"billingPeriodUnit":"Day","countryCode":"IN","introPricePeriodUnit":null,"discounts":[],"title":"Sample consumable product","price":"₹ 99.00","billingPeriod":0,"group":null,"priceMicros":99000000,"currency":"INR","introPricePeriod":null,"introPriceMicros":null},"countryCode":"IN"}]
⚡️  [log] - [CdvPurchase.Adapters] INFO: AppStore receipts loaded: [{"className":"Receipt","transactions":[],"platform":"ios-appstore"}]
⚡️  [log] - [CdvPurchase.AdapterListener] DEBUG: setSupportedPlatforms: ios-appstore (1 have their receipts ready)
⚡️  [log] - [CdvPurchase.AdapterListener] DEBUG: triggering receiptsReady()
⚡️  [log] - [CdvPurchase] DEBUG: Calling callback: type=ready() name=#6af97bda7b4a9d622adb364dcf47befd reason=initialize_promise_resolved
⚡️  [log] - [CdvPurchase] INFO: verify(Receipt)
⚡️  [log] - [CdvPurchase.Validator] DEBUG: Schedule validation: {"className":"Receipt","transactions":[],"platform":"ios-appstore"}
⚡️  [log] - [CdvPurchase.Validator] DEBUG: Validation requests=1 responses=0
⚡️  [log] - [CdvPurchase] INFO: finish(Receipt)
⚡️  [log] - [CdvPurchase] DEBUG: Calling callback: type=receiptsReady() name=receiptsMonitor_setup reason=adapterListener_setSupportedPlatforms
⚡️  [log] - [CdvPurchase.ReceiptsMonitor] DEBUG: receiptsReady...
⚡️  [log] - [CdvPurchase] DEBUG: Calling callback: type=receiptsReady() name=#b63d85336be5e93f79fcf5de4adcbd04 reason=adapterListener_setSupportedPlatforms
⚡️  [log] - [CdvPurchase.Validator] DEBUG: Validation requests=1 responses=1
⚡️  [log] - [CdvPurchase.AppleAppStore] DEBUG: receipt updated.
⚡️  [log] - [CdvPurchase.AdapterListener] DEBUG: receiptsUpdated: [{"className":"Receipt","transactions":[],"platform":"ios-appstore"}]
⚡️  [log] - [CdvPurchase] DEBUG: Calling callback: type=receiptUpdated() name=#d3b2adbbd920494790ac72920cc1d18a reason=adapterListener_receiptsUpdated

⚡️  [log] - [CdvPurchase.ReceiptsMonitor] DEBUG: keep checking every 10s...
⚡️  [log] - [CdvPurchase.ReceiptsMonitor] DEBUG: check(1/1)
⚡️  [log] - [CdvPurchase.ReceiptsMonitor] INFO: receiptsVerified()

⚡️  [log] - [CdvPurchase] INFO: order(sample_consumable_product_01)
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: order
To Native Cordova ->  InAppPurchase purchase InAppPurchase749584154 ["options": [sample_consumable_product_01, 1, <null>, {
}]]
[CdvPurchase.AppleAppStore.objc] purchase: About to do IAP
[CdvPurchase.AppleAppStore.objc] paymentQueue:updatedTransactions: sample_consumable_product_01
[CdvPurchase.AppleAppStore.objc] paymentQueue:updatedTransactions: Purchasing...
[CdvPurchase.AppleAppStore.objc] paymentQueue:updatedTransactions: State: PaymentTransactionStatePurchasing
[CdvPurchase.AppleAppStore.objc] processTransactionUpdate:withArgs: transactionIdentifier=
⚡️  [log] - [CdvPurchase.AppleAppStore.Bridge] DEBUG: Purchase enqueued sample_consumable_product_01
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: purchaseEnqueued: sample_consumable_product_01 - 1
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: order.success
⚡️  [log] - [CdvPurchase.AdapterListener] DEBUG: receiptsUpdated: [{"className":"Receipt","transactions":[{"className":"Transaction","transactionId":"virtual.sample_consumable_product_01","state":"initiated","products":[{"id":"sample_consumable_product_01"}],"platform":"ios-appstore"}],"platform":"ios-appstore"}]
⚡️  [log] - [CdvPurchase.AppleAppStore.Bridge] DEBUG: transaction updated: state:PaymentTransactionStatePurchasing product:sample_consumable_product_01
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: purchasing: sample_consumable_product_01
⚡️  [log] - [CdvPurchase.AdapterListener] DEBUG: receiptsUpdated: [{"className":"Receipt","transactions":[{"className":"Transaction","transactionId":"virtual.sample_consumable_product_01","state":"initiated","products":[{"id":"sample_consumable_product_01"}],"platform":"ios-appstore"}],"platform":"ios-appstore"}]
⚡️  [log] - [CdvPurchase] DEBUG: Calling callback: type=receiptUpdated() name=#d3b2adbbd920494790ac72920cc1d18a reason=adapterListener_receiptsUpdated
⚡️  [log] - [CdvPurchase] DEBUG: Calling callback: type=receiptUpdated() name=#d3b2adbbd920494790ac72920cc1d18a reason=adapterListener_receiptsUpdated
elpollodiablo commented 3 months ago

I seem to have the exact same issue, just with a subscription. Can you verify that there is no debug output at all from the plugin when you finish the storekit popup, and no events are triggered either?

ragulbit commented 3 months ago

Yes, there is no debug output generated by the plugin, and no events are being triggered upon the completion of the purchase. The StoreKit popup displays "done," closes momentarily, but after some time, it reappears. But, if I manually close the StoreKit popup without purchase, debug output is then generated.

[CdvPurchase.AppleAppStore.objc] paymentQueue:updatedTransactions: sample_consumable_product_01
[CdvPurchase.AppleAppStore.objc] paymentQueue:updatedTransactions: Error ERR_PAYMENT_CANCELLED - The operation couldn’t be completed. (SKErrorDomain error 2.)
[CdvPurchase.AppleAppStore.objc] paymentQueue:updatedTransactions: State: PaymentTransactionStateFailed
[CdvPurchase.AppleAppStore.objc] processTransactionUpdate:withArgs: transactionIdentifier=
⚡️  [log] - [CdvPurchase.AppleAppStore.Bridge] DEBUG: transaction updated: state:PaymentTransactionStateFailed product:sample_consumable_product_01
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: purchaseFailed: sample_consumable_product_01 - 6777006 - The operation couldn’t be completed. (SKErrorDomain error 2.)
⚡️  [log] - [CdvPurchase.AdapterListener] DEBUG: receiptsUpdated: [{"className":"Receipt","transactions":[],"platform":"ios-appstore"}]
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: order.paymentMonitor => failed  
⚡️  [error] - [CdvPurchase.AppleAppStore] ERROR: ERROR: 6777006 - The operation couldn’t be completed. (SKErrorDomain error 2.)
⚡️  [error] - [CdvPurchase.AppleAppStore] ERROR: error@user-script:21:268:32
error@user-script:21:2768:43
protectCall@user-script:21:3295:35
transactionUpdated@user-script:21:3586:40
@capacitor://localhost/purchase:1:107
@user-script:18:1133:13
@user-script:18:1157:52
global code@capacitor://localhost/purchase:1:55
⚡️  [log] - [CdvPurchase.AppleAppStore] INFO: order.paymentMonitor => cancelled  
⚡️  [log] - [CdvPurchase] DEBUG: Calling callback: type=receiptUpdated() name=#d3b2adbbd920494790ac72920cc1d18a reason=adapterListener_receiptsUpdated
rohithmahesh3 commented 3 months ago

I have also stumbled upon the same issue. Tried with v11, v13.8.6 and v13.10.0 without luck.

elpollodiablo commented 3 months ago

@rohithmahesh3 @ragulbit what are your test environments? Are you testing on simulator or on physical devices? Which IOS Version? Are you using xcode supplied storekit configurations/products or appstore connect supplied ones? Capacitor/Cordova/Ionic?

I'm using ios 17.2.1 on simulator, and I have the product configured both in xcode and appstore connect, and I'm on an ionic capacitor project.

@rohithmahesh3 it's weird that the problem persists to version 11 - did you do ionic cap sync (if you're on capacitor)?

ragulbit commented 3 months ago

@elpollodiablo I'm using iOS 17.2 on simulator. It is working fine on the physical devices. Need to check the same with Google Play Store IAP

j3k0 commented 3 months ago

Based on the logs, the plugin doesn't seem to make multiple calls to the underlying SDK to initiate the purchase again, so that looks more like an issue with Apple StoreKit SDK itself. I always find it better to test with products defined on AppStore Connect on a real device, or right on the Mac (designed for iPad).

JanST123 commented 3 months ago

Had the same problem when testing on the simulator. Defining the product in XCode with the storekit file fixed it.

NicholasStine commented 3 months ago

Had the same problem when testing on the simulator. Defining the product in XCode with the storekit file fixed it.

This fix worked for me.

selcukbeyhan commented 2 months ago

I have the same issue. I created the storekit file as well but it didnt help. Besides, I dont see any relation to this file neither. There is no such instruction in the documentation neither.

mvaljento commented 3 weeks ago

@selcukbeyhan Did you find a solution to this?

Not sure if related, but...

I've configured the App scheme to use the local storekit file with locally defined products, but the simulator keeps showing the product prices defined in the App Store Connect and asking me to sign in to the App Store.

The storekit should not ask for login so I'm assuming the simulator is not using the correct storekit definition.

Anyone know how to debug this?

I'm launching the app using the "cap run ios" command instead of Xcode. Even if I modify the path for "StoreKitConfigurationFileReference" to non-existing file, the app still launches and gives me the products from App Store Connect, so it seems the file is not read at all.

mvaljento commented 3 weeks ago

@JanST123 Did you do anything else? For me defining the storekit file (with either App Store Connect or locally defined products) does not seem to have any effect.

elpollodiablo commented 3 weeks ago

@mvaljento testing on simulator simply isn't supported for applications using storekit. Not with this plugin, not with another, not natively.

mvaljento commented 3 weeks ago

@elpollodiablo That's strange. Maybe I'm not understanding. According to Apple's documentation it definitely is possible to test in-app purchases natively using the simulator. Even according to messages in this thread it should be possible. Doesn't the plugin use the native libraries under the hood?

https://developer.apple.com/documentation/storekit/in-app_purchase/original_api_for_in-app_purchase/testing_in-app_purchases_in_xcode

https://www.swiftwithvincent.com/blog/how-to-easily-test-in-app-purchases

elpollodiablo commented 3 weeks ago

@mvaljento oh. well, while I believe I read it somewhere on developer.apple.com too, my (rather recent, few months ago) experience with this particular plugin is, that the above described problem i had while testing on the simulator (i believe i wasn't getting a callback/receipt after a purchase) went away when I tested on a physical device with the same code. I also used/tried to use a storekit file.

I then went on to use glassfy (sadly, because this plugin is a massive, massive pain in the a... to use, and involves WAY too much boilerplate work), and glassfy documentation also clearly states it's capacitor plugin will test on physical devices only.

JanST123 commented 3 weeks ago

@JanST123 Did you do anything else? For me defining the storekit file (with either App Store Connect or locally defined products) does not seem to have any effect.

@mvaljento You may need to select the storekit configuration in the Run-Configuration in Xcode (click on the App in the breadcrumb and "Edit scheme" -> Run -> Options -> Storekit configuration

mvaljento commented 3 weeks ago

@JanST123 Thanks very much for the reply. Yes, I did that and I checked that the App.xcscheme file correctly reflects that change (see "localTest.storekit" in the snippet below). However, even if I edit the filename to point to non-existent path, it still runs the app without errors. To me it seems, that the StoreKitConfigurationFileReference is never read. If you got it working, would you be kind enough to post your working scheme configuration?


<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "1520"
   version = "1.7">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "..."
               BuildableName = "App.app"
               BlueprintName = "App"
               ReferencedContainer = "container:App.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES"
      shouldAutocreateTestPlan = "YES">
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "..."
            BuildableName = "App.app"
            BlueprintName = "App"
            ReferencedContainer = "container:App.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
      <StoreKitConfigurationFileReference
         identifier = "../localTest.storekit">
      </StoreKitConfigurationFileReference>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "..."
            BuildableName = "App.app"
            BlueprintName = "App"
            ReferencedContainer = "container:App.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>
JanST123 commented 3 weeks ago

@mvaljento Yes you can have it :) But I don't see anything special about my configuration.. unfortunately I can't remember all the details as the project is finished since some months.

<?xml version="1.0" encoding="UTF-8"?>
<Scheme
   LastUpgradeVersion = "1500"
   version = "1.7">
   <BuildAction
      parallelizeBuildables = "YES"
      buildImplicitDependencies = "YES">
      <BuildActionEntries>
         <BuildActionEntry
            buildForTesting = "YES"
            buildForRunning = "YES"
            buildForProfiling = "YES"
            buildForArchiving = "YES"
            buildForAnalyzing = "YES">
            <BuildableReference
               BuildableIdentifier = "primary"
               BlueprintIdentifier = "xxx"
               BuildableName = "App.app"
               BlueprintName = "App"
               ReferencedContainer = "container:App.xcodeproj">
            </BuildableReference>
         </BuildActionEntry>
      </BuildActionEntries>
   </BuildAction>
   <TestAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      shouldUseLaunchSchemeArgsEnv = "YES"
      shouldAutocreateTestPlan = "YES">
   </TestAction>
   <LaunchAction
      buildConfiguration = "Debug"
      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
      launchStyle = "0"
      useCustomWorkingDirectory = "NO"
      ignoresPersistentStateOnLaunch = "NO"
      debugDocumentVersioning = "YES"
      debugServiceExtension = "internal"
      allowLocationSimulation = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "xxx"
            BuildableName = "App.app"
            BlueprintName = "App"
            ReferencedContainer = "container:App.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
      <StoreKitConfigurationFileReference
         identifier = "../SyncedProducts.storekit">
      </StoreKitConfigurationFileReference>
   </LaunchAction>
   <ProfileAction
      buildConfiguration = "Release"
      shouldUseLaunchSchemeArgsEnv = "YES"
      savedToolIdentifier = ""
      useCustomWorkingDirectory = "NO"
      debugDocumentVersioning = "YES">
      <BuildableProductRunnable
         runnableDebuggingMode = "0">
         <BuildableReference
            BuildableIdentifier = "primary"
            BlueprintIdentifier = "504EC3031FED79650016851F"
            BuildableName = "App.app"
            BlueprintName = "App"
            ReferencedContainer = "container:App.xcodeproj">
         </BuildableReference>
      </BuildableProductRunnable>
   </ProfileAction>
   <AnalyzeAction
      buildConfiguration = "Debug">
   </AnalyzeAction>
   <ArchiveAction
      buildConfiguration = "Release"
      revealArchiveInOrganizer = "YES">
   </ArchiveAction>
</Scheme>