Skip to main content
The single purchase path: the SDK never runs purchase code you didn’t write. You register a controller at configure(); when a user accepts an offer that leads to a purchase, Encore invokes it with the product to buy and awaits your verdict.

Definition

PurchaseRequest

What your controller receives when Encore needs a purchase.

Implementations

A production Play Billing controller also connects the billing client, launches the flow on the activity you receive, and acknowledges the purchase before returning Purchased. Follow Google’s Play Billing integration guide for those steps; the contract below is everything Encore requires of you.

The contract

  • One invocation returns one verdict, or throws. A returned value lands on the result record as the publisher axis (PublisherOutcome.Purchased / Cancelled / Pending) and on Encore.outcomes; a throw lands as PublisherOutcome.Failed.
  • The controller is invoked on Dispatchers.Main.immediate. Usually this happens inside the sheet’s lifetime, so your billing UI overlays the sheet and the sheet resolves after you return. One exception: a purchase-first variant invokes your controller over your own Activity before any Encore UI exists, and returning Cancelled there means no sheet is shown and the result is NotPresented(IapFirstDeclined).
  • The activity parameter is valid only for the duration of the call. Do not retain it; do not finish() it.
  • A thrown exception carries your error type into analytics (controller_threw: <Type>); cancelling your own coroutine carries only the generic controller_threw: CancellationException. Bound your own pre-flight steps (connecting a billing client, catalog lookups) with short timeouts; only the user-facing purchase dialog deserves long waits.
  • A controller that never resolves is abandoned as failed after 5 minutes. A purchase that completes late within a bounded window is still recorded and linked; beyond that, the Play server notification backstops the money facts.