Class CommerceManager
Client facade for the Codename One Commerce service. It does not replace
the Purchase API -- it wraps it: purchases still go through the
platform store, and this class adds server-side validation and a
store-agnostic entitlement check ("does this user have pro?")
instead of per-SKU receipt juggling.
Typical use:
CommerceManager cm = CommerceManager.getInstance();
cm.setAppUserId(myAccountId); // optional; stable per user
cm.subscribe("pro_monthly"); // delegates to Purchase
// later, off the EDT:
cm.refresh(); // validate receipts with the cloud
if (cm.isEntitled("pro")) { ... } // entitlement, not SKU
Graceful degradation. When the cloud is unreachable, or the
developer's account is over its monthly validated-volume cap, the cloud
stops validating and isDegraded() becomes true. Entitlement checks
then fall back to the store-direct signal (the platform's own receipt), so
a paying user is never locked out -- exactly the server-side behaviour,
mirrored on the device.
The cloud endpoint, build key and package are stamped into the build by
the Codename One build server when commerce is enabled
(codename1.arg.commerce.cloud.enabled=true); when they are absent
this class is inert and every call is a safe no-op that defers to
Purchase.
-
Method Summary
Modifier and TypeMethodDescriptionvoidAdds a listener that is called on the EDT whenever the customer information changes.voidanalyticsEvent(String name, String offeringId, String packageId, String productId, String key, String value) Reports a commerce event to the analytics providers the application registered withAnalytics, in the categorycommerce.The page where the customer manages the subscription, asking the cloud for a billing portal when the newest active entitlement -- the one that expires last -- was bought on the web (stripeorpaddle).Snapshot of the entitlement ids currently considered active.The current (explicit or generated-anonymous) app user id.The customer center the console configured for this application, as parsed JSON: thepathsto offer, the support address and the cancel reasons.The last customer information the cloud answered with.static CommerceManagerThe shared instance.The page where the customer manages the subscription, or null when there is none.The offerings the cloud configured for this customer.getOfferings(String placement) The offerings the cloud configured for this customer at a placement, a named place in the application ("onboarding","settings") that the console can give an offering of its own.getWebPurchaseUrl(CommercePackage pkg, String successUrl, String cancelUrl) Asks the cloud for a hosted checkout page that sells a package for its web price.booleanWhether cloud commerce is active in this build.booleanTrue after arefresh()that could not get a server-validated answer -- the cloud was unreachable or the account is over its monthly cap.booleanisEntitled(String entitlementId) Whether the user currently holdsentitlementId.booleanWhetherpurchase(CommercePackage)sells a package through a web checkout: the package has no product of this platform's store, and the platform has no store to sell one -- the browser and the desktop, wherePurchasesupports neither managed payments nor subscriptions.voidReports a paywall event to the cloud, where the console charts the funnel of each offering and paywall.voidReports an event to the cloud.booleanTells the cloud that the current customer is now known asnewAppUserId, typically when the user signs in to the application's own account.voidlogOut()Forgets the current customer: a new anonymous id is generated and the customer information becomes empty, so the next user of the device does not inherit the previous one's entitlements.voidpurchase(CommercePackage pkg) Buys a package through the platform store: a subscription for every package that is one, a one time purchase otherwise.voidbooleanSells a package through a hosted checkout page, opened withDisplay.execute(String).booleanpurchaseWithPromotionalOffer(String productId, String offerId) Buys a subscription under one of its App Store promotional offers.voidrefresh()Validates the device's current receipts with the cloud, then asks the cloud what the customer is entitled to and takes that answer as the entitlement state.voidRemoves a listener added withaddCustomerInfoListener(ActionListener).voidrestore()Asks the store to restore the purchases of the store account on this device, when the platform supports that.voidsetAppUserId(String id) Sets the stable per-user id the cloud keys entitlements on.booleansetAttributes(Map attributes) Attaches attributes to the current customer in the cloud, where targeting rules and the console can read them.voidvoidunsubscribe(String sku)
-
Method Details
-
getInstance
The shared instance. -
isCloudEnabled
public boolean isCloudEnabled()Whether cloud commerce is active in this build. True for any cloud build (one that carries abuild_key) unless the developer explicitly disabled it withcodename1.commerce.cloud.enabled=false. In the simulator / a local build there is no build key, so this is false and every call safely defers toPurchase. -
isDegraded
public boolean isDegraded()True after arefresh()that could not get a server-validated answer -- the cloud was unreachable or the account is over its monthly cap. Entitlement checks fall back to the store-direct signal while this is true. -
setAppUserId
Sets the stable per-user id the cloud keys entitlements on. Pass your own account id once the user signs in; if never set, an anonymous id is generated and persisted so entitlements survive restarts on the device. -
getAppUserId
The current (explicit or generated-anonymous) app user id. -
logIn
Tells the cloud that the current customer is now known as
newAppUserId, typically when the user signs in to the application's own account. Purchases made under an anonymous id move to the account, so a subscription bought before signing in, or on another platform under the same account, unlocks here.Blocking network call -- invoke off the EDT. The id is switched only when the cloud accepted the change; on failure the manager is degraded, the previous id stays, and the call can be repeated. When the cloud is not enabled in this build the id is switched locally and nothing else happens.
This id is commerce's own. It is independent of the user id of
Analytics.setUserId, which stays whatever the application set: logging in or out here never changes it, and an application that wants its analytics under the same id sets it there as well.Parameters
newAppUserId: the application's stable id for the user
Returns
true if the id was switched
-
logOut
public void logOut()Forgets the current customer: a new anonymous id is generated and the customer information becomes empty, so the next user of the device does not inherit the previous one's entitlements. Listeners are told. Nothing is sent to the cloud; callrefresh()afterwards to pick up what the store account on the device still owns. -
setAttributes
Attaches attributes to the current customer in the cloud, where targeting rules and the console can read them. A null value deletes the attribute; any other value is sent as its string form.
Blocking network call -- invoke off the EDT. Safe no-op when the cloud is not enabled in this build.
Parameters
attributes: attribute names to values
Returns
true if the cloud accepted the attributes
-
restore
public void restore()Asks the store to restore the purchases of the store account on this device, when the platform supports that. The restored receipts reach the cloud through the receipt synchronization that follows, which refreshes this manager by itself. -
getCustomerInfo
The last customer information the cloud answered with. Never null: before any answer it is an empty customer.
The last accepted answer is stored on the device, so this answers after a cold start and with no network. A stored entitlement is reported exactly as it was stored, even when its expiry date has passed by the device's clock: the device clock is the user's to set, so only the service's clock decides when an entitlement ends, and it does so on the next
refresh(). -
addCustomerInfoListener
Adds a listener that is called on the EDT whenever the customer information changes. The event's source is the newCustomerInfo. -
removeCustomerInfoListener
Removes a listener added withaddCustomerInfoListener(ActionListener). -
purchase
-
subscribe
-
unsubscribe
-
isEntitled
Whether the user currently holdsentitlementId. Uses the last cloud-validated answer when available; otherwise (cloud disabled or degraded) falls back to the store-direct signal, treating the entitlement id as a subscription SKU so a paying user keeps access. -
getActiveEntitlements
Snapshot of the entitlement ids currently considered active. -
getOfferings
The offerings the cloud configured for this customer. Same as
getOfferings(String)with no placement.Returns
the offerings; never null, and empty when there is nothing to answer from
-
getOfferings
The offerings the cloud configured for this customer at a placement, a named place in the application (
"onboarding","settings") that the console can give an offering of its own.Blocking network call -- invoke off the EDT. The last accepted answer is stored on the device and is what this returns when the cloud cannot be reached. After a fresh answer the store is asked for the products of the packages, when the platform lists products, and each is attached to its
CommercePackage.Parameters
placement: the placement, or null for the default offerings
Returns
the offerings; never null, and empty when the cloud is not enabled in this build or there is nothing to answer from
-
purchase
Buys a package through the platform store: a subscription for every package that is one, a one time purchase otherwise. The outcome arrives the way every store purchase does, and through the customer information listeners once the cloud validated it.
Parameters
pkg: the package to buy; null or a package with no product does nothing
-
isWebPurchase
Whether
purchase(CommercePackage)sells a package through a web checkout: the package has no product of this platform's store, and the platform has no store to sell one -- the browser and the desktop, wherePurchasesupports neither managed payments nor subscriptions.Parameters
pkg: the package asked about
Returns
true when buying the package opens a hosted checkout page
-
getWebPurchaseUrl
Asks the cloud for a hosted checkout page that sells a package for its web price.
Blocking network call -- invoke off the EDT.
Parameters
-
pkg: the package to sell -
successUrl: where the checkout sends the customer after paying, or null for the service's own page -
cancelUrl: where the checkout sends a customer who gave up, or null for the service's own page
Returns
the address of the checkout page, or null when the cloud is not enabled in this build, could not be reached, or has no web price for the package
-
-
purchaseOnWeb
Sells a package through a hosted checkout page, opened with
Display.execute(String). The customer pays outside the application, so nothing reports the outcome here: once the application is back in the foreground the caller runsrefresh()off the EDT, and the customer information listeners hear what was bought.PaywallViewdoes that itself.May be called on the EDT, which keeps dispatching events while the cloud is asked for the page.
Parameters
pkg: the package to sell
Returns
true when a checkout page was opened, false when there was none
-
purchaseWithPromotionalOffer
Buys a subscription under one of its App Store promotional offers. The cloud signs the offer for this customer and the store is then asked to sell the product with that signature, as
Purchase.purchase(String, PromotionalOffer)does.May be called on the EDT, which keeps dispatching events while the cloud is asked for the signature.
Parameters
-
productId: the subscription product -
offerId: the promotional offer of that product, as App Store Connect names it
Returns
true when the store was asked to sell the offer; false when no signature is available -- the platform's store has no promotional offers, the cloud is not enabled or it refused -- in which case nothing was bought
-
-
getManagementUrl
The page where the customer manages the subscription, or null when there is none. Never touches the network: for a subscription bought on the web it is the billing portalfetchManagementUrl()last answered, and otherwise -- or before that was ever asked -- the store's page from the last customer information. -
fetchManagementUrl
The page where the customer manages the subscription, asking the cloud for a billing portal when the newest active entitlement -- the one that expires last -- was bought on the web (
stripeorpaddle). A portal address is short lived, so it is asked for when it is about to be opened. For a store subscription this isgetManagementUrl()and nothing is asked.Blocking network call -- invoke off the EDT.
Returns
the address, or null when there is none
-
getCustomerCenterConfiguration
The customer center the console configured for this application, as parsed JSON: the
pathsto offer, the support address and the cancel reasons.CustomerCenterpresents it.Blocking network call -- invoke off the EDT.
Returns
the configuration, or null when the cloud is not enabled in this build, could not be reached or refused to answer
-
logEvent
Reports a paywall event to the cloud, where the console charts the funnel of each offering and paywall. Same as
logEvent(String, String, String, String, String)with no reason.Parameters
-
type: the event, such asIMPRESSION,PURCHASE_START,PURCHASEorCLOSE -
offeringId: the offering shown, or null -
paywallId: the paywall shown, or null -
packageId: the package concerned, or null
-
-
logEvent
public void logEvent(String type, String offeringId, String paywallId, String packageId, String reason) Reports an event to the cloud. The call returns at once on any thread: events are collected and sent together from a background thread, and an event that cannot be sent is dropped. Reporting never delays or fails a purchase. Safe no-op when the cloud is not enabled in this build.
Parameters
-
type: the event, such asIMPRESSIONorCANCEL_REASON -
offeringId: the offering shown, or null -
paywallId: the paywall shown, or null -
packageId: the package concerned, or null -
reason: the id of the reason chosen, for aCANCEL_REASONevent, or null
-
-
analyticsEvent
public void analyticsEvent(String name, String offeringId, String packageId, String productId, String key, String value) Reports a commerce event to the analytics providers the application registered with
Analytics, in the categorycommerce.PaywallViewand the customer center call this for what they show; an application that draws its own paywall can call it with the same names so its reports read the same.The event carries the parameters
offering,packageandproductfor the values that are not null,placementwhen the offering was fetched for a placement, andexperimentandvariantwhen the offering was chosen by an experiment. Nothing is sent without the user's analytics consent, and the call does nothing at all when no provider is registered. It never throws and never blocks.Parameters
-
name: the event name, such aspaywall_view -
offeringId: the offering concerned, or null -
packageId: the package concerned, or null -
productId: the store product concerned, or null -
key: the name of one more parameter, or null -
value: the value of that parameter, or null to leave it out
-
-
refresh
public void refresh()Validates the device's current receipts with the cloud, then asks the cloud what the customer is entitled to and takes that answer as the entitlement state. The customer is asked even when the device holds no receipt at all, which is what unlocks a purchase made on another platform or granted from the console.
Blocking network call -- invoke off the EDT. Safe no-op when the cloud is not enabled in this build. On any failure the manager flips to
degradedand leaves the previous (or store-direct) answers in place.
-