Skip to main content
Every purchase triggered by an Encore offer runs through an EncorePurchaseController your app registers with configure(). The SDK has no built-in billing and never runs purchase code you did not write: your controller owns product lookup, receipt validation, restore handling, and entitlement bookkeeping, exactly as it does for every other purchase in your app. Encore controls when a purchase happens; you own how.

Definition

Each native plugin owns the native conformance and forwards every request over the method channel, waiting until your Dart code answers.
  • Throwing records a failure. A throw lands on the result as EncorePublisherOutcome.failed, and the flow continues. Map your billing layer’s “user cancelled” error to cancelled rather than throwing it.
  • An unrecognized answer is a failure, never purchased, because a phantom success would grant access nobody paid for.
  • The controller survives reset(). It is app-level wiring, not user state.
pending is a first-class result, not a soft failure. It means Ask to Buy (parental approval) on iOS, or SCA or a pending Play transaction on Android: the user has neither bought nor abandoned, and the store’s eventual webhook is the source of truth. Returning cancelled for a deferred purchase records a sale still in flight as a decline. Route your billing library’s deferred branch to pending.

EncorePurchaseRequest

What your controller receives when Encore needs a purchase.
Android’s native controller also hands over the foreground Activity. The plugin keeps it on the native side, since it is valid only for the duration of the call, so one Dart contract covers both platforms.

Implementations