Saltar al contenido
ESENIr al Portal

Funciones por integración

Devoluciones y avisos por WhatsApp: qué podés usar, cómo se piden y qué elegís vos.

Dos funciones se configuran por integración:

Función Cómo la activás Qué elegís vos, en Configuración
Avisos por WhatsApp Ya vienen activos (Chytapay puede limitarlos) Si sale el aviso del cobro
Devoluciones Pedilas a contacto@chytapay.com.ar Qué devoluciones automáticas corren

Cómo se activan

Se configuran en Producción. Lo que tu integración no tiene aparece bloqueado, con un botón para pedirlo. El Portal no tiene un botón para devolver un cobro: eso lo hacés por API, o lo hace soporte de Chytapay.

Devoluciones

La plata vuelve a la cuenta desde la que se pagó. Pedí los modos que vayas a usar:

Modo Qué hace
Por API Devolvés un cobro, total o parcial, con el endpoint de devoluciones.
Automática por excedente Si el pagador transfiere de más, devolvemos la diferencia (desde $1).
Automática por pago de menos Si el pagador transfiere menos del total, devolvemos el pago entero. Llega payment.unmatched con motivo partial_not_accepted.
Automática sin asignar Si una transferencia no corresponde a ningún cobro, la devolvemos.

Devolver por API

Necesitás dos cosas: el modo por API en tu integración y la autorización del comercio. Mandá la autorización escrita del comercio a [email protected] o por WhatsApp al +54 9 351 543 0077. Hasta entonces el endpoint responde 403 RefundsNotConsentedError. Se devuelven pagos de los últimos 10 días. Con el id_token del comercio:

cURL

curl -X POST https://integration-api.test.chytapay.com.ar/payment-request/pedido-1001/refunds \
  -H "Authorization: Bearer $ID_TOKEN" \
  -H "Idempotency-Key: devolucion-pedido-1001-a" \
  -H "Content-Type: application/json" \
  -d '{ "amount": 5000, "reason": "Producto sin stock" }'

Respuesta

{
  "refundId": "00000000-0000-0000-0000-000000000000",
  "paymentRequest": { "referenceId": "pedido-1001", "state": "total_payment" },
  "origin": "api",
  "trigger": null,
  "status": "pending",
  "requestedAmount": 5000,
  "refundedAmount": 0,
  "reason": "Producto sin stock",
  "items": [{ "amount": 5000, "status": "pending" }]
}

Responde 202: la devolución es asincrónica y el resultado llega por webhook.

Campo ¿Obligatorio? Qué es
Idempotency-Key (header) Sí De 1 a 255 caracteres. Un reintento con la misma clave y el mismo cuerpo devuelve la misma devolución.
amount No Pesos, mayor a 0, hasta 2 decimales. Sin él, se devuelve todo lo que queda de los pagos de los últimos 10 días. Con él, esa parte, del pago más nuevo al más viejo.
reason No Hasta 500 caracteres.

Podés hacer devoluciones parciales una tras otra hasta el total, de a una por vez. Para consultar una devolución, GET /refunds/{refundId} (incluye las automáticas).

status es pending, processing, succeeded, failed o partially_failed. Un cobro devuelto pasa a refunded o partially_refunded.

Ver los errores de devoluciones

Los mensajes de la API están en inglés.

Status Error Cuándo
400 IdempotencyKeyRequiredError Falta el header Idempotency-Key o tiene más de 255 caracteres.
403 RefundsNotEnabledError Tu integración no tiene devoluciones. Pedilas.
403 ApiRefundsNotAllowedError Tu integración no tiene el modo por API. Pedilo.
403 RefundsNotConsentedError Falta la autorización del comercio para devolver por API.
404 PaymentRequestNotFoundError No hay un cobro con ese referenceId en tu integración.
409 RefundAlreadyRefundedError, RefundInProgressError Ya está devuelto, o tiene una devolución en curso.
409 RefundNoPaymentsError, RefundPaymentTooOldError No hay pagos para devolver, o ninguno en los últimos 10 días.
409 RefundPaymentNotSettledError, RefundPaymentWithoutOriginError Un pago todavía no llegó a la cuenta principal del comercio, o no tiene cuenta de origen.
409 RefundInvoicedPaymentRequestError El cobro está facturado: pedí la devolución a soporte.
409 RefundInsufficientBalanceError El comercio no tiene saldo para la devolución.
409 IdempotencyRequestInProgressError Otra solicitud con la misma clave sigue en curso.
422 RefundAmountExceedsRefundableError El monto supera lo que queda por devolver.
422 IdempotencyKeyReusedError La clave ya se usó con otro cuerpo.
503 PrincipalBalanceUnavailableError No pudimos consultar el saldo. No se creó nada: reintentá con la misma clave.

Devoluciones automáticas

Elegís cuáles corren en Configuración, Devoluciones. Un modo recién activado arranca prendido, salvo que ya hayas elegido sobre él: desde ese momento, las transferencias que cumplan la condición se devuelven solas. No necesitan la autorización del comercio.

No corren si el comercio tiene más de una integración activa y la transferencia no se asignó a un cobro.

Eventos de devolución

refund.succeeded (toda la plata volvió al pagador) y refund.failed (al menos una parte no se pudo devolver) vienen apagados. Activalos en Webhooks, pestaña Eventos. Llegan a las mismas URLs que el resto, con la misma firma.

Ejemplo de refund.succeeded:

JSON
{
  "event": "refund.succeeded",
  "livemode": false,
  "refundId": "00000000-0000-0000-0000-000000000000",
  "paymentRequest": { "referenceId": "pedido-1001", "state": "partially_refunded" },
  "origin": "api",
  "trigger": null,
  "status": "succeeded",
  "requestedAmount": 5000,
  "refundedAmount": 5000,
  "reason": "Producto sin stock",
  "items": [{ "amount": 5000, "status": "succeeded" }],
  "merchantUserId": "00000000-0000-4000-8000-000000000001",
  "merchantTaxId": "30712345671",
  "merchantName": "Comercio de Prueba"
}
  • origin dice quién la pidió: api, merchant, chyta (soporte) o auto.
  • trigger solo viaja con auto: unmatched, partial o excess.
  • paymentRequest es null en la devolución automática de una transferencia que no se asignó a ningún cobro.
  • reason es null en las devoluciones que pide soporte.
  • tenantKey viaja solo si el comercio está en una sede.

Avisos por WhatsApp

Son mensajes de Chytapay al pagador:

Mensaje Qué manda
Aviso del cobro El link de pago por WhatsApp al crear el cobro, y sus recordatorios. Solo sale si el cobro tiene monto y customer.phoneNumber.
Confirmación de pago Avisa al pagador cuando el pago se acredita.

Qué arranca activado

Por defecto sale la confirmación de pago. El aviso del cobro arranca apagado: lo prendés vos en Configuración, Avisos por WhatsApp, y recién entonces rige.

Lo que elegís ahí vale cuando el cobro no dice nada. Lo que el cobro manda gana:

  • sendWhatsappNotification omitido usa tu elección. true o false en el cobro la pisa.
  • sendWhatsappPaymentConfirmation omitido conserva el comportamiento de cada modo de conciliación. Está en confirmación de pago.

Si un cobro pide un mensaje que tu integración no tiene, la API responde 403 (WhatsappNotEnabledError, WhatsappNotificationNotAllowedError o WhatsappPaymentConfirmationNotAllowedError). Escribinos para activarlo. El tope diario de mensajes sigue rigiendo.