Stripe live mode — real cards will be charged.
← Back to Sea-Esta
GatewayStripe live · PayPal staged

Payment Flow Launchpad

Flows built here can run locally (Stripe) or be exported to the NoblePort Payment Gateway (Stripe + PayPal) that serves all NoblePort dapps. Direct mode uses this app's own live Stripe integration; Gateway mode produces a deployment package — a JSON flow definition plus a client snippet that calls POST https://gateway.nobleport.app/v1/checkout.

Where this flow runs

Gateway target

Gateway mode: nothing executes here. The builder emits a deployment package for the central NoblePort Payment Gateway.

Stripe / PayPal / Both

Processor

Stripe · LivePayPal · Staged

Staged — connect PayPal credentials in the NoblePort Payment Gateway. PayPal is generated as exportable configuration only — order create + capture for one-time payments, a billing plan for subscriptions, and a partial capture with balance due for deposits. No PayPal transaction is executed by this app.

Definition

Flow configuration

Flow type
Additional currencies

Each currency exports its own amount. Stripe gets currency_options; PayPal gets one order/plan per currency. Leave an amount blank to reuse the base amount.

Export to NoblePort

Deployment package

Charge now
499.00 USD · 459.00 EUR
Type
Subscription
Processor
Both
Warnings
  • additionalCurrencies PayPal cannot mix currencies in one plan — the export generates one per currency.

Copy or download the JSON definition and the client snippet below, then deploy them to the NoblePort Payment Gateway. The gateway holds the Stripe and PayPal credentials for every NoblePort dapp.

nobleport.payment_flow

Flow definition (JSON)

schema v1.3.0builder v1.3.0templates v1.1.0released 2026-08-01
Schema changelog (embedded in every export)
  • v1.3.0 · 2026-08-01
    • Added `schema` block with schema/builder versions, changelog and template provenance.
  • v1.2.0 · 2026-07-01
    • Added multi-currency `pricing[]` with per-currency minor units and PayPal support flags.
    • Stripe exports use `currency_options`; PayPal exports one order/plan per currency.
  • v1.1.0 · 2026-06-01
    • Added `webhooks` configuration block and signed handler snippet generation.
  • v1.0.0 · 2026-05-01
    • Initial payment_flow document: one-time, subscription and deposit flows.
{
  "version": "1.0",
  "kind": "nobleport.payment_flow",
  "id": "flow_sea_esta_host_membership",
  "name": "Host Membership",
  "type": "subscription",
  "processor": "both",
  "target": "gateway",
  "amount": {
    "value": 499,
    "minor_units": 49900,
    "currency": "USD"
  },
  "charge_now": {
    "value": 499,
    "minor_units": 49900,
    "currency": "USD"
  },
  "currencies": [
    "USD",
    "EUR"
  ],
  "pricing": [
    {
      "currency": "USD",
      "decimals": 2,
      "amount": {
        "value": 499,
        "minor_units": 49900,
        "display": "499.00 USD"
      },
      "charge_now": {
        "value": 499,
        "minor_units": 49900,
        "display": "499.00 USD"
      },
      "paypal_supported": true
    },
    {
      "currency": "EUR",
      "decimals": 2,
      "amount": {
        "value": 459,
        "minor_units": 45900,
        "display": "459.00 EUR"
      },
      "charge_now": {
        "value": 459,
        "minor_units": 45900,
        "display": "459.00 EUR"
      },
      "paypal_supported": true
    }
  ],
  "schedule": {
    "interval": "year",
    "interval_count": 1
  },
  "urls": {
    "success_url": "https://seaesta.lovable.app/checkout/return",
    "cancel_url": "https://seaesta.lovable.app/"
  },
  "metadata": {
    "product": "host_membership",
    "dapp": "Sea-Esta",
    "platform": "NoblePort",
    "currencies": "USD,EUR"
  },
  "processors": {
    "stripe": {
      "mode": "subscription",
      "ui_mode": "embedded_page",
      "currency": "usd",
      "currencies": [
        "USD",
        "EUR"
      ],
      "line_items": [
        {
          "quantity": 1,
          "price_data": {
            "currency": "usd",
            "unit_amount": 49900,
            "product_data": {
              "name": "Host Membership"
            },
            "recurring": {
              "interval": "year"
            },
            "currency_options": {
              "eur": {
                "unit_amount": 45900
              }
            }
          }
        }
      ],
      "return_url": "https://seaesta.lovable.app/checkout/return",
      "cancel_url": "https://seaesta.lovable.app/",
      "metadata": {
        "product": "host_membership",
        "dapp": "Sea-Esta",
        "platform": "NoblePort",
        "flow_type": "subscription",
        "currencies": "USD,EUR"
      },
      "execution": "live"
    },
    "paypal": {
      "intent": "SUBSCRIPTION",
      "execution": "staged",
      "execution_note": "Staged — connect PayPal credentials in the NoblePort Payment Gateway",
      "currencies": [
        "USD",
        "EUR"
      ],
      "plan": {
        "product_id": "PROD-HOST_MEMBERSHIP",
        "name": "Host Membership (USD)",
        "status": "ACTIVE",
        "billing_cycles": [
          {
            "frequency": {
              "interval_unit": "YEAR",
              "interval_count": 1
            },
            "tenure_type": "REGULAR",
            "sequence": 1,
            "total_cycles": 0,
            "pricing_scheme": {
              "fixed_price": {
                "value": "499.00",
                "currency_code": "USD"
              }
            }
          }
        ],
        "payment_preferences": {
          "auto_bill_outstanding": true,
          "setup_fee_failure_action": "CANCEL",
          "payment_failure_threshold": 2
        }
      },
      "by_currency": {
        "USD": {
          "product_id": "PROD-HOST_MEMBERSHIP",
          "name": "Host Membership (USD)",
          "status": "ACTIVE",
          "billing_cycles": [
            {
              "frequency": {
                "interval_unit": "YEAR",
                "interval_count": 1
              },
              "tenure_type": "REGULAR",
              "sequence": 1,
              "total_cycles": 0,
              "pricing_scheme": {
                "fixed_price": {
                  "value": "499.00",
                  "currency_code": "USD"
                }
              }
            }
          ],
          "payment_preferences": {
            "auto_bill_outstanding": true,
            "setup_fee_failure_action": "CANCEL",
            "payment_failure_threshold": 2
          }
        },
        "EUR": {
          "product_id": "PROD-HOST_MEMBERSHIP",
          "name": "Host Membership (EUR)",
          "status": "ACTIVE",
          "billing_cycles": [
            {
              "frequency": {
                "interval_unit": "YEAR",
                "interval_count": 1
              },
              "tenure_type": "REGULAR",
              "sequence": 1,
              "total_cycles": 0,
              "pricing_scheme": {
                "fixed_price": {
                  "value": "459.00",
                  "currency_code": "EUR"
                }
              }
            }
          ],
          "payment_preferences": {
            "auto_bill_outstanding": true,
            "setup_fee_failure_action": "CANCEL",
            "payment_failure_threshold": 2
          }
        }
      },
      "application_context": {
        "brand_name": "Sea-Esta",
        "user_action": "SUBSCRIBE_NOW",
        "return_url": "https://seaesta.lovable.app/checkout/return",
        "cancel_url": "https://seaesta.lovable.app/"
      }
    }
  },
  "webhooks": {
    "endpoint": "https://seaesta.lovable.app/api/public/gateway/events",
    "events": [
      "checkout.completed",
      "checkout.failed",
      "checkout.canceled",
      "subscription.activated",
      "subscription.renewed",
      "subscription.canceled",
      "payment.refunded"
    ],
    "signature": {
      "algorithm": "hmac-sha256",
      "header": "x-nobleport-signature",
      "timestamp_header": "x-nobleport-timestamp",
      "signed_payload": "{timestamp}.{raw_body}",
      "tolerance_seconds": 300,
      "secret_name": "NOBLEPORT_GATEWAY_WEBHOOK_SECRET"
    },
    "retry": {
      "max_attempts": 5,
      "backoff": "exponential"
    },
    "idempotency": {
      "key": "event_id",
      "scope": "flow"
    },
    "handling": "ui_status_only",
    "note": "Staged — the gateway endpoint only records events and updates flow UI status. It never touches Stripe billing state, which stays owned by the existing Stripe webhook."
  },
  "generated_at": "2026-08-03T16:43:02.793Z",
  "schema": {
    "schema_version": "1.3.0",
    "builder_version": "1.3.0",
    "kind_version": "1.0",
    "released_at": "2026-08-01",
    "source": "gateway_launchpad",
    "changelog": [
      {
        "version": "1.3.0",
        "date": "2026-08-01",
        "changes": [
          "Added `schema` block with schema/builder versions, changelog and template provenance."
        ]
      },
      {
        "version": "1.2.0",
        "date": "2026-07-01",
        "changes": [
          "Added multi-currency `pricing[]` with per-currency minor units and PayPal support flags.",
          "Stripe exports use `currency_options`; PayPal exports one order/plan per currency."
        ]
      },
      {
        "version": "1.1.0",
        "date": "2026-06-01",
        "changes": [
          "Added `webhooks` configuration block and signed handler snippet generation."
        ]
      },
      {
        "version": "1.0.0",
        "date": "2026-05-01",
        "changes": [
          "Initial payment_flow document: one-time, subscription and deposit flows."
        ]
      }
    ]
  }
}
POST /v1/checkout

Gateway API snippet

// Sea-Esta → NoblePort Payment Gateway
// POST https://gateway.nobleport.app/v1/checkout with your app API key.
// Flow: flow_sea_esta_host_membership (Subscription, Both)
// Currencies: USD, EUR
// Schema 1.3.0 · builder 1.3.0 · generated 2026-08-03T16:43:02.793Z


const GATEWAY_URL = "https://gateway.nobleport.app/v1/checkout";
const APP_API_KEY = process.env.NOBLEPORT_APP_API_KEY!; // server-side only

// Charge-now amounts in minor units, per presentment currency.
export const PRICES = {
  USD: { amount: 49900, currency: "USD" },
  EUR: { amount: 45900, currency: "EUR" },
} as const;

export type FlowCurrency = keyof typeof PRICES;
export const DEFAULT_CURRENCY: FlowCurrency = "USD";

export async function startCheckout(
  opts: { customerEmail?: string; processor?: "stripe" | "paypal"; currency?: FlowCurrency } = {},
) {
  const price = PRICES[opts.currency ?? DEFAULT_CURRENCY];
  if (!price) throw new Error(`Unsupported currency: ${opts.currency}`);

  const res = await fetch(GATEWAY_URL, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${APP_API_KEY}`,
      "X-NoblePort-Dapp": "Sea-Esta",
    },
    body: JSON.stringify({
      flow_id: "flow_sea_esta_host_membership",
      processor: opts.processor ?? "stripe",
      amount: price.amount,        // minor units for the selected currency
      currency: price.currency,
      type: "subscription",
      schedule: { interval: "year", interval_count: 1 },
      success_url: "https://seaesta.lovable.app/checkout/return",
      cancel_url: "https://seaesta.lovable.app/",
      customer_email: opts.customerEmail,
      metadata: {"product":"host_membership","dapp":"Sea-Esta","platform":"NoblePort","currencies":"USD,EUR"},
    }),
  });


  if (!res.ok) throw new Error(`Gateway error ${res.status}: ${await res.text()}`);

  // { checkout_url, client_secret?, session_id, processor }
  return res.json();
}

// NOTE: PayPal leg is "Staged — connect PayPal credentials in the NoblePort Payment Gateway".
// The gateway executes it once PayPal credentials are connected there.
18 ready-made flows

Example templates

One worked example for every flow type × processor × mode combination. Download the JSON definition or the client snippet, or load a template into the builder above to tweak it. PayPal blocks stay staged configuration until credentials are connected in the gateway.

One-time payment · Stripe · Direct
Single 250 USD charge, executed by this app.
One-time payment · Stripe · Gateway
Single 250 USD charge, handed to the central NoblePort gateway.
One-time payment · PayPal · DirectNot runnable
PayPal cannot execute in Direct mode — switch the target to Gateway.
One-time payment · PayPal · Gateway
Single 250 USD charge, handed to the central NoblePort gateway. PayPal is exported as staged configuration only.
One-time payment · Both · Direct
Single 250 USD charge, executed by this app. PayPal is exported as staged configuration only.
One-time payment · Both · Gateway
Single 250 USD charge, handed to the central NoblePort gateway. PayPal is exported as staged configuration only.
Subscription · Stripe · Direct
Recurring 499 USD per year, executed by this app.
Subscription · Stripe · Gateway
Recurring 499 USD per year, handed to the central NoblePort gateway.
Subscription · PayPal · DirectNot runnable
PayPal cannot execute in Direct mode — switch the target to Gateway.
Subscription · PayPal · Gateway
Recurring 499 USD per year, handed to the central NoblePort gateway. PayPal is exported as staged configuration only.
Subscription · Both · Direct
Recurring 499 USD per year, executed by this app. PayPal is exported as staged configuration only.
Subscription · Both · Gateway
Recurring 499 USD per year, handed to the central NoblePort gateway. PayPal is exported as staged configuration only.
Deposit (partial payment) · Stripe · Direct
25% deposit of 4800 USD now, balance later, executed by this app.
Deposit (partial payment) · Stripe · Gateway
25% deposit of 4800 USD now, balance later, handed to the central NoblePort gateway.
Deposit (partial payment) · PayPal · DirectNot runnable
PayPal cannot execute in Direct mode — switch the target to Gateway.
Deposit (partial payment) · PayPal · Gateway
25% deposit of 4800 USD now, balance later, handed to the central NoblePort gateway. PayPal is exported as staged configuration only.
Deposit (partial payment) · Both · Direct
25% deposit of 4800 USD now, balance later, executed by this app. PayPal is exported as staged configuration only.
Deposit (partial payment) · Both · Gateway
25% deposit of 4800 USD now, balance later, handed to the central NoblePort gateway. PayPal is exported as staged configuration only.
/api/public/gateway/events

Webhook configuration

Staged — the gateway endpoint only records events and updates flow UI status. It never touches Stripe billing state, which stays owned by the existing Stripe webhook.

POST https://seaesta.lovable.app/api/public/gateway/events
checkout.completedcheckout.failedcheckout.canceledsubscription.activatedsubscription.renewedsubscription.canceledpayment.refunded
  1. Register the endpoint in the NoblePort Gateway
    In the gateway dashboard for “Sea-Esta”, add a webhook destination pointing at https://seaesta.lovable.app/api/public/gateway/events (POST, JSON).
  2. Subscribe to this flow's events
    checkout.completed, checkout.failed, checkout.canceled, subscription.activated, subscription.renewed, subscription.canceled, payment.refunded
  3. Generate a signing secret and store it as NOBLEPORT_GATEWAY_WEBHOOK_SECRET
    The gateway signs HMAC-SHA256 over "{timestamp}.{raw_body}" and sends it in x-nobleport-signature, with the unix timestamp in x-nobleport-timestamp. Add the same secret to this project's backend secrets.
  4. Scope the handler to UI status only
    The bundled handler verifies the signature, de-duplicates by event_id and records status for the UI. Stripe billing state stays owned by the existing Stripe webhook at /api/public/payments/webhook — do not write membership entitlements from gateway events.
  5. Send a test event and confirm a 200
    Use the gateway's “Send test event” action with checkout.completed. A 401 means the secret differs; a 400 means the timestamp is outside the 5-minute tolerance.
// Sea-Esta → NoblePort Gateway webhook receiver (PLACEHOLDER)
// Route: POST /api/public/gateway/events   Flow: flow_sea_esta_host_membership
//
// Staged — the gateway endpoint only records events and updates flow UI status. It never touches Stripe billing state, which stays owned by the existing Stripe webhook.
import { createFileRoute } from "@tanstack/react-router";
import { createHmac, timingSafeEqual } from "node:crypto";

const TOLERANCE_SECONDS = 300;
const HANDLED_EVENTS = [
  "checkout.completed",
  "checkout.failed",
  "checkout.canceled",
  "subscription.activated",
  "subscription.renewed",
  "subscription.canceled",
  "payment.refunded"
] as const;

function verify(raw: string, timestamp: string, signature: string, secret: string) {
  const age = Math.abs(Date.now() / 1000 - Number(timestamp));
  if (!Number.isFinite(age) || age > TOLERANCE_SECONDS) return false;
  const expected = createHmac("sha256", secret).update(`${timestamp}.${raw}`).digest("hex");
  const a = Buffer.from(signature);
  const b = Buffer.from(expected);
  return a.length === b.length && timingSafeEqual(a, b);
}

export const Route = createFileRoute("/api/public/gateway/events")({
  server: {
    handlers: {
      POST: async ({ request }) => {
        const secret = process.env["NOBLEPORT_GATEWAY_WEBHOOK_SECRET"];
        if (!secret) return Response.json({ received: true, staged: true });

        const raw = await request.text();
        const signature = request.headers.get("x-nobleport-signature") ?? "";
        const timestamp = request.headers.get("x-nobleport-timestamp") ?? "";
        if (!verify(raw, timestamp, signature, secret)) {
          return new Response("Invalid signature", { status: 401 });
        }

        const event = JSON.parse(raw) as { id: string; type: string; data?: unknown };
        if (!HANDLED_EVENTS.includes(event.type as never)) {
          return Response.json({ received: true, ignored: event.type });
        }

        // TODO: persist UI status for event.id (idempotent upsert on event_id).
        // Do NOT grant entitlements here — Stripe billing state is owned by
        // the existing Stripe webhook.
        console.log("[nobleport] gateway event", event.id, event.type);

        return Response.json({ received: true });
      },
    },
  },
});

How the Launchpad and the Gateway relate

This app remains the live Stripe implementation for Sea-Esta memberships. The Launchpad is the flow-builder companion to the central NoblePort Payment Gateway: you design a flow once, run it locally on Stripe, or ship it to the gateway where Stripe and PayPal credentials live and where every NoblePort dapp calls the same REST API with its own app key.