@piparotech/subkit-expo
v0.1.19
Published
SubKit Expo IAP SDK with automatic purchase sync.
Readme
@piparotech/subkit-expo
Expo / React Native SDK for SubKit offerings, purchases, restore/sync, CustomerInfo, and entitlement checks. SubKit is the access authority; expo-iap is only the native Store adapter.
Install
Install Expo from the public npm registry with its required Core peer and the optional storage adapters your app uses:
pnpm add @piparotech/subkit-core@^0.1.11 @piparotech/subkit-expo@^0.1.12Minimal setup
import { configureSubKit } from '@piparotech/subkit-expo'
configureSubKit({
sdkKey: 'sk_sdk_replace_me',
installationId: persistentInstallationId,
persistence: { storage: appJsonStorage, keyPrefix: 'my-app.subkit.v1' },
appUserId: currentUserId,
})Mobile apps use only a public app-bound sk_sdk_… key. Keep the installation ID persistent, render package identifiers and native prices from Runtime Offerings, and unlock only from SubKit's Effective Access decision. A pending purchase never grants access.
const access = await client.getAccess('pro')
if (access.state === 'granted') unlockPaidFeatures()React apps use useSubKitAccess('pro') for recovery/status UI or the fail-closed useSubKitHasAccess('pro') Boolean. Do not combine raw entitlement and device fields in application code.
Public adapters are available at:
@piparotech/subkit-expo/expo-iap@piparotech/subkit-expo/expo-secure-store@piparotech/subkit-expo/mmkv@piparotech/subkit-expo/async-storage
Purchase and restore recovery
A durable reconcile job that is still running returns null from restore/sync, not a failed verification or an empty restore. The last known CustomerInfo and identity remain unchanged. Resume with syncPurchases({ force: true, reason: 'queue_retry' }); fetching CustomerInfo alone does not drain the receipt queue.
After the native Store returns a purchase, later transport or verification exceptions return pending. Do not offer another purchase. A terminal verification failure carries error.metadata.purchaseMayHaveCompleted: true; this means the Store purchase needs recovery or support, not that no charge occurred. Ownership conflicts include the server's resolution in error metadata. Neither terminal failures nor pending results grant access.
Documentation
- Expo overview
- Installation
- Configuration and persistence
- Purchases
- Effective access and offline behavior
- Migration from manual access checks
- Troubleshooting
For custom IAP adapters, optional Google trial fallback requires
SubKitIapSubscriptionOffer.isBasePlan: true from provider evidence, an exact
basePlanId, and an offer token. The built-in adapter reads Google's absent
promotional offerId for the matching token. Missing evidence fails closed;
never infer a regular base plan from a display identifier alone.
