Skip to content

Server-verified consumables: buy with an account token, finish after the server accepts - #11

Merged
Ramiz69 merged 1 commit into
mainfrom
feature/server-verified-consumables
Oct 9, 2026
Merged

Ramiz69 merged 1 commit into
mainfrom
feature/server-verified-consumables

Conversation

@Ramiz69

@Ramiz69 Ramiz69 commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Apps whose server credits purchases to an account (coins, tokens, credits) could not use the kit safely:

  • No appAccountToken. A purchase could not carry one, so the server had no signed proof of which account a purchase belongs to.
  • Finished before the server saw it. The kit finished every transaction immediately, both after a purchase and for every Transaction.updates delivery. A finished consumable is never redelivered. If the request to the server was then lost, the customer had paid and nothing would ever credit them.

What changes (additive, minor version)

  • FinishPolicy - .automatic (default, unchanged behaviour) or .manual. Set via configure(identifiers:finishing:), which defaults to .automatic, so existing call sites compile and behave as before.
  • purchase(productID:appAccountToken:) and the visionOS purchase(productID:appAccountToken:confirmIn:). The token is signed into the transaction.
  • finish(_:).
    • Finishes a transaction once the server has accepted it.
    • A value without its StoreKit transaction is looked up in Transaction.unfinished by id.
    • Finishing twice does nothing.
  • unfinishedTransactions() - drain at launch and after sign-in.
  • transactionUpdates - every verified update: Ask to Buy approvals, pending payments, launch replays. One fresh stream per access, like purchasedProducts.
  • StoreTransaction.jwsRepresentation - the App Store's signed form for the server to verify. The public initializer gains it as a trailing defaulted parameter.
  • ServerVerifiedPurchasesProtocol - the new surface as its own protocol. Adding requirements to PurchasesProtocol would have broken every existing conformer, including test stand-ins. PurchasesManager conforms to both.

Under .manual the purchase path and the update listener both leave transactions unfinished. Under .automatic both finish exactly as before.

Verified

  • swift test: 34 tests pass, 4 new ones on the protocol surface and the signed form.
  • xcodebuild build for iOS, Mac Catalyst, watchOS, tvOS and visionOS: all succeed.
  • xcodebuild docbuild: no warnings. Links to the old configure(identifiers:) are updated.

Not covered by automated tests: the StoreKit-backed finish path itself. SKTestSession reports invalidApp outside an app host, the same limitation the existing suite has.

@Ramiz69
Ramiz69 merged commit d37c760 into main Oct 9, 2026
1 check passed
@Ramiz69
Ramiz69 deleted the feature/server-verified-consumables branch October 9, 2026 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant