Procese su primer pago sandbox
Procese el pago de un pedido de sandbox desde el backend de su comerciante y confirme el resultado final a través de un webhook verificado.
En esta página
Este inicio rápido utiliza el punto final de compra del comerciante. Antes de comenzar, complete configuración de cuenta, elige tu integracióny confirme que su comerciante sandbox tenga:
- Una clave API privada almacenada en su servidor.
- Al menos una conexión de pago activa y una estrategia de enrutamiento.
- Un token de pedido y un token de método de pago creados por la integración del cliente seleccionado.
- Un punto final HTTPS público que puede recibir webhooks DEUNA.
Preparar la solicitud del servidor#
Cargue la clave privada de la zona de pruebas desde el almacenamiento secreto de su servidor. Mantenga el token de pedido y el token de método de pago producidos por el mismo flujo de espacio aislado disponibles para el cuerpo de la solicitud.
DEUNA_PRIVATE_API_KEY=YOUR_SANDBOX_PRIVATE_API_KEYProcesar el pago del pedido#
Envíe el pedido y el método de pago tokenizado al punto final de compra del comerciante verificado. Reutilizar lo mismo X-Idempotency-Key y el cuerpo de la solicitud si un tiempo de espera de la red hace que el resultado sea incierto.
curl --request POST \
--url https://api.sandbox.deuna.io/v2/merchants/orders/purchase \
--header "X-Api-Key: ${DEUNA_PRIVATE_API_KEY}" \
--header "X-Idempotency-Key: order_1042-attempt_1" \
--header "Content-Type: application/json" \
--data '{
"order_token": "YOUR_SANDBOX_ORDER_TOKEN",
"payer_info": {
"email": "buyer@example.com",
"external_user_id": "customer_1042"
},
"payment_source": {
"method_type": "credit_card",
"payment_method": "YOUR_PAYMENT_METHOD_TOKEN"
}
}'const response = await fetch("https://api.sandbox.deuna.io/v2/merchants/orders/purchase", {
method: "POST",
headers: {
"X-Api-Key": "${DEUNA_PRIVATE_API_KEY}",
"X-Idempotency-Key": "order_1042-attempt_1",
"Content-Type": "application/json"
},
body: JSON.stringify({
"order_token": "YOUR_SANDBOX_ORDER_TOKEN",
"payer_info": {
"email": "buyer@example.com",
"external_user_id": "customer_1042"
},
"payment_source": {
"method_type": "credit_card",
"payment_method": "YOUR_PAYMENT_METHOD_TOKEN"
}
})
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const data = await response.json();import requests
response = requests.request(
"POST",
"https://api.sandbox.deuna.io/v2/merchants/orders/purchase",
headers={
"X-Api-Key": "${DEUNA_PRIVATE_API_KEY}",
"X-Idempotency-Key": "order_1042-attempt_1",
"Content-Type": "application/json"
},
json={
"order_token": "YOUR_SANDBOX_ORDER_TOKEN",
"payer_info": {
"email": "buyer@example.com",
"external_user_id": "customer_1042"
},
"payment_source": {
"method_type": "credit_card",
"payment_method": "YOUR_PAYMENT_METHOD_TOKEN"
}
},
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.sandbox.deuna.io/v2/merchants/orders/purchase",
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-Api-Key: ${DEUNA_PRIVATE_API_KEY}",
"X-Idempotency-Key: order_1042-attempt_1",
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => json_encode([
"order_token" => "YOUR_SANDBOX_ORDER_TOKEN",
"payer_info" => [
"email" => "buyer@example.com",
"external_user_id" => "customer_1042"
],
"payment_source" => [
"method_type" => "credit_card",
"payment_method" => "YOUR_PAYMENT_METHOD_TOKEN"
]
])
]);
$response = curl_exec($curl);
curl_close($curl);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.sandbox.deuna.io/v2/merchants/orders/purchase"))
.header("X-Api-Key", "${DEUNA_PRIVATE_API_KEY}")
.header("X-Idempotency-Key", "order_1042-attempt_1")
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString("{\n \"order_token\": \"YOUR_SANDBOX_ORDER_TOKEN\",\n \"payer_info\": {\n \"email\": \"buyer@example.com\",\n \"external_user_id\": \"customer_1042\"\n },\n \"payment_source\": {\n \"method_type\": \"credit_card\",\n \"payment_method\": \"YOUR_PAYMENT_METHOD_TOKEN\"\n }\n }"))
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
"strings"
)
func main() {
request, err := http.NewRequest("POST", "https://api.sandbox.deuna.io/v2/merchants/orders/purchase", strings.NewReader("{\n \"order_token\": \"YOUR_SANDBOX_ORDER_TOKEN\",\n \"payer_info\": {\n \"email\": \"buyer@example.com\",\n \"external_user_id\": \"customer_1042\"\n },\n \"payment_source\": {\n \"method_type\": \"credit_card\",\n \"payment_method\": \"YOUR_PAYMENT_METHOD_TOKEN\"\n }\n }"))
if err != nil { panic(err) }
request.Header.Set("X-Api-Key", "${DEUNA_PRIVATE_API_KEY}")
request.Header.Set("X-Idempotency-Key", "order_1042-attempt_1")
request.Header.Set("Content-Type", "application/json")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}el exacto payment_source y cualquier specific_fields Depende del método de pago seleccionado y del proveedor. Ver Procesar el pago de un pedido para el contrato de solicitud completo.
Manejar el resultado inmediato#
Leer order.payment.data.status y cualquier acción siguiente requerida del pedido devuelto. Un HTTP 2xx significa que DEUNA aceptó o tramitó la solicitud; por sí solo no prueba que el dinero se haya movido.
- Continuar el cumplimiento solo para el estado de éxito confirmado documentado en Flujo y estados de pago.
- Presente cualquier acción del cliente, como la autenticación 3DS, antes de volver a intentarlo.
- Para resultados pendientes o inciertos, recupere el pedido original en lugar de crear un intento duplicado.
- Utilice una nueva clave de idempotencia sólo para un intento de pago materialmente nuevo.
Confirmar el estado final#
Utilice la respuesta sincrónica para actualizar la experiencia del cliente, pero tome decisiones de cumplimiento a partir del último estado verificado. Configure un webhook de comerciante, verifique su firma, elimine la duplicación del evento y luego concilie el pedido.
app.post('/webhooks/deuna', express.raw({type: 'application/json'}), async (request, response) => {
const event = verifyDeunaSignature(request.body, request.headers);
await storeEventOnce(event.id);
await reconcileOrder(event.data.order_token);
response.sendStatus(200);
});