Saltar a contenido

🤖 Explicar con IA

Integración de la API de pagos de 4Geeks en una aplicación Node.js

Descripción general

4Geeks Payments es una plataforma Merchant of Record (MoR) que maneja todo el ciclo de vida de las transacciones, desde la aceptación de pagos hasta la gestión de suscripciones, el cumplimiento fiscal y la prevención del fraude. Este tutorial le muestra cómo integrar la API REST de pagos de 4Geeks en una aplicación Node.js.

En este tutorial, podrás:

  • Configure su cuenta de pagos 4Geeks y obtenga claves API
  • Crear un cargo (pago único)
  • Crear y gestionar clientes.
  • Generar enlaces de pago.
  • Manejar webhooks para eventos de pago.
  • Procesar reembolsos

Requisitos previos

  • Una cuenta de 4Geeks Payments activada (activar servicio)
  • Node.js 18+ instalado
  • administrador de paquetes npm o hilo
  • Conocimientos básicos de API REST y Express.js.

Paso 1: Obtenga sus claves API

  1. Inicie sesión en console.4geeks.io
  2. Vaya a PagosConfiguraciónClaves API
  3. Haga clic en “Generar clave API”
  4. Copie y almacene de forma segura su:
  5. Clave pública (para operaciones del lado del cliente)
  6. Clave secreta (para operaciones del lado del servidor; nunca la expongas)

Importante: Utilice claves de zona de pruebas para realizar pruebas. Cambie a claves de producción cuando esté listo para comenzar a funcionar.

Paso 2: Configure su proyecto

mkdir my-payment-app && cd my-payment-app
npm init -y
npm install express axios dotenv cors

Crea la estructura de tu proyecto:

my-payment-app/
├── .env
├── server.js
├── routes/
│   └── payments.js
└── package.json

Paso 3: Configurar variables de entorno

Cree un archivo .env:

FOURGEEKS_PAYMENTS_SECRET_KEY=sk_test_your_secret_key_here
FOURGEEKS_PAYMENTS_PUBLIC_KEY=pk_test_your_public_key_here
FOURGEEKS_PAYMENTS_API_URL=https://api.4geeks.io/v1
PORT=3000

Paso 4: Crear el servidor Express

Cree server.js:

require('dotenv').config();
const express = require('express');
const cors = require('cors');
const paymentRoutes = require('./routes/payments');

const app = express();

app.use(cors());
app.use(express.json());
app.use('/api/payments', paymentRoutes);

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

Paso 5: Crear rutas de pago

Cree rutas/pagos.js:

const express = require('express');
const axios = require('axios');
const router = express.Router();

const API_URL = process.env.FOURGEEKS_PAYMENTS_API_URL;
const SECRET_KEY = process.env.FOURGEEKS_PAYMENTS_SECRET_KEY;

const api = axios.create({
  baseURL: API_URL,
  headers: {
    'Authorization': `Bearer ${SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
});

// Create a one-time charge
router.post('/charges', async (req, res) => {
  try {
    const { amount, currency, customer_id, description } = req.body;

    const response = await api.post('/charges', {
      amount,           // Amount in cents (e.g., 1000 = $10.00)
      currency,         // e.g., 'USD', 'EUR', 'CRC'
      customer_id,      // Existing customer ID or create new
      description,
      capture: true,    // Auto-capture the charge
    });

    res.json({ success: true, charge: response.data });
  } catch (error) {
    console.error('Charge error:', error.response?.data || error.message);
    res.status(error.response?.status || 500).json({
      success: false,
      error: error.response?.data || 'Failed to create charge',
    });
  }
});

// Create a customer
router.post('/customers', async (req, res) => {
  try {
    const { email, name, phone, metadata } = req.body;

    const response = await api.post('/customers', {
      email,
      name,
      phone,
      metadata, // Optional: custom key-value pairs
    });

    res.json({ success: true, customer: response.data });
  } catch (error) {
    res.status(error.response?.status || 500).json({
      success: false,
      error: error.response?.data || 'Failed to create customer',
    });
  }
});

// Generate a payment link
router.post('/payment-links', async (req, res) => {
  try {
    const { amount, currency, description, customer_email, success_url, cancel_url } = req.body;

    const response = await api.post('/payment-links', {
      amount,
      currency,
      description,
      customer_email,
      success_url,    // Redirect after successful payment
      cancel_url,     // Redirect if customer cancels
    });

    res.json({ success: true, payment_link: response.data });
  } catch (error) {
    res.status(error.response?.status || 500).json({
      success: false,
      error: error.response?.data || 'Failed to create payment link',
    });
  }
});

// Process a refund
router.post('/charges/:charge_id/refund', async (req, res) => {
  try {
    const { charge_id } = req.params;
    const { amount, reason } = req.body;

    const response = await api.post(`/charges/${charge_id}/refunds`, {
      amount,  // Optional: partial refund (in cents). Omit for full refund
      reason,  // e.g., 'duplicate', 'fraudulent', 'requested_by_customer'
    });

    res.json({ success: true, refund: response.data });
  } catch (error) {
    res.status(error.response?.status || 500).json({
      success: false,
      error: error.response?.data || 'Failed to process refund',
    });
  }
});

// Get charge details
router.get('/charges/:charge_id', async (req, res) => {
  try {
    const { charge_id } = req.params;
    const response = await api.get(`/charges/${charge_id}`);
    res.json({ success: true, charge: response.data });
  } catch (error) {
    res.status(error.response?.status || 500).json({
      success: false,
      error: error.response?.data || 'Failed to get charge',
    });
  }
});

module.exports = router;

Paso 6: Manejar webhooks

Los webhooks notifican a su servidor sobre eventos de pago (cargos exitosos, pagos fallidos, reembolsos, etc.).

Agregar a server.js:

// Webhook endpoint
app.post('/webhooks/payments', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-4geeks-signature'];
  const payload = req.body;

  // Verify webhook signature (implement verification logic)
  // const isValid = verifyWebhookSignature(payload, signature);
  // if (!isValid) return res.status(401).send('Invalid signature');

  const event = JSON.parse(payload);

  switch (event.type) {
    case 'charge.succeeded':
      console.log('Payment successful:', event.data.charge_id);
      // Update order status, send confirmation email, etc.
      break;
    case 'charge.failed':
      console.log('Payment failed:', event.data.charge_id);
      // Notify customer, retry logic, etc.
      break;
    case 'refund.completed':
      console.log('Refund processed:', event.data.refund_id);
      // Update order status, notify customer, etc.
      break;
    case 'subscription.created':
      console.log('New subscription:', event.data.subscription_id);
      // Activate subscription, send welcome email, etc.
      break;
    default:
      console.log('Unhandled event type:', event.type);
  }

  res.json({ received: true });
});

Paso 7: Pruebe su integración

Inicie el servidor:

node server.js

Prueba con rizo:

# Create a customer
curl -X POST http://localhost:3000/api/payments/customers \
  -H "Content-Type: application/json" \
  -d '{"email": "test@example.com", "name": "John Doe"}'

# Create a charge
curl -X POST http://localhost:3000/api/payments/charges \
  -H "Content-Type: application/json" \
  -d '{"amount": 1000, "currency": "USD", "customer_id": "cus_xxx", "description": "Test charge"}'

# Generate a payment link
curl -X POST http://localhost:3000/api/payments/payment-links \
  -H "Content-Type: application/json" \
  -d '{"amount": 2500, "currency": "USD", "description": "Premium Plan", "success_url": "https://yoursite.com/success", "cancel_url": "https://yoursite.com/cancel"}'

Tarjetas de prueba

Utilice estas tarjetas de prueba en modo sandbox:

Número de tarjeta Resultado
4242 4242 4242 4242 Pago exitoso
4000 0000 0000 9995 Rechazado (fondos insuficientes)
4000 0000 0000 0002 Requiere autenticación 3D Secure
4000 0000 0000 0010 Requiere verificación CVC

Mejores prácticas

Seguridad

  • Nunca expongas tu clave secreta en el código del lado del cliente
  • Usar variables de entorno para todas las credenciales
  • Verificar firmas de webhooks para evitar eventos falsificados
  • Implementar claves de idempotencia para la creación de cargos y evitar duplicados

Manejo de errores

  • Siempre verifique error.response?.data para ver mensajes de error detallados
  • Implementar lógica de reintento para fallas transitorias.
  • Registre todos los eventos de pago para auditoría
  • Maneja las redirecciones 3D Secure con elegancia

Cumplimiento

  • 4Geeks Payments es compatible con PCI DSS: los datos de la tarjeta nunca tocan sus servidores
  • El cumplimiento fiscal se gestiona automáticamente (IVA, impuesto sobre las ventas, GST)
  • Como comerciante registrado, 4Geeks maneja la responsabilidad de devolución de cargo

¿Qué sigue?

¿Necesitas ayuda?


Aún con dudas? Pregunta en Discord o explore tutoriales