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

FechaVersiónBreaking changesCambios
24 feb 20262.1.0NOAhora se puede forzar el lenguaje mediante el método initialize

V2.1.0

Integración

Agregar el script de wallets de Koin.

  1. Producción: https://payments.koin.com.br/checkout/sdk/v1/methods.js
  2. Sandbox: https://portal-dev.koin.com.br/checkout/sdk/v1/methods.js

API

  1. Luego de agregar el script de wallets de Koin a tu página tendrás disponible dentro de window un objeto llamado KoinPayments.
  2. 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);
  1. 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:

  1. 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.
  2. 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.
    • Los errores relacionados a esta función también se devuelven en el onError.
  3. 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.
  4. 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).
  5. 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.
  6. onFinish(data): Callback que se ejecuta solo si la orden ya estaba terminada al llamar a initialize. El data contiene { status, message } y el mensaje es Order already finished. Aprobar el pago llega por onSuccess. Cancelar llega por el evento PAYMENT_CANCELLED. status es Authorized, Collected, Cancelled, Failed o Voided.
  7. 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

CodeDescriptionPayload
PAYMENT_STARTEDOcurre cuando se inicia el flujo de pago con PayPal.
PAYMENT_CANCELLEDOcurre cuando el usuario cierra el checkout de PayPal o PayPal cierra el checkout internamente.
WALLET_DESTROYEDOcurre cuando se llamó a destroy() y la instancia fue eliminada.

Errores

CodeMessageOrigin
INITIALIZATION_ERRORFailed to render PayPal buttonPAYPAL
PAYMENT_ON_APPROVE_ERRORFailed to capture PayPal paymentPAYPAL
PAYMENT_ERRORError durante el proceso de pago.PAYPAL
CANCEL_ERRORPayment was cancelled by the userPAYPAL
NETWORK_ERRORError de red durante la operación.PAYPAL
GENERAL_ERROR{dynamic}PAYPAL
CodeMessageOrigin
NOT_INITIALIZEDYou need to initialize the instance first.KOIN
INIT_MISSING_ORDER_IDthe orderId is missingKOIN
INIT_MISSING_CLIENT_IDClient ID is required during initialization.KOIN
INIT_MISSING_CURRENCYCurrency is required during initialization.KOIN
INIT_MISSING_AMOUNTAmount is required.KOIN
INIT_MISSING_CREATE_ORDERCreate order data is missing.KOIN
INIT_MISSING_KOIN_ORDER_IDKoin order ID is required during initialization.KOIN
PAYMENT_INTERNAL_SERVER_ERRORError 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.

statusDescription
AuthorizedLa orden ya estaba autorizada al llamar a initialize.
CollectedLa orden ya estaba cobrada al llamar a initialize.
CancelledLa orden ya estaba cancelada al llamar a initialize.
FailedLa orden ya estaba fallida al llamar a initialize.
VoidedLa autorización ya estaba anulada al llamar a initialize.

FAQ

¿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?

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?

Sí. Como el status sale de ese mismo GET, no hay demora. El estado ya está reflejado en la API.

Ejemplo