Skip to main content

Payments

Process payments and validate credit card information for e-commerce transactions.

Validate Credit Card

POST /api/ecom/pagos/validate

Validate credit card number using Luhn algorithm
Validate a credit card number before processing payment. This endpoint uses the Luhn algorithm to verify card number validity.
This endpoint does not require authentication and can be used for client-side validation before checkout.

Request Body

card_number
string
required
Credit card number (13-19 digits)Spaces and hyphens are automatically removed during validation.

Response

valid
boolean
Whether the card number is valid
card_number
string
Validated card number (returned only if valid)
message
string
Error message (returned only if invalid)

Example Request

curl -X POST https://api.example.com/api/ecom/pagos/validate \
  -H "Content-Type: application/json" \
  -d '{
    "card_number": "4532015112830366"
  }'

Example Responses

200 OK - Valid Card
{
  "valid": true,
  "card_number": "4532015112830366"
}
400 Bad Request - Invalid Card
{
  "valid": false,
  "message": "Número de tarjeta de crédito inválido"
}
400 Bad Request - Invalid Format
{
  "valid": false,
  "message": "El número de tarjeta de crédito debe tener entre 13 y 19 dígitos"
}
400 Bad Request - Missing Card Number
{
  "message": "card_number es requerido"
}

Card Validation Rules

The validation endpoint enforces the following rules:
  1. Length: Card number must be between 13 and 19 digits
  2. Format: Only numeric digits (spaces and hyphens are automatically removed)
  3. Luhn Algorithm: Card number must pass Luhn checksum validation
This validation only checks if the card number format is valid using the Luhn algorithm. It does NOT:
  • Verify if the card actually exists
  • Check card balance or limits
  • Process actual payments
  • Validate expiration dates or CVV

Checkout and Process Payment

POST /api/ecom/pagos/checkout

Process payment for the customer’s shopping cart
Complete the purchase by processing payment for all items in the authenticated customer’s cart.
This endpoint requires authentication. Include the JWT token in the Authorization header.

Headers

Authorization
string
required
Bearer token from login responseFormat: Bearer {token}

Request Body

card_number
string
required
Valid credit card number (13-19 digits)Must pass Luhn validation

Response

message
string
Success message: “Pago realizado en línea”
fac_codigo
string
Invoice/receipt code for the completed transaction

Example Request

curl -X POST https://api.example.com/api/ecom/pagos/checkout \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "card_number": "4532015112830366"
  }'

Example Response

201 Created - Success
{
  "message": "Pago realizado en línea",
  "fac_codigo": "FAC001234"
}

Error Responses

401 Unauthorized
{
  "message": "Token inválido o sin email"
}
400 Bad Request - Missing Card Number
{
  "message": "card_number es requerido"
}
400 Bad Request - Invalid Card
{
  "message": "Número de tarjeta de crédito inválido"
}
404 Not Found
{
  "message": "Carrito no encontrado"
}
400 Bad Request - Empty Cart
{
  "message": "No se puede pagar: el carrito está vacío"
}
400 Bad Request - Insufficient Stock
{
  "message": "Stock insuficiente para el producto XYZ"
}
500 Internal Server Error
{
  "message": "Error en checkout"
}

Payment Processing Flow

The checkout process follows these steps:
  1. Validate Card: Card number is validated using Luhn algorithm
  2. Verify Cart: Check that the customer has an active cart
  3. Check Cart Contents: Ensure cart is not empty
  4. Process Transaction: Execute payment in database (atomic transaction)
  5. Generate Invoice: Create invoice record and return invoice code
  6. Clear Cart: Cart is emptied after successful payment
The payment processing is wrapped in a database transaction to ensure data consistency. If any step fails, all changes are rolled back.

Transaction Safety

The checkout endpoint ensures:
  • Atomic Operations: All database operations succeed or fail together
  • Stock Validation: Products are checked for sufficient stock
  • Price Consistency: Prices are locked at transaction time
  • Cart Clearing: Cart is automatically emptied after successful payment

Complete Payment Workflow

Typical e-commerce payment flow:
const token = 'your_jwt_token_here';
const baseURL = 'https://api.example.com';

async function completeCheckout(cardNumber) {
  try {
    // Step 1: Validate card (optional, for better UX)
    console.log('Validating card...');
    const validateResponse = await fetch(`${baseURL}/api/ecom/pagos/validate`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ card_number: cardNumber })
    });
    
    const validateResult = await validateResponse.json();
    if (!validateResult.valid) {
      throw new Error(validateResult.message);
    }
    console.log('Card is valid');
    
    // Step 2: Get cart to show final total
    console.log('Fetching cart...');
    const cartResponse = await fetch(`${baseURL}/api/ecom/carrito?page=1`, {
      headers: { 'Authorization': `Bearer ${token}` }
    });
    const cart = await cartResponse.json();
    console.log(`Cart total: $${cart.carrito.crr_total}`);
    console.log(`Items: ${cart.detalles.length}`);
    
    // Step 3: Process payment
    console.log('Processing payment...');
    const checkoutResponse = await fetch(`${baseURL}/api/ecom/pagos/checkout`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ card_number: cardNumber })
    });
    
    const checkoutResult = await checkoutResponse.json();
    
    if (checkoutResponse.status === 201) {
      console.log('Payment successful!');
      console.log(`Invoice: ${checkoutResult.fac_codigo}`);
      return {
        success: true,
        invoice: checkoutResult.fac_codigo,
        message: checkoutResult.message
      };
    } else {
      throw new Error(checkoutResult.message);
    }
    
  } catch (error) {
    console.error('Checkout failed:', error.message);
    return {
      success: false,
      error: error.message
    };
  }
}

// Usage
const result = await completeCheckout('4532015112830366');
if (result.success) {
  console.log('Order completed! Invoice:', result.invoice);
} else {
  console.log('Order failed:', result.error);
}

Business Rules

The payment system enforces these business rules:

Cart Validation

  • Cart must exist for the authenticated customer
  • Cart must contain at least one item
  • All products in cart must have sufficient stock

Card Validation

  • Card number must be 13-19 digits
  • Card must pass Luhn algorithm validation
  • Card number is required for all payments

Transaction Processing

  • All operations are atomic (succeed or fail together)
  • Stock is decremented after successful payment
  • Cart is automatically cleared after payment
  • Invoice is generated with unique code
Empty carts cannot be processed. Customers must add at least one product before checkout.

Error Handling

Validation Errors

Card validation errors (400 Bad Request) include:
  • Invalid card format
  • Failed Luhn check
  • Missing card number

Business Logic Errors

Checkout errors include:
  • Empty cart (400)
  • Insufficient stock (400)
  • Cart not found (404)
  • Invalid authentication (401)

System Errors

Server errors (500) may occur due to:
  • Database connection issues
  • Transaction failures
  • Unexpected exceptions
Stock-related errors include the product name in the error message to help identify which product caused the issue.

Testing Credit Cards

For testing purposes, you can use these Luhn-valid test card numbers:
  • Visa: 4532015112830366
  • Mastercard: 5425233430109903
  • Amex: 374245455400126
  • Discover: 6011111111111117
These are test numbers that pass Luhn validation but are not real credit cards. They can be used for development and testing.

Source Code Reference

Implementation details can be found in:
  • Routes: /src/routes/ecom.pagos.routes.js:1-14
  • Controller: /src/controllers/ecom.pagos.controller.js:1-87
  • DTOs: /src/dtos/pagos.dto.js:1-36
  • Model: /src/models/pagos.model.js

Luhn Algorithm Implementation

The Luhn validation is implemented in /src/dtos/pagos.dto.js:6-23:
function luhnCheck(cardNumber) {
  cardNumber = cardNumber.replace(/\s+/g, '').replace(/-/g, '');
  if (!/^\d+$/.test(cardNumber)) return false;

  let sum = 0;
  let shouldDouble = false;

  for (let i = cardNumber.length - 1; i >= 0; i--) {
    let digit = parseInt(cardNumber.charAt(i), 10);
    if (shouldDouble) {
      digit *= 2;
      if (digit > 9) digit -= 9;
    }
    sum += digit;
    shouldDouble = !shouldDouble;
  }
  return sum % 10 === 0;
}

Build docs developers (and LLMs) love