Skip to content
Kayana for Business

Construir una Integración Avanzada de Kayana con Stripe en PHP

Last updated Mar 17, 2026

Crea una integración avanzada de Kayana para recopilar pagos con tarjeta de forma segura utilizando la API de Pagos de Kayana impulsada por Stripe para tu tienda de comercio electrónico.

1. Descripción general

La API de pagos de Kayana te permite aceptar pagos sin tener que crear tu propio checkout compatible con PCI.

Esta guía te muestra cómo integrar el flujo de Stripe Embedded Checkout utilizando PHP en modo sandbox.

2. Lo que construirás

En esta guía, podrás:

  1. Crear una instancia de pago en tu servidor PHP
  2. Recuperar la clave publicable de Stripe
  3. Inicializar Stripe en el frontend
  4. Renderizar la cápsula de Embedded Checkout segura de Stripe
  5. Completar el pago de forma segura

3. Antes de comenzar

Necesitarás:

  • Un ID de propiedad de Kayana
  • Acceso al entorno sandbox
  • Conocimientos básicos de PHP
  • Un servidor backend de PHP (se recomienda PHP 7.4+)
  • Un frontend (HTML/JavaScript o cualquier framework)

4. Sandbox vs Producción

Sandbox

Entorno de prueba seguro:

  • Utiliza claves de prueba de Stripe
  • Sin transacciones reales
  • Ideal para desarrollo y pruebas

Producción

  • Requiere un token de autorización
  • Utiliza claves de Stripe en vivo
  • Procesa pagos reales

5. Cómo funciona

El flujo de pagos de Stripe consta de:

5. Cómo funciona
ComponenteDescripción
Lado del servidor (PHP)Crear una instancia de pago usando la API de Kayana
El servidor recibeclient_secret y publishable_key
Lado del clienteInicializar Stripe y renderizar Embedded Checkout
StripeManeja la confirmación de pago de forma segura

6. Configuración del Servidor (PHP)

URL Base

URL Base
EntornoURL
Sandboxhttps://integration.dev.kayana.co.uk
Producciónhttps://integration.kayana.co.uk

Estructura del Proyecto

your-project/ ├── config/ │ └── config.php ├── api/ │ └── create-payment.php ├── public/ │ └── index.html └── .htaccess

7. Paso 1 — Crear un Pago (Backend PHP)

Crea un endpoint de API PHP que llame a la API de pagos de Kayana.

Archivo de Configuración

config/config.php

<?php

return [ 'kayana' => [ 'api_key' => 'YOUR_API_KEY', 'base_url' => 'https://integration.dev.kayana.co.uk', 'property_id' => 'Prop_abc123example', ], 'stripe' => [ 'psp_code' => 'STRIPE', ], ];

⚠️ Importante: Nunca expongas tu clave API en el frontend ni la confirmes en el control de versiones.

Implementación del Servidor PHP

api/create-payment.php

<?php

header('Content-Type: application/json'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type');

// Maneja solicitudes preliminares if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit(); }

// Solo permite solicitudes POST if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode([ 'status' => false, 'message' => 'Método no permitido' ]); exit(); }

// Carga configuración $config = require_once __DIR__ . '/../config/config.php';

// Obtiene el cuerpo de la solicitud $input = json_decode(file_get_contents('php://input'), true);

// Establece valores por defecto o utiliza valores proporcionados $amount = $input['amount'] ?? 12.00; $currency = $input['currency_code'] ?? 'GBP'; $customerEmail = $input['customer_email'] ?? 'customer@example.com';

// Prepara el payload de la solicitud $payload = [ 'property_id' => $config['kayana']['property_id'], 'psp_code' => $config['stripe']['psp_code'], 'currency_code' => $currency, 'amount' => $amount, 'customer_email' => $customerEmail, ];

// Inicializa cURL $ch = curl_init();

curl_setopt_array($ch, [ CURLOPT_URL => $config['kayana']['base_url'] . '/business/payment', CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'x-api-key: ' . $config['kayana']['api_key'], 'type: business', ], CURLOPT_TIMEOUT => 30, CURLOPT_SSL_VERIFYPEER => true, ]);

$response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch);

curl_close($ch);

// Maneja errores de cURL if ($curlError) { http_response_code(500); echo json_encode([ 'status' => false, 'message' => 'Error de conexión: ' . $curlError ]); exit(); }

// Maneja errores HTTP if ($httpCode !== 200) { http_response_code($httpCode); echo json_encode([ 'status' => false, 'message' => 'La creación del pago falló', 'http_code' => $httpCode ]); exit(); }

// Devuelve la respuesta echo $response;

Alternativa: Usando el Cliente HTTP Guzzle

Si prefieres usar Composer y Guzzle:

Instala Guzzle:

composer require guzzlehttp/guzzle

api/create-payment-guzzle.php

<?php

require_once __DIR__ . '/../vendor/autoload.php';

use GuzzleHttp\Client; use GuzzleHttp\Exception\RequestException;

header('Content-Type: application/json'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type');

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { http_response_code(200); exit(); }

if ($_SERVER['REQUEST_METHOD'] !== 'POST') { http_response_code(405); echo json_encode([ 'status' => false, 'message' => 'Método no permitido' ]); exit(); }

$config = require_once __DIR__ . '/../config/config.php'; $input = json_decode(file_get_contents('php://input'), true);

$client = new Client([ 'base_uri' => $config['kayana']['base_url'], 'timeout' => 30, ]);

try { $response = $client->post('/business/payment', [ 'headers' => [ 'Content-Type' => 'application/json', 'x-api-key' => $config['kayana']['api_key'], 'type' => 'business', ], 'json' => [ 'property_id' => $config['kayana']['property_id'], 'psp_code' => $config['stripe']['psp_code'], 'currency_code' => $input['currency_code'] ?? 'GBP', 'amount' => $input['amount'] ?? 12.00, 'customer_email' => $input['customer_email'] ?? 'customer@example.com', ], ]);

echo $response->getBody()->getContents();

} catch (RequestException $e) { http_response_code(500); echo json_encode([ 'status' => false, 'message' => 'La creación del pago falló: ' . $e->getMessage() ]); }

Parámetros de Solicitud

Parámetros de Solicitud
ParámetroTipoDescripción
property_idstringFormato Prop_*
psp_codestringSTRIPE
currency_codestringGBP, EUR, USD
amountnumberCantidad decimal (ejemplo: 12.0)
customer_emailstringEmail del cliente

Ejemplo de Respuesta de API

{ "status": true, "data": { "instance_id": "Payment_xyz789example", "client_secret": "cs_test_abc123_secret_xyz456", "publishable_key": "pk_test_abc123example", "next_step": { "action": "FORM", "proceed": true }, "transaction_id": "Tx_txn456example" } }

Parámetros de Respuesta

Parámetros de Respuesta
ParámetroDescripción
instance_idID de instancia de pago único
client_secretSecreto de sesión de Stripe Checkout
publishable_keyClave pública de Stripe
transaction_idReferencia de transacción interna

⚠️ Importante: client_secret debe usarse solo en el frontend para inicializar Stripe.

8. Paso 2 — Integración Frontend (Stripe Embedded Checkout)

Implementación HTML/JavaScript

public/index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Kayana Stripe Payment</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"> <style> body { min-height: 100vh; background: linear-gradient(135deg, #f3e8ff, #e9d5ff); } .checkout-card { max-width: 600px; border-radius: 16px; box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08); } .pay-btn { background: linear-gradient(90deg, #ef4444, #f97316); border: none; height: 52px; font-size: 16px; font-weight: 600; border-radius: 10px; } .btn-spinner { width: 20px; height: 20px; border: 2px solid rgba(255, 255, 255, 0.4); border-top-color: #fff; border-radius: 50%; animation: spin 0.7s linear infinite; display: inline-block; vertical-align: middle; } @keyframes spin { to { transform: rotate(360deg); } } #checkout-container { min-height: 400px; } </style> </head> <body> <div class="container d-flex align-items-center justify-content-center py-5"> <div class="card checkout-card w-100"> <div class="card-body p-4"> <div class="text-center mb-4"> <h5 class="fw-bold mb-1">Pago con Stripe</h5> <p class="text-muted mb-0">Complete su pago de forma segura</p> </div>

<div id="payment-form-container"> <div class="mb-3"> <label class="form-label">Correo Electrónico</label> <input type="email" id="email" class="form-control" placeholder="customer@example.com" required> </div>

<div class="mb-3"> <label class="form-label">Cantidad</label> <input type="number" id="amount" class="form-control" value="12.00" step="0.01" min="0.50" required> </div>

<div class="mb-4"> <label class="form-label">Moneda</label> <select id="currency" class="form-select"> <option value="GBP">GBP - Libra Esterlina</option> <option value="EUR">EUR - Euro</option> <option value="USD">USD - Dólar Estadounidense</option> </select> </div>

<button id="pay-btn" class="btn pay-btn text-white w-100"> <span class="btn-text">Abrir Pago</span> </button>

<div id="error-message" class="alert alert-danger mt-3 d-none"></div> </div>

<div id="checkout-container"></div> </div> </div> </div>

<script src="https://js.stripe.com/clover/stripe.js"></script> <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> <script> let stripe = null;

function showLoader() { $('#pay-btn') .prop('disabled', true) .html('<span class="btn-spinner"></span> Procesando...'); }

function hideLoader() { $('#pay-btn') .prop('disabled', false) .html('<span class="btn-text">Abrir Pago</span>'); }

function showError(message) { $('#error-message').text(message).removeClass('d-none'); }

function hideError() { $('#error-message').addClass('d-none'); }

$('#pay-btn').on('click', async function() { hideError(); showLoader();

const email = $('#email').val(); const amount = parseFloat($('#amount').val()); const currency = $('#currency').val();

if (!email || !amount) { showError('Por favor, complete todos los campos requeridos.'); hideLoader(); return; }

try { const response = await fetch('/api/create-payment.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ customer_email: email, amount: amount, currency_code: currency, }), });

const data = await response.json();

if (data.status && data.data) { stripe = Stripe(data.data.publishable_key); $('#payment-form-container').addClass('d-none');

const checkout = await stripe.initEmbeddedCheckout({ clientSecret: data.data.client_secret, });

checkout.mount('#checkout-container'); } else { showError(data.message || 'No se pudo crear la sesión de pago.'); hideLoader(); } } catch (error) { console.error('Error:', error); showError('Ocurrió un error inesperado. Por favor, intente nuevamente.'); hideLoader(); } }); </script> </body> </html>

9. Flujo de Pago

El usuario hace clic en "Pagar" ↓ Frontend llama a la API PHP ↓ PHP llama a la API de Kayana ↓ Kayana crea sesión de Stripe Checkout ↓ Devuelve: client_secret publishable_key ↓ Frontend carga Stripe ↓ Aparece Stripe Embedded Checkout ↓ El usuario ingresa detalles de la tarjeta ↓ Stripe confirma el pago

10. Pruebas en Sandbox

Usa tarjetas de prueba de Stripe:

10. Pruebas en Sandbox
Número de tarjetaMarcaEscenario
4242 4242 4242 4242VisaExitoso
4000 0025 0000 3155VisaRequiere 3D Secure
4000 0000 0000 9995VisaRechazado

Detalles adicionales:

  • Vencimiento → Cualquier fecha futura
  • CVC → Cualquier 3 dígitos
  • ZIP → Cualquier formato válido

⚠️ Advertencia: Nunca uses tarjetas de prueba en producción.

11. Manejo de Errores

Todas las respuestas incluyen:

{ "status": false, "message": "Description of error" }

Errores Comunes

Errores Comunes
ErrorCausaSolución
Clave API inválidax-api-key incorrectoVerificar con Kayana
ID de propiedad inválidoFormato incorrectoDebe comenzar con Prop_*
Moneda no compatibleNo habilitadaContactar a Kayana
Configuración de Stripe faltantePSP no habilitadoContactar a Kayana

12. Gestor de Webhook (Opcional)

api/webhook.php

<?php

$config = require_once __DIR__ . '/../config/config.php';

$payload = file_get_contents('php://input'); $sigHeader = $_SERVER['HTTP_STRIPE_SIGNATURE'] ?? ''; $endpointSecret = $config['stripe']['webhook_secret'] ?? '';

try { $event = json_decode($payload, true);

switch ($event['type']) { case 'checkout.session.completed': $session = $event['data']['object']; // Manejar pago exitoso // Actualizar estado del pedido en la base de datos error_log('Payment completed: ' . $session['id']); break;

case 'payment_intent.succeeded': $paymentIntent = $event['data']['object']; error_log('PaymentIntent succeeded: ' . $paymentIntent['id']); break;

case 'payment_intent.payment_failed': $paymentIntent = $event['data']['object']; error_log('PaymentIntent failed: ' . $paymentIntent['id']); break;

default: error_log('Unhandled event type: ' . $event['type']); }

http_response_code(200); echo json_encode(['received' => true]);

} catch (Exception $e) { http_response_code(400); echo json_encode(['error' => $e->getMessage()]); }

13. Lista de verificación para puesta en producción

Antes de producción:

Obtén production x-api-key

Cambia a production base URL

Usa live Stripe publishable key

Prueba transacciones con tarjetas reales

Implementa Stripe webhooks

Configura un registro de errores adecuado

Habilita HTTPS en tu servidor

Nunca:

  • Uses claves sandbox en producción
  • Expongas claves secretas en el frontend
  • Registres datos de pago sensibles

14. Mejores prácticas de seguridad

  1. Almacena las claves API de forma segura - Utiliza variables de entorno o archivos de configuración seguros
  2. Valida todas las entradas - Sanitiza y valida la entrada del usuario en el servidor
  3. Utiliza HTTPS - Siempre sirve tus páginas de pago a través de HTTPS
  4. Implementa protección CSRF - Añade tokens CSRF a tus formularios
  5. Limitación de velocidad - Implementa limitación de velocidad en tus puntos finales de API

15. Soporte

  • Soporte Técnico: Equipo Técnico de Kayana
  • Credenciales de producción: Póngase en contacto con el Gestor de Cuenta de Kayana
  • Documentación: Centro de Ayuda de Kayana

Próximos Pasos

Si prefieres usar RYFT como tu Proveedor de Servicios de Pago (PSP), Kayana también admite un flujo de integración completo de RYFT. Consulta nuestra guía sobre Crear una integración avanzada de Kayana en PHP.

Still need a hand?Contact support← All help
Escríbenos por WhatsApp