This commit adds comprehensive COD support using Saleor's native Transaction system:
**Architecture:**
- Uses Saleor's native Transaction objects (not metadata)
- Modular payment method configuration
- Extensible design for future payment types (cards, bank transfer, etc.)
**New Components:**
- PaymentMethodSelector: Reusable payment method selection UI
- PaymentMethodCard: Individual payment method card
- CODInstructions: COD-specific instructions and guidance
- PaymentSection: Checkout integration wrapper
**Core Features:**
- COD selected by default for Serbia (default-channel)
- Transaction created automatically on order completion
- Transaction visible in Saleor Dashboard
- Multi-language support (EN, SR, DE, FR)
- No additional fees
- Instructions shown to customer (prepare cash, inspect order, no fee)
**Files Added:**
- docs/COD-IMPLEMENTATION-PLAN.md
- src/lib/config/paymentMethods.ts
- src/lib/saleor/payments/types.ts
- src/lib/saleor/payments/cod.ts
- src/components/payment/PaymentMethodSelector.tsx
- src/components/payment/PaymentMethodCard.tsx
- src/components/payment/CODInstructions.tsx
- src/components/payment/index.ts
- src/app/[locale]/checkout/components/PaymentSection.tsx
**Files Modified:**
- src/app/[locale]/checkout/page.tsx (added payment section, transaction creation)
- src/i18n/messages/{en,sr,de,fr}.json (payment translations)
**Technical Details:**
- Transaction status: NOT_CHARGED
- Available actions: [CHARGE]
- PSP Reference format: COD-{orderNumber}-{timestamp}
- Staff collects cash and fulfills order via Dashboard
Closes: Cash on Delivery payment implementation
8.1 KiB
8.1 KiB
Cash on Delivery (COD) Implementation Plan
Branch: feature/cash-on-delivery
Status: In Development
Created: March 29, 2026
1. ARCHITECTURE DECISIONS
Payment Method Type: Simple Transaction
- Uses Saleor's native
Transactionobjects - No Payment App required (COD is manual payment)
- Creates transaction with status
NOT_CHARGED - Staff marks as paid via Dashboard when cash collected
Why This Approach:
- ✅ Native Saleor data structures
- ✅ Appears in Dashboard automatically
- ✅ No metadata hacks
- ✅ Extensible to other simple payments (Bank Transfer)
- ✅ Compatible with Payment Apps later (Stripe, etc.)
2. FILE STRUCTURE
src/
├── lib/
│ ├── config/
│ │ └── paymentMethods.ts # Payment methods configuration
│ └── saleor/
│ └── payments/
│ ├── types.ts # Payment type definitions
│ ├── cod.ts # COD-specific logic
│ └── createTransaction.ts # Generic transaction creator
│
├── components/
│ └── payment/
│ ├── PaymentMethodSelector.tsx # Payment method selection UI
│ ├── PaymentMethodCard.tsx # Individual payment card
│ └── CODInstructions.tsx # COD-specific instructions
│
├── app/[locale]/checkout/
│ ├── page.tsx # Updated checkout page
│ └── components/
│ └── PaymentSection.tsx # Checkout payment section wrapper
│
└── i18n/messages/
├── en.json # Payment translations
├── sr.json # Payment translations
├── de.json # Payment translations
└── fr.json # Payment translations
3. DATA MODELS
PaymentMethod Interface
interface PaymentMethod {
id: string;
name: string;
description: string;
type: 'simple' | 'app';
fee: number;
available: boolean;
availableInChannels: string[];
icon?: string;
}
COD Transaction Structure
const codTransaction = {
name: "Cash on Delivery",
pspReference: `COD-${orderNumber}-${timestamp}`,
availableActions: ["CHARGE"],
amountAuthorized: { amount: 0, currency: "RSD" },
amountCharged: { amount: 0, currency: "RSD" }
};
4. IMPLEMENTATION PHASES
Phase 1: Configuration & Types (Files 1-3)
Files:
lib/config/paymentMethods.ts- Payment methods configlib/saleor/payments/types.ts- Type definitionslib/saleor/payments/cod.ts- COD transaction logic
Deliverables:
- Payment methods configuration
- TypeScript interfaces
- COD transaction creation function
Phase 2: UI Components (Files 4-6)
Files:
4. components/payment/PaymentMethodCard.tsx
5. components/payment/PaymentMethodSelector.tsx
6. components/payment/CODInstructions.tsx
Deliverables:
- Payment method selection UI
- COD instructions component
- Responsive design
Phase 3: Checkout Integration (Files 7-8)
Files:
7. app/[locale]/checkout/components/PaymentSection.tsx
8. app/[locale]/checkout/page.tsx (updated)
Deliverables:
- Payment section in checkout
- Integration with checkout flow
- Transaction creation on complete
Phase 4: Translations (Files 9-12)
Files:
9-12. Update i18n/messages/{en,sr,de,fr}.json
Deliverables:
- All translation keys
- Serbian, English, German, French
Phase 5: Testing
Tasks:
- Test COD flow end-to-end
- Verify transaction created in Saleor
- Test mobile responsiveness
- Test locale switching
5. CHECKOUT FLOW
1. User adds items to cart
↓
2. User proceeds to checkout
↓
3. Checkout page loads with:
- Contact form (email, phone)
- Shipping address form
- Billing address form (same as shipping default)
- Shipping method selector
- PAYMENT METHOD SELECTOR (NEW)
└─ COD selected by default
- Order summary
- Complete Order button
↓
4. User fills all required fields
↓
5. User clicks "Complete Order"
↓
6. System:
a. Validates all fields
b. Creates order via checkoutComplete
c. Creates COD Transaction on order
d. Redirects to order confirmation
↓
7. Order Confirmation page shows:
- Order number
- Total amount
- Payment method: "Cash on Delivery"
- Instructions: "Please prepare cash for delivery"
↓
8. Staff sees order in Dashboard:
- Status: UNFULFILLED
- Payment Status: NOT_CHARGED
- Transaction: "Cash on Delivery (COD-123)"
↓
9. On delivery:
- Delivery person collects cash
- Staff marks order as FULFILLED in Dashboard
- (Optional: Create CHARGE_SUCCESS transaction event)
6. SALESOR DASHBOARD VIEW
Order Details:
Order #1234
├─ Status: UNFULFILLED
├─ Payment Status: NOT_CHARGED
├─ Transactions:
│ └─ Cash on Delivery (COD-1234-1743214567890)
│ ├─ Status: NOT_CHARGED
│ ├─ Amount: 3,200 RSD
│ └─ Available Actions: [CHARGE]
└─ Actions: [Fulfill] [Cancel]
When Cash Collected:
Staff clicks [Fulfill]
↓
Order Status: FULFILLED
Payment Status: (still NOT_CHARGED, but order is complete)
7. TRANSLATION KEYS
English (en.json):
{
"Payment": {
"title": "Payment Method",
"cod": {
"name": "Cash on Delivery",
"description": "Pay when you receive your order",
"instructions": {
"title": "Payment Instructions",
"prepareCash": "Please prepare the exact amount in cash",
"inspectOrder": "You can inspect your order before paying",
"noFee": "No additional fee for cash on delivery"
}
},
"card": {
"name": "Credit Card",
"description": "Secure online payment",
"comingSoon": "Coming soon"
},
"selectMethod": "Select payment method",
"securePayment": "Secure payment processing"
}
}
Serbian (sr.json):
{
"Payment": {
"title": "Način Plaćanja",
"cod": {
"name": "Plaćanje Pouzećem",
"description": "Platite kada primite porudžbinu",
"instructions": {
"title": "Uputstva za Plaćanje",
"prepareCash": "Pripremite tačan iznos u gotovini",
"inspectOrder": "Možete pregledati porudžbinu pre plaćanja",
"noFee": "Bez dodatne naknade za plaćanje pouzećem"
}
}
}
}
8. TESTING CHECKLIST
Functional Tests:
- COD radio button selected by default
- Payment section visible in checkout
- Order completes with COD selected
- Transaction created with correct details
- Transaction visible in Saleor Dashboard
- Order confirmation shows COD
- Translations work in all locales
Edge Cases:
- Checkout validation fails - payment method preserved
- Network error during transaction creation
- User switches payment methods (when multiple available)
- Mobile viewport - payment section responsive
Integration Tests:
- End-to-end COD flow
- Order appears in Dashboard
- Staff can fulfill COD order
- Multiple payment methods display correctly
9. FUTURE ENHANCEMENTS
Phase 2 (Post-MVP):
- Add Bank Transfer payment method
- Payment method icons
- Save payment preference for logged-in users
Phase 3 (Advanced):
- Bitcoin (manual) payment method
- Bitcoin (automated) via custom handler
- Payment Apps integration (Stripe, etc.)
10. NOTES
Why No Metadata:
- Saleor has native Transaction objects
- Transactions are typed and validated
- Appear in Dashboard automatically
- Support proper lifecycle (NOT_CHARGED → CHARGED)
Why Simple Type (Not App):
- COD doesn't need async processing
- No external API to integrate
- No PCI compliance requirements
- Manual verification by staff
Compatibility:
- Current architecture supports Payment Apps later
- Can add Stripe/PayPal as
type: 'app'without breaking COD - Bitcoin can be added as
type: 'async'when ready
Last Updated: March 29, 2026
Next Review: After Phase 1 completion