Payment endpoints integrate with Stripe for card payments and support bank transfer orders. Most endpoints require authentication.
Create Payment Intent
Create a Stripe Payment Intent for processing card payments. Validates cart items, applies coupons, and creates a Stripe customer if needed.
Authentication
Required. User must be authenticated via Clerk.
Request Body
Array of items to purchase
Product object with _id field
shippingAddress.streetAddress
Street address
shippingAddress.phoneNumber
Contact phone number
Optional coupon code for discount
Response
Stripe client secret for completing the payment on the frontend
Example Request
curl -X POST https://api.donpalitojr.com/api/payment/create-intent \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"cartItems": [
{
"product": {"_id": "65f8a1b2c3d4e5f6g7h8i9j3"},
"quantity": 2
}
],
"shippingAddress": {
"fullName": "Juan Pérez",
"streetAddress": "Calle 123 #45-67",
"city": "Bogotá",
"phoneNumber": "+57 300 123 4567"
},
"couponCode": "WELCOME10"
}'
Example Response
{
"clientSecret": "pi_3ABC123DEF456_secret_XYZ789",
"paymentIntentId": "pi_3ABC123DEF456"
}
Error Responses
Cart is empty, shipping address missing, insufficient stock, invalid coupon, or amount below minimum
{
"error": "Cart is empty"
}
{
"error": "Insufficient stock for Empanada de Pollo"
}
{
"error": "El cupón no es válido o ha expirado."
}
{
"error": "The minimum amount to process payments is $2000 COP"
}
{
"error": "Product Empanada de Pollo not found"
}
Stripe Webhook Handler
Webhook endpoint for Stripe to notify payment events. Handles payment_intent.succeeded events to create orders automatically.
Authentication
No authentication required. Validates Stripe signature instead.
Stripe webhook signature for verification
Request Body
Stripe event object (raw body required for signature verification).
Response
Event Handling
When a payment_intent.succeeded event is received:
- Validates payment hasn’t already been processed
- Creates order with items from payment metadata
- Reduces product stock
- Marks coupon as used (if applicable)
- Sends order confirmation emails to customer and admin
Example Webhook Event
{
"type": "payment_intent.succeeded",
"data": {
"object": {
"id": "pi_3ABC123DEF456",
"amount": 1700000,
"currency": "cop",
"metadata": {
"userId": "65f8a1b2c3d4e5f6g7h8i9j1",
"clerkId": "user_2abc123def456",
"orderItems": "[{\"product\":\"65f8a1b2c3d4e5f6g7h8i9j3\",\"price\":3500,\"quantity\":2}]",
"shippingAddress": "{\"fullName\":\"Juan Pérez\",\"streetAddress\":\"Calle 123\",\"city\":\"Bogotá\",\"phoneNumber\":\"+57 300 123 4567\"}",
"totalPrice": "17000",
"couponCode": "WELCOME10"
}
}
}
}
Error Responses
Invalid webhook signature
{
"error": "Webhook Error: Invalid signature"
}
Create Transfer Order
Create an order with bank transfer as the payment method. The order is created immediately with “pending” status.
Authentication
Required. User must be authenticated via Clerk.
Request Body
Array of items to purchase
Product object with _id field
Shipping address details (same fields as payment intent)
Optional coupon code for discount
Response
Payment info with id like “transfer_1234567890” and status: "pending"
Total order price (includes discount, no shipping cost)
Order status (always “pending” initially)
Example Request
curl -X POST https://api.donpalitojr.com/api/payment/create-transfer-order \
-H "Authorization: Bearer YOUR_AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"cartItems": [
{
"product": {"_id": "65f8a1b2c3d4e5f6g7h8i9j3"},
"quantity": 2
}
],
"shippingAddress": {
"fullName": "Juan Pérez",
"streetAddress": "Calle 123 #45-67",
"city": "Bogotá",
"phoneNumber": "+57 300 123 4567"
},
"couponCode": "SAVE15"
}'
Example Response
{
"order": {
"_id": "65f8a1b2c3d4e5f6g7h8i9j0",
"user": "65f8a1b2c3d4e5f6g7h8i9j1",
"clerkId": "user_2abc123def456",
"orderItems": [
{
"product": "65f8a1b2c3d4e5f6g7h8i9j3",
"name": "Empanada de Pollo",
"price": 3500,
"quantity": 2
}
],
"shippingAddress": {
"fullName": "Juan Pérez",
"streetAddress": "Calle 123 #45-67",
"city": "Bogotá",
"phoneNumber": "+57 300 123 4567"
},
"paymentResult": {
"id": "transfer_1710512400000",
"status": "pending"
},
"totalPrice": 5950,
"status": "pending",
"createdAt": "2024-03-15T10:30:00.000Z"
}
}
Error Responses
Cart is empty, shipping address missing, insufficient stock, or invalid/expired coupon
{
"error": "Cart is empty"
}
{
"error": "Stock insuficiente para Empanada de Pollo"
}
{
"error": "Ya usaste este cupón anteriormente."
}
{
"error": "Producto no encontrado"
}
Payment Flow
Create Payment Intent
Call /api/payment/create-intent to get a Stripe client secret
Complete Payment on Frontend
Use Stripe.js with the client secret to collect payment details
Stripe Processes Payment
Stripe charges the customer and sends webhook to /api/payment/webhook
Order Created Automatically
Webhook handler creates the order, reduces stock, and sends emails
Alternative: Bank Transfer Flow
Create Transfer Order
Call /api/payment/create-transfer-order to create order with pending status
Customer Transfers Payment
Customer makes bank transfer offline
Admin Confirms Payment
Admin updates order status to “paid” via admin endpoints