> ## Documentation Index
> Fetch the complete documentation index at: https://developers.uvvipay.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Apple Pay

> Aceite Apple Pay no seu app iOS ou no seu site processando os pagamentos pela UvviPay

## Visão Geral

Com o Apple Pay, o usuário paga com os cartões já cadastrados na Wallet do iPhone, iPad, Mac ou Apple Watch, com autenticação por Face ID/Touch ID — sem digitar número de cartão. O seu app ou site recebe do iOS/Safari um token de pagamento criptografado ([`PKPaymentToken`](https://developer.apple.com/documentation/passkit/pkpaymenttoken)) e o envia para a API da UvviPay, que faz a decriptação e o processamento.

**Não há tarifa adicional** para processar Apple Pay: a precificação é a mesma das demais transações com cartão de crédito da sua conta. Funciona em apps a partir do iOS 10 e na web com Safari (iOS 10+/macOS Sierra+) — consulte os [dispositivos compatíveis](https://support.apple.com/pt-br/102896) e os [bancos participantes](https://support.apple.com/pt-br/HT204916) na documentação da Apple.

<Info>
  **Seu sistema nunca vê os dados do cartão.** O token do Apple Pay é cifrado pela Apple diretamente para a UvviPay — o número do cartão não passa pelo seu código nem pelos seus servidores, o que reduz drasticamente o seu escopo PCI.
</Info>

### Propriedades da forma de pagamento

| Propriedade               | Valor                                                                                      |
| ------------------------- | ------------------------------------------------------------------------------------------ |
| Família                   | Carteira digital (wallet)                                                                  |
| Confirmação do pagamento  | Iniciada pelo cliente                                                                      |
| Moeda                     | BRL                                                                                        |
| Tarifas                   | As mesmas de cartão de crédito, sem adicional                                              |
| Bandeiras                 | Visa e Mastercard (Elo em homologação com a adquirente)                                    |
| Pagamentos recorrentes    | Não (por enquanto — apenas pagamentos avulsos)                                             |
| Parcelamento              | Sim, como crédito (campo `installments`)                                                   |
| Frequência de repasses    | Mesma agenda de recebíveis de cartão de crédito                                            |
| Estornos totais/parciais  | Sim/Sim — iguais aos de cartão de crédito                                                  |
| Contestações (chargeback) | Sim — mesmo fluxo de cartão de crédito                                                     |
| Dispositivos              | [Dispositivos compatíveis com Apple Pay](https://support.apple.com/pt-br/102896)           |
| Cartões                   | Emitidos por [bancos participantes do Apple Pay](https://support.apple.com/pt-br/HT204916) |

<Warning>
  **Recorrência**: por enquanto o Apple Pay está disponível apenas para pagamentos avulsos. Cobranças recorrentes com Apple Pay ainda não são suportadas.
</Warning>

### Suporte de produto

* **Link de Pagamento** — o Apple Pay já aparece automaticamente no checkout dos seus links de pagamento, sem nenhuma configuração (sujeito à habilitação do método para a sua conta).
* **API de Pagamentos** — integração própria no seu app iOS ou site, descrita neste guia.

## Aceitar Apple Pay

A configuração depende de onde o botão vai aparecer — escolha o caminho:

<Columns cols={2}>
  <Card title="App iOS" icon="mobile" href="#configuração-—-app-ios">
    Merchant ID próprio + certificado via CSR da UvviPay + capability no Xcode. Três etapas, uma única vez por app.
  </Card>

  <Card title="Site (web)" icon="globe" href="#configuração-—-web">
    Sem conta Apple Developer: registre seus domínios pela API e hospede o arquivo de verificação. O botão roda no Safari com Apple Pay JS.
  </Card>
</Columns>

## Configuração — App iOS

<Warning>
  **Elegibilidade na App Store**: a Apple só permite Apple Pay dentro de apps para **bens físicos e serviços consumidos fora do app** (delivery, transporte, ingressos, e-commerce, pagamento de contas etc.). Conteúdo digital, funcionalidades do app e assinaturas de conteúdo devem usar In-App Purchase, conforme a [regra 3.1.1 das App Review Guidelines](https://developer.apple.com/app-store/review/guidelines/#in-app-purchase). Confirme o enquadramento do seu produto antes de integrar.
</Warning>

A configuração é feita uma única vez por app e envolve três etapas — as duas primeiras no [Apple Developer Portal](https://developer.apple.com/account), a terceira no Xcode.

<Steps>
  <Step title="Registre um Apple Merchant ID">
    No Apple Developer Portal, acesse **Certificates, Identifiers & Profiles → Identifiers → Merchant IDs** e [crie um novo Merchant ID](https://developer.apple.com/help/account/identifiers/create-a-merchant-identifier/) para o seu app.

    * **Description**: o nome do seu negócio (ex.: `Minha Empresa LTDA`)
    * **Identifier**: um identificador único no formato reverso do seu domínio, prefixado com `merchant.` (ex.: `merchant.com.minhaempresa.app`)

    Guarde esse identificador — ele será usado nas etapas seguintes.
  </Step>

  <Step title="Crie o certificado de processamento com o CSR da UvviPay">
    O [Payment Processing Certificate](https://developer.apple.com/help/account/certificates/create-apple-pay-payment-processing-certificates/) é o que permite à UvviPay decriptar os tokens do Apple Pay do seu app. A chave privada desse certificado fica sob custódia da UvviPay — por isso o CSR (Certificate Signing Request) **deve ser o emitido pela nossa API**, e não um gerado por você. Todo o ciclo é self-service:

    1. Emita o CSR pelo [`POST /v1/certificates`](/api-reference/certificates/issue) e salve o campo `signingRequestPem` como um arquivo `.csr`:

       ```bash Emitir CSR theme={null}
       curl -X POST https://api.uvvipay.com.br/v1/certificates \
         -H "client-id: SUA_CLIENT_ID" \
         -H "client-secret: SUA_CLIENT_SECRET" \
         -H "Content-Type: application/json" \
         -d '{ "type": "apple_pay_payment_processing" }'
       ```

    2. No Apple Developer Portal, abra o seu Merchant ID e, em **Apple Pay Payment Processing Certificate**, clique em **Create Certificate** e envie o `.csr`.

    3. Baixe o certificado emitido pela Apple (`apple_pay.cer`) e ative-o pelo [`POST /v1/certificates/{id}/activate`](/api-reference/certificates/activate), enviando o arquivo em base64:

       ```bash Ativar certificado theme={null}
       curl -X POST https://api.uvvipay.com.br/v1/certificates/{id}/activate \
         -H "client-id: SUA_CLIENT_ID" \
         -H "client-secret: SUA_CLIENT_SECRET" \
         -H "Content-Type: application/json" \
         -d "{ \"certificate\": \"$(base64 -i apple_pay.cer)\" }"
       ```

    A ativação valida na hora que o certificado corresponde ao CSR emitido; com status `active`, ele já vale para as transações — sem contato com o suporte. Acompanhe seus certificados (status, validade) pelo [`GET /v1/certificates`](/api-reference/certificates/list).

    <Info>
      Nenhuma chave ou segredo trafega nesse processo: o CSR e o `.cer` são material público. A chave privada nasce e permanece na UvviPay.
    </Info>

    <Warning>
      Cada CSR emite exatamente **um** certificado na Apple. Para trocar de certificado (rotação, revogação ou mudança de Merchant ID), emita um novo CSR pelo mesmo endpoint. Não use certificados criados a partir de CSRs próprios — a ativação os rejeita, e tokens gerados com eles não podem ser decriptados.
    </Warning>
  </Step>

  <Step title="Habilite o Apple Pay no Xcode">
    No Xcode, abra o target do seu app em **Signing & Capabilities**, [adicione a capability **Apple Pay**](https://developer.apple.com/help/account/configure-app-capabilities/configure-apple-pay/) e marque o Merchant ID criado na etapa 1.

    Com isso o `PKPaymentRequest` do seu app já pode usar o seu `merchantIdentifier`.
  </Step>
</Steps>

## Configuração — Web

Para exibir o botão Apple Pay no seu site você **não precisa de conta Apple Developer nem de Merchant ID próprio**: a validação da sessão é feita pela UvviPay. O único requisito é registrar cada domínio onde o botão será exibido.

O uso do Apple Pay na web está sujeito às [diretrizes de uso aceitável da Apple para sites](https://developer.apple.com/apple-pay/acceptable-use-guidelines-for-websites/).

<Note>
  A verificação automática de domínios está em fase de habilitação junto à Apple. Se o `validate` responder `503`, os passos de registro e hospedagem do arquivo permanecem os mesmos — acione o suporte da UvviPay, que conclui a verificação por você.
</Note>

<Steps>
  <Step title="Registre seus domínios pela API">
    Registre cada domínio onde o botão Apple Pay aparecerá com o [`POST /v1/payment-method-domains`](/api-reference/payment-method-domains/create):

    ```bash Registrar domínio theme={null}
    curl -X POST https://api.uvvipay.com.br/v1/payment-method-domains \
      -H "client-id: SUA_CLIENT_ID" \
      -H "client-secret: SUA_CLIENT_SECRET" \
      -H "Content-Type: application/json" \
      -d '{ "domainName": "checkout.minhaloja.com.br" }'
    ```

    O domínio é criado com status `pending`, e a resposta já traz o **arquivo de verificação** que você precisa hospedar (campo `verificationFile`: caminho exato + conteúdo). Regras de registro:

    * Registre o domínio **exatamente como o usuário o acessa**: `www.exemplo.com.br` e `exemplo.com.br` contam como domínios distintos (`www` é um subdomínio).
    * Cada subdomínio precisa ser registrado individualmente (ex.: `checkout.exemplo.com.br`).
    * Inclua também os domínios de homologação, se quiser testar antes de ir à produção.

    Consulte seus domínios e os respectivos status a qualquer momento com o [`GET /v1/payment-method-domains`](/api-reference/payment-method-domains/list).

    <Note>
      O registro é idempotente: re-registrar um domínio já cadastrado devolve o registro existente, sem duplicar.
    </Note>
  </Step>

  <Step title="Hospede o arquivo de verificação de domínio">
    Salve o `verificationFile.content` da resposta anterior, em texto puro, no caminho indicado:

    ```text Caminho do arquivo theme={null}
    https://SEU_DOMINIO/.well-known/apple-developer-merchantid-domain-association
    ```

    Requisitos para a verificação da Apple funcionar:

    * Servido por **HTTPS** com certificado válido, sem redirecionamentos
    * Acessível publicamente (sem autenticação, sem bloqueio por WAF/geolocalização)
    * Content-Type de texto simples

    <Warning>
      **Mantenha o arquivo hospedado permanentemente.** A Apple revalida os domínios periodicamente — se o arquivo sair do ar, o Apple Pay para de funcionar no seu site.
    </Warning>
  </Step>

  <Step title="Dispare a verificação">
    Com o arquivo no ar, chame o [`POST /v1/payment-method-domains/{id}/validate`](/api-reference/payment-method-domains/validate):

    ```bash Verificar domínio theme={null}
    curl -X POST https://api.uvvipay.com.br/v1/payment-method-domains/{id}/validate \
      -H "client-id: SUA_CLIENT_ID" \
      -H "client-secret: SUA_CLIENT_SECRET"
    ```

    Registramos o domínio junto à Apple **na hora** — os servidores da Apple buscam o arquivo de verificação no seu domínio durante a chamada. Resposta `200` com status `verified` significa domínio verificado de fato. Em caso de falha, o motivo vem no erro e fica registrado em `lastVerificationError` — corrija a hospedagem do arquivo e chame novamente.
  </Step>
</Steps>

### Fluxo no frontend

Com o domínio verificado, o fluxo no seu site usa a [Apple Pay JS API](https://developer.apple.com/documentation/apple_pay_on_the_web) em duas chamadas à UvviPay — sempre intermediadas pelo seu backend, que é quem guarda as credenciais:

1. **`onvalidatemerchant`**: repasse o `validationURL` (fornecido pelo Safari) ao **seu backend**, que chama o [`POST /v1/payments/apple-pay/validate-merchant`](/api-reference/payments/apple-pay-validate-merchant) e devolve o merchant session ao `ApplePaySession`. A validação só é aceita para domínios `verified`.
2. **`onpaymentauthorized`**: envie o `payment.token.paymentData` (em base64) no campo `applePay` da requisição de pagamento — ver [Processando o Pagamento](#processando-o-pagamento).

<CodeGroup>
  ```javascript JavaScript (seu site) theme={null}
  const session = new ApplePaySession(3, {
    countryCode: "BR",
    currencyCode: "BRL",
    supportedNetworks: ["visa", "masterCard"],
    merchantCapabilities: ["supports3DS"],
    total: { label: "Minha Loja", amount: "75.00" },
  });

  session.onvalidatemerchant = async (event) => {
    try {
      // Seu backend chama POST /v1/payments/apple-pay/validate-merchant
      const res = await fetch("/api/apple-pay/validate-merchant", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          validationUrl: event.validationURL,
          domain: window.location.hostname,
        }),
      });
      if (!res.ok) throw new Error("validação de sessão falhou");
      session.completeMerchantValidation(await res.json());
    } catch {
      session.abort(); // sem abort a tela do Apple Pay fica pendurada
    }
  };

  session.onpaymentauthorized = async (event) => {
    const paymentData = btoa(JSON.stringify(event.payment.token.paymentData));
    const network = event.payment.token.paymentMethod.network;
    // Seu backend chama POST /v1/payments com o bloco applePay
    const ok = await processarPagamento(paymentData, network);
    session.completePayment(
      ok ? ApplePaySession.STATUS_SUCCESS : ApplePaySession.STATUS_FAILURE
    );
  };

  session.begin(); // sempre a partir de um gesto do usuário (clique no botão)
  ```

  ```bash cURL (validação de sessão, no seu backend) theme={null}
  curl -X POST https://api.uvvipay.com.br/v1/payments/apple-pay/validate-merchant \
    -H "client-id: SUA_CLIENT_ID" \
    -H "client-secret: SUA_CLIENT_SECRET" \
    -H "Content-Type: application/json" \
    -d '{
      "validationUrl": "https://apple-pay-gateway.apple.com/paymentservices/startSession",
      "domain": "checkout.minhaloja.com.br"
    }'
  ```
</CodeGroup>

### Considerações da integração web

* **HTTPS obrigatório** em todas as páginas que exibem o botão — inclusive em homologação.
* **Gesto do usuário**: a Apple exige que o `ApplePaySession` seja criado por uma ação do usuário (clique/toque no botão). Chame `session.begin()` **diretamente no handler do gesto**, antes de qualquer código assíncrono ou demorado — invocação automática ou tardia é bloqueada pelo Safari. Pelo mesmo motivo, mantenha curto o intervalo entre o gesto e a confirmação do pagamento (busque preços, frete e totais **antes** de exibir o botão, não depois do clique).
* **Disponibilidade**: o Apple Pay na web funciona no Safari (macOS/iOS) e em navegadores no iOS 16+. Exiba o botão apenas quando `window.ApplePaySession?.canMakePayments()` for verdadeiro.
* **Iframes**: se o checkout roda em um iframe, o Safari 17+ exige o atributo `allow="payment"` e que **ambos** os domínios (página e iframe) estejam registrados.
* **Domínio exibido = domínio registrado**: o hostname enviado na validação deve ser exatamente o da página onde o botão está — domínios não registrados são recusados.
* **Aparência do botão**: siga as [diretrizes da Apple para botões Apple Pay](https://developer.apple.com/design/human-interface-guidelines/apple-pay) (marca, dimensões e variações claro/escuro).

## Processando o Pagamento

Tanto no app quanto na web, ao receber a autorização do usuário envie o `paymentData` do token (em base64) no campo `applePay` do [`POST /v1/payments`](/api-reference/payments/create) — no lugar do bloco `card`:

<CodeGroup>
  ```swift Swift (app iOS) theme={null}
  import PassKit

  let request = PKPaymentRequest()
  request.merchantIdentifier = "merchant.com.minhaempresa.app"
  request.supportedNetworks = [.visa, .masterCard]
  request.merchantCapabilities = .threeDSecure
  request.countryCode = "BR"
  request.currencyCode = "BRL"
  request.paymentSummaryItems = [
    PKPaymentSummaryItem(label: "Minha Loja", amount: NSDecimalNumber(string: "75.00"))
  ]

  // No callback de autorização:
  func paymentAuthorizationController(
    _ controller: PKPaymentAuthorizationController,
    didAuthorizePayment payment: PKPayment,
    handler completion: @escaping (PKPaymentAuthorizationResult) -> Void
  ) {
    let paymentData = payment.token.paymentData.base64EncodedString()
    let network = payment.token.paymentMethod.network?.rawValue ?? ""
    // Envie paymentData e network para o SEU backend, que chama a API da UvviPay
  }
  ```

  ```jsx React Native theme={null}
  import { PaymentRequest } from "react-native-payments";

  const paymentRequest = new PaymentRequest(
    [{
      supportedMethods: ["apple-pay"],
      data: {
        merchantIdentifier: "merchant.com.minhaempresa.app",
        supportedNetworks: ["visa", "mastercard"],
        countryCode: "BR",
        currencyCode: "BRL",
      },
    }],
    { total: { label: "Minha Loja", amount: { currency: "BRL", value: "75.00" } } }
  );

  const response = await paymentRequest.show();
  // paymentData = conteúdo do PKPaymentToken.paymentData, em base64
  const paymentData = base64Encode(JSON.stringify(response.details.paymentData));
  const network = response.details.paymentMethod?.network;

  // Envie ao SEU backend, que chama POST /v1/payments com o bloco applePay
  await meuBackend.pagarComApplePay({ paymentData, network });
  await response.complete("success");
  ```

  ```bash cURL (seu backend) theme={null}
  curl -X POST https://api.uvvipay.com.br/v1/payments \
    -H "client-id: SUA_CLIENT_ID" \
    -H "client-secret: SUA_CLIENT_SECRET" \
    -H "Content-Type: application/json" \
    -d '{
      "externalId": "ORDER-12345",
      "amount": 7500,
      "paymentMethod": "credit_card",
      "applePay": {
        "paymentData": "eyJ2ZXJzaW9uIjoiRUNfdjEiLCJkYXRhIjoiLi4uIn0=",
        "network": "Visa",
        "installments": 1
      },
      "customer": {
        "name": "João da Silva",
        "email": "joao@example.com",
        "document": { "type": "cpf", "number": "12345678900" }
      },
      "items": [
        { "title": "Pedido ORDER-12345", "quantity": 1, "unitPrice": 7500 }
      ]
    }'
  ```
</CodeGroup>

<Note>
  O campo `applePay.network` deve vir de `paymentMethod.network` do token — a bandeira é informada pela Apple, já que o número tokenizado (DPAN) não passa por validação de BIN convencional.
</Note>

<Warning>
  Envie `card` **ou** `applePay`, nunca os dois na mesma requisição. Com `applePay`, o próprio token faz o papel de credencial e de autenticação: CVV e 3DS são dispensados.
</Warning>

## Testando

* **Use um cartão real.** Não é possível salvar cartões de teste comuns na Wallet — a Apple só provisiona cartões emitidos por [bancos participantes](https://support.apple.com/pt-br/HT204916). Valide o fluxo com uma transação de valor baixo e estorne em seguida ([`PUT /v1/payments/{id}/refund`](/api-reference/payments/refund)).
* **Sandbox da Apple**: para testar sem cartão real, a Apple oferece o [ambiente de sandbox](https://developer.apple.com/apple-pay/sandbox-testing/) com cartões de teste provisionáveis em contas sandbox — útil para validar a integração do app/site, mas a autorização financeira de ponta a ponta só acontece com cartão real.
* **Web**: se o botão não aparece, verifique na ordem: dispositivo/navegador compatível, `canMakePayments()`, domínio `verified` no [`GET /v1/payment-method-domains`](/api-reference/payment-method-domains/list) e o arquivo de associação no ar.

## Boas Práticas

* **Chame a API pelo seu backend.** O `paymentData` deve ser encaminhado do app/site para o seu servidor e de lá para a UvviPay — `client-id`/`client-secret` nunca devem ser embarcados no app nem expostos no front-end.
* **Envie logo após a autorização.** O token do Apple Pay tem janela de validade curta; não o armazene para uso posterior.
* **Trate o resultado na tela de pagamento (payment sheet).** Retorne sucesso ou falha (`PKPaymentAuthorizationResult` / `session.completePayment`) conforme a resposta da API, para o usuário ver o estado correto na animação do Apple Pay.
* **Verifique a disponibilidade.** No iOS, use [`canMakePayments(usingNetworks:)`](https://developer.apple.com/documentation/passkit/pkpaymentauthorizationcontroller/canmakepayments\(usingnetworks:\)); na web, `ApplePaySession.canMakePayments()` — e só então exiba o botão.
* **Use o botão oficial.** No iOS, [`PKPaymentButton`](https://developer.apple.com/documentation/passkit/pkpaymentbutton); na web, os estilos das [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/apple-pay).

## Erros Comuns

| Erro                                       | Causa provável                                                                                                  | Solução                                                                                                                            |
| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `422` token rejeitado                      | Certificado criado a partir de um CSR que não é o da UvviPay                                                    | Revogue o certificado no Merchant ID e crie outro com o nosso CSR                                                                  |
| `422` estrutura inválida                   | `paymentData` não é o base64 do JSON do `PKPaymentToken.paymentData`                                            | Envie o `paymentData` sem transformações além do base64                                                                            |
| `400` domínio não registrado (web)         | Domínio da página não registrado, ou registrado com hostname diferente (`www` vs apex)                          | Registre pelo [`POST /v1/payment-method-domains`](/api-reference/payment-method-domains/create)                                    |
| `400` domínio aguardando verificação (web) | Registro feito, mas a verificação junto à Apple ainda não concluiu                                              | Confirme o arquivo de associação no ar e chame o [`POST /{id}/validate`](/api-reference/payment-method-domains/validate) novamente |
| Pagamento recusado com Elo                 | Bandeira ainda não suportada no Apple Pay                                                                       | Restrinja `supportedNetworks` a Visa e Mastercard                                                                                  |
| Tela do Apple Pay não abre (iOS)           | Capability ausente ou Merchant ID não vinculado ao app                                                          | Revise a etapa 3 da configuração iOS                                                                                               |
| Tela do Apple Pay não abre (web)           | `session.begin()` chamado fora do gesto do usuário, ou após código assíncrono                                   | Crie a sessão diretamente no handler do clique                                                                                     |
| Botão some após funcionar (web)            | Arquivo `/.well-known/apple-developer-merchantid-domain-association` saiu do ar e a Apple revogou a verificação | Restaure o arquivo e solicite nova verificação                                                                                     |

## Veja também

* [Criar pagamento](/api-reference/payments/create) — referência completa do `POST /v1/payments`
* [Registrar domínio](/api-reference/payment-method-domains/create) e [Listar domínios](/api-reference/payment-method-domains/list)
* [Emitir CSR](/api-reference/certificates/issue), [Ativar](/api-reference/certificates/activate) e [Listar certificados](/api-reference/certificates/list)
* [Validar sessão Apple Pay (web)](/api-reference/payments/apple-pay-validate-merchant)
* [Recusas de cartão](/recusas-de-cartao) — como interpretar os motivos de recusa
* [Webhooks](/webhooks) — notificações de status do pagamento
* [Human Interface Guidelines — Apple Pay](https://developer.apple.com/design/human-interface-guidelines/apple-pay) — diretrizes oficiais do botão e da experiência
