3 - Realizar Pagamento
Configure o SDK Tap to Pay no iOS e realize pagamentos com Swift e SwiftUI, incluindo tratamento seguro de erros com sdkError.
Realize seu primeiro pagamento Tap to Pay no iPhone configurando o SDK e enviando uma cobrança em crédito.
① Configurar credenciais → ② Aplicar setConfig() → ③ Chamar pay()Optional: para antecipar a inicialização e a criação de sessão antes da primeira cobrança, veja 5 - Otimizar pagamento.
Antes de começar
- Conclua a instalação do SDK em 1 - Adicionar ao projeto.
- Importe
TapOnPhoneSDKno arquivo em que fará a integração. - Separe suas credenciais de
marketplace,sellereaccessKeyantes de configurar o SDK.
Configurar
Neste passo, você vai definir as credenciais e aplicar a configuração inicial do SDK.
Chame
TapOnPhone.setConfig()apenas uma vez, no ponto da aplicação que fizer mais sentido para a preparação inicial do app.
1. Criar as credenciais
Crie uma variável para armazenar as credenciais usadas pelo SDK.
let credentials = TapOnPhoneCredentials(
marketplace: "coloque seu marketplace aqui",
seller: "coloque seu seller aqui",
accessKey: "coloque seu access key aqui"
)2. Optional: Personalizar a aparência com SdkConfig
SdkConfigUse SdkConfig para alterar o tema e o comportamento visual do SDK. Se você não quiser customizar as views agora, pode manter a configuração padrão.
let sdkConfig = SdkConfig()Quando usar SdkConfig?
Use SdkConfig quando você quiser alinhar a experiência do SDK com a identidade visual do seu app. Se a personalização não for necessária neste momento, basta omitir esse parâmetro ao chamar setConfig().
3. Aplicar a configuração do SDK
Depois de criar as credenciais, chame TapOnPhone.setConfig() para aplicar a configuração do SDK com os parâmetros da sua integração.
TapOnPhone.setConfig(
configParameters: ConfigParameters(
credentials: credentials,
environment: .production, // opcional
logLevel: .error, // opcional
sdkConfig: sdkConfig // opcional
)
)Exemplo completo de configuração
O exemplo abaixo mostra uma configuração mínima dentro de uma View em SwiftUI.
import SwiftUI
import TapOnPhoneSDK
struct HomeView: View {
var body: some View {
Button("Configuração SDK") {
let credentials = TapOnPhoneCredentials(
marketplace: "coloque seu marketplace aqui",
seller: "coloque seu seller aqui",
accessKey: "coloque seu accessKey aqui"
)
TapOnPhone.setConfig(
configParameters: ConfigParameters(
credentials: credentials,
environment: .production, // opcional
logLevel: .error, // opcional
sdkConfig: SdkConfig() // opcional
)
)
}
}
}Pagamento
Use TapOnPhone.pay() para processar a venda e trate os erros com sdkError para diferenciar falhas de pagamento e falhas do SDK com mais segurança.
Prefira
response.sdkErrorno callbackonError. Essa abordagem evita casts frágeis comas!e ainda cobre casos desconhecidos com.unknown.
Se você quiser reduzir o tempo percebido no início da cobrança, veja 5 - Otimizar pagamento para antecipar
initialize(...)eactivateSession(...)antes de chamarpay().
1. Verificar os requisitos de plataforma
PaymentRequesteTapOnPhone.payestão disponíveis a partir de iOS 16.4.- Antes de vender, aplique a configuração do SDK com
TapOnPhone.setConfig().
2. Montar o PaymentRequest
PaymentRequestCrie o PaymentRequest (objeto que representa os dados da transação) com o valor, tipo de pagamento e parâmetros opcionais da cobrança.
let request = PaymentRequest(
amount: 100,
paymentType: .credit,
installments: 1
)O valor
100representa R$ 1,00. Sempre envieamountem centavos.
Inicialização de PaymentRequest
public init(
amount: Int,
paymentType: TapOnPhonePaymentType,
installments: Int = 1,
metadata: String? = nil,
referenceId: String? = nil
)| Campo | Tipo | Padrão | Descrição |
|---|---|---|---|
amount | Int | obrigatório | Valor da transação em centavos. Exemplo: 100 = R$ 1,00. |
paymentType | TapOnPhonePaymentType | obrigatório | Use .credit ou .debit. |
installments | Int | 1 | Número de parcelas. Para parcelado, use 2 ou mais. |
metadata | String? | nil | Metadados opcionais com limite de 512 caracteres. |
referenceId | String? | nil | Identificador opcional definido pelo cliente. Pode retornar na resposta de sucesso. |
3. Enviar o pagamento
Com a requisição pronta, chame TapOnPhone.pay() e trate os três retornos do fluxo: sucesso, erro e eventos.
import SwiftUI
import TapOnPhoneSDK
struct PaymentView: View {
@State private var showSuccess = false
@State private var showError = false
@State private var successMessage = ""
@State private var errorMessage = ""
var body: some View {
VStack(spacing: 20) {
Button("Realizar pagamento") {
let request = PaymentRequest(
amount: 1000, // R$ 10,00
paymentType: .credit,
installments: 2,
metadata: """
{
"clientId": "1234",
"name": "John Doe"
}
""",
referenceId: "order-abc-123"
)
TapOnPhone.pay(
payRequest: request,
onSuccess: { result in
successMessage = "Pagamento aprovado! id: \(result.transactionId)"
showSuccess = true
},
onError: { response in
switch response.sdkError {
case .payment(let paymentError):
let err = paymentError.error
errorMessage = "Pagamento negado — id: \(paymentError.transactionId ?? "desconhecido")\ncode: \(err.code.rawValue)\nname: \(err.code.description)\nmessage: \(err.message)\nsource: \(err.source)"
if let acquirer = paymentError.acquirerCode {
errorMessage += "\nacquirerCode: \(acquirer)"
}
case .tapOnPhone(let sdkError):
errorMessage = "Erro do SDK — code: \(sdkError.code.rawValue)\nname: \(sdkError.code.description)\nmessage: \(sdkError.message)\nsource: \(sdkError.source)"
case .unknown(let underlying):
errorMessage = "Erro não tipado: \(underlying)"
}
showError = true
},
onEvent: { event in
print("ApplicationEvent: \(event)")
}
)
}
}
.alert("Sucesso", isPresented: $showSuccess) {
Button("OK", role: .cancel) { }
} message: {
Text(successMessage)
}
.alert("Erro", isPresented: $showError) {
Button("OK", role: .cancel) { }
} message: {
Text(errorMessage)
}
}
}Saída esperada em caso de sucesso
Pagamento aprovado! id: <transactionId>Saída esperada em caso de erro de pagamento
Pagamento negado — id: <transactionId>
code: <código>
name: <nome do erro>
message: <mensagem>
source: <origem>
acquirerCode: <código da adquirente>Saída esperada em caso de erro do SDK
Erro do SDK — code: <código>
name: <nome do erro>
message: <mensagem>
source: <origem>O que cada callback faz?
onSuccess: recebe umPaymentApprovedResponsequando a transação é aprovada.onError: recebe umErrorResponsecom o erro encapsulado emsdkError.onEvent: recebe eventos intermediários do fluxo de pagamento.
4. Entender a resposta de sucesso
Quando o pagamento é aprovado, o SDK retorna um PaymentApprovedResponse com os principais identificadores da transação.
| Campo | Descrição |
|---|---|
transactionId | Identificador da transação na Zoop. |
cardBrand | Bandeira do cartão, como Visa ou Mastercard. |
readerIdentifier | Identificador do leitor, quando houver sessão. |
referenceId | Eco do referenceId enviado em PaymentRequest, se houver. |
readResultId | Identificador do resultado da leitura do cartão. |
binNumber | BIN do cartão, quando disponível. |
paymentDevice | Dispositivo usado no pagamento, como CARD, MOBILE, NON_CARD, WATCH ou UNKNOWN. |
Estrutura completa de sucesso
public struct PaymentApprovedResponse: Equatable, Hashable {
public let transactionId: String
public let cardBrand: String
public let readerIdentifier: String?
public let referenceId: String?
public let readResultId: String
public let binNumber: String?
public let paymentDevice: String?
}5. Resolver erros com sdkError
sdkErrorUse sdkError como fonte principal para o tratamento de erro. Esse padrão é mais seguro porque expõe o tipo real do erro sem depender apenas de type e casts manuais.
onError: { response in
switch response.sdkError {
case .payment(let paymentError):
let err = paymentError.error
print("Pagamento negado — id:", paymentError.transactionId ?? "desconhecido")
print("code:", err.code.rawValue)
print("name:", err.code.description)
print("message:", err.message)
print("source:", err.source)
if let acquirer = paymentError.acquirerCode {
print("acquirerCode:", acquirer)
}
case .tapOnPhone(let sdkError):
print("Erro do SDK — code:", sdkError.code.rawValue)
print("name:", sdkError.code.description)
print("message:", sdkError.message)
print("source:", sdkError.source)
case .unknown(let underlying):
print("Erro não tipado:", underlying)
}
}| Caso | Quando esperar | Tipo retornado |
|---|---|---|
.payment(PaymentErrorResponse) | Pagamento negado ou falha após leitura do cartão | Erro de pagamento com dados da transação, como transactionId, cardBrand e acquirerCode |
.tapOnPhone(TapOnPhoneError) | Erro de configuração, sessão, inicialização ou falha interna do SDK | Erro do SDK com code, message, source e outros metadados |
.unknown(Any) | Cenário não tipado ou inesperado | Valor bruto para fallback e diagnóstico |
Em fluxos de pagamento negado, type costuma ser .payment e sdkError será .payment(PaymentErrorResponse). Falhas antes ou durante a preparação do fluxo podem chegar como erro de SDK, normalmente encapsuladas em .tapOnPhone(TapOnPhoneError).
Optional: Tratamento legado com type e cast
Use este formato apenas para compatibilidade com implementações anteriores. Para novas integrações, prefira sdkError.
onError: { response in
if response.type == .payment,
let paymentError = response.error as? PaymentErrorResponse {
// usar paymentError
} else if let sdkError = response.error as? TapOnPhoneError {
// usar sdkError
}
}Estruturas completas de erro
public struct ErrorResponse {
public let type: ErrorType
public let error: Any
public var sdkError: SDKError { get }
}
public enum SDKError {
case tapOnPhone(TapOnPhoneError)
case payment(PaymentErrorResponse)
case unknown(Any)
}
public enum ErrorType: String, Codable {
case initialize
case payment
case onboarding
}
public struct PaymentErrorResponse: Equatable, Hashable, Error {
public let error: TapOnPhoneError
public let transactionId: String?
public let cardBrand: String?
public let readResultId: String?
public let binNumber: String?
public let paymentDevice: String?
public let acquirerCode: String?
}
public struct TapOnPhoneError: Equatable, Error, Hashable {
public let code: TapOnPhoneErrorCode
public let source: TapOnPhoneErrorSource
public let message: String
public let description: String?
public let readerIdentifier: String?
public let timestamp: Double
}Optional: Acompanhar eventos de pagamento
Use onEvent para acompanhar as etapas intermediárias do fluxo. Para mais detalhes sobre os eventos de pagamento, ver aqui.
Próximo passo
Depois de validar o fluxo básico de pagamento, avance para 5 - Otimizar pagamento para antecipar a inicialização e a criação de sessão. Se você precisar aprofundar o diagnóstico do fluxo, revise também a documentação de eventos do SDK.
Updated 4 days ago
