Superwall-iOS icon indicating copy to clipboard operation
Superwall-iOS copied to clipboard

[BUG] AppAccountToken still empty in StoreKit Transactions as its not passed properly

Open botrufus opened this issue 6 months ago • 3 comments

New issue checklist

  • [x] I have reviewed the README and documentation
  • [x] I have searched existing issues and this is not a duplicate
  • [x] I have attempted to reproduce the issue and include an example project.

General information

  • Superwall version: 4.3.5
  • iOS version(s): 18.4.1
  • CocoaPods/Carthage version (if applicable):
  • Xcode version: 16.2
  • Devices/Simulators affected: Iphone 13
  • Reproducible in the demo project? (Yes/No):
  • Related issues: https://github.com/superwall/Superwall-iOS/pull/303

Describe the bug

In ProductPurchaserSK2.swift:90-105 the appAccountToken is actually not set. While debugging I noticed the options Set is still empty after line 91-94, leading to the appAccountToken not being present in the StoreKit transaction. I need the appAccountToken in order to handle new transactions and map them to the corresponding Superwall users.

      var options: Set<StoreKit.Product.PurchaseOption> = []
      if let appUserId = identityManager.appUserId,
        let uuid = UUID(uuidString: appUserId) {
        options.insert(.appAccountToken(uuid))
      }

      let result: StoreKit.Product.PurchaseResult

      #if os(visionOS)
      guard let scene = await UIApplication.shared.connectedScenes.first else {
        return .cancelled
      }
      result = try await product.purchase(confirmIn: scene, options: options)
      #else
      result = try await product.purchase(options: options)
      #endif

When inspecting the values, you can see that _appUserId is nil and the options Set is empty because of it. Not really sure what the reason is for this.

Image

Expected Behaviour

appAccountToken being present in the StoreKit transaction and to be set to the Superwall user id

botrufus avatar May 06 '25 14:05 botrufus

Hi, is your user ID that you identify with in your app a UUID? Can you give me an example userID that I can check? Thanks

yusuftor avatar May 06 '25 14:05 yusuftor

Hi, is your user ID that you identify with in your app a UUID? Can you give me an example userID that I can check? Thanks

Ok I misunderstood the _appUserId. I thought its the Superwall uuid. In that case, whats the best way to map the StoreKit transactions I get from the Appstore Connect Server Notifications API to a Superwall uuid?

The only solution I could think of with my current understanding, would be to call identify() with the Superwall uuid and then access it in my web hook handler over the appAccountToken.

botrufus avatar May 06 '25 14:05 botrufus

The only solution I could think of with my current understanding, would be to call identify() with the Superwall uuid and then access it in my web hook handler over the appAccountToken.

Nevermind, this won’t work because identify() also sets Superwall.shared.userId, which I currently rely on to identify users across the project using the default Superwall alias (with the prefix). Changing it would break user identification elsewhere.

Ideally, the SDK should allow setting appAccountToken directly or at least use the default alias (without the Superwall prefix) as the appAccountToken by default.

botrufus avatar May 06 '25 15:05 botrufus

Thanks for the suggestion. You're right it should use the alias without the prefix as default if there's no given userId from identify. We'll add that in the next release. For your case it's probably best to use a PurchaseController and set the token yourself since you identifying with the alias is not going to work. You can check out our docs about that here.

yusuftor avatar May 07 '25 10:05 yusuftor

Alright, thank you!

Do you have an estimate for the next release? I'm currently integrating an MMP with server-side attribution, and this is the last missing piece before I can go live. If the release is just around the corner, I’d prefer not to spend time building a custom PurchaseController.

While we're at it: I think Superwall could really benefit from built-in support for the major MMPs’ server-to-server APIs. Many Superwall users run ads to promote their apps, and with a built-in S2S integration, they could have a no-code setup for attribution. It’s always a pain to set up manually. RevenueCat already offers this, and since Superwall already has the necessary notifications/event infrastructure, forwarding these events should be relatively simple. I even considered using RevenueCat just to avoid doing the MMP integration myself.

botrufus avatar May 07 '25 11:05 botrufus

It'll be released soon today but if you're already identifying with our aliasId then this update isn't going to work because that userId will have the superwall prefix on it. Re the MMP stuff, we have thought about this but it's not top priority right now as most people just use the delegate to forward events. That doesn't mean it won't be added in the future though.

yusuftor avatar May 07 '25 13:05 yusuftor

Yes, that's why I didn't implement this approach with identifying user the aliasId in the first place. I’m still relying on the default generated aliasId to track users across my project. Since the aliasId is now passed as the appAccountToken (when no userId is provided via identify, which is my case), I can access it in my backend, prepend the Superwall prefix, and map it to the Superwall users stored on my end. Therefore this does exactly what I need. Thanks again!

botrufus avatar May 07 '25 13:05 botrufus

Ahh I understand. Perfect. I just released 4.3.7 now (not 4.3.6) which includes this fix. Thanks!

yusuftor avatar May 07 '25 13:05 yusuftor