Apple Pay via widget
Nesta página
Este guia orienta você na integração Apple Pague usando os SDKs DEUNA
| Widget de pagamento | Cofre de Pagamentos | |
|---|---|---|
| O que isso faz** | Lida com o checkout completo: UI, processamento de pagamento e confirmação | Tokeniza apenas o cartão – retorna um card_id para você usar |
| Quem processa a compra | DEUNA (internamente) | Você (por meio da API de compra do seu back-end) |
| Botão Apple Pay | Renderizado dentro do iframe da DEUNA | Renderizado por você, em sua própria UI |
| Método SDK | initPaymentWidget | initElements({ types: ['APPLE_PAY'] }) |
| Usar quando | Você quer uma experiência de checkout imediato | Você precisa de controle sobre o fluxo de pagamento ou deseja guardar o cartão para mais tarde |
1. Pré-requisitos#
Antes de começar, certifique-se de que o seguinte esteja em vigor:
| Requisito | Notas |
|---|---|
| Conta DEUNA | Conta de comerciante ativa no DEUNA Dashboard. |
publicApiKey | Chave API pública emitida pela DEUNA. Obrigatório para DeunaSDK.initialize. |
orderToken | Gerado em seu backend por meio da API DEUNA Orders. Necessário para iniciar um pagamento. |
userToken (opcional) | Necessário apenas quando você deseja tokenizar o cartão contra um usuário DEUNA conhecido. |
| Domínio HTTPS | O Apple Pay exige que a página seja veiculada por HTTPS. localhost é permitido apenas para desenvolvimento. |
| Requisitos de compatibilidade | Consulte o oficial Apple Pay na Web e Implementação do Apple Pay documentação. O Apple Pay requer Safari no iOS 10+ ou macOS 10.12+; em navegadores não Safari (Chrome, Edge, Firefox), um fluxo de código QR está disponível para usuários com iPhone executando iOS 18 ou posterior. |
Verificação de domínio do 1. (obrigatório para ambos os caminhos)
Todo domínio que renderiza um botão Apple Pay – seja por meio do widget de pagamento ou do Vault – deve ser registrado na Apple por meio da DEUNA. Isso se aplica a domínios de produção e a qualquer ambiente de teste ou visualização.
Passo a passo
- Obtenha o arquivo de associação de domínio do DEUNA Dashboard (ou do Apple Pay se estiver usando seu próprio ID de comerciante). O arquivo normalmente é nomeado
apple-developer-merchantid-domain-association(sem extensão) ou.txt. - Hospede o arquivo inalterado em:
Certifique-se de:Plain text
https://<your-domain>/.well-known/apple-developer-merchantid-domain-association- A resposta é entregue HTTPS.
Content-Typeétext/plain; charset=utf-8.- Sem redirecionamento, sem parede de autenticação, sem 404. A resposta deve ser
200 OK.
- Verifique o domínio no DEUNA Dashboard (ou portal Apple Pay Developer). A Apple irá buscar o arquivo no seu servidor; se corresponder, o domínio está registrado.
- Repita por domínio. Cada nome de host que carrega o widget (por exemplo
checkout.mystore.com,staging.mystore.com) deve servir o arquivo e ser registrado separadamente.
Implementação de referência (Next.js - Exemplo)
Este repositório já implementa o endpoint de verificação. Duas coisas estão ligadas:
next.config.js - reescreve tanto o canônico quanto o .txt caminhos para uma rota de API:
async rewrites() {
return [
{
source: '/.well-known/apple-developer-merchantid-domain-association',
destination: '/api/apple-verification',
},
{
source: '/.well-known/apple-developer-merchantid-domain-association.txt',
destination: '/api/apple-verification',
},
];
}src/pages/api/apple-verification.ts — retorna o conteúdo do arquivo como text/plain:
import { NextApiRequest, NextApiResponse } from 'next';
export default function domainVerification(
_req: NextApiRequest,
res: NextApiResponse,
) {
const fileContents = process.env.NEXT_PUBLIC_APPLE_VALIDATION_CONTENT_FILE;
res.setHeader('Content-Type', 'text/plain; charset=utf-8');
res.status(200).send(fileContents);
}O conteúdo do arquivo é armazenado em uma variável de ambiente (NEXT_PUBLIC_APPLE_VALIDATION_CONTENT_FILE) para que possam ser alternados por ambiente sem alteração de código.
Como verificar se funciona
curl -i https://<your-domain>/.well-known/apple-developer-merchantid-domain-associationconst response = await fetch("https://<your-domain>/.well-known/apple-developer-merchantid-domain-association", {
method: "GET"
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const data = await response.json();import requests
response = requests.request(
"GET",
"https://<your-domain>/.well-known/apple-developer-merchantid-domain-association",
)
response.raise_for_status()
data = response.json()<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://<your-domain>/.well-known/apple-developer-merchantid-domain-association",
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_RETURNTRANSFER => true
]);
$response = curl_exec($curl);
curl_close($curl);import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://<your-domain>/.well-known/apple-developer-merchantid-domain-association"))
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient().send(
request, HttpResponse.BodyHandlers.ofString()
);
System.out.println(response.body());
}
}package main
import (
"fmt"
"io"
"net/http"
)
func main() {
request, err := http.NewRequest("GET", "https://<your-domain>/.well-known/apple-developer-merchantid-domain-association", nil)
if err != nil { panic(err) }
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
body, _ := io.ReadAll(response.Body)
fmt.Println(string(body))
}Espere:
- HTTP
200 OK Content-Type: text/plain; charset=utf-8- Um corpo começando com
7B22...(a bolha da Apple)
2. Integração#
Certifique-se de seguir o guia de primeiros passos para nossos SDKs, dependendo da sua integração específica:
2.1. Widget de pagamento
Particularidades do Apple Pay
- Nenhuma configuração extra necessária no código. O Apple Pay está ativado ou desativado no painel DEUNA. Se o estabelecimento comercial o tiver ativo e o dispositivo do usuário for compatível, o botão aparecerá automaticamente.
userTokené opcional — necessário apenas quando você deseja associar o pagamento a uma conta de usuário DEUNA conhecida.- Os retornos de chamada de widget padrão (
onSuccess,onError,onClosed,onPaymentProcessing) funcionam da mesma forma que para outros métodos de pagamento.
Quando você precisa de getWalletsAvailable no widget de pagamento?
Se você abrir o widget com todos os métodos de pagamento habilitados, não será necessário chamar esse método — DEUNA renderiza o seletor de método de pagamento (incluindo botões de carteira) e resolve a disponibilidade internamente.
Você só precisa getWalletsAvailable quando você renderiza seu próprio botão Apple Pay fora do seletor e usa o widget de pagamento no modo autônomo para ir diretamente para esse método de pagamento. Nesse caso, ligue com antecedência para decidir se deseja mostrar seu botão.
const { DeunaSDK } = window; // from https://cdn.deuna.io/web-sdk/v1.6/index.js
await DeunaSDK.initialize({
env: 'sandbox',
publicApiKey: '<YOUR_PUBLIC_API_KEY>',
});
// If Apple Pay is available, it should return it within an array, such as: ["APPLE_PAY"]
const available = await DeunaSDK.getWalletsAvailable();
if (available.includes('APPLE_PAY')) {
// Render button for Apple Pay and append a listener (EXAMPLE)
btn.addEventListener('click', () => {
DeunaSDK.initPaymentWidget({
orderToken: '<order-token>', // REQUIRED
paymentMethods: [
{
paymentMethod: 'wallet',
processors: ['apple_pay'],
},
], // In case only the specific payment method is to be used
callbacks: {
onSuccess: (order) => {
console.log('Payment completed:', order);
},
onError: (error) => {
console.error('Payment failed:', error.metadata.message);
},
onClosed: (action) => {
console.log('Widget closed:', action);
},
},
});
});
} else {
console.error('Apple Pay is not available on this device.');
}2.2. Cofre de pagamento
SDK Web
Deixe o Web SDK resolver as credenciais do Apple Pay do backend DEUNA usando seu publicApiKey e (opcionalmente) um orderToken.
Para mais informações consulte o getWalletsAvailable documentation.
const { DeunaSDK } = window; // from https://cdn.deuna.io/web-sdk/v1.6/index.js
await DeunaSDK.initialize({
env: 'sandbox',
publicApiKey: '<YOUR_PUBLIC_API_KEY>',
});
// If Apple Pay is available, it should return it within an array, such as: ["APPLE_PAY"]
const available = await DeunaSDK.getWalletsAvailable();
if (available.includes('APPLE_PAY')) {
// Render button for Apple Pay and append a listener (EXAMPLE)
btn.addEventListener('click', () => {
deuna.initElements({
types: [{ name: 'APPLE_PAY' }],
orderToken: '<order-token>', // REQUIRED FOR MERCHANTS
userInfo: {
email: '<email>',
firstName: '<firstName>',
lastName: '<lastName>',
},
callbacks: {
// Called after user approves the Google Pay sheet.
// Send the token to your backend, return the result.
onSuccess: async (payload) => {
const cardId = payload.data.id;
// use the cardId to process payment
},
onError: (error) => {
console.error('Payment failed:', error.metadata.message);
},
},
});
});
} else {
console.error('Apple Pay is not available on this device.');
}SDK iOS
Pré-requisitos da carteira Apple Pay (iOS)
Para usar o Apple Pay Wallet com o SDK no iOS, certifique-se de que todos os itens a seguir estejam configurados corretamente.
-
Configuração de aplicativo e equipe
- Seu aplicativo deve ser assinado com um Equipe de desenvolvedores da Apple isso tem Apple Pay ativado.
- O alvo PRODUCT_BUNDLE_IDENTIFIER deve corresponder ao App ID configurado no Apple Developer.
- O aplicativo deve ser instalado em um dispositivo iOS real (Apple Pay não funciona totalmente no simulador).
-
Configuração do ID do comerciante
- Crie ou use um ID de comerciante no Apple Developer (exemplo: comerciante.test.deuna.dev.pay).
- Atribua esse ID do comerciante ao App ID do aplicativo em Identificadores > ID do aplicativo > Apple Pay.
- No Xcode, habilite Assinatura e recursos > Apple Pay e selecione o mesmo ID do comerciante.
-
Certificados necessários
Para o Merchant ID usado pelo SDK, você deve ter:- Certificado de processamento de pagamento Apple Pay (obrigatório para processamento de token Apple Pay no aplicativo).
-
Perfis de provisionamento
- Gere novamente perfis de provisionamento após alterar os recursos do Apple Pay ou as atribuições de ID do comerciante.
- Reinstale o aplicativo após alterações de perfil/recurso (Limpar pasta de compilação + excluir aplicativo do dispositivo + reinstalar).
-
Requisitos de consistência de SDK/back-end
-
O ID do comerciante retornado pelas credenciais de back-end (external_merchant_id) deve corresponder exatamente ao ID do comerciante habilitado no direito do aplicativo.
-
O fluxo da carteira do SDK deve incluir o contexto do usuário (userInfo) quando exigido pelo seu back-end para retornar userToken e userId.
-
Se userToken/userId estiverem faltando, a tokenização poderá falhar mesmo se a UI do Apple Pay for aberta.
-
Passo 1 – Verifique a disponibilidade Chame getWalletsAvailable() uma vez antes da etapa de pagamento. O SDK valida a configuração do comerciante DEUNA e a disponibilidade do Apple Pay no dispositivo.
import DeunaSDK
let deunaSDK = DeunaSDK(
environment: .sandbox,
publicApiKey: "YOUR_PUBLIC_API_KEY"
)
deunaSDK.getWalletsAvailable(
params: GetWalletsAvailableParams(
orderToken: "<order-token>", // optional at this stage
userInfo: DeunaSDK.UserInfo(
email: "user@example.com",
firstName: "Jane",
lastName: "Doe"
) // recommended for wallet auth flows
)
) { wallets, error in
if let error = error {
// handle fetch error
return
}
let applePayAvailable = wallets.contains(.applePay)
// show or hide your Apple Pay button based on applePayAvailable
}getWalletsAvailable() armazena em cache o resultado. As chamadas subsequentes retornam as carteiras em cache imediatamente, portanto, é seguro chamar a cada carregamento de tela.
Passo 2 — Inicie o Apple Pay Quando o usuário tocar no botão Apple Pay, chame initElements com APPLE_PAY como tipo. O SDK busca credenciais de pedido e lança a planilha nativa do Apple Pay.
deunaSDK.initElements(
userToken: "YOUR_ORDER_TOKEN", // required for apple pay wallet
callbacks: ElementsCallbacks(
onSuccess: { payload in
// payload contains tokenized card data
},
onError: { error in
// error.metadata?.code / message
},
onClosed: { _ in
// user dismissed the sheet
},
onEventDispatch: nil
),
closeEvents: [],
userInfo: DeunaSDK.UserInfo(
email: "user@example.com",
firstName: "Jane",
lastName: "Doe"
),
styleFile: nil,
types: [["name": "APPLE_PAY"]],
language: nil,
orderToken: "<order-token>",
widgetExperience: nil,
behavior: nil,
fraudCredentials: nil,
customUserAgent: nil,
domain: nil
)SDK React Native
Use este caminho quando quiser renderizar uma planilha nativa do Apple Pay diretamente, sem um WebView. O SDK verifica a disponibilidade do dispositivo, busca as credenciais do Apple Pay no back-end da DEUNA e inicia a planilha de pagamento. O resultado é uma carga de cartão tokenizada entregue ao retorno de chamada onSuccess.
Pré-requisitos:
- Ative o recurso Apple Pay no destino do seu aplicativo (Xcode → destino → Assinatura e recursos → + Capacidade → Apple Pay).
- Adicione seu ID de comerciante nesse recurso (por exemplo, comerciante.io.seu-domínio.com).
- O mesmo Merchant ID deve ser retornado pelas credenciais DEUNA (external_merchant_id). Confirme isso com sua equipe de conta DEUNA.
- Em Portal do desenvolvedor Apple, esse ID do comerciante deverá ter um certificado de processamento de pagamento Apple Pay ativo.
- Após qualquer alteração de capacidade ou comerciante, gere novamente seus perfis de provisionamento e reinstale o aplicativo em um dispositivo real.
Expo — declare o direito em app.json e execute npx expo prebuild para aplicá-lo:
{
"expo": {
"ios": {
"entitlements": {
"com.apple.developer.in-app-payments": ["merchant.io.your-domain.com"]
}
}
}
}Reagir CLI nativo- adicione-o a ios/<AppName>/<AppName>.entitlements:
<key>com.apple.developer.in-app-payments</key>
<array>
<string>merchant.io.your-domain.com</string>
</array>import { useState, useEffect } from 'react';
import { DeunaSDK } from '@deuna/react-native-sdk';
// 1) Initialize the SDK
const sdk = new DeunaSDK({
publicApiKey: '<YOUR_PUBLIC_API_KEY>',
environment: 'sandbox', // 'production' | 'sandbox'
});
// 2) Check availability
const available = await sdk.getWalletsAvailable();
// 3) Launch
if (available.includes('apple_pay')) {
sdk.initElements({
orderToken: '<order-token>', // required
types: [{ name: 'apple_pay' }],
userInfo: { // required
email: '<email>',
firstName: '<firstName>',
lastName: '<lastName>',
},
callbacks: {
onSuccess: (payload) => {
const cardId = payload?.card_id;
// use cardId to process payment on your backend
},
onError: (error) => {
console.error('Payment failed:', error.metadata.message);
},
onClosed: (action) => {
console.log('Sheet dismissed by', action);
},
},
});
}4. Pegadinhas#
| Te peguei | Correção |
|---|---|
| Botão não renderiza | Verifique getWalletsAvailable() resultado, suporte ao navegador e HTTPS. |
| Folha de pagamento abre e congela | Falha na validação do comerciante – verifique o arquivo de verificação de domínio e as credenciais DEUNA. |
session.begin() silenciosamente rejeitado | Você perdeu o gesto do usuário. Não await trabalho de longa duração entre clique e session.begin(). Use o orderToken + userInfo Caminho SSR para pré-resolução transactionInfo. |
| Funciona no Safari, não no Chrome | Esperado – a planilha nativa requer Safari. Outros navegadores recorrem ao fluxo do código QR (iOS 18+). |
Referência rápida
| API | Objetivo |
|---|---|
DeunaSDK.getWalletsAvailable() | Verifique quais carteiras estão disponíveis no dispositivo. |
DeunaSDK.initElements({ types, orderToken?, callbacks }) | Inicialize o Apple Pay. Renderize seu próprio botão Apple Pay |
DeunaSDK.initPaymentWidget({ orderToken, callbacks, ... }) | Abra o widget de pagamento completo da DEUNA (Apple Pay incluído). |
.well-known/apple-developer-merchantid-domain-association | Arquivo de verificação de domínio que você deve hospedar em todos os domínios |