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:
- Adicione as libraries 
libabecs.a,libmpos.a,libmposios.aelibtms.a— que estão incluídas na distribuição do SDK (pastalib) — nas configurações do projeto Xcode em Build Phases > Link Binary With Libraries; - Adicione o diretório 
includeda distribuição do SDK a Build Settings > Search Paths > Header Search Paths; - Adicione o diretório 
libda distribuição do SDK a Build Settings > Search Paths > Library Search Paths; - Mude a opção Build Settings > Build Options > Enable Bitcode de 
YesparaNo; - 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
- Adicione um header file ao seu projeto para fazer o bridging, e insira:
 
#import <mpos-ios.h>
- No campo Build Settings > Swift Compiler - Code Generation > Objective-C Bridging Header, insira este header;
 - Ao adicionar o Header, a classe 
PMMposControllerestará 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:
- Download das tabelas EMV pela API Pagar.me;
 - 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âmetro | Significado | 
|---|---|
| amount | Quantia a ser cobrada em centavos (ex. 100 = R$1,00) | 
| applications | Um 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. | 
| magstripePaymentMethod | A 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âmetro | Significado | 
|---|---|
| responseCode | Integer dentro da propriedade acquirer_response_code do objeto transaction | 
| emvData | card_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
0e emvData deve sernull.
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).
Updated almost 8 years ago
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:
