PurchaseController your app registers. 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
Binding a controller
Pass your controller toconfigure(). Binding it is part of configuring, so the SDK is never configured without the purchase path it was meant to have.
EncoreProvider forwards its purchaseController prop into the configure() call it makes on mount, so these are one binding written two ways. Pick whichever matches where your app starts up.
Binding is build-time wiring, not user state. It survives
reset(), so logging a user out does not require binding again.Omitting the controller
Omitting the controller is a supported configuration, not a broken one. The SDK passes no controller to the native layer, never attempts a purchase, keeps its ownnot_attempted record and sdk_iap_no_purchase_controller diagnostic, and every presentation resolves publisher: 'not_attempted'. That is a different and more accurate fact than a failed the publisher never caused.
Replacing the controller
Encore.setPurchaseController() swaps the controller bound at configure(). The controller the native SDK holds is the bridge itself, and the bridge always forwards to whichever handler is currently bound, so the swap is a JavaScript-side concern that takes effect on the next purchase request.
{ success: false }, and logs why, when configure() ran without a purchase path: the native SDKs take the controller as a configure() argument and Android has no setter, so no controller can be added to an SDK that is already configured. Pass yours to configure() instead.
PurchaseResult
Throw for a real failure. A throw is recorded as
publisher: 'failed' with your error message, and the flow continues.
Returning anything else, including a bare true (the 1.x shape) or forgetting to return, is rejected rather than guessed at: the bridge fails that request with a message naming what it received. Failing loudly beats silently reporting a purchase that never happened.
PurchaseRequest
What your controller receives when Encore needs a purchase.Android’s native controller also hands over the foreground
Activity. The bridge absorbs it rather than leaking it to JavaScript: it has no JavaScript representation, it is valid only for the duration of the call, and a React Native host’s billing library resolves the current Activity itself. One contract therefore covers both platforms.Implementations
- RevenueCat
- react-native-iap
- Custom
Related
- configure(), which binds the controller.
- PresentationResult, where the controller’s answer lands as
publisher. - Present offers for the end-to-end walkthrough.