SmartPOS Integration
41 min
device connect permite conectar todos nuestros dispositivos para ser utilizados en modalidad pinpad o controlado este servicio podrá ser utilizado en macos (apple silicon) macos (intel) windows linux linux amd64 pc o linux tradicional linux arm64 — raspberry pi 3/4/5 con os de 64 bits (raspberry pi os 64 bit) linux armv7 — raspberry pi 3/4 con os de 32 bits (raspberry pi os 32 bit) android versiones versión para pc o raspberry pi docid\ woshla3gz9q5 gflbkihq versión android docid\ yctnse5fqa9sig72lhibk flujo procesamiento guía completa del flujo de procesamiento de pagos con tarjeta presente utilizando sdconn (desktop o android) junto con la api de mobbex/suga resumen del flujo el procesamiento de un pago con tarjeta presente consta de 4 pasos flowchart lr a\["1 obtener\<br/>intent token"] > b\["2 detectar tarjeta\<br/>(opcional)"] a > c\["3 leer tarjeta\<br/>con sdconn"] b > c c > d\["4 procesar\<br/>operación"] d > e\["5 mostrar\<br/>resultado"] style a fill #4a90d9,color #fff style b fill #f5a623,color #fff style c fill #7ed321,color #fff style d fill #4a90d9,color #fff style e fill #9b59b6,color #fff flowchart td start(\[inicio]) > token choice{intent token} token choice >|opción a automático| auto\["sdconn genera token\<br/>internamente"] token choice >|opción b externo| ext\["tu backend genera token\<br/>post /p/pos/physical"] auto > read\["sdconn lee tarjeta\<br/>del dispositivo pos"] ext > read read > detect{detectar cuotas?} detect >|sí| det api\["post /p/sources/detect/{token}\<br/>obtener planes de cuotas"] detect >|no| process det api > select\["usuario elige\<br/>plan de cuotas"] select > process process\["procesar operación\<br/>post /p/operations/{token}\<br/>source { sourcedata }"] process > result{resultado} result >|aprobado| display ok\["display(status 200)\<br/>círculo verde ✓"] result >|rechazado| display err\["display(status 400)\<br/>círculo rojo ✗"] style start fill #333,color #fff style token choice fill #4a90d9,color #fff style auto fill #7ed321,color #fff style ext fill #f5a623,color #fff style read fill #7ed321,color #fff style detect fill #f5a623,color #fff style det api fill #f5a623,color #fff style select fill #f5a623,color #fff style process fill #4a90d9,color #fff style result fill #9b59b6,color #fff style display ok fill #2ecc71,color #fff style display err fill #e74c3c,color #fff paso responsable descripción 1 intent token api o backend propio crear la intención de pago 2 detección de tarjeta api (opcional) identificar tarjeta y planes de cuotas 3 lectura de tarjeta sdconn (sdk/desktop) leer datos encriptados de la tarjeta 4 procesamiento api ejecutar el cobro paso 1 obtener el intent token el intent token define las características de la operación hay dos formas de obtenerlo opción a generación a través de sdconn (automático) sdconn genera el intent token internamente al llamar a la operación de lectura solo se necesita tener configuradas las credenciales de mobbex desktop (http) curl x post http //localhost 8484/api/v1/read \\ h "content type application/json" \\ d '{ "total" 15 00, "currency" "ars", "test" false }' android (sdk) val result = sdconn read(readrequest( total = 15 00, currency = "ars", test = false )) en ambos casos, sdconn internamente obtiene serialnumber del dispositivo obtiene la geolocalización llama a post https //api mobbex com/p/pos/physical con los datos usa el token recibido para iniciar la lectura opcion b generación externa (desde tu backend) tu backend genera el intent token directamente contra la api de mobbex y se lo envía a sdconn endpoint post https //api mobbex com/p/pos/physical headers header valor descripción api key tu api key privada clave privada de la entidad content type application/json cuerpo de la petición { "total" 15 00, "serialnumber" "sn12345", "currency" "ars", "test" false, "description" "venta #1234", "reference" "orden 1234", "webhook" "https //tu servidor com/webhook/mobbex", "geolocation" \[ 31 4201, 64 1888], "intent" "payment v2" } campos campo tipo requerido descripción total number sí monto de la operación serialnumber string sí número de serie del lector (lo obtiene sdconn del dispositivo) test boolean no true para operaciones de prueba currency string no moneda en formato iso 4217 (ej "ars", "usd") otheramount number no monto adicional para cashback (requiere habilitación) intent string no flujo de operación "payment v2" (captura automática) o "payment 2 step" (autorización + captura) reference string no referencia externa de la operación description string no descripción de la operación webhook string no url para notificaciones de actualización geolocation array no coordenadas \[latitud, longitud] objeto submerchant (requerido para agregadores/payfac) { "submerchant" { "reference" "comercio 123", "country" "arg", "legalname" "razón social sa", "name" "nombre comercial", "taxidtype" "arg cuit", "taxid" "30 12345678 9", "mcc" "5411", "city" "córdoba", "state" "córdoba", "zipcode" "x5000abc", "currency" "ars", "address" { "street" "av colón", "number" "1234", "notes" "piso 2, of b" }, "owner" { "name" "juan", "lastname" "pérez", "identification" "30123456789", "identificationtype" "arg cuit" } } } campo descripción reference identificador único del subcomercio country país en formato iso 3166 3 (arg, chl, ury, mex) taxidtype tipo de identificación fiscal arg cuit, arg cuil, arg dni, chl rut, ury rut, mex rfc mcc código de categoría del comercio zipcode código postal (argentina cpa de 8 dígitos) respuesta { "result" true, "data" { "intent" { "type" "payment v2", "token" "620198a7 291e 4bde 9248 43b34d59e8c9" }, "test" true } } importante guardar el valor de data intent token este es el intent token que se usará en los pasos siguientes ejemplo curl curl x post 'https //api mobbex com/p/pos/physical' \\ h 'api key 8bjocpu4xw5gchsp5ydhzsmhmnqu1kfw7nw' \\ h 'content type application/json' \\ d '{ "total" 3 21, "serialnumber" "2gkj23h1324", "currency" "ars", "description" "venta en sucursal", "test" true }' paso 2 detección de tarjeta ingresada (opcional) permite identificar el tipo de tarjeta y los planes de cuotas disponibles a partir del bin (primeros 8 dígitos del pan) nota esta api está restringida a comercios que hayan solicitado el módulo de cálculo de promociones endpoint post https //api mobbex com/p/sources/detect/{intent token} headers header valor descripción api key tu api key publica clave pública de la entidad content type application/json cuerpo { "type" "card", "data" { "bin" "451700" }, "options" { "installments" true } } campo tipo requerido descripción type string sí tipo de medio de pago valor fijo "card" data bin string no primeros 6 dígitos del número de tarjeta options installments boolean no habilitar cálculo de planes de cuotas respuesta { "result" true, "data" { "type" "card", "source" { "reference" "visa", "name" "visa", "shortname" "visa", "card" { "level" "classic", "product" { "name" "visa", "variant" "credit", "lengths" \[16], "gaps" \[4, 8, 12], "code" { "name" "cvv", "length" 3, "position" 1 }, "logo" "https //res mobbex com/images/sources/png/visa png", "validation" \["length", "exp", "cvv", "luhn"] }, "issuer" { "name" "visa", "color" "#122d98", "logo" "https //res mobbex com/images/sources/png/visa png" } } }, "installments" \[ { "name" "1 pago", "reference" "1", "count" 1, "totals" { "installment" { "amount" 5 00, "count" 1 }, "total" 5 00, "financial" { "percentage" 0, "amount" 0 } } }, { "name" "3 cuotas", "reference" "3", "count" 3, "totals" { "installment" { "amount" 1 92, "count" 3 }, "total" 5 75, "financial" { "percentage" 15, "amount" 0 75 } } }, { "name" "6 cuotas", "reference" "6", "count" 6, "totals" { "installment" { "amount" 1 08, "count" 6 }, "total" 6 50, "financial" { "percentage" 30, "amount" 1 50 } } }, { "name" "ahora 12", "reference" "ahora 12", "count" 12, "totals" { "installment" { "amount" 0 48, "count" 12 }, "total" 5 75, "financial" { "percentage" 15, "amount" 0 75 } } } ] } } importante guardar el valor de installments\[] uid del plan de cuotas elegido por el usuario para usarlo al procesar la operación ejemplo curl curl x post 'https //api mobbex com/p/sources/detect/620198a7 291e 4bde 9248 43b34d59e8c9' \\ h 'api key xxxxxxxxxxxxxxxxxxxxxx' \\ h 'content type application/json' \\ d '{ "type" "card", "data" { "bin" "45170000" }, "options" { "installments" true } }' paso 3 lectura de tarjeta con sdconn este paso lo realiza sdconn (desktop o android sdk) el sdk se encarga de enviar el intent token al dispositivo pos y esperar a que el usuario pase/inserte la tarjeta con intent token externo (opción b del paso 1) cuando se generó el token externamente, se envía a sdconn con el campo intenttoken desktop (http) curl x post http //localhost 8484/api/v1/read \\ h "content type application/json" \\ d '{ "total" 15 00, "currency" "ars", "intenttoken" "620198a7 291e 4bde 9248 43b34d59e8c9" }' android (sdk) val result = sdconn read(readrequest( total = 15 00, currency = "ars", intenttoken = "620198a7 291e 4bde 9248 43b34d59e8c9" )) nota cuando se usa un token externo, sdconn no contacta a la api de mobbex y no requiere credenciales configuradas además, incluye la geolocation del dispositivo en la respuesta sin intent token (opción a del paso 1) sdconn genera el token automáticamente (requiere credenciales configuradas) curl x post http //localhost 8484/api/v1/read \\ h "content type application/json" \\ d '{ "total" 15 00, "currency" "ars" }' respuesta de sdconn flujo estándar (token generado por sdconn) { "result" true, "intenttoken" "620198a7 291e 4bde 9248 43b34d59e8c9", "sourcedata" { "pin" "d4f2a1 ", "emvdata" "9f26089c4a ", "cryptogram" "arqc ", "ksn" "ffff9876 ", "track2" "4517001234 " } } flujo con token externo { "result" true, "intenttoken" "620198a7 291e 4bde 9248 43b34d59e8c9", "geolocation" \[ 31 4201, 64 1888], "sourcedata" { "pin" "d4f2a1 ", "emvdata" "9f26089c4a ", "cryptogram" "arqc ", "ksn" "ffff9876 ", "track2" "4517001234 " } } campos de la respuesta campo tipo descripción result boolean true si la lectura fue exitosa intenttoken string token utilizado (generado o externo) geolocation array \[latitud, longitud] — solo cuando se usa token externo sourcedata object datos encriptados de la tarjeta leída error string descripción del error (solo si result es false) contenido de sourcedata campo descripción pin pin encriptado (si fue ingresado) emvdata datos emv del chip cryptogram criptograma de la transacción ksn key serial number para dukpt track2 datos del track 2 encriptados importante los datos de sourcedata están encriptados por el dispositivo pos no pueden ser leídos directamente — deben enviarse al procesador en el paso 4 cancelar lectura si el usuario desea cancelar mientras espera la tarjeta desktop delete http //localhost 8484/api/v1/read android sdconn cancelread() paso 4 procesar la operación con el intenttoken y los datos de sourcedata obtenidos en el paso anterior, se envía la operación al procesador para ejecutar el cobro procesamiento simplificado en este esquema se envían los datos de la tarjeta directamente dentro del campo source, sin necesidad de tokenizar previamente endpoint post https //api mobbex com/p/operations/{intent token} cuerpo { "source" { "pin" "d4f2a1 ", "emvdata" "9f26089c4a ", "cryptogram" "arqc ", "ksn" "ffff9876 ", "track2" "4517001234 " }, "installmentcount" 1, "customer" { "name" "juan pérez", "identification" "30123456789", "email" "juan\@ejemplo com", "phone" "3511234567" } } es decir todo el contenido de sourcedata que devolvió sdconn se envía dentro del campo source campos campo tipo requerido descripción source object sí contenido completo de sourcedata devuelto por sdconn installmentcount number no cantidad de cuotas (cuando no se usa detección automática) installment string no referencia del plan de cuotas (obtenido en el paso 2) customer object no datos del comprador customer name string no nombre del comprador customer identification string no documento de identidad customer email string no email del comprador customer phone string no teléfono del comprador authcode string no código de autenticación (para operaciones que lo requieran) recomendación si se utiliza procesamiento simplificado, enviar la información del customer al crear el intent token (paso 1) para optimizar el flujo respuesta exitosa { "result" true, "data" { "id" "ks6d18und", "status" { "code" "200", "text" "aprobado", "message" "transacción aprobada" } } } códigos de estado comunes código texto significado 200 aprobado transacción aprobada 3 aprobado aprobado (variante) 4 aprobado aprobado (variante) 400 rechazado transacción rechazada 500 error error en el procesamiento paso 5 mostrar resultado en el dispositivo después de procesar el pago, se debe informar al usuario en la pantalla del dispositivo pos desktop (http) curl x post http //localhost 8484/api/v1/display \\ h "content type application/json" \\ d '{ "status" "success", "title" "pago aprobado", "total" 15 00, "currency" "ars", "text" "id ks6d18und", "timeout" 10 }' android (sdk) sdconn display(displayrequest( status = "success", // o el código numérico de status code title = "pago aprobado", total = 15 00, currency = "ars", text = "id ks6d18und", timeout = 10 )) se puede enviar directamente el status code de la respuesta del procesador y el dispositivo lo resuelve automáticamente a la animación correspondiente códigos animación 3, 4, 200, 300 302, 605, 800 círculo verde con check (success) 400 417, 500, 603, 604 círculo rojo con x (error) 1, 2, 100, 210, 600 602, 610 círculo naranja con reloj (neutral) devoluciones (refunds) para realizar devoluciones de operaciones procesadas se requiere generar un nuevo intent token de devolución endpoint post https //api mobbex com/p/pos/physical/{uid}/refund parámetro ubicación descripción uid url path id del cupón/transacción a devolver headers header valor descripción api key tu api key privada clave privada de la entidad x suga entity entity uid uid de la entidad (debe coincidir con submerchant reference original) cuerpo (opcional) { "total" 5 00 } campo tipo requerido descripción total number no monto para devolución parcial omitir para devolución total / cancelación respuesta { "intent" { "token" "nuevo token para devolucion" }, "requirecard" true } si requirecard es true, se debe leer la tarjeta nuevamente usando este token con sdconn (paso 3) y luego procesar la devolución (paso 4) diagramas de flujo completo flujo con token generado por sdconn (más simple) sequencediagram participant app as tu app participant sc as sdconn participant pos as dispositivo pos participant api as api mobbex app >>sc read(total 15 00, currency "ars") rect rgb(240, 248, 255) note over sc,pos obtener info del dispositivo sc >>pos get /device/info pos >>sc { serialnumber, model, } sc >>pos get /device/location pos >>sc { latitude, longitude } end rect rgb(255, 248, 240) note over sc,api generar intent token sc >>api post /p/pos/physical\<br/>{ total, serialnumber, geolocation } api >>sc { intent token } end rect rgb(240, 255, 240) note over sc,pos lectura de tarjeta sc >>pos read card { token } note over pos usuario pasa/inserta tarjeta pos >>sc { sourcedata } end sc >>app { result true, intenttoken, sourcedata } rect rgb(248, 240, 255) note over app,api procesamiento app >>api post /p/operations/{token}\<br/>{ source { sourcedata } } api >>app { id, status { code "200", text "aprobado" } } end rect rgb(245, 245, 245) note over app,pos mostrar resultado app >>sc display(status "200", title "aprobado") sc >>pos display result note over pos pantalla verde ✓ end flujo con token externo (control total desde tu backend) sequencediagram participant app as tu app participant back as tu backend participant sc as sdconn participant pos as dispositivo pos participant api as api mobbex rect rgb(255, 248, 240) note over app,api 1 backend genera intent token app >>back iniciar pago (total 15 00) back >>api post /p/pos/physical\<br/>{ total, serialnumber, geolocation } api >>back { intent token } back >>app intenttoken end app >>sc read(total 15 00, intenttoken "token") rect rgb(240, 248, 255) note over sc,pos 2 obtener info del dispositivo sc >>pos get /device/info pos >>sc { serialnumber, model, } sc >>pos get /device/location pos >>sc { latitude, longitude } end note over sc no llama a api mobbex\<br/>(usa token externo) rect rgb(240, 255, 240) note over sc,pos 3 lectura de tarjeta sc >>pos read card { token } note over pos usuario pasa/inserta tarjeta pos >>sc { sourcedata } end sc >>app { result true, intenttoken, geolocation, sourcedata } rect rgb(248, 240, 255) note over app,api 4 procesamiento app >>back sourcedata + geolocation back >>api post /p/operations/{token}\<br/>{ source { sourcedata } } api >>back { id, status { code "200" } } back >>app resultado end rect rgb(245, 245, 245) note over app,pos 5 mostrar resultado app >>sc display(status "200", title "aprobado") sc >>pos display result note over pos pantalla verde ✓ end flujo con detección de cuotas sequencediagram participant app as tu app participant back as tu backend participant sc as sdconn participant pos as dispositivo pos participant api as api mobbex rect rgb(255, 248, 240) note over back,api 1 generar intent token back >>api post /p/pos/physical api >>back { intent token } end rect rgb(240, 255, 240) note over app,pos 2 leer tarjeta app >>sc read(total 500, intenttoken "token") sc >>pos get /device/info + location pos >>sc info + location sc >>pos read card { token } note over pos usuario pasa tarjeta pos >>sc { sourcedata } sc >>app { sourcedata, intenttoken, geolocation } end rect rgb(255, 243, 224) note over app,api 3 detectar tarjeta y cuotas app >>api post /p/sources/detect/{token}\<br/>{ type "card", data { bin "451700" },\<br/>options { installments true } } api >>app { source "visa", installments \[ ] } note over app usuario elige plan \<br/>"3 cuotas" → reference "3" end rect rgb(248, 240, 255) note over app,api 4 procesar con cuotas app >>api post /p/operations/{token}\<br/>{ source { sourcedata },\<br/>installment "3" } api >>app { status { code "200", text "aprobado" } } end rect rgb(245, 245, 245) note over app,pos 5 mostrar resultado app >>sc display(status "200") sc >>pos display result ✓ end flujo de devolución sequencediagram participant app as tu app participant back as tu backend participant sc as sdconn participant pos as dispositivo pos participant api as api mobbex rect rgb(255, 240, 240) note over back,api 1 solicitar devolución back >>api post /p/pos/physical/{uid}/refund\<br/>headers api key, x suga entity\<br/>body { total 5 00 } (parcial, opcional) api >>back { intent token, requirecard true } end alt requirecard = true rect rgb(240, 255, 240) note over app,pos 2 leer tarjeta para devolución app >>sc read(total 5 00, intenttoken "refund token") sc >>pos read card { refund token } note over pos usuario pasa tarjeta pos >>sc { sourcedata } sc >>app { sourcedata, intenttoken } end rect rgb(248, 240, 255) note over back,api 3 procesar devolución back >>api post /p/operations/{refund token}\<br/>{ source { sourcedata } } api >>back { status { code "200" } } end end rect rgb(245, 245, 245) note over app,pos 4 mostrar resultado app >>sc display(status "200", title "devolución ok") sc >>pos display result ✓ end ejemplo completo paso a paso ejemplo 1 flujo simple con sdconn desktop \# 1 leer tarjeta (sdconn genera el token automáticamente) response=$(curl s x post http //localhost 8484/api/v1/read \\ h "content type application/json" \\ d '{ "total" 150 00, "currency" "ars", "test" true }') echo $response # { # "result" true, # "intenttoken" "620198a7 291e 4bde 9248 43b34d59e8c9", # "sourcedata" { # "pin" "d4f2a1 ", # "emvdata" "9f26089c4a ", # "cryptogram" "arqc ", # "ksn" "ffff9876 ", # "track2" "4517001234 " # } # } # 2 extraer intenttoken y sourcedata token=$(echo $response | jq r ' intenttoken') source=$(echo $response | jq ' sourcedata') # 3 procesar el pago contra la api result=$(curl s x post "https //api mobbex com/p/operations/$token" \\ h "content type application/json" \\ d "{ \\"source\\" $source, \\"installmentcount\\" 1 }") echo $result # { # "result" true, # "data" { # "id" "ks6d18und", # "status" { "code" "200", "text" "aprobado", "message" "transacción aprobada" } # } # } # 4 mostrar resultado en el dispositivo status code=$(echo $result | jq r ' data status code') curl x post http //localhost 8484/api/v1/display \\ h "content type application/json" \\ d "{ \\"status\\" $status code, \\"title\\" \\"pago aprobado\\", \\"total\\" 150 00, \\"currency\\" \\"ars\\", \\"text\\" \\"id ks6d18und\\", \\"timeout\\" 10 }" ejemplo 2 flujo con token externo en android // 1 tu backend genera el intent token val intenttoken = tubackend crearintenttoken(total = 150 00, currency = "ars") // 2 leer tarjeta con el token externo val readresult = sdconn read(readrequest( total = 150 00, currency = "ars", intenttoken = intenttoken // token externo → no llama a api mobbex )) if (!readresult result) { log e("pago", "error en lectura ${readresult error}") return } // 3 readresult contiene // readresult sourcedata → datos encriptados de la tarjeta // readresult intenttoken → mismo token enviado // readresult geolocation → \[lat, lng] del dispositivo // 4 enviar sourcedata a tu backend para procesar val processingresult = tubackend procesarpago( intenttoken = readresult intenttoken!!, source = readresult sourcedata!!, // va dentro de "source" { sourcedata } geolocation = readresult geolocation, installmentcount = 1 ) // 5 mostrar resultado en el dispositivo sdconn display(displayrequest( status = processingresult statuscode, // "200", "400", etc title = processingresult message, total = 150 00, currency = "ars", timeout = 10 )) ejemplo 3 flujo con detección de cuotas // 1 generar intent token desde tu backend val intenttoken = tubackend crearintenttoken(total = 500 00) // 2 leer tarjeta val readresult = sdconn read(readrequest( total = 500 00, intenttoken = intenttoken )) // 3 detectar tarjeta y obtener cuotas (llamada desde tu app/backend) // post https //api mobbex com/p/sources/detect/{intenttoken} // { "type" "card", "data" { "bin" primeros6digitosdeltrack2 }, "options" { "installments" true } } val cuotas = tubackend detectarcuotas(intenttoken, bin = "451700") // 4 mostrar planes al usuario y obtener selección val planelegido = mostrarselectorcuotas(cuotas) // ej "3", "6", "ahora 12" // 5 procesar con el plan elegido // post https //api mobbex com/p/operations/{intenttoken} // { "source" { sourcedata }, "installment" "3" } val resultado = tubackend procesarpago( intenttoken = intenttoken, source = readresult sourcedata!!, installment = planelegido // referencia del plan seleccionado ) // 6 mostrar resultado sdconn display(displayrequest( status = resultado statuscode, title = if (resultado aprobado) "pago aprobado" else "rechazado", total = 500 00, timeout = 10 )) resumen de endpoints paso método url responsable intent token post https //api mobbex com/p/pos/physical api / sdconn detección post https //api mobbex com/p/sources/detect/{token} api lectura post http //localhost 8484/api/v1/read (desktop) / sdconn read() (android) sdconn procesamiento post https //api mobbex com/p/operations/{token} api display post http //localhost 8484/api/v1/display (desktop) / sdconn display() (android) sdconn devolución post https //api mobbex com/p/pos/physical/{uid}/refund api