Concepts, value, and typical clone scenarios — less code.
Concepts, value, and typical clone scenarios — less code.
Preparing Ring content
Preparing Ring content
Preparing Ring content
Status: PaymentConductor is the live money SSOT for store, membership one-shots, news promotion, wallet credit top-up, confidential native onramp, and public-pool (DAO jar) card/PayPal chip-ins. Recurring membership PayPal uses SubscriptionConductor (Subscriptions v1) — not a separate cart API. Use Founder / Developer tabs in the docs sidebar to filter this page.
Ring routes buyer rails (card | paypal | credit_balance | native_token) through PaymentConductor (lib/payments/conductor/). The card rail settles via WayForPay or Stripe (payment.cardPaymentProcessor / purpose env) — UI never picks a PSP id. Browser handoff is Conductor CheckoutRedirect (navigate | form_post) via followCheckoutResult. Rates and presentment come from Ring Oracle.
| Previous / common assumption | Ring equivalent |
|---|---|
| Brand-named checkout buttons (WayForPay / Stripe) in UI | Rail card → Conductor resolves processor |
Generic /api/cart/* checkout REST | No cart payment REST — store UI uses Server Action placeAndPayStoreOrder → PaymentConductor.createCheckout |
| Optional REST by rail | POST /api/store/payments/{card|wayforpay|stripe|credit|token|paypal} (same Conductor SSOT) |
| Hosted PSP “Donate” products for jars | Purpose public_pool_contribution + desk oracle — see Public Pools |
| Recurring membership on PaymentConductor Orders only | One-shot Orders here; Subscriptions v1 on SubscriptionConductor |
| Rail | Typical processor | Store entry | Gateway fee (config) | Notes |
|---|---|---|---|---|
card | WayForPay or Stripe | Action + POST …/card (alias) / …/wayforpay / …/stripe | WFP ~2.5% · Stripe ~2.9% + fixed | Primary Ukraine = WayForPay HPP (form_post) |
paypal | PayPal Orders v2 | Action + POST …/paypal | ~2.9% + fixed when enabled | Needs NEXT_PUBLIC_PAYMENT_STORE_ALLOW_PAYPAL=true + gateways.paypal.enabled + PAYPAL_* |
credit_balance | Internal | Action + POST …/credit | 0% | Fiat credit ledger; gated by PAYMENT_STORE_ALLOW_CREDIT / gateway |
Canonical PSP webhooks (settlement): POST /api/payments/{wayforpay,stripe,paypal}/webhook. Money truth for WayForPay: serviceUrl Approved settles — browser returnUrl is UX only.
| Purpose | Buyer outcome | Typical rails / PSP |
|---|---|---|
store_order | Cart → paid order | card / credit / native_token / paypal |
membership_upgrade | Role upgrade one-shot | card / native / paypal (recurring → SubscriptionConductor) |
news_promotion | Sponsored news | card (WFP / Stripe) |
wallet_topup | Fiat credit points | card (PAYMENT_WALLET_TOPUP_PROCESSOR) or paypal |
native_token_onramp | Card/PayPal → treasury native | Confidential+ when CONFIDENTIAL_TOKEN_ONRAMP=true |
public_pool_contribution | DAO jar chip-in |
Extended purposes (project_order, task_escrow, collective_order_slot, scheduled_service_slot) share the same Conductor — details on PaymentConductor.
Membership native pay is membership_upgrade + native_token through PaymentConductor (soft launch: treasury SPL + ledger; deployed: on-chain RingMembership), then SubscriptionConductor ledger-only via metadata.tx_hash — see SubscriptionConductor. Its gate is payment.supportedMethods (isPaymentMethodEnabled('native_token')), not PAYMENT_STORE_ALLOW_TOKEN.
Idempotency: native pay (store + membership) follows the shared contract — one client idempotencyKey per intent; paid rows replay (same txHash), in-flight rows return 409 IDEMPOTENCY_IN_FLIGHT.
Native refunds: POST /api/admin/payments/[orderReference]/refund (platform admin or owning vendor; full-amount, idempotent, marks payment_transactions refunded).
WayForPay hosted Донати, Stripe submit_type=donate, and PayPal Donate SDK are not Ring jar SSOT. Use Public Pools.
Skill / desk: Cursor + Ring docs cluster — start from operator checklist Payment Gateway Integration, then deep-dive PaymentConductor.
Starter prompt (does not mutate until you approve env/config changes):
Configure this clone’s PaymentConductor: set
PAYMENT_DEFAULT_PROCESSOR, WayForPay or Stripe credentials fromenv.local.template, enable store rails (card+ optional credit/token/PayPal flags), registerhttps://YOUR_HOST/api/payments/{processor}/webhook, and verify store checkout usesplaceAndPayStoreOrder+CheckoutRedirect— no/api/cartpayment routes.
Inputs checklist: clone host · ring-config.json payment.* · PSP cabinet credentials · webhook URL reachable from the internet · data/migrations/004_payment_transactions.sql applied.
Set payment.cardPaymentProcessor (wayforpay or stripe) and payment.gateways.*.enabled in ring-config.json. Optional per-purpose env: PAYMENT_STORE_PROCESSOR, PAYMENT_MEMBERSHIP_PROCESSOR, PAYMENT_NEWS_PROCESSOR, PAYMENT_WALLET_TOPUP_PROCESSOR, PAYMENT_PUBLIC_POOL_CONTRIBUTION_PROCESSOR, PAYMENT_NATIVE_TOKEN_ONRAMP_PROCESSOR.
Copy WayForPay / Stripe / PayPal keys from env.local.template (also docker.env.template). WayForPay SSOT: WAYFORPAY_MERCHANT_ACCOUNT, WAYFORPAY_SECRET_KEY, WAYFORPAY_MERCHANT_PASSWORD, WAYFORPAY_DOMAIN, WAYFORPAY_API_URL — no WAYFORPAY_MERCHANT_ID.
PAYMENT_STORE_ALLOW_CREDIT / NEXT_PUBLIC_PAYMENT_STORE_ALLOW_CREDIT from disabling credit.PAYMENT_STORE_ALLOW_TOKEN=true and NEXT_PUBLIC_PAYMENT_STORE_ALLOW_TOKEN=true.NEXT_PUBLIC_PAYMENT_STORE_ALLOW_PAYPAL=true, gateways.paypal.enabled: true, plus PAYPAL_CLIENT_ID / PAYPAL_CLIENT_SECRET / PAYPAL_WEBHOOK_ID / PAYPAL_MODE.Register cabinet callbacks to /api/payments/wayforpay/webhook (and Stripe/PayPal twins). Apply 004_payment_transactions.sql before production traffic.
Place a store order (card rail). Expect CheckoutRedirect — WayForPay HPP via POST form, not a GET query URL. Confirm settlement only after webhook Approved / capture — not on return URL alone.
payment_transactions covers store, membership one-shots, news, wallet top-up, and DAO jar chip-ins.
WayForPay HPP keeps PCI scope at the PSP; Stripe for international clones.
Card top-up adds fiat credit points — not on-chain RING. Desk / onramp are separate paths.
PayPal Subscriptions v1 + manage page at .
No. Store checkout places the order and pays through PaymentConductor (Server Action or the store payment routes above). There is no fabricated cart checkout REST API.
No. PayPal is its own rail. Card still resolves to WayForPay or Stripe independently.
Switch copy and components to rails (card / paypal / credit_balance / native_token). Keep processor selection in config/env. See PaymentConductor.
Use SubscriptionConductor (PayPal Subscriptions v1, Stripe Subscriptions, WayForPay regularApi, credit, native, NFT gate). PaymentConductor still owns one-shot membership upgrades and store Orders.
For WayForPay, settlement is serviceUrl webhook Approved — not returnUrl. Check cabinet webhook URL, HMAC secrets, and dispatcher logs.
User detail Payments tab → GET /api/admin/users/[id]/payments (membership / wallet top-up and other ledger rows).
Deep-dive: purposes, rails vs processors, handlers, and module paths.
Depends-on: WayForPay HPP env SSOT, HMAC, and returnUrl vs serviceUrl money truth.
Same-workflow: wallet_topup credit points vs desk/onramp native paths.
Next-step: recurring membership SubscriptionConductor (PayPal Subscriptions v1).
Status: PaymentConductor is the live money SSOT for store, membership one-shots, news promotion, wallet credit top-up, confidential native onramp, and public-pool (DAO jar) card/PayPal chip-ins. Recurring membership PayPal uses SubscriptionConductor (Subscriptions v1) — not a separate cart API. Use Founder / Developer tabs in the docs sidebar to filter this page.
Ring routes buyer rails (card | paypal | credit_balance | native_token) through PaymentConductor (lib/payments/conductor/). The card rail settles via WayForPay or Stripe (payment.cardPaymentProcessor / purpose env) — UI never picks a PSP id. Browser handoff is Conductor CheckoutRedirect (navigate | form_post) via followCheckoutResult. Rates and presentment come from Ring Oracle.
| Previous / common assumption | Ring equivalent |
|---|---|
| Brand-named checkout buttons (WayForPay / Stripe) in UI | Rail card → Conductor resolves processor |
Generic /api/cart/* checkout REST | No cart payment REST — store UI uses Server Action placeAndPayStoreOrder → PaymentConductor.createCheckout |
| Optional REST by rail | POST /api/store/payments/{card|wayforpay|stripe|credit|token|paypal} (same Conductor SSOT) |
| Hosted PSP “Donate” products for jars | Purpose public_pool_contribution + desk oracle — see Public Pools |
| Recurring membership on PaymentConductor Orders only | One-shot Orders here; Subscriptions v1 on SubscriptionConductor |
| Rail | Typical processor | Store entry | Gateway fee (config) | Notes |
|---|---|---|---|---|
card | WayForPay or Stripe | Action + POST …/card (alias) / …/wayforpay / …/stripe | WFP ~2.5% · Stripe ~2.9% + fixed | Primary Ukraine = WayForPay HPP (form_post) |
paypal | PayPal Orders v2 | Action + POST …/paypal | ~2.9% + fixed when enabled | Needs NEXT_PUBLIC_PAYMENT_STORE_ALLOW_PAYPAL=true + gateways.paypal.enabled + PAYPAL_* |
credit_balance | Internal | Action + POST …/credit | 0% | Fiat credit ledger; gated by PAYMENT_STORE_ALLOW_CREDIT / gateway |
Canonical PSP webhooks (settlement): POST /api/payments/{wayforpay,stripe,paypal}/webhook. Money truth for WayForPay: serviceUrl Approved settles — browser returnUrl is UX only.
| Purpose | Buyer outcome | Typical rails / PSP |
|---|---|---|
store_order | Cart → paid order | card / credit / native_token / paypal |
membership_upgrade | Role upgrade one-shot | card / native / paypal (recurring → SubscriptionConductor) |
news_promotion | Sponsored news | card (WFP / Stripe) |
wallet_topup | Fiat credit points | card (PAYMENT_WALLET_TOPUP_PROCESSOR) or paypal |
native_token_onramp | Card/PayPal → treasury native | Confidential+ when CONFIDENTIAL_TOKEN_ONRAMP=true |
public_pool_contribution | DAO jar chip-in |
Extended purposes (project_order, task_escrow, collective_order_slot, scheduled_service_slot) share the same Conductor — details on PaymentConductor.
Membership native pay is membership_upgrade + native_token through PaymentConductor (soft launch: treasury SPL + ledger; deployed: on-chain RingMembership), then SubscriptionConductor ledger-only via metadata.tx_hash — see SubscriptionConductor. Its gate is payment.supportedMethods (isPaymentMethodEnabled('native_token')), not PAYMENT_STORE_ALLOW_TOKEN.
Idempotency: native pay (store + membership) follows the shared contract — one client idempotencyKey per intent; paid rows replay (same txHash), in-flight rows return 409 IDEMPOTENCY_IN_FLIGHT.
Native refunds: POST /api/admin/payments/[orderReference]/refund (platform admin or owning vendor; full-amount, idempotent, marks payment_transactions refunded).
WayForPay hosted Донати, Stripe submit_type=donate, and PayPal Donate SDK are not Ring jar SSOT. Use Public Pools.
Skill / desk: Cursor + Ring docs cluster — start from operator checklist Payment Gateway Integration, then deep-dive PaymentConductor.
Starter prompt (does not mutate until you approve env/config changes):
Configure this clone’s PaymentConductor: set
PAYMENT_DEFAULT_PROCESSOR, WayForPay or Stripe credentials fromenv.local.template, enable store rails (card+ optional credit/token/PayPal flags), registerhttps://YOUR_HOST/api/payments/{processor}/webhook, and verify store checkout usesplaceAndPayStoreOrder+CheckoutRedirect— no/api/cartpayment routes.
Inputs checklist: clone host · ring-config.json payment.* · PSP cabinet credentials · webhook URL reachable from the internet · data/migrations/004_payment_transactions.sql applied.
Set payment.cardPaymentProcessor (wayforpay or stripe) and payment.gateways.*.enabled in ring-config.json. Optional per-purpose env: PAYMENT_STORE_PROCESSOR, PAYMENT_MEMBERSHIP_PROCESSOR, PAYMENT_NEWS_PROCESSOR, PAYMENT_WALLET_TOPUP_PROCESSOR, PAYMENT_PUBLIC_POOL_CONTRIBUTION_PROCESSOR, PAYMENT_NATIVE_TOKEN_ONRAMP_PROCESSOR.
Copy WayForPay / Stripe / PayPal keys from env.local.template (also docker.env.template). WayForPay SSOT: WAYFORPAY_MERCHANT_ACCOUNT, WAYFORPAY_SECRET_KEY, WAYFORPAY_MERCHANT_PASSWORD, WAYFORPAY_DOMAIN, WAYFORPAY_API_URL — no WAYFORPAY_MERCHANT_ID.
PAYMENT_STORE_ALLOW_CREDIT / NEXT_PUBLIC_PAYMENT_STORE_ALLOW_CREDIT from disabling credit.PAYMENT_STORE_ALLOW_TOKEN=true and NEXT_PUBLIC_PAYMENT_STORE_ALLOW_TOKEN=true.NEXT_PUBLIC_PAYMENT_STORE_ALLOW_PAYPAL=true, gateways.paypal.enabled: true, plus PAYPAL_CLIENT_ID / PAYPAL_CLIENT_SECRET / PAYPAL_WEBHOOK_ID / PAYPAL_MODE.Register cabinet callbacks to /api/payments/wayforpay/webhook (and Stripe/PayPal twins). Apply 004_payment_transactions.sql before production traffic.
Place a store order (card rail). Expect CheckoutRedirect — WayForPay HPP via POST form, not a GET query URL. Confirm settlement only after webhook Approved / capture — not on return URL alone.
payment_transactions covers store, membership one-shots, news, wallet top-up, and DAO jar chip-ins.
WayForPay HPP keeps PCI scope at the PSP; Stripe for international clones.
Card top-up adds fiat credit points — not on-chain RING. Desk / onramp are separate paths.
PayPal Subscriptions v1 + manage page at .
No. Store checkout places the order and pays through PaymentConductor (Server Action or the store payment routes above). There is no fabricated cart checkout REST API.
No. PayPal is its own rail. Card still resolves to WayForPay or Stripe independently.
Switch copy and components to rails (card / paypal / credit_balance / native_token). Keep processor selection in config/env. See PaymentConductor.
Use SubscriptionConductor (PayPal Subscriptions v1, Stripe Subscriptions, WayForPay regularApi, credit, native, NFT gate). PaymentConductor still owns one-shot membership upgrades and store Orders.
For WayForPay, settlement is serviceUrl webhook Approved — not returnUrl. Check cabinet webhook URL, HMAC secrets, and dispatcher logs.
User detail Payments tab → GET /api/admin/users/[id]/payments (membership / wallet top-up and other ledger rows).
Deep-dive: purposes, rails vs processors, handlers, and module paths.
Depends-on: WayForPay HPP env SSOT, HMAC, and returnUrl vs serviceUrl money truth.
Same-workflow: wallet_topup credit points vs desk/onramp native paths.
Next-step: recurring membership SubscriptionConductor (PayPal Subscriptions v1).
Status: PaymentConductor is the live money SSOT for store, membership one-shots, news promotion, wallet credit top-up, confidential native onramp, and public-pool (DAO jar) card/PayPal chip-ins. Recurring membership PayPal uses SubscriptionConductor (Subscriptions v1) — not a separate cart API. Use Founder / Developer tabs in the docs sidebar to filter this page.
Ring routes buyer rails (card | paypal | credit_balance | native_token) through PaymentConductor (lib/payments/conductor/). The card rail settles via WayForPay or Stripe (payment.cardPaymentProcessor / purpose env) — UI never picks a PSP id. Browser handoff is Conductor CheckoutRedirect (navigate | form_post) via followCheckoutResult. Rates and presentment come from Ring Oracle.
| Previous / common assumption | Ring equivalent |
|---|---|
| Brand-named checkout buttons (WayForPay / Stripe) in UI | Rail card → Conductor resolves processor |
Generic /api/cart/* checkout REST | No cart payment REST — store UI uses Server Action placeAndPayStoreOrder → PaymentConductor.createCheckout |
| Optional REST by rail | POST /api/store/payments/{card|wayforpay|stripe|credit|token|paypal} (same Conductor SSOT) |
| Hosted PSP “Donate” products for jars | Purpose public_pool_contribution + desk oracle — see Public Pools |
| Recurring membership on PaymentConductor Orders only | One-shot Orders here; Subscriptions v1 on SubscriptionConductor |
| Rail | Typical processor | Store entry | Gateway fee (config) | Notes |
|---|---|---|---|---|
card | WayForPay or Stripe | Action + POST …/card (alias) / …/wayforpay / …/stripe | WFP ~2.5% · Stripe ~2.9% + fixed | Primary Ukraine = WayForPay HPP (form_post) |
paypal | PayPal Orders v2 | Action + POST …/paypal | ~2.9% + fixed when enabled | Needs NEXT_PUBLIC_PAYMENT_STORE_ALLOW_PAYPAL=true + gateways.paypal.enabled + PAYPAL_* |
credit_balance | Internal | Action + POST …/credit | 0% | Fiat credit ledger; gated by PAYMENT_STORE_ALLOW_CREDIT / gateway |
Canonical PSP webhooks (settlement): POST /api/payments/{wayforpay,stripe,paypal}/webhook. Money truth for WayForPay: serviceUrl Approved settles — browser returnUrl is UX only.
| Purpose | Buyer outcome | Typical rails / PSP |
|---|---|---|
store_order | Cart → paid order | card / credit / native_token / paypal |
membership_upgrade | Role upgrade one-shot | card / native / paypal (recurring → SubscriptionConductor) |
news_promotion | Sponsored news | card (WFP / Stripe) |
wallet_topup | Fiat credit points | card (PAYMENT_WALLET_TOPUP_PROCESSOR) or paypal |
native_token_onramp | Card/PayPal → treasury native | Confidential+ when CONFIDENTIAL_TOKEN_ONRAMP=true |
public_pool_contribution | DAO jar chip-in |
Extended purposes (project_order, task_escrow, collective_order_slot, scheduled_service_slot) share the same Conductor — details on PaymentConductor.
Membership native pay is membership_upgrade + native_token through PaymentConductor (soft launch: treasury SPL + ledger; deployed: on-chain RingMembership), then SubscriptionConductor ledger-only via metadata.tx_hash — see SubscriptionConductor. Its gate is payment.supportedMethods (isPaymentMethodEnabled('native_token')), not PAYMENT_STORE_ALLOW_TOKEN.
Idempotency: native pay (store + membership) follows the shared contract — one client idempotencyKey per intent; paid rows replay (same txHash), in-flight rows return 409 IDEMPOTENCY_IN_FLIGHT.
Native refunds: POST /api/admin/payments/[orderReference]/refund (platform admin or owning vendor; full-amount, idempotent, marks payment_transactions refunded).
WayForPay hosted Донати, Stripe submit_type=donate, and PayPal Donate SDK are not Ring jar SSOT. Use Public Pools.
Skill / desk: Cursor + Ring docs cluster — start from operator checklist Payment Gateway Integration, then deep-dive PaymentConductor.
Starter prompt (does not mutate until you approve env/config changes):
Configure this clone’s PaymentConductor: set
PAYMENT_DEFAULT_PROCESSOR, WayForPay or Stripe credentials fromenv.local.template, enable store rails (card+ optional credit/token/PayPal flags), registerhttps://YOUR_HOST/api/payments/{processor}/webhook, and verify store checkout usesplaceAndPayStoreOrder+CheckoutRedirect— no/api/cartpayment routes.
Inputs checklist: clone host · ring-config.json payment.* · PSP cabinet credentials · webhook URL reachable from the internet · data/migrations/004_payment_transactions.sql applied.
Set payment.cardPaymentProcessor (wayforpay or stripe) and payment.gateways.*.enabled in ring-config.json. Optional per-purpose env: PAYMENT_STORE_PROCESSOR, PAYMENT_MEMBERSHIP_PROCESSOR, PAYMENT_NEWS_PROCESSOR, PAYMENT_WALLET_TOPUP_PROCESSOR, PAYMENT_PUBLIC_POOL_CONTRIBUTION_PROCESSOR, PAYMENT_NATIVE_TOKEN_ONRAMP_PROCESSOR.
Copy WayForPay / Stripe / PayPal keys from env.local.template (also docker.env.template). WayForPay SSOT: WAYFORPAY_MERCHANT_ACCOUNT, WAYFORPAY_SECRET_KEY, WAYFORPAY_MERCHANT_PASSWORD, WAYFORPAY_DOMAIN, WAYFORPAY_API_URL — no WAYFORPAY_MERCHANT_ID.
PAYMENT_STORE_ALLOW_CREDIT / NEXT_PUBLIC_PAYMENT_STORE_ALLOW_CREDIT from disabling credit.PAYMENT_STORE_ALLOW_TOKEN=true and NEXT_PUBLIC_PAYMENT_STORE_ALLOW_TOKEN=true.NEXT_PUBLIC_PAYMENT_STORE_ALLOW_PAYPAL=true, gateways.paypal.enabled: true, plus PAYPAL_CLIENT_ID / PAYPAL_CLIENT_SECRET / PAYPAL_WEBHOOK_ID / PAYPAL_MODE.Register cabinet callbacks to /api/payments/wayforpay/webhook (and Stripe/PayPal twins). Apply 004_payment_transactions.sql before production traffic.
Place a store order (card rail). Expect CheckoutRedirect — WayForPay HPP via POST form, not a GET query URL. Confirm settlement only after webhook Approved / capture — not on return URL alone.
payment_transactions covers store, membership one-shots, news, wallet top-up, and DAO jar chip-ins.
WayForPay HPP keeps PCI scope at the PSP; Stripe for international clones.
Card top-up adds fiat credit points — not on-chain RING. Desk / onramp are separate paths.
PayPal Subscriptions v1 + manage page at .
No. Store checkout places the order and pays through PaymentConductor (Server Action or the store payment routes above). There is no fabricated cart checkout REST API.
No. PayPal is its own rail. Card still resolves to WayForPay or Stripe independently.
Switch copy and components to rails (card / paypal / credit_balance / native_token). Keep processor selection in config/env. See PaymentConductor.
Use SubscriptionConductor (PayPal Subscriptions v1, Stripe Subscriptions, WayForPay regularApi, credit, native, NFT gate). PaymentConductor still owns one-shot membership upgrades and store Orders.
For WayForPay, settlement is serviceUrl webhook Approved — not returnUrl. Check cabinet webhook URL, HMAC secrets, and dispatcher logs.
User detail Payments tab → GET /api/admin/users/[id]/payments (membership / wallet top-up and other ledger rows).
Deep-dive: purposes, rails vs processors, handlers, and module paths.
Depends-on: WayForPay HPP env SSOT, HMAC, and returnUrl vs serviceUrl money truth.
Same-workflow: wallet_topup credit points vs desk/onramp native paths.
Next-step: recurring membership SubscriptionConductor (PayPal Subscriptions v1).
native_token |
| On-chain |
Action + POST …/token |
| 0% |
Needs PAYMENT_STORE_ALLOW_TOKEN=true (+ public twin for UI) |
card / paypal → desk FX → pledged_native_token |
/membership/managePAYPAL_* is ready.PAYMENT_DEFAULT_PROCESSOR=stripe (or purpose overrides); same rails UI.publicPools.platformFeePercentByRole — not donation products.GET /api/admin/users/[id]/payments).ring-config.json payment sectionSymbols are examples — replace with your clone’s store.mainCurrency and tokens.nativeToken.symbol.
UI store rails are driven by getClientStorePaymentRails() (env + gateways) — not by inventing PSP buttons.
followCheckoutResult / followCheckoutRedirect |
| Store action | app/_actions/store-checkout-payment.ts | Primary store UI path |
| Client rails | lib/ring-config-client.ts → getClientStorePaymentRails | Card / credit / token / paypal toggles |
| Processors | lib/payments/processors/*.processor.ts | wayforpay, stripe, paypal, credit-balance, native-token |
| Dispatcher | lib/payments/conductor/webhook-dispatcher.ts | Purpose → handlers |
| Webhooks | app/api/payments/{wayforpay,stripe,paypal}/webhook | Canonical PSP callbacks |
| Method | Path | Role |
|---|---|---|
| — | Server Action placeAndPayStoreOrder | Primary checkout UI |
POST | /api/store/payments/card | Card rail alias → wayforpay route |
POST | /api/store/payments/wayforpay | Card via WFP processor path |
POST | /api/store/payments/stripe | Card via Stripe |
POST | /api/store/payments/credit | Credit rail |
POST | /api/store/payments/token | Native token rail |
POST | /api/store/payments/paypal | PayPal Orders v2 |
GET | /api/store/payments/[orderId]/status | Processing poll |
There is no /api/cart/... payment surface. Cart state stays client/feature-store; money always enters via Conductor.
Templates: env.local.template, docker.env.template, docker-compose.template.yml. Ledger: data/migrations/004_payment_transactions.sql.
Deep-dive: CheckoutRedirect DTO, idempotency, and webhook dispatcher.
{
"payment": {
"cardPaymentProcessor": "wayforpay",
"supportedMethods": ["wayforpay", "credit_balance", "native_token"],
"futureMethods": ["stripe", "paypal", "nft_gate"],
"gateways": {
"wayforpay": { "enabled": true, "feePercent": 2.5, "currency": "<main_currency>" },
"stripe": { "enabled": false, "feePercent": 2.9, "feeFixedCents": 30, "currency": "<main_currency>" },
"credit_balance": { "enabled": true, "feePercent": 0, "currency": "<main_currency>" },
"native_token": { "enabled": true, "feePercent": 0, "currency": "<native_token_symbol>", "label": "Tokens" },
"paypal": { "enabled": false, "feePercent": 2.9, "feeFixedCents": 30, "currency": "USD" }
}
}
}native_token |
| On-chain |
Action + POST …/token |
| 0% |
Needs PAYMENT_STORE_ALLOW_TOKEN=true (+ public twin for UI) |
card / paypal → desk FX → pledged_native_token |
/membership/managePAYPAL_* is ready.PAYMENT_DEFAULT_PROCESSOR=stripe (or purpose overrides); same rails UI.publicPools.platformFeePercentByRole — not donation products.GET /api/admin/users/[id]/payments).ring-config.json payment sectionSymbols are examples — replace with your clone’s store.mainCurrency and tokens.nativeToken.symbol.
UI store rails are driven by getClientStorePaymentRails() (env + gateways) — not by inventing PSP buttons.
followCheckoutResult / followCheckoutRedirect |
| Store action | app/_actions/store-checkout-payment.ts | Primary store UI path |
| Client rails | lib/ring-config-client.ts → getClientStorePaymentRails | Card / credit / token / paypal toggles |
| Processors | lib/payments/processors/*.processor.ts | wayforpay, stripe, paypal, credit-balance, native-token |
| Dispatcher | lib/payments/conductor/webhook-dispatcher.ts | Purpose → handlers |
| Webhooks | app/api/payments/{wayforpay,stripe,paypal}/webhook | Canonical PSP callbacks |
| Method | Path | Role |
|---|---|---|
| — | Server Action placeAndPayStoreOrder | Primary checkout UI |
POST | /api/store/payments/card | Card rail alias → wayforpay route |
POST | /api/store/payments/wayforpay | Card via WFP processor path |
POST | /api/store/payments/stripe | Card via Stripe |
POST | /api/store/payments/credit | Credit rail |
POST | /api/store/payments/token | Native token rail |
POST | /api/store/payments/paypal | PayPal Orders v2 |
GET | /api/store/payments/[orderId]/status | Processing poll |
There is no /api/cart/... payment surface. Cart state stays client/feature-store; money always enters via Conductor.
Templates: env.local.template, docker.env.template, docker-compose.template.yml. Ledger: data/migrations/004_payment_transactions.sql.
Deep-dive: CheckoutRedirect DTO, idempotency, and webhook dispatcher.
{
"payment": {
"cardPaymentProcessor": "wayforpay",
"supportedMethods": ["wayforpay", "credit_balance", "native_token"],
"futureMethods": ["stripe", "paypal", "nft_gate"],
"gateways": {
"wayforpay": { "enabled": true, "feePercent": 2.5, "currency": "<main_currency>" },
"stripe": { "enabled": false, "feePercent": 2.9, "feeFixedCents": 30, "currency": "<main_currency>" },
"credit_balance": { "enabled": true, "feePercent": 0, "currency": "<main_currency>" },
"native_token": { "enabled": true, "feePercent": 0, "currency": "<native_token_symbol>", "label": "Tokens" },
"paypal": { "enabled": false, "feePercent": 2.9, "feeFixedCents": 30, "currency": "USD" }
}
}
}native_token |
| On-chain |
Action + POST …/token |
| 0% |
Needs PAYMENT_STORE_ALLOW_TOKEN=true (+ public twin for UI) |
card / paypal → desk FX → pledged_native_token |
/membership/managePAYPAL_* is ready.PAYMENT_DEFAULT_PROCESSOR=stripe (or purpose overrides); same rails UI.publicPools.platformFeePercentByRole — not donation products.GET /api/admin/users/[id]/payments).ring-config.json payment sectionSymbols are examples — replace with your clone’s store.mainCurrency and tokens.nativeToken.symbol.
UI store rails are driven by getClientStorePaymentRails() (env + gateways) — not by inventing PSP buttons.
followCheckoutResult / followCheckoutRedirect |
| Store action | app/_actions/store-checkout-payment.ts | Primary store UI path |
| Client rails | lib/ring-config-client.ts → getClientStorePaymentRails | Card / credit / token / paypal toggles |
| Processors | lib/payments/processors/*.processor.ts | wayforpay, stripe, paypal, credit-balance, native-token |
| Dispatcher | lib/payments/conductor/webhook-dispatcher.ts | Purpose → handlers |
| Webhooks | app/api/payments/{wayforpay,stripe,paypal}/webhook | Canonical PSP callbacks |
| Method | Path | Role |
|---|---|---|
| — | Server Action placeAndPayStoreOrder | Primary checkout UI |
POST | /api/store/payments/card | Card rail alias → wayforpay route |
POST | /api/store/payments/wayforpay | Card via WFP processor path |
POST | /api/store/payments/stripe | Card via Stripe |
POST | /api/store/payments/credit | Credit rail |
POST | /api/store/payments/token | Native token rail |
POST | /api/store/payments/paypal | PayPal Orders v2 |
GET | /api/store/payments/[orderId]/status | Processing poll |
There is no /api/cart/... payment surface. Cart state stays client/feature-store; money always enters via Conductor.
Templates: env.local.template, docker.env.template, docker-compose.template.yml. Ledger: data/migrations/004_payment_transactions.sql.
Deep-dive: CheckoutRedirect DTO, idempotency, and webhook dispatcher.
{
"payment": {
"cardPaymentProcessor": "wayforpay",
"supportedMethods": ["wayforpay", "credit_balance", "native_token"],
"futureMethods": ["stripe", "paypal", "nft_gate"],
"gateways": {
"wayforpay": { "enabled": true, "feePercent": 2.5, "currency": "<main_currency>" },
"stripe": { "enabled": false, "feePercent": 2.9, "feeFixedCents": 30, "currency": "<main_currency>" },
"credit_balance": { "enabled": true, "feePercent": 0, "currency": "<main_currency>" },
"native_token": { "enabled": true, "feePercent": 0, "currency": "<native_token_symbol>", "label": "Tokens" },
"paypal": { "enabled": false, "feePercent": 2.9, "feeFixedCents": 30, "currency": "USD" }
}
}
}