API Referencia
undefined

Onepay

Conceptos y SDKs

El flujo de Onepay varía ligeramente según el canal mediante el cual se enlaza la transacción con la app Onepay en el teléfono del usuario. Los canales son:

  • WEB: Web desktop. En este caso aparece un QR en la pantalla del comercio que le permite al usuario escanearlo con la app Onepay y confirmar la transacción. El comercio es notificado cuando el usuario ha completado la transacción.

  • MOBILE: Web móvil. Aquí el navegador móvil abre la app Onepay, donde el usuario confirma directamente la transacción. Luego la app Onepay abre una nueva pestaña del navegador del sistema para notificar al comercio que se ha completado la transacción.

  • APP: Integración app-to-app. Aquí el comercio cuenta con una app móvil que abre la app Onepay cuando el usuario desea pagar usando este medio de pago. Una vez se completa la transacción, la app Onepay invoca nuevamente la app del comercio.

Para los dos primeros canales (WEB y MOBILE) se ofrece un SDK Javascript con dos modalidades de integración:

  • Checkout: Integración recomendada que maneja toda la comunicación con Onepay e informa al usuario de los pasos a seguir a través de un diálogo "modal". En esta modalidad el comercio indica dos urls que conectan el frontend del comercio con el backend. La primera url es la encargada de crear la transacción. La segunda url es la que toma el control después de que el usuario completa el flujo en la app. Checkout se encarga de hacer invisibles las diferencias entre el canal WEB y MOBILE.

  • QR Directo: La versión "hágalo usted mismo" para usuarios avanzados. Provee más flexibilidad pero es más compleja y requiere más trabajo la integración. Se le entregan al comercio las herramientas para dibujar el código QR y para "escuchar" los eventos que van ocurriendo en la app del usuario. También se incluye una forma de abrir la app de Onepay en caso de canal MOBILE, pero toda la lógica debe ser manejada por el comercio.

Para el canal APP se ofrecen SDKs iOS y Android

Finalmente, para las labores del backend, se ofrecen SDKs para Java, .NET, PHP, Ruby y Python. Estos SDKs se utilizan en todos los casos, independiente del canal y de la modalidad de integración web.

Integración Checkout

1. Front-end: Configuración.

Para realizar la integración checkout debes utilizar nuestro SDK Javascript siguiendo las instrucciones de instalación.

Luego en tu frontend debes invocar a Onepay.checkout de la siguiente forma:

Onepay.checkout({
  endpoint: './transaction-create',
  commerceLogo: 'https://tu-url.com/images/icons/logo-01.png',
  callbackUrl: './onepay-result'
});

Esto abrirá un modal que se encargará de toda la interacción con el usuario.

A continuación una descripción de los parámetros recibidos por esta función:

  • endpoint : corresponde a la URL de tu backend que tiene la lógica de crear la transacción usando alguno de nuestros SDK disponibles o invocando directamente al API de Onepay.

El SDK enviara el parámetro channel a tu endpoint, cuyo valor podría ser "WEB" o "MOBILE". Debes asegurarte de capturar este parámetro para poder enviar el channel adecuado al API de Onepay.

Se espera que el endpoint retorne un JSON como el del siguiente ejemplo:

{
 "externalUniqueNumber":"38bab443-c55b-4d4e-86fa-8b9f4a2d2d13",
 "amount":88000,
 "qrCodeAsBase64":"QRBASE64STRING",
 "issuedAt":1534216134,
 "occ":"1808534370011282",
 "ott":89435749
}

En el paso 2 más abajo podrás ver más información sobre este endpoint.

  • commerceLogo: Corresponde a la URL full del logo de comercio que se mostrará en el modal. Como el modal reside en un dominio externo, no puede ser una URL relativa (a diferencia de los otros parámetros). El logo se redimensionará a 125 pixeles de ancho y la altura se calcula automáticamente para mantener las proporciones de la imagen.
  • callbackUrl : URL que se invocará desde el SDK una vez que la transacción ha sido autorizada por el comercio. En este callback el comercio debe hacer la confirmación de la transacción, para lo cual dispone de 30 segundos desde que la transacción se autorizó, de lo contrario esta sera automáticamente reversada.

En el paso 3 más abajo podrás ver más sobre cómo se invoca este callback.

2. Back-end: Crear una Transacción

Como puedes imaginar, para completar la integración necesitarás programar el código que maneja las llamadas en las URLs indicadas por endpoint y callbackUrl.

Primero que nada, deberás configurar también el callbackUrl en el backend. La razón detrás de esto es que si el canal es MOBILE no es el componente javascript quien invocará el callback, sino que la propia app Onepay que reside en el teléfono del usuario. La configuración del callback en el backend le permite a la app Onepay saber donde redireccionar en ese caso:

import cl.transbank.onepay.Onepay;


// URL de retorno para canal MOBILE (web móvil). También será usada en canal WEB
// si integras la modalidad checkout del SDK javascript.
Onepay.setCallbackUrl("https://www.misitioweb.com/onepay-result");
use Transbank\Onepay\OnepayBase;

OnepayBase::setCallbackUrl('https://www.misitioweb.com/onepay-result');
using Transbank.Onepay;

Onepay.CallbackUrl = "https://www.misitioweb.com/onepay-result";
require 'transbank/sdk'

Transbank::Onepay::Base.callback_url = "https://miapp.cl/endPayment"
from transbank import onepay
onepay.callback_url = "https://www.misitioweb.com/onepay-result"

Con eso estás preparado para crear una transacción. Para esto se debe crear en primera instancia un objeto ShoppingCart que se debe llenar un Item (o varios):

import cl.transbank.onepay.model.*;

//...

ShoppingCart cart = new ShoppingCart();
cart.add(
    new Item()
        .setDescription("Zapatos")
        .setQuantity(1)
        .setAmount(15000)
        .setAdditionalData(null)
        .setExpire(-1));
use Transbank\Onepay\ShoppingCart;
use Transbank\Onepay\Item;
use Transbank\Onepay\Transaction;

$cart = new ShoppingCart();
$cart->add(new Item('Zapatos', 1, 15000));
using Transbank.Onepay:
using Transbank.Onepay.Model:

//...

ShoppingCart cart = new ShoppingCart();
cart.Add(new Item(
    description: "Zapatos",
    quantity: 1,
    amount: 15000,
    additionalData: null,
    expire: -1));
require 'transbank/sdk'

cart = Transbank::Onepay::ShoppingCart.new
cart.add(Transbank::Onepay::Item.new(amount: 15000,
                  quantity: 1,
                  description: "Zapatos",
                  additional_data: nil,
                  expire: -1))
from transbank.onepay.cart import ShoppingCart, Item

cart = ShoppingCart()
cart.add(Item(description="Zapatos", 
              quantity=1, amount=15000, 
              additional_data=None, expire=None))

Item con amount negativo

$cart->add(new Item('Descuento', 1, -100));
cart.add(new Item()
        .setDescription("Descuento")
        .setQuantity(1)
        .setAmount(-100));
cart.Add(new Item(description: "Descuento",
                quantity: 1,
                amount: -100));
cart.add(Transbank::Onepay::Item.new(amount: -100,
                quantity: 1,
                description: "Descuento"))
cart.add(Item(description="Descuento",
            quantity=1,
            amount=-100))

Se permite agregar un Item al carro con amount negativo que generalmente representa un descuento. Lo importante es que el monto total en el carro de compras debe ser positivo, en caso contrario se lanzará una excepción.

Luego que el carro de compras contiene todos los ítems, se crea la transacción:

import cl.transbank.onepay.model.*;

// ...

Onepay.Channel channel = Onepay.Channel.valueOf(request.getParameter("channel"));
TransactionCreateResponse response = Transaction.create(cart, channel);
$channel = $request->input("channel");
$response = Transaction::create($cart, $channel);
using Transbank.Onepay;
using Transbank.Onepay.Model:

// ...
ChannelType channelType = ChannelType.Parse(channel);
var response = Transaction.Create(cart, channelType);
require 'transbank/sdk'

channel = params["channel"]
response = Transbank::Onepay::Transaction.create(shopping_cart: cart,
                                                 channel: channel)
from transbank.onepay.transaction import Transaction, Channel

channel = Channel(request.form.get("channel"))
response = Transaction.create(cart, channel)

El segundo parámetro en el ejemplo corresponde al channel y debes capturar el valor que el frontend envió cuando invoco al endpoint que está creando la transacción para fijar el valor correcto ("WEB" si se trata de web desktop, "MOBILE" si se trata de web móvil).

El resultado entregado contiene la confirmación de la creación de la transacción, en la forma de un objeto TransactionCreateResponse.

"occ": "1807983490979289",
"ott": 64181789,
"signature": "USrtuoyAU3l5qeG3Gm2fnxKRs++jQaf1wc8lwA6EZ2o=",
"externalUniqueNumber": "f506a955-800c-4185-8818-4ef9fca97aae",
"issuedAt": 1532103896,
"qrCodeAsBase64": "QRBASE64STRING"

El externalUniqueNumber corresponde a un UUID generado por SDK que identifica la transacción en el lado del comercio. Opcionalmente, puedes especificar tus propios external unique numbers.

En el caso que no se pueda completar la transacción o responseCode en la respuesta del API sea distinto de ok se lanzará una excepción.

Con eso ya tienes la información suficiente para responder el JSON que espera la modalidad checkout, pues sólo debes eliminar signature y agregar amount desde el ShoppingCart que construiste anteriormente. Con eso retornas algo como esto:

{
"occ": "1807983490979289",
"ott": 64181789,
"externalUniqueNumber": "f506a955-800c-4185-8818-4ef9fca97aae",
"issuedAt": 1532103896,
"qrCodeAsBase64": "QRBASE64STRING",
"amount":88000
}

Y en este punto el SDK frontend toma el control de la coordinación. Si el canal es WEB se le mostrará un "modal" al usuario donde podrá escanear el código QR y también recibirá las instrucciones de cada paso a realizar para autorizar el pago. Si el canal es MOBILE el SDK javascript automáticamente abrirá la app Onepay en el mismo teléfono del usuario.

3. Back-end: Confirmar la Transacción

Eventualemnte la transacción llegará a término y el control retornará al backend mediante el metodo GET en la url indicada en el callbackUrl en el paso 1 (frontend) y 2 (backend). Es muy importante que pongas la misma URL en ambos pasos. De esta forma sólo tienes que escribir un único código que maneje la confirmación de la transacción independiente si el canal es WEB o MOBILE.

Para el canal WEB (desktop) en la integración checkout el resultado de éxito o fracaso le aparecerá comunicado al usuario dentro del diálogo modal, para luego redirigir al usuario al callback espeficado en el paso 1. Para el canal MOBILE la app de Onepay abrirá una nueva pestaña en el navegador móvil del usuario y en esa pestaña se invocará la url de callback especificado en el paso 2.

En este callback el comercio debe hacer la confirmación de la transacción, para lo cual dispone de 30 segundos desde que la transacción se autorizó. De lo contrario esta sera automáticamente reversada.

El callback será invocado vía GET e irán los parametros occ y externalUniqueNumber con los cuales podrás invocar la confirmación de la transacción desde tu backend. Adicionalmente se envía el parámetro status, que puede tomar los siguientes valores:

  • PRE_AUTHORIZED: El estado de éxito. Debes confirmar la transacción para completar el flujo.
  • CANCELLED_BY_USER: El tarjetahabiente decidió abortar la autorización.
  • REJECTED: La transacción fue rechazada.
  • REVERSED: No se pudo confirmar el pago.
  • REVERSE_NOT_COMPLETED: Se intentó reversar (ver estado anterior) pero falló por alguna razón interna.

Si se recibe cualquier otro valor, el comercio debe asumir que ocurrió un error.

Finalmente, se debe confirmar la transacción:

import cl.transbank.onepay.model.*;

String status = request.getParameter("status");
String externalUniqueNumber = request.getParameter("externalUniqueNumber");
String occ = request.getParameter("occ");

if (null != status && status.equalsIgnoreCase("PRE_AUTHORIZED")) {
    try { 
        TransactionCommitResponse response =
            Transaction.commit(occ, externalUniqueNumber);
        // Procesar response
    } catch (TransbankException e) {
        // Error al confirmar la transaccion
    }
} else {
    // Mostrar página de error
}
use Transbank\Onepay\Transaction;

$status = $request->input("status");
$externalUniqueNumber = $request->input("externalUniqueNumber");
$occ = $request->input("occ");

if (!empty($status) && strcasecmp($status,"PRE_AUTHORIZED") == 0) {
    try { 
        $response = Transaction::commit($occ, $externalUniqueNumber);
        // Procesar $response
    } catch (Exception $e) {
        // Error al confirmar la transaccion
    }
} else {
    // Mostrar página de error
}
using Transbank.Onepay;

 if (null != status && status.Equals("PRE_AUTHORIZED", StringComparison.InvariantCultureIgnoreCase))
 {
    try
    { 
        var response = Transaction.Commit(occ, externalUniqueNumber);
        // Procesar response
    }
    catch (TransbankException e)
    {
        // Error al confirmar la transaccion
    }
}
else
{
    // Mostrar página de error
}
require 'transbank/sdk'

if params["status"] == "PRE_AUTHORIZED"
  response = Transbank::Onepay::Transaction.commit(
    occ: params["occ"],
    external_unique_number: params["external_unique_number"]
  )
  # Procesar response

else
  # Mostrar página de error
end

rescue Transbank::Onepay::Errors::TransactionCommitError => e
  # Manejar el error de confirmación de transacción
if (status and status.upper() == "PRE_AUTHORIZED"):
  try:
    response = Transaction.commit(occ, external_unique_number)
    # Procesar response
  except TransactionCommitError:
    # Error al confirmar la transacción
else:
  # Mostrar página de error

El resultado obtenido en response tiene una forma como la de este ejemplo:

"occ": "1807983490979289",
"authorizationCode": "623245",
"issuedAt": 1532104549,
"signature": "FfY4Ab89rC8rEf0qnpGcd0L/0mcm8SpzcWhJJMbUBK0=",
"amount": 27500,
"transactionDesc": "Venta Normal: Sin cuotas",
"installmentsAmount": 27500,
"installmentsNumber": 1,
"buyOrder": "20180720122456123"

Para completar el flujo, solo queda que le des la noticia al usuario de que el pago ha sido exitoso y le muestres un comprobante de ser necesario.

Integración en App Móvil Comercio

Si tu comercio posee una app móvil, entonces debes integrar también los SDKs móviles. Comienza revisando la manera de instalar el SDK Android y el SDK iOS.

A diferencia de la modalidad Checkout, en la integración con tu app tú debes encargarte directamente de la comunicación entre tu app y tu backend.

Pero como ya tienes creado el código que maneja la transacción, lo que te falta por hacer eso sólo conectar las partes.

Primero tienes en el backend que configurar el equivalente al callbackUrl pero para apps. Se trata del appScheme, que le dice a la app de Onepay cómo entregarle de vuelta el control a tu propia aplicación:

import cl.transbank.onepay.Onepay;

Onepay.setAppScheme("mi-app://mi-app/onepay-result");
use Transbank\Onepay\OnepayBase;

OnepayBase::setAppScheme("mi-app://mi-app/onepay-result");
using Transbank.Onepay:

Onepay.AppScheme = "mi-app://mi-app/onepay-result";
require 'transbank/sdk'

Transbank::Onepay::Base.app_scheme = "mi-app://mi-app/onepay-result"
from transbank import onepay

onepay.app_scheme = "mi-app://mi-app/onepay-result"

Luego puedes invocar al mismo endpoint que construiste para Checkout, pero ahora lo llamas desde tu app pasando APP en el parámetro channel (via POST).

Con eso obtendrás en tu app los datos de la nueva transacción. Usando el occ puedes usar nuestro SDK para invocar la app de Onepay:

import OnePaySDK
import os.log
//...

let onepay = OnePay();
onepay.initPayment("aqui-va-la-occ",
    callback: {(statusCode, description) in
        switch statusCode {
        case OnePayState.occInvalid:
            // Algo anda mal con el occ que obtuviste desde el backend
            // Debes reintentar obtener el occ o abortar
            os_log("OCC inválida")
        case OnePayState.notInstalled:
            // Onepay no está instalado.
            // Debes abortar o pedir al usuario instalar Onepay (y luego reintentar initPayment)
            os_log("Onepay no instalado")
        }
    }
)

En Android:

import cl.ionix.tbk_ewallet_sdk_android.Error;
import cl.ionix.tbk_ewallet_sdk_android.OnePay;
import cl.ionix.tbk_ewallet_sdk_android.callback.OnePayCallback;
//...

OnePay onepay = new OnePay(this);
onepay.initPayment("occ", new OnePayCallback() {
    @Override
    public void failure(Error error, String s) {
        switch (error) {
            case INVALID_OCC:
                // Algo anda mal con el occ que obtuviste desde el backend
                // Debes reintentar obtener el occ o abortar
                break;
            case ONE_PAY_NOT_INSTALLED:
                // Onepay no está instalado.
                // Debes abortar o pedir al usuario instalar Onepay (y luego reintentar initPayment)
                break;
            default:
                Log.e(TAG, "Error inesperado al iniciar pago Onepay " + error.toString() + ":" + s);
                // Aborta o reintenta
        }
    }
});

Si todo funciona OK, el control pasará a la app Onepay donde el usuario podrá autorizar la transacción.

Una vez el usuario realice el pago, el control volverá a tu app usando el appScheme que configuraste anteriormente.

Para eso, en iOS debes agregar una entrada a Info.plist para majar el scheme indicado. Por ejemplo, si tu appScheme fuera mi-app://mi-app/onepay-result, agregarías lo siguiente:

    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>mi-app</string>
            </array>
            <key>CFBundleURLName</key>
            <string>cl.micomercio.mi-app</string>
        </dict>
    </array>

Y en tu AppDelegate deberás manejar esas urls que comiencen con mi-app:

func application(_ app: UIApplication, open url: URL,
                 options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {

    let sendingAppID = options[.sourceApplication]
    print("source application = \(sendingAppID ?? "Unknown")")
    guard
        let components = NSURLComponents(url: url, resolvingAgainstBaseURL: true),
        let host = components.host,
        let path = components.path,
        let params = components.queryItems
        else {
            os_log("URL, host, path o params inválidos: %s", url.absoluteString)
            return false
    }
    if (host == "mi-app" && path == "onepay-result") {
        guard
            let occ = params.first(where: { $0.name == "occ" })?.value,
            let externalUniqueNumber = params.first(where: { $0.name == "externalUniqueNumber" })?.value
            else {
                os_log("Falta un parámetro occ o externalUniqueNumber: %s", url.absoluteString)
                return false
        }
        // Envia el occ y el externalUniqueNumber a tu backend para que
        // confirme la transacción
        print(occ, externalUniqueNumber)

    } else {
        // Otras URLs que quizás maneja tu app
    }
    return false

}

En Android debes registrar un Activity que responda a la URL registrada en dicho appScheme. Para eso debes configurar un intent filter a tu activity.

<activity ...>
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="mi-app" android:host="mi-app" android:path="onepay-result" />
  </intent-filter>
</activity>

Luego en ese Activity podrás obtener el resultado de la transacción a través del Intent:

Intent intent = getIntent();
String occ = intent.getStringExtra("occ");
String externalUniqueNumber = intent.getStringExtra("externalUniqueNumber");

Finalmente deberás enviar el occ y el externalUniqueNumber a tu backend (quizás quieras reusar el mismo callbackUrl que confirma transacciones en modo checkout, pasando el status "PRE_AUTHORIZED" y algun parámetro adicional que le haga saber a tu backend que devuelva JSON en lugar de dibujar una página web con el comprobante).

Con eso has concluido la integración de Onepay, incluyendo sus cuatro componentes: backend, frontend-web (soportando canales WEB y MOBILE) y las dos apps móviles (para el canal APP). ¡Felicitaciones!

Integración en modalidad "cortafila"

Las modalidades vistas hasta ahora contemplan que tu aplicación es usada directamente por el comprador (tarjetahabiente), quien compra directamente desde tu app móvil o desde tu web (y es dirigido a la app Onepay de la manera más apropiada).

Onepay ofrece la flexibilidad para ser usado también en la modalidad "cortafila" en tus tiendas físicas. Allí un vendedor usando por ejemplo un tablet puede acercarse a los compradores y procesar rápidamente su compra usando Onepay.

Para hacer funcionar este proceso la integración es un poco diferente a las vistas anteriormente. Suponiendo que la app para el vendedor es una app móvil, ahora verás los pasos necesarios para realizar la integración.

1. Tu app móvil inicia el flujo.

Para comenzar, la app móvil del vendedor será la que inicie la transacción.
Esta app debe invocar a tu backend (por ejemplo a través de un API REST).

2. Tu backend crea la transacción Onepay

import cl.transbank.onepay.Onepay;
import cl.transbank.onepay.model.*;

// ...

Onepay.setCallbackUrl("https://miapp.cl/endPayment");
TransactionCreateResponse response = Transaction.create(cart, Channel.MOBILE);
use Transbank\Onepay;

OnepayBase::setCallbackUrl("https://miapp.cl/endPayment");
$channel = ChannelEnum::MOBILE();
$response = Transaction::create($cart, $channel);
using Transbank.Onepay;
using Transbank.Onepay.Model;

// ...
Onepay.CallbackUrl = "https://miapp.cl/endPayment";
var response = Transaction.Create(cart, ChannelType.MOBILE);
require 'transbank/sdk'

Transbank::Onepay::Base.callback_url = "https://miapp.cl/endPayment"
channel = Transbank::Onepay::Channels::MOBILE
response = Transbank::Onepay::Transaction.create(
    shopping_cart: cart, channel: channel)
from transbank import onepay
from transbank.onepay.transaction import Transaction, Channel

onepay.callback_url = "https://miapp.cl/endPayment"
response = Transaction.create(cart, Channel.MOBILE)

A partir de la información entregada por la app móvil del vendedor (información que debe estar autenticada y autorizada), deberás crear una transacción usando MOBILE como channel. Ten en cuenta que el callback que indiques será invocado en el dispositivo móvil del comprador y no del vendedor (como verás en el paso 4).

Luego en la respuesta que le enviarás a la app móvil del vendedor debes incluir la respuesta de la transacción Onepay.

3. Dibujar el código QR en la app móvil.

En base a lo retornado por tu backend (que a su vez retornó la transacción Onepay creada), debes dibujar el código QR para que el vendedor le permita al comprador usar su app Onepay. Para eso puedes usar el campo qrCodeAsBase64 de la respuesta a la creación de la transacción onepay.

Te recomendamos también implementar un timeout y/o una interfaz para que el vendedor aborte la operación. Porque desde este momento el control lo tendrá el comprador en su propio dispositivo móvil.

4. Retomar el control en el navegador móvil del comprador.

Cuando el comprador escanee el QR con su app Onepay, no tendrás manera de saber el progreso de la operación. Pero cuando el comprador termine (exitosamente o con error), tu callback será invocado en el navegador móvil del comprador.

import cl.transbank.onepay.model.*;

String status = request.getParameter("status");
String externalUniqueNumber = request.getParameter("externalUniqueNumber");
String occ = request.getParameter("occ");

if (null != status && status.equalsIgnoreCase("PRE_AUTHORIZED")) {
    try { 
        TransactionCommitResponse response =
            Transaction.commit(occ, externalUniqueNumber);
        // Procesar response
        // Si response es exitoso, renderear página de exito
        // en el navegador web del tarjetahabiente y despachar
        // una push notification al dispositivo móvil que inició
        // esta transacción.
    } catch (TransbankException e) {
        // Error al confirmar la transaccion
    }
} else {
    // Mostrar página de error
}
use Transbank\Onepay\Transaction;

$status = $request->input("status");
$externalUniqueNumber = $request->input("externalUniqueNumber");
$occ = $request->input("occ");

if (!empty($status) && strcasecmp($status,"PRE_AUTHORIZED") == 0) {
    try { 
        $response = Transaction::commit($occ, $externalUniqueNumber);
        // Procesar $response.
        // Si $response es exitoso, renderear página de exito
        // en el navegador web del tarjetahabiente y despachar
        // una push notification al dispositivo móvil que inició
        // esta transacción.
    } catch (Exception $e) {
        // Error al confirmar la transaccion
    }
} else {
    // Mostrar página de error
}
using Transbank.Onepay;

 if (null != status && status.Equals("PRE_AUTHORIZED", StringComparison.InvariantCultureIgnoreCase))
 {
    try
    { 
        var response = Transaction.Commit(occ, externalUniqueNumber);
        // Procesar response
        // Si response es exitoso, renderear página de exito
        // en el navegador web del tarjetahabiente y despachar
        // una push notification al dispositivo móvil que inició
        // esta transacción.
    }
    catch (TransbankException e)
    {
        // Error al confirmar la transaccion
    }
}
else
{
    // Mostrar página de error
}
require 'transbank/sdk'

if params["status"] == "PRE_AUTHORIZED"
  response = Transbank::Onepay::Transaction.commit(
    occ: params["occ"], 
    external_unique_number: params["external_unique_number"]
  )
  # Procesar response
  # Si response es exitoso, renderear página de exito
  # en el navegador web del tarjetahabiente y despachar
  # una push notification al dispositivo móvil que inició
  # esta transacción.
else
  # Mostrar página de error
end

rescue Transbank::Onepay::Errors::TransactionCommitError => e
  # Manejar el error de confirmación de transacción
if (status and status.upper() == "PRE_AUTHORIZED"):
  try:
    response = Transaction.commit(occ, external_unique_number)
    # Procesar response
    # Si response es exitoso, renderear página de exito
    # en el navegador web del tarjetahabiente y despachar
    # una push notification al dispositivo móvil que inició
    # esta transacción.
  except TransactionCommitError:
    # Error al confirmar la transacción
else:
  # Mostrar página de error

En ese callback debes confirmar la transacción. Y si tiene éxito la transacción debes mostrar al comprador que todo salió ok al mismo tiempo que notificas a tu app del vendedor (por ejemplo con una push notification) para que esa app también muestre a su usuario que la venta realmente se ha cobrado.

Credenciales del comercio

Para establecer las credenciales de tu comercio (y no seguir usando las credenciales pre-configuradas que solo fucnionan en TEST), puedes realizarlo así:

import cl.transbank.onepay.Onepay;
//...

Onepay.setApiKey("api-key-entregado-por-transbank");
Onepay.setSharedSecret("secreto-entregado-por-transbank");
use Transbank\Onepay\OnepayBase;

OnepayBase::setApiKey("api-key-entregado-por-transbank");
OnepayBase::setSharedSecret("secreto-entregado-por-transbank");
using Transbank.Onepay;

Onepay.ApiKey = "api-key-entregado-por-transbank";
Onepay.SharedSecret = "secreto-entregado-por-transbank";
require 'transbank/sdk'

Transbank::Onepay::Base.api_key = "entregado por transbank"
Transbank::Onepay::Base.shared_secret = "entregado por transbank"
from transbank import onepay

onepay.api_key = "api-key-entregado-por-transbank"
onepay.shared_secret = "secreto-entregado-por-transbank"

También puedes configurar el api key y secret de una petición específica:

import cl.transbank.onepay.model.Options;
//...

Options options = new Options()
                  .setApiKey("api-key-entregado-por-transbank")
                  .setSharedSecret("secreto-entregado-por-transbank");
use Transbank\Onepay\Options;

$options = new Options(
    'api-key-entregado-por-transbank',
    'secreto-entregado-por-transbank');
var options = new Options()
        {
            ApiKey = "api-key-entregado-por-transbank",
            SharedSecret = "secreto-entregado-por-transbank"
        }
require 'transbank/sdk'

options = { api_key: 'api-key-entregado-por-transbank',
            shared_secret: 'shared-secret-entregado-por-transbank' }
from transbank.onepay import Options

options = Options("api-key-entregado-por-transbank", 
                  "secreto-entregado-por-transbank")

Esas opciones puedes pasarlas como parámetro a cualquier método transaccional de Onepay (Transaction.create, Transaction.commit y Refund.create).

Apuntar a producción

Puedes configurar el SDK para utilizar los servicios del ambiente de LIVE (Producción) de la siguiente forma:

import cl.transbank.onepay.Onepay;
//...
Onepay.setIntegrationType(Onepay.IntegrationType.LIVE);
use Transbank\Onepay\OnepayBase;

OnepayBase::setCurrentIntegrationType('LIVE');
using Transbank.Onepay;

Onepay.IntegrationType = Transbank.Onepay.Enums.OnepayIntegrationType.LIVE;
require 'transbank/sdk'

Transbank::Onepay::Base.integration_type = :LIVE
from transbank import onepay

onepay.integration_type = onepay.IntegrationType.LIVE

Más funcionalidades

Consulta la referencia del API para más funcionalidades ofrecidas por Onepay: