Introducción
El SDK de Clip para iOS permite integrar la experiencia de pago de Clip en tu aplicación nativa de iOS.
El SDK para iOS permite que los desarrolladores puedan crear aplicaciones personalizadas de venta y tomar los pagos utilizando los beneficios que ya ofrece la plataforma de Clip, como el cumplimiento con los estándares PCI y compatibilidad con tarjetas de débito, crédito y otras.
La integración con dispositivos iOS extiende su uso a dispositivos móviles como celulares y tabletas, ofreciendo versatilidad en la experiencia del usuario.
Las características que ofrece la integración del lector Clip con tu aplicación son:
- Conectividad con Clip Plus y Clip Plus 2
- Flujos de inicio y cierre de sesión
- Métodos de pago por medio de banda magnética, tarjetas con chip y contactless
- Propinas y pagos diferidos en mensualidades
- Historial de transacciones
- Personalización del número de referencia del pago
Cómo funciona
El SDK de Clip es una librería que extiende las capacidades de tu aplicación de punto de venta.
Las funciones que permite desarrollar la librería son:
- Aceptar pagos con tarjeta
- Obtener el historial de transacciones
- Iniciar y cerrar la sesión de Clip desde tu aplicación
- Configurar los ajustes del dispositivo (Settings)
Integración con iOS
Para integrar la librería de Clip, sólo es necesario importarla en tu proyecto de iOS como parte de las dependencias.
El SDK de Clip te ofrece un proyecto demo para integrar el SDK a tu aplicación y poder analizar ejemplos de código para integrar la solución personalizada a tu propia aplicación móvil de iOS.
El SDK de Clip para iOS soporta la integración con aplicaciones desarrolladas en Swift y Objective-C.
Prerrequisitos
Para poder integrar el SDK de Clip a tu aplicación de iOS, debes cumplir los siguientes prerrequisitos:
- Tener una cuenta de Clip
- Tener una aplicación iOS con versión mínima iOS 10 o superior
- Agregar las librerías del SDK como dependencias en el proyecto de iOS
- Configurar los permisos del dispositivo requeridos por el SDK
- Utilizar Carthage versión 0.38
Ambientes de desarrollo
NOTA: Por el momento no existe un ambiente “sandbox” para pruebas y sólo está disponible el ambiente de producción.
Configuración del proyecto
Es necesario configurar los ajustes iniciales en tu proyecto para poder integrar tu solución con las librerías del SDK de Clip.
Agregando las librerías
Es necesario agregar las librerías para el SDK de Clip como dependencias de tu proyecto de iOS.
- Librerías de Clip: las librerías de Clip se proporcionan con los archivos del proyecto SDK y se integran de forma directa.
- Librerías externas: las librerías de terceros están disponibles por medio de Carthage, una herramienta diseñada para manejar dependencias.
Librerías de Clip
- Abre con Xcode el proyecto de tu aplicación iOS para el SDK de Clip.
- Selecciona tu proyecto de la lista Target en la parte superior izquierda.
- Dirígete a la sección Linked Frameworks and Libraries en la pestaña General de tu proyecto.
- Agrega los siguientes archivos con extensión .framework:
ClipAuthenticationSDK.framework
ClipCommonSDK.framework
ClipPaymentSDK.framework
ClipPaymentUISDK.framework
ClipReaderSDK.framework
Librerías externas
Para poder integrar las librerías externas, es necesario utilizar el manejador de dependencias Carthage.
Los siguientes pasos muestran cómo implementar las librerías con Carthage:
-
Instala Carthage siguiendo la referencia de la documentación oficial. https://github.com/Carthage/Carthage#quick-start
-
Incluye las siguientes dependencias en el Cartfile:
github "JohnSundell/Wrap" "3.0.1"
github "evsinev/BerTlv" "0.2.3"
github "SnapKit/SnapKit" ~> 5.0.0
github "lyft/mapper"
github "airbnb/lottie-ios" "master"
- Agrega los framework generados por Carthage en la configuración de tu proyecto.
Configurando Info
Esta sección contiene información relacionada a configuraciones en la pestaña de Info en tu proyecto.
En la sección de Localizations, agrega soporte para idioma Español.
Configurando Build Phases
Esta sección contiene información relacionada a configuraciones en la pestaña de Build Phases en el Target de tu proyecto.
Agrega el siguiente Run Script .
/usr/local/bin/carthage copy-frameworks
Agrega el siguiente Input File, reemplazando Project_Name por el nombre de tu proyecto.
$(SRCROOT)/Carthage/Build/iOS/*Project_Name*.framework
Configurando los permisos en info.plist
Para poder integrar el SDK de Clip en tu aplicación de iOS, es necesario incluir las siguientes propiedades dentro de tu archivo info.plist para el dispositivo que utilizará la aplicación.
Configura tu info.plist con los siguientes permisos:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Clip uses your device's bluetooth to connect to card readers</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app needs to use bluetooth to communicate with the Clip Reader</string>
<key>NSLocationUsageDescription</key>
<string>This app needs to know your location in order to charge payments</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>This app needs to know your location in order to charge payments</string>
La tabla siguiente incluye una descripción para cada uno de los permisos requeridos:
Permiso |
Funcionalidad |
Descripción |
NSBluetoothAlwaysUsageDescription |
Bluetooth |
Para descubrir y emparejar nuevos dispositivos desde la aplicación iOS. |
NSBluetoothPeripheralUsageDescription |
Bluetooth |
Para conectarse con la terminal de Clip.
|
NSLocationUsageDescription |
Ubicación |
Para poder tomar y procesar el pago. |
NSLocationWhenInUseUsageDescription |
Ubicación |
Para poder tomar y procesar el pago. |
En el mismo archivo, agrega las siguientes configuraciones para asegurar la compatibilidad de tu aplicación con el SDK de Clip:
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>es</string>
</array>
La tabla siguiente incluye una descripción para cada una de las configuraciones requeridas:
Configuración |
Descripción |
UIUserInterfaceStyle |
Compatibilidad de la interfaz para temas claros (light theme).
El SDK sólo es compatible con un tema claro para tu aplicación. Si se utiliza un tema oscuro algunos elementos pueden no mostrarse correctamente. |
UISupportedInterfaceOrientations |
Compatibilidad con la orientación de la aplicación para iPhone con soporte para retrato y panorama. |
UISupportedInterfaceOrientations~ipad |
Compatibilidad con la orientación de la aplicación para iPad con soporte para retrato y panorama. |
CFBundleLocalizations |
Compatibilidad con idiomas español e inglés. |
Trabajando con el proyecto demo
Clip SDK para iOS te ofrece un proyecto demo para integrar el SDK a tu aplicación y contiene ejemplos de uso de las funciones de la librería.
Las funciones que permite desarrollar la librería son:
- Crear un objeto de pago
- Inicio y cierre de sesión de Clip desde tu aplicación
Código de ejemplo
El siguiente bloque de código muestra un ejemplo del ViewController de la implementación del SDK de Clip en una aplicación de iOS.
Las secciones siguientes, contienen descripciones detalladas de los componentes más importantes de este ejemplo.
//
// ViewController.swift
// ExampleSDKClipCarthage
//
// Created by MiguelJasso on 15/09/20.
// Copyright © 2020 MiguelJasso. All rights reserved.
//
import UIKit
import ClipCommonSDK
import ClipPaymentUISDK
import ClipAuthenticationSDK
import ClipPaymentSDK
class ViewController: UIViewController{
var sdk: ClipAuthentication! = nil
override func viewDidLoad() {
super.viewDidLoad()
sdk = ClipSDKModule.createClipSDKModule(delegate: self)
// Do any additional setup after loading the view.
}
@IBAction func login(_ sender: Any) {
sdk.login()
}
@IBAction func logout(_ sender: Any) {
sdk.logout()
}
}
extension ViewController : ClipAuthenticationDelegate {
func didLLoginSDKProtocologinSuccess() {
let payWrapper = PaymentProcessManager()
.set(amount: NSDecimalNumber(value: ))
.set(baseView: )
.set(tips: )
.set(contaclessEnabled: )
.set(delegate: )
.set(payWithPoints: )
payWrapper.startPayment()
}
func didFailLoginWith(error: StatusCode) {
}
func didLogout() {
}
func didFailLogout(error: StatusCode) {
}
}
extension ViewController: PaymentProcessDelegate {
func onErrorOcurred(_ error: StatusCode, _ subStatusDetail: SubStatusDetail?) {
}
func successTransaction(_ payment: Payment) {
}
}
Inicializando la aplicación
Agrega las librerías importadas anteriormente a tu aplicación.
import UIKit
import ClipCommonSDK
import ClipPaymentUISDK
import ClipAuthenticationSDK
import ClipPaymentSDK
Crea una instancia de ClipAuthentication para iniciar sesión y hacer uso del token de autenticación.
var sdk: ClipAuthentication! = nil
Mira cómo hacerlo
Consulta la receta con los pasos necesarios para configurar el SDK en tu proyecto.
Iniciar la sesión de Clip
Desde tu aplicación, puedes iniciar la sesión de Clip en tu aplicación.
Para iniciar la sesión de Clip desde la aplicación, implementa la siguiente función:
sdk.login()
Esta función también permite validar si ya existe una sesión abierta de Clip para continuar recibiendo pagos. Es importante validar el estado de tu sesión de Clip antes de iniciar una transacción, de lo contrario se regresará un código de error.
Cerrar la sesión de Clip
Desde tu aplicación, puedes solicitar cerrar la sesión de Clip en tu aplicación.
Para cerrar la sesión de Clip desde la aplicación, implementa la siguiente función:
sdk.logout()
Configurar los ajustes del dispositivo
La librería de Clip permite configurar ciertos ajustes del dispositivo Clip desde tu aplicación de iOS.
Actualmente, los ajustes de configuración que se pueden consultar son:
- Batería: muestra el nivel de batería en el dispositivo Clip.
- Firmware: muestra la versión de firmware instalada en el dispositivo Clip.
- Tiempo de apagado: permite configurar el tiempo de apagado automático en tu Clip Plus 2 para ahorrar batería.
- Sesión de Clip: la pantalla de ajustes permite cerrar sesión en la cuenta Clip.
- Lector conectado: permite conectar o desconectar un lector Clip por medio de conexión Bluetooth.
Nota
La configuración de Tiempo de apagado solo está disponible para el dispositivo Clip Plus 2.
Para agregar la función de configuración de ajustes en tu aplicación iOS, agrega la siguiente función :
Settings.presentView(self, logoutEnabled: logoutSwitch.isOn)
La siguiente tabla incluye una descripción para los parámetros de la función:
Elemento |
Descripción |
|
presentView |
Permite mostrar la pantalla de ajustes del dispositivo. |
|
logoutEnabled |
Permite cerrar la sesión de la cuenta Clip desde la aplicación iOS y mostrar un botón para la acción.
|
Crear un objeto de Pago
Para integrar la función de pago con Clip, se requiere:
- Crear un objeto de pago en la aplicación
- Agregar un botón o elemento gráfico de pago en tu aplicación
Para crear un objeto de pago, implementa la siguiente función dentro del estado de login didLLoginSDKProtocologinSuccess():
let payWrapper = PaymentProcessManager()
.set(amount: NSDecimalNumber(value: ))
.set(baseview: )
.set(tips: )
.set(contactlessEnabled: )
.set(delegate: )
.set(payWithPoints: )
.set(reference: )
payWrapper.startPayment()
La siguiente tabla describe los elementos del objeto PaymentProcessManager:
Elemento |
Tipo de Dato |
Descripción |
||
amount |
NSDecimalNumber |
Cantidad de la transacción. |
||
baseView |
ViewController |
Clase base que presenta las vistas que se utilizan en la aplicación. |
||
tips |
Boolean |
Permite mostrar la pantalla de selección de propina en el flujo de pago. Se modifica con las propiedades noTip o enabled . |
||
|
.noTip |
|
Propinas desactivadas. |
|
|
.enabled |
|
Propinas activadas. Tiene propiedades adicionales para calcular con o sin centavos. |
|
|
|
.roundUp |
|
Redondea la cantidad de propina. |
|
|
.exact |
|
Propinas exactas con pesos y centavos. |
contactlessEnabled |
Boolean |
Permite recibir pagos contactless en terminales Clip Plus 2. |
||
delegate |
Clase |
Clase que recibe los errores y status del proceso de la transacción. |
||
payWithPoints |
Boolean |
Permite recibir pagos con los puntos que otorga el banco al usuario de la tarjeta. |
||
reference |
String |
Referencia personalizada proporcionada por el cliente. Longitud: 100 caracteres Validación: cadena alfanumérica y los siguientes caracteres especiales @ # $ & ( ) _ - , . |
Iniciar una transacción
En el listener del botón de pago de tu aplicación, agrega la siguiente función:
.startPayment()
Implementar la clase Delegate
Después de crear un objeto de pago, se requiere implementar un Delegate para poder manejar el estado de éxito o error que resulta de la transacción.
Crea una extensión de la clase PaymentProcessDelegate:
Extension PrincipalViewController: PaymentProcessDelegate{
func onErrorOcurred(_ error: StatusCode, _ subStatusDetail: SubStatusDetail?){
}
func successTransaction(_ payment: Payment) {
}
}
La siguiente tabla muestra una descripción de las funciones contenidas en la clase PaymentProcessDelegate:
Elemento |
Descripción |
|
onErrorOcurred |
Regresa un error de tipo StatusCode. Algunos errores incluyen una descripción adicional subStatusDetail . |
|
successTransaction |
Regresa un objeto tipo Payment con la información del pago que se realizó. |
Esquema del objeto Payment:
ClipTransaction {
var totalAmount: Decimal
let cardType: CardType
let currency: String?
let paymentDate: Date
let invoiceNumber: String?
let last4: String
let latitude: String?
let longitude: String?
let receiptNumber: String
let installment: Installment?
let amount: Decimal
let tip: Decimal?
let status: TransactionStatus
}
La siguiente tabla incluye una descripción para los parámetros del objeto tipo Payment:
Elemento |
Descripción |
Tipo de dato |
|||
receiptNumber |
Identificador único de la transacción |
String |
|||
amount |
Cantidad del pago |
Decimal |
|||
tip |
Cantidad de la propina |
Decimal |
|||
totalAmount |
Cantidad total del pago incluyendo propina |
Decimal |
|||
cardType |
Tipo de tarjeta utilizada para el pago:
CardType
|
Enum |
|||
last4 |
Últimos cuatro dígitos de la tarjeta utilizada para el pago |
String |
|||
installment |
Indica si el pago se difiere en mensualidades:
Installment
|
Enum |
|||
merchantInvoiceId |
Referencia alfanumérica proporcionada por el vendedor |
String |
|||
status |
Estado de la transacción. Lista de posibles estados de la transacción:
TransactionStatus
|
Enum |
|||
currency |
Código de divisa para la transacción del pago conforme a ISO 4217 |
String |
|||
paymentDate |
Fecha de creación del pago |
Date |
|||
latitude |
Coordenada de latitud para la ubicación de la transacción |
String |
|||
longitude |
Coordenada de longitud para la ubicación de la transacción |
String |
Mira cómo hacerlo
Consulta la receta con los pasos necesarios para recibir un pago con tarjeta en tu proyecto.
Obtener el historial de transacciones
El SDK de Clip permite obtener el historial de transacciones que se han realizado.
Las funciones disponibles para trabajar con el historial son las siguientes:
- getTransactionHistory(by: TransactionHistoryQuery): permite realizar una búsqueda de transacciones del mismo día y aplicar distintos filtros.
do {
try TransactionHistory.shared.getTransactionHistory(by:.date(Date()) { (result) in
switch result {
case .success(let transactions):
case .failure(let error):
}
catch {
print(error)
}
Elemento |
Tipo de Dato |
Descripción |
||
TransactionHistoryQuery |
Enum |
Tipo de búsqueda |
||
|
.card(last4: String) |
|
Últimos 4 dígitos de la tarjeta. Se valida que el parámetro tenga el siguiente formato: "^\\d{0,4}$" De no cumplir con el formato se regresa un error de tipo: InvalidParameterFormat |
|
|
.date(Foundation.Date) |
|
Fecha en que se realizó el pago. |
|
|
.receipt(receiptNum: String) |
|
Número de evoucher generado por Clip. Se valida que el parámetro tenga el siguiente formato: "^[a-zA-Z0-9-_]{0,}$" De no cumplir con el formato se regresa un error de tipo: InvalidParameterFormat |
La siguiente tabla muestra los elementos en el objeto de respuesta ClipTransaction que regresan las funciones anteriores:
Elemento |
Descripción |
Tipo de dato |
|||
receiptNumber |
Identificador único de la transacción |
String |
|||
amount |
Cantidad del pago |
Decimal |
|||
tip |
Cantidad de la propina |
Decimal |
|||
totalAmount |
Cantidad total del pago incluyendo propina |
Decimal |
|||
cardType |
Tipo de tarjeta utilizada para el pago:
CardType
|
Enum |
|||
last4 |
Últimos cuatro dígitos de la tarjeta utilizada para el pago |
String |
|||
installment |
Indica si el pago se difiere en mensualidades:
Installment
|
Enum |
|||
merchantInvoiceId |
Referencia alfanumérica proporcionada por el vendedor |
String |
|||
status |
Estado de la transacción. Lista de posibles estados de la transacción:
TransactionStatus
|
Enum |
|||
currency |
Código de divisa para la transacción del pago conforme a ISO 4217 |
String |
|||
paymentDate |
Fecha de creación del pago |
Date |
|||
latitude |
Coordenada de latitud para la ubicación de la transacción |
String |
|||
longitude |
Coordenada de longitud para la ubicación de la transacción |
String |
Refund Transaction
Una transacción se puede reembolsar al enviar el id (String) del evoucher.
Si una transacción ya fue reembolsada o existe algún error en el proceso, se regresa el error 13002:
PAYMENT_HISTORY_REFUND_FAILED
El método regresa un success con dos posibles estados:
- True: indica que el reembolso fue exitoso
- False: indica que el reembolso no fue exitoso
También se retorna el estado de la transacción del tipo PaymentCancelStatus, esta puede ser:
enum PaymentCancelStatus: Int{
case processed = 1
case refundUnavailable = -2
case error = -3
case timeout = -4
}
Estado |
Descripción |
processed |
La cancelación se realizó de forma exitosa. |
refundUnavailable |
La cancelación no pudo realizarse. El tiempo para hacerlo ha pasado o se trata de un pago hecho con una tarjeta de puntos. |
error |
Ocurrió un error al realizar la cancelación. |
timeout |
Se solicitó la cancelación pero no hubo respuesta del servicio. |
El siguiente ejemplo de código muestra la implementación de la función para reembolso de transacción.
do {
try TransactionHistory.shared.refundTransaction(by: String , completion: { (result) in
switch result {
case .success(let success, let status):
print(success)
print(status)
case .failure(let error):
print(error)
}
})
} catch {
print(error)
}