dist/codex/saleor-commerce/skills/saleor-payments/SKILL.md
Implement Saleor payment processing — transaction-based payment flow, payment Apps, sync webhook events, Stripe/Adyen patterns, and refunds. Use when building payment integrations.
npx skillsauth add orcaqubits/agentic-commerce-claude-plugins saleor-paymentsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Fetch live docs:
site:docs.saleor.io transaction payment flow for the transaction-based payment modelsite:docs.saleor.io payment app sync webhooks for payment App implementation patternssite:docs.saleor.io transaction events CHARGE_REQUESTED for transaction event typeshttps://docs.saleor.io/docs/developer/payments and review the full payment lifecyclesite:docs.saleor.io refund transactionRequestAction for refund processing flowhttps://docs.saleor.io/docs/developer/app-store/apps/stripe and review Stripe App integration patternsSaleor uses a transaction-based payment model (replacing the legacy Payment model):
| Step | Component | Description |
|------|-----------|-------------|
| 1. List gateways | checkout.availablePaymentGateways | Query available payment Apps for the checkout |
| 2. Initialize session | transactionInitialize | Send payment request to the payment App |
| 3. Process (if needed) | transactionProcess | Handle additional steps (3DS, redirect) |
| 4. Transaction events | Automatic | Payment App reports events via webhooks |
| 5. Complete checkout | checkoutComplete | Finalize order after successful payment |
The transaction flow is designed for asynchronous payment processing. The payment App controls the actual charge timing and reports results back via transaction events.
Transaction events track the lifecycle of a payment:
| Event Type | Description |
|------------|-------------|
| AUTHORIZATION_REQUEST | Request to authorize (hold) funds |
| CHARGE_REQUEST | Request to capture payment |
| REFUND_REQUEST | Request to refund payment |
| CANCEL_REQUEST | Request to void/cancel authorization |
| Event Type | Description |
|------------|-------------|
| AUTHORIZATION_SUCCESS | Funds successfully authorized |
| CHARGE_SUCCESS | Payment successfully captured |
| REFUND_SUCCESS | Refund successfully processed |
| CANCEL_SUCCESS | Authorization successfully cancelled |
| Event Type | Description |
|------------|-------------|
| AUTHORIZATION_FAILURE | Authorization failed |
| CHARGE_FAILURE | Charge failed |
| REFUND_FAILURE | Refund failed |
| CANCEL_FAILURE | Cancellation failed |
| Event Type | Description |
|------------|-------------|
| AUTHORIZATION_ACTION_REQUIRED | Additional customer action needed (e.g., 3DS) |
| CHARGE_ACTION_REQUIRED | Additional step required to complete charge |
Fetch live docs for the complete
TransactionEventTypeEnum-- additional event types may exist for pending states and information events.
Payment processing in Saleor is handled by Apps that implement sync webhooks:
| Component | Description | |-----------|-------------| | Payment App | A Saleor App that handles payment gateway communication | | Sync webhooks | Synchronous webhook calls from Saleor to the App | | Transaction events | App reports payment status back to Saleor | | Gateway config | Per-channel payment gateway configuration |
| Webhook Event | When Triggered | Expected Response |
|---------------|----------------|-------------------|
| PAYMENT_GATEWAY_INITIALIZE_SESSION | When storefront queries payment gateways | Gateway configuration and client-side data |
| TRANSACTION_INITIALIZE_SESSION | On transactionInitialize mutation | Payment session data (e.g., client secret) |
| TRANSACTION_PROCESS_SESSION | On transactionProcess mutation | Updated payment status and next actions |
| TRANSACTION_CHARGE_REQUESTED | On transactionRequestAction with CHARGE | Charge result event |
| TRANSACTION_REFUND_REQUESTED | On transactionRequestAction with REFUND | Refund result event |
| TRANSACTION_CANCELATION_REQUESTED | On transactionRequestAction with CANCEL | Cancellation result event |
A payment App must:
| Step | Description |
|------|-------------|
| 1. Register webhooks | Subscribe to the sync webhook events above |
| 2. Handle initialize | Create payment session with the gateway (e.g., Stripe PaymentIntent) |
| 3. Return session data | Send client-side data back (e.g., clientSecret for Stripe Elements) |
| 4. Handle process | Process additional steps and return updated status |
| 5. Report events | Use transactionEventReport to report async payment updates |
| 6. Handle actions | Process charge, refund, and cancel requests |
Staff and Apps can request actions on existing transactions:
| Action | Mutation | Description |
|--------|----------|-------------|
| Charge | transactionRequestAction with CHARGE | Capture authorized funds |
| Refund | transactionRequestAction with REFUND | Refund charged amount |
| Cancel | transactionRequestAction with CANCEL | Void authorization |
For manual or offline payments:
| Mutation | Purpose |
|----------|---------|
| transactionCreate | Create a transaction record manually |
| transactionUpdate | Update transaction details |
| transactionEventReport | Report payment events from external systems |
Saleor implements a two-step refund process:
| Step | Mutation | Description |
|------|----------|-------------|
| 1. Grant refund | orderGrantRefundCreate | Merchant decides refund amount or lines |
| 2. Process refund | transactionRequestAction with REFUND | Payment App processes the actual refund |
| Option | Description | |--------|-------------| | Amount-based | Specify a flat refund amount | | Line-based | Specify order lines and quantities to refund | | Shipping refund | Include shipping cost in the refund | | Reason | Optional text reason for the refund |
The grant-then-process pattern allows merchants to review and approve refunds before the payment is actually reversed.
| Legacy Mutation | Replacement |
|-----------------|-------------|
| checkoutPaymentCreate | transactionInitialize |
| checkoutComplete (with payment data) | transactionProcess + checkoutComplete |
| orderCapture | transactionRequestAction with CHARGE |
| orderRefund | orderGrantRefundCreate + transactionRequestAction |
| orderVoid | transactionRequestAction with CANCEL |
Legacy payment mutations are deprecated. All new integrations should use the transaction-based flow. Existing integrations should migrate to transactions.
The official Saleor Stripe App follows this flow:
| Step | Client | Server |
|------|--------|--------|
| 1. Initialize | Call transactionInitialize | App creates Stripe PaymentIntent |
| 2. Client secret | Receive data.clientSecret | -- |
| 3. Confirm | Use Stripe.js to confirm payment | -- |
| 4. Process | Call transactionProcess if needed | App checks PaymentIntent status |
| 5. Webhook | -- | Stripe webhook updates transaction |
The official Saleor Adyen App follows a similar pattern:
| Step | Client | Server |
|------|--------|--------|
| 1. Initialize | Call transactionInitialize | App creates Adyen session |
| 2. Session data | Receive Adyen Drop-in config | -- |
| 3. Submit | Use Adyen Web Components | -- |
| 4. Process | Call transactionProcess with result | App verifies with Adyen |
| 5. Webhook | -- | Adyen webhook updates transaction |
transactionInitialize to prevent duplicate chargesACTION_REQUIRED events for 3DS and redirect-based payment methodstransactionEventReport for webhook-based async payment updates from gatewaysmetadata for debuggingcheckout.totalPrice matches the amount passed to transactionInitializeFetch the Saleor payment and transaction documentation for exact webhook payloads, event types, and App implementation patterns before implementing.
development
Build with Spree's headless Next.js storefront — the official `spree/storefront` repo (Next.js 16 App Router with Server Actions and Turbopack, React 19 Server Components, Tailwind CSS 4, TypeScript 5, `@spree/sdk`, Sentry), server-only auth (httpOnly JWT cookies + publishable key), MeiliSearch faceted catalog, one-page checkout with Apple/Google Pay/Klarna/Affirm/SEPA, multi-region market routing, GA4 + JSON-LD SEO, and Vercel/Docker deployment. Use when forking or customizing the storefront, or evaluating headless adoption.
tools
Build Spree extensions as Rails engines — gem scaffolding, `bin/rails g spree:extension`, mounting routes/migrations/assets, the modern `prepend` decorator pattern (`*_decorator.rb` with `self.prepended(base)`), generators (`spree:model_decorator`, `spree:controller_decorator`), the four customization surfaces in preference order (Events > Webhooks > Dependencies > Decorators), Spree::Dependencies for swapping service objects, gem release/versioning, and the deprecated Deface engine. Use when building a reusable Spree extension or adding non-trivial customization to an app.
development
Build with Spree's event bus and Webhooks 2.0 — `Spree::Events` publication, `Spree::Subscriber` DSL with `subscribes_to` and `on`, wildcard matching, lifecycle events (`{model}.created/.updated/.deleted` via `publishes_lifecycle_events`), the canonical event catalog (order.*, payment.*, shipment.*, product.*), Webhooks 2.0 endpoints, HMAC-SHA256 signing (`X-Spree-Webhook-Signature`), exponential-backoff retries, and Sidekiq job orchestration. Use when wiring event-driven business logic, building webhook consumers, or replacing ActiveSupport callback chains.
tools
Cross-cutting Spree development patterns — the customization preference hierarchy (Events > Webhooks > Dependencies > Decorators), `Spree::Dependencies` service-object swapping, the `_decorator.rb` + `prepend` + `self.prepended` idiom, idempotent subscribers and webhook receivers, multi-store scoping discipline, prefixed IDs, calculator polymorphism (shipping/promotion/tax share the base), service-object composition with `dry-monads` or simple results, why to avoid `class_eval` reopening and Deface, and Spree-on-Rails idioms (Hotwire/Turbo Stimulus, ActiveStorage, Action Cable, Sidekiq). Use when designing the architecture of a Spree extension or solving cross-cutting concerns.