Pagamento com Google Pay
O Google Pay é a carteira digital do Google. Com ele, o comprador paga com um cartão já salvo em sua conta Google — em Android ou em qualquer navegador suportado — sem informar número, validade ou CVV: seleciona o cartão na folha de pagamento do Google e confirma. O cartão trafega cifrado do Google diretamente para a adquirente; nem a loja nem a Appmax têm acesso ao número, o que elimina do checkout o formulário de cartão e a exposição a dados sensíveis.
Na App Store da Appmax, o Google Pay é um meio de pagamento disponível a qualquer aplicativo instalado por um lojista. Ele utiliza as mesmas credenciais do merchant, o mesmo fluxo de cliente e pedido e o mesmo estorno já empregados para cartão de crédito, Pix e Boleto. A única diferença está na origem dos dados do cartão, que passam a vir do Google em vez de um formulário da loja.
Esta página cobre o endpoint: o que a loja precisa ter antes de começar, como autorizar a instalação, como montar o payload a partir do que o Google devolve e o que fazer com cada resposta.
Implementando o botão Google Pay com o Appmax JS
cobre o navegador: onde ancorar o botão, como inicializar o script e
como os callbacks onUpdate e onAuthorize se comportam.
Para quem já integrou o Apple Pay,
o caminho é o mesmo e mais curto: o init() do Appmax JS é o mesmo, e
não há domínio a cadastrar nem arquivo .well-known a publicar.
Compatibilidade
O botão do Google Pay é exibido em Chrome, Firefox, Safari, Edge, Opera e UC Browser, em páginas servidas por HTTPS, tanto em desktop quanto em dispositivos móveis. O comprador precisa estar autenticado em uma conta Google com ao menos um cartão Visa, Mastercard ou Elo salvo.
| Contexto | O que o comprador vê |
|---|---|
| Android, Windows ou Linux em navegador suportado | botão do Google Pay |
| iOS ou macOS com Apple Pay disponível | botão do Apple Pay — a seleção é feita automaticamente pelo script |
| Navegador sem suporte à Google Pay API | nenhum botão; o bloco permanece oculto |
Em sandbox, o Google exibe sua própria lista de cartões de teste assim que a folha abre, em qualquer navegador suportado. Isso permite validar botão, folha e callbacks sem um dispositivo físico — veja "Testes e Sandbox".
Como funciona
A integração é realizada por meio do Appmax JS, o mesmo script empregado na tokenização de cartão e no Apple Pay. A loja ancora um botão e implementa dois callbacks; o script executa as demais etapas.
A folha do Google abre dentro de um iframe da Appmax, e não na página da loja. O Google valida a origem de onde a folha é aberta contra o domínio aprovado em seu console; ao abrir no iframe da Appmax, um único domínio aprovado atende a todos os integradores. Por isso não é necessário criar perfil no Google Pay & Wallet Console, cadastrar domínio nem configurar credenciais do Google ou da adquirente.
Diferença em relação ao Apple Pay
Não há equivalente ao arquivo .well-known nem ao parâmetro
domain_name da instalação. Se o aplicativo já está instalado para
cartão, Pix ou Apple Pay, nenhuma nova autorização é necessária.
| O que fica com você | O que fica com a Appmax |
|---|---|
Ancorar o botão e chamar o init() com externalId, onUpdate e onAuthorize |
Montar a folha do Google e abrir o iframe — domínio aprovado e configuração da folha |
Devolver o total do carrinho no onUpdate |
Exibir o botão oficial do Google e tratar o clique |
Enviar o paymentMethodData do onAuthorize ao seu backend e chamar POST /v1/payments/google-pay |
Validar o token, identificar o tipo de cartão e autorizar na adquirente |
Glossário
| Termo | Descrição |
|---|---|
| Google Pay | Carteira digital do Google. O comprador paga com um cartão salvo em sua conta Google, sem digitá-lo. |
| Folha (payment sheet) | Interface do Google na qual o comprador seleciona o cartão salvo e confirma o pagamento. Aberta em um iframe da Appmax. |
paymentMethodData |
Objeto devolvido pelo Google após a confirmação e recebido no onAuthorize. É enviado à Appmax integralmente, em payment_data.google_pay.payment_data. Gerado por transação. |
| Token | String em tokenizationData.token, dentro do paymentMethodData, com o cartão cifrado para a adquirente. Repassado sem alteração. |
onUpdate |
Callback implementado pela loja: retorna o total do carrinho antes da abertura da folha. |
onAuthorize |
Callback implementado pela loja: recebe o paymentMethodData após a confirmação do comprador. |
external_id |
UUID que identifica o par (app instalado + loja). Gerado na instalação e usado pelo init() do Appmax JS. Veja Instalação do aplicativo. |
pay_reference |
Identificador da cobrança, retornado no 201. Utilizado na conciliação e no estorno. |
Pré-requisitos
Do lado do comprador, para o botão aparecer:
- Conta Google com ao menos um cartão Visa, Mastercard ou Elo salvo.
- Navegador suportado — Chrome, Firefox, Safari, Edge, Opera ou UC Browser.
- Página servida por HTTPS.
Do lado da integração:
- Instalação do app autorizada, com o
external_iddisponível (passo 1). - Appmax JS incluído e inicializado com
onUpdateeonAuthorize(passo 2). - Token Bearer do merchant, obtido em
POST /oauth2/tokencom as credenciais do merchant — não as do aplicativo. Veja Autenticação.
Componentes do fluxo:
- Script JS:
https://scripts.appmax.com.br/appmax.min.js(produção) — em sandbox usehttps://scripts.sandboxappmax.com.br/appmax.min.js. Veja Ambientes. - Requisição de pagamento para a API Appmax com o
paymentMethodData,order_idecustomer_idválidos.
1. Autorizar a instalação do aplicativo
O fluxo é o mesmo de qualquer outro meio de pagamento da API: o lojista
autoriza a instalação (POST /app/authorize → redirecionamento →
POST /app/client/generate), a Appmax aciona a URL de validação do
aplicativo e, ao final, são entregues as
credenciais do merchant e o external_id
daquela instalação. Veja Instalação do aplicativo
para o fluxo completo, com diagrama de sequência de todas as chamadas.
curl --location 'https://api.appmax.com.br/app/authorize' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer SEU_TOKEN' \
--data '{
"app_id": "APP_ID",
"external_key": "EXTERNAL_KEY",
"url_callback": "URL_CALLBACK"
}'
INFO
Diferente do Apple Pay, o Google Pay não utiliza o parâmetro
domain_name. O passo a passo completo da instalação está em
Instalação do aplicativo e
Valide sua URL de validação. O external_id é
detalhado em external-id.
2. Incluir e inicializar o Appmax JS
TIP
Para o passo a passo completo — seletores
do botão, ordem de carregamento em SPA, contrato do onUpdate, o
comportamento do onAuthorize e troubleshooting — veja
Implementando o botão Google Pay com o Appmax JS.
WARNING
O externalId esperado aqui é o mesmo external_id que você retornou
com HTTP 200 na etapa de
Instalação do aplicativo.
O appmax.min.js faz três coisas:
- Monta a folha do Google e a abre em um iframe da Appmax — você não configura domínio nem credenciais do Google.
- Renderiza o botão oficial do Google na âncora
[data-appmax-google-pay]e trata o clique. - Dispara os callbacks de atualização (
onUpdate), autorização (onAuthorize) e erro (onError).
2.1 Inicializar com externalId, onIp, onError, onUpdate e onAuthorize
<!-- Gatilho da coleta de IP: obrigatório, e precisa existir antes do init -->
<form data-appmax-customer hidden></form>
<div data-appmax-checkout data-appmax-merchant-name="Nome da loja">
<div data-appmax-google-pay-wrapper>
<button data-appmax-google-pay style="height: 48px; width: 100%"></button>
</div>
</div>
<script>
// Produção: https://scripts.appmax.com.br/appmax.min.js
// Sandbox: https://scripts.sandboxappmax.com.br/appmax.min.js
const onUpdate = () => ({ total: 150.90 }); // em reais, como número
const onAuthorize = async (paymentMethodData) => {
await processGooglePayPayment(paymentMethodData); // veja o passo 3
};
const checkoutData = {
customer: {}
};
const onIp = ({ ip }) => {
checkoutData.customer.ip = ip;
};
const onError = ({ code, message, stage }) => console.error('Erro no Google Pay:', code, stage, message);
window.AppmaxScripts.init({ externalId, onIp, onError, onUpdate, onAuthorize });
</script>
Valores do `onUpdate` são informados em reais
O onUpdate é um contrato do Appmax JS, e não da API. Por isso, o campo total deve ser informado em reais, enquanto os valores enviados para a API são informados em centavos.
Por exemplo, para uma cobrança de R$ 150,90:
- No
onUpdate:total: 150.90 - Em
POST /v1/orders:15090, pois a API utiliza valores monetários inteiros em centavos.
Essa diferença é importante porque utilizar o formato da API no onUpdate não gera um erro, mas altera o valor exibido ao comprador. Por exemplo, total: 15090 será interpretado como R$ 15.090,00.
Além disso, o corpo da requisição POST /v1/payments/google-pay não possui um campo para informar o valor da cobrança: o pagamento utiliza o valor total do pedido. Dessa forma, um total incorreto no onUpdate pode fazer com que o comprador veja um valor na folha de pagamento diferente do valor efetivamente cobrado.
Para mais detalhes, consulte O que o onUpdate deve retornar e Valores monetários.
INFO
No Google Pay, a folha já está fechada quando o onAuthorize é
invocado e o valor retornado não é utilizado — a aprovação ou recusa é
tratada na sua tela, a partir da resposta do passo 3. Isso difere do
Apple Pay; veja
Como o onAuthorize se comporta.
3. Processar o pagamento
O onAuthorize recebe o paymentMethodData, que deve ser enviado ao
backend da loja. O backend executa a sequência padrão da API: cliente,
pedido e pagamento.
POST /v1/customers— cria ou atualiza o cliente; armazenedata.customer.id.POST /v1/orders— cria o pedido; armazenedata.order.id.POST /v1/payments/google-pay— efetua o pagamento, com ocustomer_ide oorder_iddos passos anteriores.
O objeto recebido no onAuthorize tem esta forma:
{
"type": "CARD",
"description": "Visa •••• 1234",
"info": {
"cardNetwork": "VISA",
"cardDetails": "1234",
"assuranceDetails": {
"accountVerified": true,
"cardHolderAuthenticated": true
}
},
"tokenizationData": {
"type": "PAYMENT_GATEWAY",
"token": "{\"signature\":\"MEUCIQ...\",\"protocolVersion\":\"ECv2\",\"signedMessage\":\"{...}\"}"
}
}
É esse objeto, integral e sem modificação, que vai em
payment_data.google_pay.payment_data.
O `gatewayMerchantId` é configurado internamente pela Appmax
Não envie, substitua ou tente definir esse identificador no payload.
Encaminhe o paymentMethodData recebido no onAuthorize integralmente
e sem alterações, em payment_data. O payload público é o do exemplo
abaixo — nenhum campo além desses é necessário.
async function processGooglePayPayment(paymentMethodData) {
// 1. Criar customer — POST /v1/customers (veja /api-reference/customers/criar-atualizar)
// 2. Criar order — POST /v1/orders (veja /api-reference/orders/criar-pedido)
// 3. Efetivar pagamento — POST /v1/payments/google-pay
const paymentPayload = {
order_id, // Order já existente na Appmax
customer_id,
payment_data: {
google_pay: {
installments: 2, // 1 a 12
holder_document_number: "51425014038", // obrigatório
soft_descriptor: "MINHALOJA", // opcional, máx. 13 caracteres
payment_data: paymentMethodData // o objeto do onAuthorize, inteiro
}
}
};
const resp = await fetch('https://api.appmax.com.br/v1/payments/google-pay', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer SEU_TOKEN` },
body: JSON.stringify(paymentPayload)
});
if (!resp.ok) throw new Error('Falha no pagamento');
const { data } = await resp.json();
// Guarde data.payment.pay_reference no seu banco. Ao front-end,
// devolva só o status — nunca o pay_reference, o documento ou o token.
return { status: 'aprovado' };
}
Atenção
- Não aplique
JSON.parseaotoken. Otokené uma string e deve ser enviado exatamente como recebido. O parse é realizado pela Appmax. - Não remova campos do objeto. Envie o objeto completo, incluindo
info. Esses dados são utilizados pela Appmax para validar a transação e compor o comprovante, incluindo a bandeira e os últimos dígitos do cartão. O número completo do cartão não trafega.
Integração via backend
A requisição deve ser realizada exclusivamente pelo backend. Credenciais e dados sensíveis, como o token Bearer, nunca devem ser expostos ao navegador.
O front-end deve receber apenas o resultado necessário para a interface: status da operação (aprovado ou recusado) e, opcionalmente, uma mensagem. Dados como credenciais, pay_reference, holder_document_number e respostas completas da API devem permanecer no backend.
INFO
-
Campos obrigatórios:
order_id,customer_id,installments(1–12),holder_document_numberepayment_data. -
soft_descriptoré opcional (máx. 13 caracteres).
A resposta 201 traz o pagamento em data.payment:
{
"data": {
"payment": {
"pay_reference": "test_localhost_1_2b5c0",
"upsell_hash": "92447142021040-1704397469-0391056001704397469",
"cashback": null
}
}
}
pay_referenceidentifica a cobrança e deve ser armazenado para conciliação e estorno.upsell_hashé utilizado no upsell.- O status do pedido é informado por webhooks e pela consulta do pedido, como em qualquer pagamento com cartão.
Erros retornam { "errors": { "message": "..." } }, exceto o 403,
que usa o envelope antigo. Os códigos e mensagens estão em
Respostas, abaixo. Recusas da adquirente chegam como
Pagamento não autorizado: <motivo>, com o status correspondente ao
motivo — exiba o motivo ao comprador e permita nova tentativa.
Testes e Sandbox
Em sandbox não é necessário cartão real
Assim que a folha abre, o Google exibe sua própria lista de cartões de teste, em qualquer navegador suportado — inclusive desktop. Não é preciso provisionar cartão no Google Wallet para começar.
Em sandbox, o Google retorna dados de cartão simulados e nenhuma cobrança é efetuada. É possível exercitar o fluxo completo — botão, folha, token e chamada de pagamento — sem envolver o cartão do comprador.
WARNING
O ambiente é definido pela Appmax, conforme a URL do script incluído.
Utilize script, API e credenciais de sandbox em conjunto
(Ambientes); a combinação de ambientes distintos
resulta em 401.
O que dá para validar em sandbox:
- O botão e a folha do Google, com os cartões de teste.
- Os callbacks
onUpdate,onAuthorizeeonError. - O contrato da chamada de pagamento e o tratamento dos erros.
- A criação de customer e order.
Antes da publicação em produção, homologue com um pagamento real em um dispositivo com cartão salvo no Google Wallet.
Ambientes
| Sandbox | Produção | |
|---|---|---|
| Script JS | https://scripts.sandboxappmax.com.br/appmax.min.js |
https://scripts.appmax.com.br/appmax.min.js |
| API | https://api.sandboxappmax.com.br |
https://api.appmax.com.br |
| Autenticação | https://auth.sandboxappmax.com.br |
https://auth.appmax.com.br |
| Cartão na folha | lista de teste do Google | cartão do comprador |
| Cobrança | não há | real |
Script e external_id devem pertencer ao mesmo ambiente — veja
Ambientes.
Perguntas frequentes (FAQ)
A folha não abre e nada aparece no console.
Se o checkout da loja é executado dentro de um iframe, esse iframe
precisa de allow="payment". Sem isso o navegador bloqueia a folha
silenciosamente.
O comprador fechou a folha. É necessário exibir erro?
Não. O Google retorna CANCELED, que corresponde a desistência — basta
permitir um novo clique. O mesmo código é retornado quando o Google
recusa o estabelecimento ou a conta e exibe o erro dentro da folha; do
ponto de vista da página da loja, os dois casos são indistinguíveis.
Foi retornado 400 com Invalid Google Pay token. O problema está no cartão?
Não. Na quase totalidade dos casos o paymentMethodData foi alterado
antes do envio — um JSON.parse no token ou campos removidos.
Repasse o objeto exatamente como recebido no onAuthorize. Se o erro
persistir, acione o suporte da Appmax.
É necessário hospedar algum arquivo ou cadastrar domínio?
Não. Não há equivalente ao
.well-known do Apple Pay,
e não é necessário perfil no Google Pay & Wallet Console. A folha abre
em um iframe da Appmax, cujo domínio já está aprovado.
É possível parcelar?
Sim. Informe installments de 1 a 12 no corpo do pagamento. Juros e
valores por parcela seguem o retornado por
Parcelas para a loja. O
installments do onUpdate não é utilizado pelo Google Pay.
Como é feito o estorno?
Pelo mesmo endpoint dos demais meios:
Criar estorno, com o
pay_reference retornado no 201. A transação é de cartão de crédito
para todos os efeitos.
O comprovante mostra os quatro últimos dígitos de qual cartão?
Dos que o Google devolve em info.cardDetails. Como o número do cartão
não trafega nesta integração, é a única fonte — por isso o campo não
deve ser removido do objeto.
Posso oferecer Apple Pay e Google Pay na mesma página?
Sim. Ancore os seletores das duas carteiras e use o mesmo init(). O
script exibe o Apple Pay onde ele está disponível e o Google Pay nos
demais navegadores suportados; o onAuthorize recebe o token da
carteira utilizada — veja
Implementando o botão Apple Pay com o Appmax JS.
Conclusão — checklist
- Autorizar a instalação do aplicativo e armazenar o
external_id— Instalação do aplicativo. - Incluir o Appmax JS do ambiente correto (Ambientes) e ancorar o botão com
data-appmax-google-pay, dentro de umdata-appmax-checkoutcomdata-appmax-merchant-name— veja Implementando o botão Google Pay. - Invocar
window.AppmaxScripts.init()comexternalId,onIp,onError,onUpdateeonAuthorize. - Retornar o carrinho no
onUpdateem reais, com valores numéricos — não em centavos, diferente dos endpoints da API. - No
onAuthorize, enviar opaymentMethodDataao backend, integral e sem parse dotoken. - Criar cliente → criar pedido → processar em
POST /v1/payments/google-pay, sempre pelo backend, com o token do merchant (Autenticação). - Tratar a folha fechada como desistência, sem mensagem de erro.
- Se o checkout é executado em iframe, garantir
allow="payment"nele. - Validar em sandbox e homologar com um pagamento real antes da publicação em produção.
Autorizações
Token Bearer do merchant obtido via POST /oauth2/token usando as
credenciais do merchant (não do app). Veja
Autenticação.
Corpo da Requisição
Respostas
Pagamento Google Pay aprovado. data.payment.pay_reference identifica a cobrança.