These docs are for v4. Click to read the latest docs for v5.

Nesta seção você irá aprender mais sobre os detalhes de cada funcionalidade do SDK iOS para mPOS. Veja como fazer o download e como configurar as bibliotecas básicas que seguem o protocolo ABECS. Entenda também o fluxo de criação de uma transação. Vamos lá!

Download do SDK

Para integrar seu PinPad com uma aplicação que utiliza da biblioteca mPOS iOS Pagar.me você precisa primeiro fazer o download em: Bibliotecas

Ao finalizar o download, você deve descompactar a pasta mpos-ios, e localizar os diretórios lib e include, já que ambos serão necessários para os próximos passos.

Configurando o ambiente

Em seu Xcode, siga os seguintes passos:

  1. Adicione as libraries libabecs.a, libmpos.a, libmposios.a e libtms.a — que estão incluídas na distribuição do SDK (pasta lib) — nas configurações do projeto Xcode em Build Phases > Link Binary With Libraries;
  2. Adicione o diretório include da distribuição do SDK a Build Settings > Search Paths > Header Search Paths;
  3. Adicione o diretório lib da distribuição do SDK a Build Settings > Search Paths > Library Search Paths;
  4. Mude a opção Build Settings > Build Options > Enable Bitcode de Yes para No;
  5. Caso seu projeto use Objective-C ou Swift (e não Objective-C++), adicione -lstdc++ a Build Settings > Linking > Other Linker Flags.

Caso você use Swift

  1. Adicione um header file ao seu projeto para fazer o bridging, e insira:
#import <mpos-ios.h>
  1. No campo Build Settings > Swift Compiler - Code Generation > Objective-C Bridging Header, insira este header;
  2. Ao adicionar o Header, a classe PMMposController estará disponível para você.

Criando uma transação

O exemplo abaixo segue todo o fluxo para capturar as informações do cartão e gerar um card_hash para que posteriormente você consiga criar uma transação. Em seguida já explicamos os principais pontos do código, segue:

//
//  ViewController.m
//  mposToDocs
//
//  Created by Aardvark on 1/25/17.
//  Copyright © 2017 Aardvark. All rights reserved.
//

#import "ViewController.h"
#import <ExternalAccessory/ExternalAccessory.h>
#import "mpos-ios.h"

@interface ViewController ()

@end

@implementation ViewController

- (void) makeATransaction{
    // Obtém um objeto EAAccessory, que representa um aparelho Bluetooth pareado.
    EAAccessory *accessory = [[[EAAccessoryManager sharedAccessoryManager]
                               connectedAccessories]
                              firstObject];
    
    PMMposController *controller = [[PMMposController alloc] initWithAccessory:accessory encryptionKey:@"SUA ENCRYPTION_KEY"];
    [controller openConnection];
    
    [controller openSessionWithCallback:^(NSError *error) {
        if (error != nil) {
            /* Lidar com Erro */
            NSLog(@"What's wrong kido: %@", error);
            return;
        }
        /* Agora vamos configurar duas aplicações, ou seja, especificar 
         duas combinações de Bandeira + Tipo de cartão que desejamos limitar o aceite, 
         sendo Visa e Master crédito. Mas para aceitar todas, passe nil no parâmetro.
         */
        NSArray *applications = @[
                                  [PMEmvApplication applicationWithCardBrand:@"visa"
                                                               paymentMethod:MPM_CREDIT],
                                  [PMEmvApplication applicationWithCardBrand:@"master"
                                                               paymentMethod:MPM_CREDIT]
                                  ];
        
        
        /* selecionar Crédito como método de pagamento de tarja */
        [controller payAmount:15000 withApplications:applications
                                    magstripePaymentMethod:MPM_CREDIT
                 withCallback:^(NSString *cardHash,
                                NSDictionary *dict,
                                NSError *error) {
            NSLog(@"Sweet you've just got a cardHash, look: %@", cardHash);
            
            /*Excelente, neste momento já pode criar uma transação usando o cardHash gerado. */
            /* recomendamos que faça a chamada para API 
                  de um servidor externo, e não diretamente do device */         
            NSLog(@"Crie a transação neste ponto");
                     
            /* E após criar essa transação, a API Pagar.Me vai retornar alguns parâmetros que
             você precisa para encerrar o processo junto ao PinPad*/
                     
            [controller finishTransactionWithSuccessfulConnection:YES
                                                     responseCode:200
                                                          emvData:@"emvDataResponse"
                                                     withCallback:^(NSError *error){
                if(error != nil){
                    NSLog(@"Something went wrong while finishing the transaction, look: %@", error);
                }
                /*Com tudo certo, você deve agora encerrar a session e a connection com o Pinpad*/
                [controller closeSessionWithMessage:@"You are terminated!" callback:^(NSError *error) {
                    /* Hora de encerrar a connection também */
                    [controller closeConnection];
                }];
            }];
        }];
    }];
}

@end
import ExternalAccessory

// Obtém um objeto EAAccessory, que representa um aparelho Bluetooth pareado.
let accessory = EAAccessoryManager.sharedAccessoryManager().connectedAccessories.first

let controller = PMMposController(accessory: accessory, encryptionKey: "SUA_ENCRYPTION_KEY")
controller.openConnection()
controller.openSessionWithCallback({ (error: NSError!) -> Void in
    if error != nil {
        /* Lidar com Erro */
        return
    }

    /* aceitar somente Visa Crédito */
    var applications = [ PMEmvApplication(cardBrand: "visa", paymentMethod: MPM_CREDIT) ];

    /* selecionar Crédito como método de pagamento de tarja */
    controller.payAmount(100, withApplications: applications, withCallback: { (cardHash: String!, error: NSError!) -> Void in
        if error != nil {
            /* Lidar com Erro */
            return
        }
        NSLog("card_hash gerado = %@", cardHash);

        /* Gerar transação com a API Pagar.me... */       
        controller.finishTransactionWithSuccess(..., withCallback: { error: NSError! -> Void in
            if error != nil {
                /* Lidar com Erro */
                return
            }

            controller.closeSessionWithMessage(message: "Message", callback: { error: NSError! -> Void in
                controller.closeConnection()
            })
        })
    })
});

Atualizando tabelas EMV

Para as diferentes aplicações de Cartão de crédito (diferentes bandeiras e diferença entre crédito e débito) existe um conjunto de especificações de como o PinPad deve se comportar, assim como certificados que permitem ao PinPad lidar com elas. Este conjunto é denominado tabelas EMV e pode ser obtido junto ao Pagar.me via SDK.

Para baixar as tabelas EMV, as seguintes operações são realizadas:

  1. Download das tabelas EMV pela API Pagar.me;
  2. Transferência das tabelas baixadas para o PinPad.

A API Pagar.me fornece as tabelas EMV e as bibliotecas, como no exemplo abaixo, fazem a instalação no PinPad:

#import <ExternalAccessory/ExternalAccessory.h>
#import "mpos-ios.h"

// Obtém um objeto EAAccessory, que representa um aparelho Bluetooth pareado.
EAAccessory *accessory = [[[EAAccessoryManager sharedAccessoryManager] connectedAccessories] firstObject];

PMMposController *controller = [[PMMposController alloc] initWithAccessory:accessory encryptionKey:@"{ENCRYPTION_KEY}"];
BOOL force = NO; // Define o comportamento da atualização de tabelas
[controller openConnection];
[controller openSessionWithCallback:^(NSError *error){
    if (error != nil) { /* Lidar com Erro */ return; }
    [controller downloadEMVTablesToDeviceWithCallback:^(BOOL loaded, NSError *error){
        if (error != nil) { /* Lidar com Erro */ return; }
        NSLog(@"Tabelas Carregadas: %d", loaded);
        [controller closeSessionWithMessage:@"Message" callback:^(NSError *error){
            [controller closeConnection];
        }];
    } forceUpdate:force];
}];
import ExternalAccessory

// Obtém um objeto EAAccessory, que representa um aparelho Bluetooth pareado.
let accessory = EAAccessoryManager.sharedAccessoryManager().connectedAccessories.first

let controller = PMMposController(accessory: accessory, encryptionKey: "ENCRYPTION_KEY")
let force = false // Define o comportamento da atualização de tabelas

controller.openConnection()
controller.openSessionWithCallback({ (error: NSError!) -> Void in
    if error != nil {
        /* Lidar com Erro */
        return
    }
    controller.downloadEMVTablesToDeviceWithCallback({ (loaded: Bool, error: NSError!) -> Void in
        if error != nil {
            /* Lidar com Erro */
            return;
        }

        NSLog("Tabelas Carregadas: %d", loaded);
        controller.closeSessionWithMessage(message: "Message", callback: { error: NSError! -> Void in
            controller.closeConnection()
        })

    }, forceUpdate: force)
});

O valor booleano force dos exemplos especifica o comportamento de atualização de tabelas no PinPad. Caso ele seja setado como true, faz o download e instala as tabelas baixadas no PinPad. Caso esteja como false, somente instala as tabelas no PinPad se a versão no PinPad for diferente da versão das tabelas na API Pagar.me, evitando instalações de forma redundante.

O parâmetro loaded nos eventos lançados por ocasião do término de atualização de tabelas indica, se true, que foram instaladas tabelas no PinPad; se false, que essa instalação não foi necessária.

Processando os dados de cartão

Para processar uma transação de cartão de crédito/débito por intermédio do PinPad e obter o card hash — que deve ser enviado à API Pagar.me para que a transação seja completada — o seguinte código pode ser utilizado:

#import <ExternalAccessory/ExternalAccessory.h>
#import "mpos-ios.h"

// Obtém um objeto EAAccessory, que representa um aparelho Bluetooth pareado.
EAAccessory *accessory = [[[EAAccessoryManager sharedAccessoryManager] connectedAccessories] firstObject];

PMMposController *controller = [[PMMposController alloc] initWithAccessory:accessory encryptionKey:@"{ENCRYPTION_KEY}"];
[controller openConnection];
[controller openSessionWithCallback:^(NSError *error){
    if (error != nil) { /* Lidar com Erro */ return; }

    /* aceitar somente Visa Crédito */
    NSArray *applications = @[ [PMEmvApplication applicationWithCardBrand:@"visa" paymentMethod:MPM_CREDIT] ];

    /* selecionar Crédito como método de pagamento de tarja */
    [controller payAmount:100 withApplications:applications magstripePaymentMethod:MPM_CREDIT withCallback:^(NSString *cardHash, NSError *error){
        if (error != nil) { /* Lidar com Erro */ return; }
        NSLog(@"card_hash gerado = %@", cardHash);

        /* Gerar transação com a API Pagar.me... */
        [controller finishTransactionWithSuccess:... withCallback:^(NSError *error){
            if (error != nil) { /* Lidar com Erro */ return; }
            [controller closeSessionWithMessage:@"Message" callback:^(NSError *error){
                [controller closeConnection];
            }];
        }];
    }];
}];
import ExternalAccessory

// Obtém um objeto EAAccessory, que representa um aparelho Bluetooth pareado.
let accessory = EAAccessoryManager.sharedAccessoryManager().connectedAccessories.first

let controller = PMMposController(accessory: accessory, encryptionKey: "{ENCRYPTION_KEY}")
controller.openConnection()
controller.openSessionWithCallback({ (error: NSError!) -> Void in
    if error != nil {
        /* Lidar com Erro */
        return
    }

    /* aceitar somente Visa Crédito */
    var applications = [ PMEmvApplication(cardBrand: "visa", paymentMethod: MPM_CREDIT) ];

    /* selecionar Crédito como método de pagamento de tarja */
    controller.payAmount(100, withApplications: applications, withCallback: { (cardHash: String!, error: NSError!) -> Void in
        if error != nil {
            /* Lidar com Erro */
            return
        }
        NSLog("card_hash gerado = %@", cardHash);

        /* Gerar transação com a API Pagar.me... */       
        controller.finishTransactionWithSuccess(..., withCallback: { error: NSError! -> Void in
            if error != nil {
                /* Lidar com Erro */
                return
            }

            controller.closeSessionWithMessage(message: "Message", callback: { error: NSError! -> Void in
                controller.closeConnection()
            })
        })
    })
});

O SDK usa a função payAmount para capturar os dados, que aceita os seguites parâmetros: amount, applications e magstripePaymentMethod.

O primeiro é um inteiro representando a quantia a ser cobrada em centavos (no caso dos exemplos, 100 = R$1,00). As opções possíveis são as seguintes, que podem ser juntadas com o operador bitwise-OR (|):

ParâmetroSignificado
amountQuantia a ser cobrada em centavos (ex. 100 = R$1,00)
applicationsUm conjunto de EMVApplication que sua aplicação deseja selecionar. Uma EMVApplication consiste da combinação bandeira e método de pagamento (ex. Visa Crédito, Master Débito, Amex Crédito). Em caso de valor nulo, a escolha de possíveis aplicações é feita pelo PinPad.
magstripePaymentMethodA tarja magnética não permite seleção de método de pagamento no PinPad, o que requer sempre que a aplicação o defina.

Caso o conjunto de aplicações especificado não seja suportado pelo cartão inserido (ex. applications contém Visa Crédito e o cartão é Master Crédito), o PinPad retorna o erro 70.

Finalizando uma transação

Após a obtenção de um card_hash por meio do processamento no SDK, e seu envio à API Pagar.me para criação de uma transação, é necessário finalizar o procedimento como um todo. Para tal, o seguinte código deve ser usado:

#import "mpos-ios.h"

BOOL connected = YES; /* Define se foi possível se conectar à API Pagar.me para processar a transação */

[controller finishTransactionWithSuccess:connected withResponseCode:[responseCode integerValue] emvData:emvData withCallback:^(NSError *error){}];
let connected = true; /* Define se foi possível se conectar à API Pagar.me para processar a transação */

controller.finishTransactionWithSuccess(connected, withResponseCode: Int(responseCode), emvData: emvData, withCallback: { error: NSError! }) -> Void in });

Os parâmetros responseCode e emvData devem ser retirados do objeto transaction retornado pela API Pagar.me:

{
  "card_pin_mode": "online",
  "acquirer_response_code": "0000",
  "card_emv_response": "124046c481.ca8c"
}

Com a seguinte correspondência:

ParâmetroSignificado
responseCodeInteger dentro da propriedade acquirer_response_code do objeto transaction
emvDatacard_emv_response: String responsável por finalizar a comunicação entre PinPad e cartão — usada somente quando a autenticação foi Pin Online, veja a seguir.

card_pin_mode

Você deve usar este parâmetro para validar se é necessário executar o finishTransaction. Sempre que o retorno estiver como online, é necessário finalizar a transação, caso contrário apenas execute o fechamento da conexão com o PinPad.

🚧

Vale ressaltar

Caso não tenha sido possível fazer uma conexão com a API Pagar.me para inicializar uma transação, e o parâmetro connected seja false, responseCode deve ser 0 e emvData deve ser null.

❗️

Parâmetro local_time

Ao criar uma transação de mundo físico, deve ser enviado o parâmetro local_time, que refere-se a data e hora do dispositivo que está efetuando a transação, em formato ISO String (2017-10-31T14:53:00.000Z).


Próximo

Excelente! Você aprendeu como integrar sua aplicação com nosso SDK para mPOS, mas caso encontre algum erro ao longo do caminho, a seguinte tabela pode te ajudar na resolução, segue: