Milio SDK para iOS
Visión General
El SDK de Milio para iOS proporciona una solución sencilla y segura para gestionar pagos y transferencias dentro de tus aplicaciones iOS. Diseñado en SwiftUI, el SDK permite una integración fluida con aplicaciones creadas en SwiftUI o UIKit, garantizando conformidad con estándares como PCI DSS para la seguridad de datos sensibles.
Instalación
Requisitos Previos
Antes de integrar el SDK, asegúrate de tener:
- Xcode 14.0 o superior.
- Swift 5.0 o superior.
- macOS Ventura o superior.
Instalación con CocoaPods
Sigue estos pasos para instalar el SDK usando CocoaPods:
- Instalar CocoaPods (si no está instalado):
- seguir los pasos :
sudo gem install cocoapods
- Verifica la instalación con:
pod --version
- Crea un archivo Podfile si no existe:
pod init
Abre el Podfile y agrega (local)
pod 'sdk-mobile-ios', :git => 'https://bitbucket.org/miliopay/sdk-mobile-ios.git', :tag => '0.0.25'
Si el SDK de Milio se distribuye a través de un repositorio privado de CocoaPods, agrégalo en tu Podfile (ios/Podfile):
# Uncomment the next line to define a global platform for your project
platform :ios, '16.0'
use_frameworks!
target 'projectTestSdk' do
pod 'sdk-mobile-ios', :git => 'https://bitbucket.org/miliopay/sdk-mobile-ios.git', :tag => '0.0.25'
end
- Instala las dependencias:
pod install --repo-update
Nota
Xcode en versiones recientes activa por defecto sandboxing para proteger el entorno de ejecución de scripts. Esto puede bloquear tareas como copiar archivos (rsync, cp, etc.) si el script no tiene los permisos adecuados. Al desactivar la opción ENABLE_USER_SCRIPT_SANDBOXING, le dices a Xcode que permita que tus scripts corran sin esas restricciones extra.
Uso del SDK
🔐 Proceso de Encriptación y Seguridad en el SDK
El sistema de transferencias y recargas del SDK utiliza un mecanismo de encriptación de datos basado en criptografía de clave pública para garantizar la seguridad de la información en cada transacción.
🔑 1. ¿Por qué se usa una llave pública?
La llave pública, generada por un endpoint especializado, es la herramienta que permite cifrar la información antes de enviarla a través del SDK. Al encriptar los datos con esta llave, aseguramos que solo el servidor que tiene la llave privada correspondiente pueda descifrarlos, evitando accesos no autorizados o modificaciones en la información.
📲 2. Procesos que requieren encriptación con la llave pública
Cada una de las transacciones en el SDK debe pasar por este proceso de encriptación antes de ser enviada al servidor:
1️⃣ Transferencia con QR
Se escanea un código QR con los datos de la transacción.
La información se encripta con la llave pública antes de enviarla.
El servidor recibe los datos cifrados y los desencripta con su llave privada.
2️⃣ Transferencia Manual
El usuario ingresa manualmente los datos de la transacción (monto, cuenta destino, etc.).
Antes de enviarlos al SDK, los datos se cifran con la llave pública.
El servidor procesa la información tras desencriptarla.
3️⃣ Transferencia Inmediata
Similar a la transferencia manual, pero con una ejecución más rápida.
La información viaja encriptada con la llave pública para evitar manipulación en el proceso.
4️⃣ Recarga de Billetera
Para recargar fondos en la billetera digital, los datos (monto, origen, destino) se protegen con encriptación.
Solo el servidor, con su llave privada, podrá acceder a la información real y procesar la recarga.
🚀 3. Beneficios de este proceso de seguridad
✅ Protección de datos sensibles en cada transacción.
✅ Evita que terceros accedan o modifiquen la información.
✅ Cumple con estándares de seguridad y auditoría en encriptación.
Cada vez que se realiza una transferencia o recarga en el SDK, los datos deben encriptarse con la llave pública antes de enviarse. Solo el servidor con la llave privada correcta podrá descifrarlos y procesar la transacción, garantizando un entorno seguro y confiable para el usuario. 🔒
import MilioSDK
MilioSDK.configure(withToken: "TU_TOKEN_DE_AUTENTICACIÓN")
Ejemplo de Integración
El SDK facilita la implementación de funcionalidades de transferencia y pago. A continuación, un ejemplo de transferencia por QR.
Ejemplo global de Encriptación
Este método se debe utilizar antes de enviar la información en las siguientes transacciones:
- Transferencia por QR
- Transferencia manual
- Transferencia inmediata
- Recarga de billetera
Cada transacción debe encriptar los datos sensibles antes de enviarlos al SDK de Milio.
import Foundation
import Security
// Llave pública proporcionada por Milio (esto es solo un ejemplo, usa la real en producción)
let publicKeyPem = """
-----BEGIN RSA PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7...
-----END RSA PUBLIC KEY-----
"""
/**
* 🔒 Método para encriptar información con la llave pública de Milio.
*
* @param publicKeyPem Llave pública en formato PEM.
* @param data Información que se desea encriptar.
* @return Datos encriptados en Base64 o nil en caso de error.
*/
func encryptWithPublicKey(publicKeyPem: String, data: String) -> String? {
guard let publicKey = getPublicKey(from: publicKeyPem) else {
print("❌ Error: No se pudo obtener la llave pública.")
return nil
}
guard let dataToEncrypt = data.data(using: .utf8) else {
print("❌ Error: No se pudo convertir la data a formato UTF-8.")
return nil
}
let bufferSize = SecKeyGetBlockSize(publicKey)
var encryptedData = Data(count: bufferSize)
var encryptedLength = bufferSize
let status = encryptedData.withUnsafeMutableBytes { encryptedBytes in
dataToEncrypt.withUnsafeBytes { plainTextBytes in
SecKeyEncrypt(publicKey,
.oaep,
plainTextBytes.baseAddress!,
dataToEncrypt.count,
encryptedBytes.baseAddress!,
&encryptedLength)
}
}
guard status == errSecSuccess else {
print("❌ Error en el cifrado RSA: \(status)")
return nil
}
encryptedData.count = encryptedLength
return encryptedData.base64EncodedString()
}
/**
* 🔑 Convierte una clave pública en formato PEM a un objeto SecKey.
*/
func getPublicKey(from pemString: String) -> SecKey? {
let keyString = pemString
.replacingOccurrences(of: "-----BEGIN RSA PUBLIC KEY-----", with: "")
.replacingOccurrences(of: "-----END RSA PUBLIC KEY-----", with: "")
.replacingOccurrences(of: "\n", with: "")
guard let keyData = Data(base64Encoded: keyString) else {
print("❌ Error: No se pudo convertir la llave pública en Base64.")
return nil
}
let options: [String: Any] = [
kSecAttrKeyType as String: kSecAttrKeyTypeRSA,
kSecAttrKeyClass as String: kSecAttrKeyClassPublic,
kSecAttrKeySizeInBits as String: 2048
]
return SecKeyCreateWithData(keyData as CFData, options as CFDictionary, nil)
}
Transferencia con QR
import MilioSDK
import Security
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 16) {
// Botón: Transferencia con QR
ActionButton(
title: "Transferencia con QR",
iconName: "svg_ic_qrcode",
iconBackgroundColor: Color(.systemGray6),
iconColor: .blue,
horizontalPadding: 24,
verticalPadding: 18
) {
let transactionData = """
{
"amount": 2000.0
}
"""
if let encryptedData = encryptWithPublicKey(
publicKeyPem: PUBLIC_KEY_PEM, data: transactionData)
{
MilioSDK.shared.openWindow(
windowType: .transferQRCode,
token: authToken,
value: encryptedData,
presentingViewController: UIApplication.shared.windows.first?.rootViewController
?? UIViewController()
)
} else {
print("❌ Error al encriptar la información")
}
}
}
.padding()
}
}
Grafico

Transferencia manual
import MilioSDK
import Security
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 16) {
// Botón: Transferencia Manual
ActionButton(
title: "Transferencia Manual",
iconName: "svg_ic_transfer",
iconBackgroundColor: Color(.systemGray6),
iconColor: .green,
horizontalPadding: 24,
verticalPadding: 18
) {
let transactionData = """
{
"amount": 1500.0,
"type": "OUT",
"thirdBankUUID": "dfb56715-ed55-4839-b5d0-18645da02dd0"
}
"""
if let encryptedData = encryptWithPublicKey(
publicKeyPem: PUBLIC_KEY_PEM, data: transactionData)
{
MilioSDK.shared.openWindow(
windowType: .manualTransfer,
token: authToken,
value: encryptedData,
presentingViewController: UIApplication.shared.windows.first?.rootViewController
?? UIViewController()
)
} else {
print("❌ Error al encriptar la información")
}
}
}
.padding()
}
}
Grafico

Transferencia inmediata
import MilioSDK
import Security
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 16) {
// Botón: Transferencia Inmediata
ActionButton(
title: "Transferencia Inmediata",
iconName: "svg_ic_flash",
iconBackgroundColor: Color(.systemGray6),
iconColor: .red,
horizontalPadding: 24,
verticalPadding: 18
) {
let transactionData = """
{
"amount": 1500.0,
"type": "OUT",
"thirdBankUUID": "dfb56715-ed55-4839-b5d0-18645da02dd0"
}
"""
if let encryptedData = encryptWithPublicKey(
publicKeyPem: PUBLIC_KEY_PEM, data: transactionData)
{
MilioSDK.shared.openWindow(
windowType: .instantTransfer,
token: authToken,
value: encryptedData,
presentingViewController: UIApplication.shared.windows.first?.rootViewController
?? UIViewController()
)
} else {
print("❌ Error al encriptar la información")
}
}
}
.padding()
}
}
Grafico

Transferencia inmediata (Tarjeta manual)
Grafico

Recarga de billetera
import MilioSDK
import Security
import SwiftUI
struct ContentView: View {
var body: some View {
VStack(spacing: 16) {
// Botón: Recarga de Billetera
ActionButton(
title: "Recargar Billetera",
iconName: "svg_ic_wallet",
iconBackgroundColor: Color(.systemGray6),
iconColor: .orange,
horizontalPadding: 24,
verticalPadding: 18
) {
let transactionData = """
{
"amount": 1500.0,
"type": "IN",
"thirdBankUUID": "dfb56715-ed55-4839-b5d0-18645da02dd0"
}
"""
if let encryptedData = encryptWithPublicKey(
publicKeyPem: PUBLIC_KEY_PEM, data: transactionData)
{
MilioSDK.shared.openWindow(
windowType: .walletRecharge,
token: authToken,
value: encryptedData,
presentingViewController: UIApplication.shared.windows.first?.rootViewController
?? UIViewController()
)
} else {
print("❌ Error al encriptar la información")
}
}
}
.padding()
}
}

Conclusión
Milio SDK ofrece una arquitectura robusta y flexible para manejar diversos tipos de transferencias y recargas. Los puntos clave incluyen:
- Escalabilidad: Los flujos se adaptan tanto a usuarios que prefieren métodos manuales como a aquellos que buscan la comodidad de los códigos QR.
- Interoperabilidad: La lógica permite integrar diferentes procesos dentro de un solo SDK, mejorando la experiencia del usuario final.
- Seguridad: Se prioriza la validación mediante tokens y datos encriptados, alineándose con los estándares de la industria como PCI DSS.
- Flexibilidad: El diseño modular permite personalizar los flujos según las necesidades de la aplicación.
Este SDK es una herramienta clave para facilitar las operaciones financieras digitales en un entorno moderno, garantizando una experiencia fluida y segura tanto para los desarrolladores como para los usuarios finales.