gemicore_flutter 0.4.0
gemicore_flutter: ^0.4.0 copied to clipboard
Purchases for Flutter: App Store and Google Play subscriptions, offerings and paywalls, card, Apple Pay and Google Pay payments, and entitlements with one API key.
0.4.0 #
- One package: the Apple Pay and Google Pay sheet that shipped separately as
gemicore_flutter_stripeis part ofgemicore_flutternow.GemicoreStripePaySheetis exported from here and is the default forpayWithSheet, soGemicore.configure(apiKey: ...)is the whole setup andnativePaySheetis only for replacing it.flutter_stripe^14.2.0 is a dependency, which means every app needs iOS 15 or higher and the Android settings listed in the README (compileSdk36, Java 17); the Apple Pay capability,FlutterFragmentActivityand an AppCompat theme are needed only to show the sheet. - Removed
GemicoreErrorCode.nativePayNotConfigured: there is always a sheet now.
0.3.0 #
- Customer attributes:
setAttributes(Map<String, String?>)(a null value deletes the key),setEmail,setDisplayNameandsetPhoneNumber. The server limits are checked before the request (50 keys per call, key pattern, 256 characters, only the reserved$names) and fail withGemicoreErrorCode.invalidAttributes; the server's own refusal isGemicoreErrorCode.attributesInvalid. Values are never logged and never put in an error. - Context headers on every request:
x-gemicore-app-version(frompackage_info_plus, or the newappVersionProviderofconfigure; left out when the lookup fails, as it does underflutter testunless a provider is passed) andx-gemicore-country(the device locale's two letter country code, upper case, left out when there is none), next tox-gemicore-platform. The API key is still the only required setting. - Placements:
getOfferings(placement:)andpresentPaywall(context, placement:).Offerings.placementsays how the server resolved it (PlacementResolution: identifier, source, and the experiment identifier and variant). Each placement has its own five minute memory copy and its own copy on the device. A placement the server does not know or rejects gives the app's current offering. Experiments need no extra call: reading the placement enrolls the customer on the server. - Android default offer: when a Google subscription is bought with no explicit offer, the offer named by the product's
defaultGoogleOfferIdis bought if Play lists it for the base plan (Play lists only the offers the customer is eligible for), otherwise the plain base plan as before.{{package.trial}}on Android now shows the trial of that offer. New fields:GemicoreProduct.defaultGoogleOfferIdanddefaultOfferDetails,ProductOffer.isDefault. - Customer Center:
getCustomerCenter(),CustomerCenterViewandCustomerCenterConfig(strings by locale with built in English for every label, seecustomerCenterEnglish), theGemicoreCustomerCenterwidget andpresentCustomerCenter(context), which returns false without showing anything while the dashboard has it off. It summarizes the active entitlements and subscriptions, opens the store page that manages a subscription, restores purchases, opens the store's own refund help (Apple Report a Problem or Google order history, by the store of the purchase), reaches support, and runs the cancel flow: survey, then an eligible retention offer through the normal promotional offer purchase, then the store's management page. It never cancels anything itself; cancellation happens in the store.sendCancelFeedbackposts the survey answer, and a failure there never blocks the customer. ExternalUrlOpener(implemented by the default opener): the Customer Center opens store pages and mailto links outside the app when the opener can, andGemicore.openExternalUrlandGemicore.platformare new.- Offerings copies belong to the customer:
logIn,logOutandsetAttributesdrop the memory copy (andsetAttributesthe device copy of what was read), and a device copy saved for another customer is ignored. An offline first read of a placement falls back to the app's saved offerings. - Customer Center details: retention offers are shown for App Store subscriptions only (a Google Play offer needs a replacement purchase, not built yet); a pending purchase shows
retention_pendingand is sent as not accepted; the screen reloads the server's view after an offer or a retry; the survey answer is sent in the background and not at all when the offer dialog is dismissed; the capitalised store name has its own keystore_app_store_title; a malformed support url sayserror_generic.Gemicore.openExternalUrltakes an optionalopener. - The default app version lookup no longer holds
configureand no longer checksFLUTTER_TEST; a provider passed toconfigureis still awaited, for up to three seconds. - Adds the
package_info_plusdependency.
0.2.0 #
- Offerings:
getOfferings()(cached in memory for five minutes and kept on the device for an offline start),currentOffering,OfferingandPackagemodels with store prices merged in, andpurchasePackage(package). - Paywalls: the
GemicorePaywallwidget draws the paywall designed in the dashboard (every node type, theme, strings by device locale, store price variables, text scale, semantics, right to left, https images, injectable link opener) andpresentPaywall(context)shows it full screen and returns aPaywallResult. Unknown or malformed nodes are left out and never throw. - Promotions:
getEligibleOffers(product)andpurchase(product, offer:)for App Store promotional and win-back offers and Google Play base plan offers. Server side introductory offer eligibility is available as the opt inuseServerIntroEligibility. - Refund reviews:
setConsumptionConsent(bool), with the answer kept inCustomerInfo.consumptionConsent. - Native pay: the
NativePaySheetinterface, thenativePaySheetparameter ofconfigureandpayWithSheet(product, email:); the sheet itself is in the gemicore_flutter_stripe package. - Breaking for custom store bridges:
StoreBridge.buytakes an optionaloffer, andStoreProductDetailshasofferId,subscriptionPeriodandtrialPeriod.basePlanIdis now set on Google Play offer entries too; the plain base plan is the entry with noofferId. - Adds the
intldependency, for the per month price on paywalls. - Verified identity: the optional
userTokenProviderofconfiguresendsx-user-tokenwhen a customer is linked to an app user id (configure(appUserId:)andlogIn). - Store updates are held until
configurehas the customer token, and a purchase the server could not take is retried on a timer, on resume and afterlogIn. - A failed
configurecloses the instance it started, so a retry does not run two store listeners. - A failing cache write (locked Keychain) no longer fails a recorded purchase or a customer refresh.
hasEntitlementno longer reports an entitlement active after its expiry, grace period aside.- A store that was unavailable once is asked again, and a failed availability check no longer sends a test key to the test store.
- Card and sheet polling: no stream emit or cache write for unchanged data, an optional
cancel:future, and a failed, expired or refunded payment throwsGemicoreErrorCode.paymentFailedinstead of returning a cancelled result. restorePurchases()called while a restore runs returns that restore.- Card sale declaration: the server refuses card checkout for a product whose card price was never declared as physical goods or a real world service (422
PURCHASE_NOT_FOR_CARD, reasoncard_sale_kind_missing).payWithCardandpayWithSheetthrowGemicoreErrorCode.cardSaleNotDeclaredfor it, with a message that says what to declare in the dashboard. A product with no card price at all still throwsnotForCard. NativePayRequest.merchantDisplayName(the app's name, from the card intent) for the payment sheet; empty from a server that does not send it.presentPaywallkeeps the paywall open and shows the message for a network error or a purchase already in progress; hero images are decoded at the drawn width.
0.1.0 #
- First release:
Gemicore.configure(apiKey:)as the only setup, anonymous customers with log in and log out, the dashboard product catalog with store prices, App Store and Google Play purchases recorded with Gemicore before the store transaction is finished, restore, one-time card, Apple Pay and Google Pay payments through the app's gateway, customer info with an offline cache and a change stream, and the Gemicore test store for test keys.