Skip to main content

PayCraft Quick Start — 15 Minutes to Billing

Get PayCraft running in your KMP app in 15 minutes using Claude AI.

Prerequisites​

  • KMP app with Koin DI
  • Supabase project (free tier works)
  • Stripe or Razorpay account
  • Claude Code with Stripe MCP (optional but recommended)

Single Command Setup​

Open Claude Code in the PayCraft repo and run:

/paycraft-adopt

Claude handles everything end-to-end:

  1. Creates .env from .env.example and collects all keys
  2. Applies Supabase migrations + deploys webhook + verifies
  3. Creates Stripe test products, prices, payment links via MCP
  4. Walks you through browser steps with exact instructions
  5. Wires PayCraft into your app directly
  6. Runs a live DB write test to confirm everything works

Every step is verified immediately. Test mode first. Live mode checklist at the end.

Claude will ask you (~12 questions):

  • Provider (stripe/razorpay)
  • Supabase project ref + credentials
  • Stripe test API key
  • Currency and plan prices
  • Which app to integrate billing into

You'll complete ~6 browser steps (Stripe Dashboard, Supabase Dashboard) with exact instructions.

3. Verify (automated in /paycraft-adopt)​

Verification runs automatically as the final phase of /paycraft-adopt. To re-run verification independently:

/paycraft-adopt-verify

Done! Your app has a verified billing system in test mode.


Option B: Manual Setup​

Step 1: Add Dependency​

# gradle/libs.versions.toml
[versions]
paycraft = "1.0.0"

[libraries]
paycraft = { module = "io.github.mobilebytelabs:cmp-paycraft", version.ref = "paycraft" }
// shared/build.gradle.kts
commonMain.dependencies {
implementation(libs.paycraft)
}

Step 2: Set Up Supabase​

Apply the migrations to your Supabase project:

# Apply manually via Supabase SQL editor, or:
./server/scripts/setup.sh \
--provider stripe \
--supabase-ref YOUR_REF \
--supabase-token YOUR_TOKEN

Stripe: Create payment links in Stripe Dashboard → Payment Links Razorpay: Create payment links in Razorpay Dashboard → Payment Links

Step 4: Configure PayCraft​

In your app initialization (before Koin):

PayCraft.configure {
supabase(
url = BuildConfig.SUPABASE_URL,
anonKey = BuildConfig.SUPABASE_ANON_KEY,
)
provider(
StripeProvider(
paymentLinks = mapOf(
"monthly" to "https://buy.stripe.com/YOUR_LINK",
"yearly" to "https://buy.stripe.com/YOUR_LINK",
),
customerPortalUrl = "https://billing.stripe.com/p/login/YOUR_ID",
)
)
plans(
BillingPlan(id = "monthly", name = "Monthly", price = "$9.99", interval = "/month", rank = 1),
BillingPlan(id = "yearly", name = "Yearly", price = "$79.99", interval = "/year", rank = 2, isPopular = true),
)
benefits(
BillingBenefit(icon = Icons.Default.Star, text = "Unlock all features"),
BillingBenefit(icon = Icons.Default.Block, text = "Ad-free experience"),
)
supportEmail("[email protected]")
}

Step 5: Add Koin Module​

startKoin {
modules(
yourModules,
PayCraftModule,
)
}

Step 6: Add UI to Settings​

@Composable
fun SettingsScreen() {
var showPaywall by remember { mutableStateOf(false) }
var showRestore by remember { mutableStateOf(false) }

// ... your other settings ...

PayCraftBanner(
onClick = { showPaywall = true },
onRestoreClick = { showRestore = true },
)

PayCraftSheet(visible = showPaywall, onDismiss = { showPaywall = false })
PayCraftRestore(visible = showRestore, onDismiss = { showRestore = false })
}

Step 7: Gate Premium Features​

val paycraft: PayCraftRepository = koinInject()
val entitlement by paycraft.entitlement.collectAsState()

if (entitlement.isPremium) { // true during a TRIAL too
PremiumContent()
} else {
FreeContent()
}

// Several paid tiers? The role is tenant-configured, so no product name is hardcoded:
if (entitlement.roleIdentifier == "guardian") { TopTierBadge() }

Gate on entitlement, not billingState: the summary holds the previous tier across Loading/Error/PaymentPending, so a settling payment never shows the paywall to someone who already paid. PayCraftRepository is the only data surface you inject — no app-authored wrapper (RULE-PAYCRAFT-SINGLE-SURFACE-001), and FakePayCraftRepository ships in the main artifact for tests.

Step 8: Set Up Webhook​

In Stripe Dashboard → Webhooks → Add endpoint:

  • URL: https://YOUR_SUPABASE_REF.supabase.co/functions/v1/stripe-webhook
  • Events: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.paid

Then set the signing secret:

supabase secrets set STRIPE_WEBHOOK_SECRET=whsec_... --project-ref YOUR_REF

What Happens at Runtime​

  1. User opens paywall → PayCraftPaywall shows plans
  2. User taps plan → PayCraft.checkout() opens payment URL in browser
  3. User pays → Provider sends webhook to Supabase Edge Function
  4. Edge Function upserts subscriptions table
  5. App calls is_premium(email) RPC → returns true
  6. PayCraftRepository.entitlement updates → UI unlocks premium features

Next Steps​