Paypal
This page will help you get started with Paypal.
Content Security Policy (CSP)Para que esta wallet funcione correctamente en tu sitio, debés incluir en tu Content Security Policy los dominios que devuelve el endpoint de Koin. Si no los agregás, el botón o el checkout pueden no cargar.
Changelog
| Fecha | Versión | Breaking changes | Cambios |
|---|---|---|---|
| 24 feb 2026 | 2.1.0 | NO | Ahora se puede forzar el lenguaje mediante el método initialize |
V2.1.0
Integración
Agregar el script de wallets de Koin.
- Producción: https://payments.koin.com.br/checkout/sdk/v1/methods.js
- Sandbox: https://portal-dev.koin.com.br/checkout/sdk/v1/methods.js
API
- Luego de agregar el script de wallets de Koin a tu página tendrás disponible dentro de window un objeto llamado KoinPayments.
- Crear una instancia de la clase order para el método de pago PAYPAL de la siguiente manera:
//Paypal
//Initialize PAYPAL by order
const paypal = await window.KoinPayments.order(orderId);- El paso anterior es el único momento donde nuestro SDK puede arrojar una excepción, por eso recomendamos capturar el error en caso que haya alguno.
Una vez hecho esto, tendremos un objeto creado con los siguientes métodos:
- initialize(afterInitializedCallback, options?)
- El afterInitializedCallback se va a ejecutar solo cuando se haya podido inicializar el sdk con éxito. Caso contrario se puede recibir el error utilizando onError. Opcionalmente podés pasar options:
{ language?: 'es' | 'en' | 'pt' }para forzar el idioma del checkout.
- El afterInitializedCallback se va a ejecutar solo cuando se haya podido inicializar el sdk con éxito. Caso contrario se puede recibir el error utilizando onError. Opcionalmente podés pasar options:
- mount(buttonCssSelector)
- Esta función recibe el siguiente parámetro:
- buttonCssSelector
- Un selector CSS que apunte a un <div> dónde se va a colocar el botón de paypal.
- buttonCssSelector
- Los errores relacionados a esta función también se devuelven en el onError.
- Esta función recibe el siguiente parámetro:
- onError({code: string; message: string; origin: string;}): Manejo de errores de Paypal o Koin. Siempre siguen el mismo formato. Adherimos a la práctica ‘Never throw’ así que no habrá excepciones en ningún momento. Todos los errores saldrán por este método.
- onSuccess({wallet_code: "PAYPAL"; email: string | undefined}): Caso exitoso. Devuelve wallet_code + email (el email es opcional dado que puede que no lo logremos obtener).
- onEvent(code, payload): Eventos para comunicar el estado del proceso cuando sea posible y mantener al tanto al consumidor de nuestro script. El payload es opcional dependiendo del evento que se dispare.
- onFinish(data): Callback que se ejecuta solo si la orden ya estaba terminada al llamar a initialize. El
datacontiene{ status, message }y el mensaje esOrder already finished. Aprobar el pago llega poronSuccess. Cancelar llega por el eventoPAYMENT_CANCELLED.statusesAuthorized,Collected,Cancelled,FailedoVoided. - destroy(): Elimina la instancia existente del SDK de PayPal si hay una.
> Todos los errores durante el flujo PAYPAL se devuelven mediante el onError.
> Los métodos onSuccess, onEvent, onError y onFinish sólo se pueden usar una vez.
Eventos
| Code | Description | Payload |
|---|---|---|
| PAYMENT_STARTED | Ocurre cuando se inicia el flujo de pago con PayPal. | |
| PAYMENT_CANCELLED | Ocurre cuando el usuario cierra el checkout de PayPal o PayPal cierra el checkout internamente. | |
| WALLET_DESTROYED | Ocurre cuando se llamó a destroy() y la instancia fue eliminada. |
Errores
| Code | Message | Origin |
|---|---|---|
| INITIALIZATION_ERROR | Failed to render PayPal button | PAYPAL |
| PAYMENT_ON_APPROVE_ERROR | Failed to capture PayPal payment | PAYPAL |
| PAYMENT_ERROR | Error durante el proceso de pago. | PAYPAL |
| CANCEL_ERROR | Payment was cancelled by the user | PAYPAL |
| NETWORK_ERROR | Error de red durante la operación. | PAYPAL |
| GENERAL_ERROR | {dynamic} | PAYPAL |
| Code | Message | Origin |
|---|---|---|
| NOT_INITIALIZED | You need to initialize the instance first. | KOIN |
| INIT_MISSING_ORDER_ID | the orderId is missing | KOIN |
| INIT_MISSING_CLIENT_ID | Client ID is required during initialization. | KOIN |
| INIT_MISSING_CURRENCY | Currency is required during initialization. | KOIN |
| INIT_MISSING_AMOUNT | Amount is required. | KOIN |
| INIT_MISSING_CREATE_ORDER | Create order data is missing. | KOIN |
| INIT_MISSING_KOIN_ORDER_ID | Koin order ID is required during initialization. | KOIN |
| PAYMENT_INTERNAL_SERVER_ERROR | Error interno del servidor al procesar el pago. | KOIN |
Estados de onFinish
Estos valores solo llegan si la orden ya estaba terminada al llamar a initialize. Opened y Published no llaman a onFinish. message es Order already finished.
| status | Description |
|---|---|
| Authorized | La orden ya estaba autorizada al llamar a initialize. |
| Collected | La orden ya estaba cobrada al llamar a initialize. |
| Cancelled | La orden ya estaba cancelada al llamar a initialize. |
| Failed | La orden ya estaba fallida al llamar a initialize. |
| Voided | La autorización ya estaba anulada al llamar a initialize. |
FAQ
¿onFinish se dispara siempre con la orden en un estado final?
onFinish se dispara siempre con la orden en un estado final?onFinish solo se dispara si la orden ya estaba en un estado final al llamar a initialize. Ese status es final: no corresponde a un evento intermedio, una revisión de antifraude, una autenticación 3DS ni un pago pendiente. Aprobar el pago en vivo llega por onSuccess. Cancelar llega por el evento PAYMENT_CANCELLED.
¿Qué pasa si hay timeout, error de red, o el usuario cierra la pestaña?
Si el usuario cierra la pestaña, el SDK no lo informa por ningún evento. Timeout, error de red y el resultado del flujo en vivo tampoco disparan onFinish. En esos casos el estado de la orden se toma de la notificación por webhook y del GET /v1/payment/orders/{id}. onError no es ese estado: aunque un fallo del SDK pueda llegar por ahí, no reemplaza a la notificación por webhook ni al GET.
Si la orden ya estaba expirada al llamar a initialize, onFinish sí se dispara con status Cancelled.
¿El status de onFinish puede diferir del GET o del webhook?
onFinish puede diferir del GET o del webhook?No. El status de onFinish sale del mismo GET /v1/payment/orders/{id} y es un estado final. Consultar ese GET en ese momento devuelve la misma respuesta.
La fuente de verdad es siempre la notificación por webhook y ese GET. No recomendamos, bajo ningún término, reemplazar la notificación por webhook o el GET Status por el onFinish del SDK.
Cuando se dispara onFinish, ¿el estado ya está en la API?
onFinish, ¿el estado ya está en la API?Sí. Como el status sale de ese mismo GET, no hay demora. El estado ya está reflejado en la API.
Ejemplo
Updated 17 days ago
