Skip to main content
What it does: Before the paid Stripe period ends, your customer completes card entry and any required 3DS challenge on Waffo. Waffo collects nothing early, starts the first charge automatically at handoff, exposes the waiting state through inquiry, and lets you cancel before handoff to prevent that charge. Integration takes three steps: switch to WaffoStripe.client(...), add the routing marker and handoff time to the target subscription, and connect the Waffo Webhook. Your existing com.stripe.* types and calling pattern stay in place. Quick start shows the complete code change; before production, also persist the idempotency key and subscription mapping described in the integration guide.
The migration tool is available for Java today: com.waffo:waffo-java-stripe. Node.js, Python, and Go versions are coming soon.

This is not the native Waffo SDK

Waffo offers two entirely different integration paths. Confirm which one fits you before going further. For a new integration, use the native SDK. The adapter earns its place in exactly one situation: you already run subscriptions on Stripe and the cost of changing that code is your main concern.

What the migration tool does for you

Routing

Decides per request whether it goes to Waffo or straight to Stripe, so your calling code needs no branching.

Parameter translation

Turns Stripe’s SessionCreateParams into a Waffo subscription request — amount, period, currency, payment method, cashier language.

Response mapping

Packs Waffo’s response back into Stripe Session and Subscription objects, so your usual getters keep working.

Notification translation

Translates Waffo subscription notifications into Stripe Events, so your existing Webhook branches still apply.

How it works

The adapter hands you a standard StripeClient. It inspects each request and applies three rules: In other words, untagged calls are completely unaffected — one-time payments, untagged subscriptions, customer objects, price objects all behave exactly as they did before. You can move a subset of subscriptions to Waffo and run both sides in parallel. A complete subscription payment flows like this:
1

Create the subscription Checkout

You call client.checkout().sessions().create(params) as usual; params just carries one more line, metadata.source=waffo. The adapter translates it into a Waffo subscription request.
2

Receive the cashier URL

You still get a Stripe Session object, and session.getUrl() holds the Waffo cashier URL. Your redirect code needs no change — it never cared where that URL pointed.
3

The customer pays

The customer completes payment on the Waffo cashier. Your application is not involved in this leg.
4

Receive and translate the notification

Waffo posts the subscription notification to your configured notifyUrl. Your endpoint calls WaffoStripeWebhooks.handle(...) and gets a WaffoStripeWebhookResult; call result.getEvent() to obtain the standard Stripe Event.
5

Existing business logic runs

Your existing switch (event.getType()) handling for customer.subscription.created and invoice.paid needs no change; it receives the translated event directly.

What is supported

The first phase targets hosted-cashier subscriptions. Use the table below to judge whether your current setup fits. For the complete fallback conditions, reason codes, and cancellation boundaries, see unsupported Stripe usage in the integration guide.

Move expiring Stripe subscriptions to Waffo

Suppose the current paid period of a Stripe subscription ends at time T. Use your existing Stripe flow to stop renewal at T, then create a Waffo subscription for the same customer that starts at T:
1

Read the handoff time

Read the paid-through period end T from the Stripe subscription.
2

Set the Waffo start time

Set subscription_data.billing_cycle_anchor to T on the Waffo-routed request and set proration_behavior=none.
3

Authorize in advance

Before T, the customer opens the Waffo cashier and completes card entry and any required 3DS challenge. No first charge is collected yet.
4

Confirm the waiting state

While waiting, retrieve the wsub_… subscription. Both billing_cycle_anchor and current_period_end equal T; metadata.waffo_current_period=0 means period 1 has not started.
5

Charge automatically at handoff

At T, Waffo initiates the first charge automatically. The customer does not need to return.
If the customer cancels the migration before T, Subscription.cancel("wsub_…") immediately cancels the Waffo subscription and prevents the scheduled first charge.
The Stripe migration tool manages the Waffo-side application, inquiry, and cancellation. It does not modify the original Stripe subscription. Use your existing Stripe code or dashboard to end the old subscription at the same T.

Quick start

The following three steps show the key code changes. In addition to those changes, persist the idempotency key before sending the request and store the relationship between the Waffo subscription id and your business order after creation. These are partial snippets for an existing class and assume your project’s surrounding imports, injected fields, and business methods.

Step 1 — Swap the client constructor

The client you get back is a standard StripeClient. Drop it in where your old one was; every call site stays untouched.

Step 2 — Add the routing tag and idempotency key

The example intentionally omits uiMode. Stripe defaults to a hosted Checkout, and the migration tool also treats an omitted value as hosted. This keeps the code compatible with stripe-java 24.11.x, 32.x, and 33.x. Do not substitute HOSTED_PAGE on 32.x or 33.x: its serialized hosted_page value is classified as a non-hosted Checkout. Do not rely on an idempotency key generated automatically by stripe-java. Explicitly pass and persist a stable key of at most 32 characters, and reuse it on every retry. See the integration guide for the full rules.

Step 3 — Integrate the Waffo Webhook

Your application still needs a new HTTP endpoint, while your existing Stripe Webhook endpoint stays unchanged. The SDK’s handle(...) method already verifies and parses the notification, translates its event, and generates the acknowledgment response. Your endpoint only passes the translated result to your business code and maps the SDK-generated acknowledgment into your Web framework’s response.
WaffoStripeWebhookResult already contains the acknowledgment body. The final lines only map it into Spring’s ResponseEntity; use the equivalent mapping for another Web framework. See the integration guide.

Integration guide

The full configuration reference, Webhook handling details, the complete unsupported-usage table, the integration checklist, and Sandbox verification requirements.

Migrate automatically with the AI skill

If you work in Claude Code, Codex, or Cursor, you can let the assistant handle the scan and the rewrite:
After installing, open your project and tell the assistant “migrate from Stripe”. It scans every Stripe call in your project, flags what cannot be routed, writes the changes once you approve them, and walks you through Sandbox acceptance.
Scan results only surface risk; they are not an acceptance conclusion. Whichever path you take, the integration is complete only after the full Sandbox flow passes through your own project’s endpoints. See Sandbox verification.

Version and prerequisites

stripe-java is a provided dependency, meaning the adapter will not upgrade or downgrade it for you—the version already in your project stays put. Make sure it is version 24.11.0 or later. Before integrating, also confirm:
  • You have a subscription agreement with Waffo and hold Sandbox credentials
  • The currencies you plan to route are within your contract; verify with paymethodconfig/inquiry
  • You have a publicly reachable HTTPS endpoint for Waffo notifications