Referência do SDK
Toda a API do assiny.js no navegador, com as funções, as opções, os eventos, os retornos, os prazos, os erros e os avisos do console.
O assiny.js é o SDK do navegador do Assiny Gateway. Esta página lista tudo o que ele expõe; o que não está aqui não existe.
Carregar
<script src="https://sdk-gateway-js.assiny.com.br/v1/assiny.js"></script>Só pela tag. O script define a função global Assiny.
Nada lança
Nenhuma função lança exceção e nenhuma promessa rejeita. Argumento inválido vira o evento loaderror (assíncrono, depois do mount) ou { error } na promessa. Uma exceção dentro de uma função sua passada a on() vai ao console.error e não para o SDK. Se a criação da instância falhar de forma inesperada, Assiny() devolve uma instância que não monta nada e responde { error } com unknown a toda promessa.
Assiny(publishableKey, options)
const assiny = Assiny('pk_test_...', { locale: 'pt-BR' });| Parâmetro | Valores |
|---|---|
publishableKey | a chave publicável, na forma pk_(test|live)_ seguida de letras e dígitos; o prefixo diz se é o Modo de teste ou o Modo real |
options.locale | 'pt-BR' (padrão) ou 'en': os textos do fragment e da tela do QR e as message de erro; outro valor vale 'pt-BR', com aviso no console |
Devolve a instância { fragments, createPaymentMethod, handleNextAction }. Com a chave aceita, Assiny() acrescenta ao body dois iframes invisíveis do SDK, que ficam na página; o recomendado é uma instância por página.
Chave recusada: nenhum iframe nasce, o mount emite loaderror com o código e toda promessa resolve { error } com ele.
code | Quando |
|---|---|
invalid_publishable_key | a chave não tem a forma acima; uma chave que começa com sk_ também ganha um aviso no console |
insecure_page | a chave do Modo real numa página que não é https:, fora de localhost e 127.0.0.1 |
page_origin_invalid | a página não tem origem real (location.origin é "null"), como num iframe com sandbox sem allow-same-origin |
assiny.fragments(options)
O objeto que assiny.fragments() devolve é o Fragments; o que fragments.create('payment') devolve é o Payment Fragment. As mensagens de erro usam esses dois nomes.
const fragments = assiny.fragments({
mode: 'payment',
amount: 12990,
currency: 'brl',
clientSecret, // opcional
appearance, // opcional
fonts, // opcional
});| Opção | Valores | Código, se inválida |
|---|---|---|
mode | 'payment', obrigatório | mode_invalid |
amount | o total em centavos: inteiro seguro (Number.isSafeInteger) maior que zero | amount_invalid |
currency | o código ISO 4217 em minúsculas de uma moeda que o navegador conhece (Intl), como 'brl' | currency_invalid |
clientSecret | opcional: o client_secret do pagamento, na forma pi_..._secret_..., guardado para o handleNextAction | invalid_client_secret |
appearance | opcional: Aparência | item inválido é ignorado com aviso |
fonts | opcional: [{ family, weights }] do catálogo (Aparência) | item inválido é ignorado com aviso |
Devolve { update, create }. Opção inválida não lança: o código chega pelo loaderror do mount. amount, currency e clientSecret se corrigem com fragments.update(): o fragment guarda o seletor do mount e monta quando o valor fica válido. mode não muda depois.
- Um por instância: o segundo
assiny.fragments()devolve um objeto cujocreate()dáloaderrorfragment_already_existsnomounte cujoupdate()resolve{ error }com o mesmo código. - O PIX exige
currency: 'brl': com'pix'empaymentMethodTypese outra moeda, omountemitepayment_method_types_invalid. appearanceefontsentram só aqui; não há como trocá-los depois na mesma instância.
fragments.update(options)
const { error } = await fragments.update({ amount: 15990 });| Opção | Efeito | Código, se inválida |
|---|---|---|
amount | o novo total; o fragment redesenha e refaz o Combinar (com partsFrom: 'page', as Partes voltam a valer só com um novo update({ parts })) | amount_invalid |
currency | a nova moeda | currency_invalid; payment_method_types_invalid com PIX e moeda que não é 'brl' |
clientSecret | guarda o client_secret para o handleNextAction | invalid_client_secret |
parts | a divisão do Combinar, só com partsFrom: 'page' e o fragment montado: [{ method, amount }, { method, amount }], com amount de pelo menos 2 centavos, valores inteiros maiores que zero que somam o amount, métodos habilitados e a combinação card + card ou card + pix, nessa ordem, entre as que o combine deixa | parts_invalid |
Resolve {} ou { error }. Com amount e parts juntos, a soma é conferida contra o amount novo; dois update seguidos valem em ordem. Outros códigos:
code | Quando |
|---|---|
parameter_invalid | o argumento não é um objeto |
request_in_progress | há um createPaymentMethod ou um handleNextAction em curso |
fragments_not_ready | o SDK não carregou |
fragment_already_exists | o update() de um segundo objeto fragments |
mode_invalid | o assiny.fragments() nasceu com mode inválido |
request_timeout | sem resposta em 2 s |
Chave desconhecida é ignorada, com aviso no console.
fragments.create('payment', options)
const payment = fragments.create('payment', {
paymentMethodTypes: ['card', 'pix'],
combine: 'auto',
partsFrom: 'component',
fields: { billingDetails: { name: 'auto', address: { country: 'auto' } } },
wallets: { applePay: 'auto' },
});| Opção | Valores | O que faz |
|---|---|---|
paymentMethodTypes | lista não vazia de 'card' e 'pix', obrigatória | as abas, nessa ordem; a primeira começa selecionada; item repetido é removido com aviso no console |
combine | 'auto' (padrão), 'never' ou lista de 'card_card' e 'card_pix' | com 'auto', a aba Combinar métodos aparece com amount de pelo menos 2 centavos: "Cartão + Cartão" (card_card) com 'card', "Cartão + PIX" (card_pix) com 'card' e 'pix'; a lista oferece só as combinações listadas, na ordem de 'auto': ['card_card', 'card_pix'] com 'card' e 'pix' vale 'auto' (com só 'card', passe ['card_card']; a lista cheia é options_invalid) e [] vale 'never' |
partsFrom | 'component' (padrão) ou 'page' | com 'page', o fragment esconde o campo de valor do Combinar e mostra a divisão de fragments.update({ parts }); 'page' com combine: 'never' ou [] é options_invalid; Partes numa combinação fora da lista são parts_invalid |
fields.billingDetails.name | 'auto' (padrão) ou 'never' | 'never' esconde o campo Nome no cartão |
fields.billingDetails.address.country | 'auto' (padrão) ou 'never' | 'never' esconde o campo País |
wallets.applePay | 'auto' (padrão) ou 'never' | reservado: aceito e sem efeito nesta versão |
Devolve { mount, unmount, on, off }. O primeiro argumento só aceita 'payment'. Os erros da criação chegam pelo loaderror do mount:
code | Quando |
|---|---|
fragment_type_invalid | o tipo não é 'payment' |
fragment_already_exists | já existe um fragment nesta instância, ou o create() é de um segundo objeto fragments |
payment_method_types_invalid | paymentMethodTypes ausente, vazia ou com valor fora de 'card' e 'pix' |
options_invalid | as opções não são um objeto, uma chave é desconhecida, um valor está fora da lista, um item de combine é repetido, desconhecido ou não permitido por paymentMethodTypes (['card_pix'] sem 'pix'), ou partsFrom: 'page' com combine: 'never' ou [] |
Um create() com opções inválidas não ocupa o lugar do fragment da instância: um create() válido depois ainda funciona.
payment.mount(selector)
payment.mount('#pagamento');selector é um seletor CSS que casa com exatamente um elemento. O fragment ocupa 100% da largura dele e a altura acompanha o conteúdo. O ready sai uma vez por mount. Elemento removido do DOM conta como desmontado. Os erros chegam pelo loaderror:
code | Quando |
|---|---|
invalid_publishable_key, insecure_page, page_origin_invalid | a chave da instância foi recusada |
o código do create() | fragment_type_invalid, fragment_already_exists, payment_method_types_invalid ou options_invalid |
mode_invalid | o mode do assiny.fragments() não é 'payment' |
mount_target_not_found | o seletor não casa com exatamente um elemento |
already_mounted | o fragment já está montado |
amount_invalid, currency_invalid, invalid_client_secret, payment_method_types_invalid | o assiny.fragments() tem um desses valores inválido, ou o PIX está com moeda que não é 'brl'; o fragment monta quando um fragments.update() corrige |
fragments_not_ready | o SDK ou o fragment não carregou em 10 s |
request_timeout | o SDK não respondeu à configuração (5 s) ou à montagem (10 s) |
unknown | uma falha inesperada |
payment.unmount()
Remove o iframe do fragment e apaga o que foi digitado. Um createPaymentMethod em curso resolve { error } com fragments_not_ready. Depois, mount() monta de novo. Um handleNextAction em curso não para.
payment.on(event, handler) e payment.off(event, handler)
Ligam e desligam uma função num evento e devolvem o próprio payment. Nome fora da lista, ou handler que não é função, é ignorado.
| Evento | Quando | Payload |
|---|---|---|
ready | uma vez por mount, com o fragment configurado; não espera as fontes | { fragmentType: 'payment' } |
change | logo depois do ready e a cada troca de aba, mudança de campo ou mudança do total | { fragmentType: 'payment', value: { type, save, parts }, complete, empty, error } |
focus | o foco entra no fragment | { fragmentType: 'payment' } |
blur | o foco sai do fragment | { fragmentType: 'payment' } |
loaderror | o fragment não montou | { fragmentType: 'payment', error: { type, code, message } } |
O payload do change:
| Campo | Tipo | O que é |
|---|---|---|
value.type | 'card', 'pix' ou 'combine' | a aba selecionada |
value.save | boolean, só com 'card' | nesta versão, sempre false |
value.parts | [{ method, amount }, { method, amount }], só com 'combine' | as Partes, quando o valor da primeira é maior que zero e menor que o total, mesmo com o cartão incompleto |
complete | boolean | cartão: número, validade e CVC completos e válidos; PIX: sempre true; Combinar: o valor válido e os cartões da combinação completos |
empty | boolean | nada digitado; no PIX, sempre true |
error | { code, message }, quando há | o erro que está na tela |
Nenhum evento traz o que foi digitado no cartão.
assiny.createPaymentMethod({ fragments, params })
const { parts, error } = await assiny.createPaymentMethod({
fragments,
params: { billing_details: { name, email, phone, tax_id, tax_id_type, address } },
});fragments: o objeto devolvido peloassiny.fragments()desta instância.params.billing_details: os dados do pagador. Cada campo que você manda vale como veio, para todas as Partes; campo que você não manda entra do fragment se o campo correspondente está ligado ('auto') e preenchido: Nome no cartão emname, País emaddress.country, por cartão. Nada é sobrescrito;'',nulleundefinedcontam como não mandado. No PIX, só o que você mandou. Chaves aceitas:name,email,phone,tax_id,tax_id_typeeaddresscomline1,line2,city,state,postal_codeecountry; outra chave é descartada, com aviso no console. Na política padrão, o pagador precisa deemailno cartão e no PIX e denameno cartão; sem eles, a criação do método de pagamento ou o confirm recusa compayer_field_missing.
Resolve { parts: [{ method, amount, payment_method }] }, com method 'card' ou 'pix' e payment_method o pm_ criado, na ordem das Partes da aba selecionada (cartão ou PIX: uma Parte com o amount inteiro; Combinar: duas, que somam o amount), ou { error: { type, code, message, part } }, com part só quando a falha é de uma Parte.
O que acontece:
- O fragment confere os campos da aba selecionada; campo incompleto ou inválido resolve um
validation_errorsem ir à API e mostra o erro no campo. - Enquanto os métodos são criados, os campos ficam desligados (
.Input:disabled). - Um
pm_por Parte, em ordem; a primeira falha interrompe as seguintes e o erro diz emparto índice da Parte que falhou. - Depois de um
{ error }, o que foi digitado fica e o campo que a API apontou fica marcado; na nova tentativa, a Parte que não mudou reusa opm_já criado. Depois de um sucesso, a próxima chamada criapm_novos.
code | Quando |
|---|---|
fragments_not_ready | o fragments não é o desta instância, o fragment não está montado e pronto, ou houve unmount() durante a chamada |
parameter_invalid | params não é um objeto ou não pode ser copiado; ou a API recusou um parâmetro |
request_in_progress | há outro createPaymentMethod ou um handleNextAction em curso |
os de validation_error | um campo do fragment, ou a divisão do Combinar (incomplete_parts, parts_invalid) |
os de card_error e os outros da API | a resposta da API, pela tabela abaixo |
request_timeout | 8 s sem resposta da API num pm_, ou 20 s na chamada inteira |
assiny.handleNextAction({ clientSecret })
const { paymentIntent, error } = await assiny.handleNextAction({
clientSecret: 'pi_..._secret_...',
});clientSecret: oclient_secretdo pagamento, na formapi_..._secret_.... O da chamada vence o guardado porassiny.fragments({ clientSecret })oufragments.update({ clientSecret }).- Funciona só com a instância de
Assiny(): não precisa do fragment montado.
O SDK lê o pagamento a cada 3 s e segue o próximo passo, uma ação por vez, até o fim:
| Status lido | O que o SDK faz |
|---|---|
succeeded, canceled, requires_payment_method, requires_confirmation | encerra e resolve { paymentIntent }; em succeeded com a tela do QR aberta, mostra o pagamento confirmado e fecha 4 s depois |
processing | lê de novo, sem desenhar |
requires_action com o QR do PIX | abre ou mantém a tela do QR do PIX (PIX e a tela do QR) |
requires_action com outra ação, ou sem ação | fecha a tela e resolve { error } com next_action_unsupported |
| qualquer outro | resolve { error } com unknown |
Esc ou Fechar na tela do QR param a leitura e resolvem { paymentIntent } com o estado da última leitura, em geral requires_action; uma nova chamada reabre a ação atual. Até a primeira leitura há 20 s; depois, a promessa vive enquanto a leitura vive.
Resolve:
{
"paymentIntent": {
"id": "pi_...",
"object": "payment_intent",
"livemode": false,
"status": "succeeded",
"amount": 12990,
"currency": "brl",
"parts": [
{ "id": "pip_...", "position": 1, "method": "pix", "amount": 12990, "status": "succeeded" }
],
"last_payment_error": null
}
}parts traz id, position, method, amount e status de cada Parte; last_payment_error é { type, code, message } ou null. Sem next_action e sem os outros campos do pagamento.
code | Quando |
|---|---|
invalid_client_secret | o clientSecret não tem a forma pi_..._secret_... |
client_secret_missing | sem clientSecret na chamada e nenhum guardado |
request_in_progress | há outro handleNextAction ou um createPaymentMethod em curso |
fragments_not_ready | o SDK não carregou |
payment_intent_not_found | a primeira leitura respondeu 404 |
o código da tabela abaixo, como api_key_invalid, permission_denied ou unknown | a primeira leitura foi recusada |
api_unavailable | a primeira leitura falhou na rede, respondeu 500 ou mais, ou veio ilegível |
request_timeout | 8 s sem resposta na primeira leitura, ou 20 s sem a primeira leitura |
next_action_unsupported | o pagamento pede uma ação que o SDK não conhece |
overlay_not_ready | a tela do QR não abriu em 10 s |
Depois da primeira leitura, uma leitura que falha não encerra: o SDK tenta na volta seguinte e, depois de três falhas seguidas, a tela do QR mostra "Sem conexão. Tentando de novo.".
Prazos
| O quê | Prazo | Ao vencer |
|---|---|---|
a configuração enviada pelo assiny.fragments() | 5 s | loaderror com request_timeout |
mount() | 10 s | loaderror com request_timeout |
unmount() | 2 s | nada visível: o iframe já saiu |
fragments.update() | 2 s | { error } com request_timeout |
createPaymentMethod(), a chamada inteira | 20 s | { error } com request_timeout |
handleNextAction(), até a primeira leitura | 20 s | { error } com request_timeout |
cada chamada à API (a criação de um pm_, uma leitura do pagamento) | 8 s | request_timeout; depois da primeira leitura, nova tentativa |
| o intervalo da leitura do pagamento | 3 s | — |
| a carga do SDK, do fragment e da tela do QR | 10 s | fragments_not_ready (SDK e fragment) ou overlay_not_ready (tela do QR) |
a tela do QR depois do succeeded | 4 s | fecha e resolve { paymentIntent } |
Erros
{ type, code, message }, e part quando a falha é de uma Parte no createPaymentMethod. A message vem do catálogo do SDK, no locale da instância, nunca do servidor. A lista é fechada: um código fora dela chega como api_error unknown.
type | code | message (pt-BR) |
|---|---|---|
validation_error | incomplete_number | O número do cartão está incompleto. |
validation_error | invalid_number | O número do cartão é inválido. |
validation_error | incomplete_expiry | A validade do cartão está incompleta. |
validation_error | invalid_expiry_month | O mês de validade do cartão é inválido. |
validation_error | invalid_expiry_year | O ano de validade do cartão é inválido. |
validation_error | incomplete_cvc | O código de segurança está incompleto. |
validation_error | invalid_cvc | O código de segurança é inválido. |
validation_error | card_brand_not_accepted | Esta bandeira não é aceita. |
validation_error | incomplete_parts | Preencha as duas partes do pagamento. |
validation_error | parts_invalid | A divisão do pagamento é inválida. |
card_error | invalid_number | O número do cartão é inválido. |
card_error | incorrect_number | O número do cartão está incorreto. |
card_error | invalid_expiry_month | O mês de validade do cartão é inválido. |
card_error | invalid_expiry_year | O ano de validade do cartão é inválido. |
card_error | invalid_cvc | O código de segurança é inválido. |
card_error | card_not_supported | Este cartão não é aceito. |
invalid_request_error | payer_field_missing | Falta um dado do pagador. |
invalid_request_error | email_invalid | O e-mail é inválido. |
invalid_request_error | method_not_supported | Este método de pagamento não é aceito. |
invalid_request_error | parameter_invalid | Um parâmetro enviado é inválido. |
invalid_request_error | api_key_invalid | A chave de API é inválida. |
invalid_request_error | permission_denied | A chave de API não tem permissão para esta chamada. |
invalid_request_error | invalid_publishable_key | A chave publicável é inválida. |
invalid_request_error | insecure_page | Uma chave live só funciona em página HTTPS. |
invalid_request_error | invalid_client_secret | O client_secret é inválido. |
invalid_request_error | amount_invalid | O valor é inválido. |
invalid_request_error | currency_invalid | A moeda é inválida. |
invalid_request_error | mode_invalid | O modo é inválido; use 'payment'. |
invalid_request_error | payment_method_types_invalid | As opções de pagamento são inválidas. |
invalid_request_error | options_invalid | As opções do Payment Fragment são inválidas. |
invalid_request_error | fragment_type_invalid | Tipo de Payment Fragment desconhecido; só 'payment' existe. |
invalid_request_error | fragment_already_exists | Já existe um Fragments ou Payment Fragment nesta instância. |
invalid_request_error | mount_target_not_found | O seletor do mount não casa com exatamente um elemento. |
invalid_request_error | page_origin_invalid | A página precisa de uma origem real para montar o Payment Fragment. |
invalid_request_error | fragments_not_ready | O Payment Fragment não está montado e pronto. |
invalid_request_error | already_mounted | O Payment Fragment já está montado. |
invalid_request_error | request_in_progress | Já existe uma chamada em andamento. |
invalid_request_error | client_secret_missing | Falta o client_secret da Intenção. |
invalid_request_error | payment_intent_not_found | A Intenção de pagamento não foi encontrada. |
api_error | api_unavailable | O serviço está indisponível; tente de novo. |
api_error | rate_limited | Muitas tentativas; aguarde um pouco. |
api_error | request_timeout | A chamada demorou demais. |
api_error | next_action_unsupported | O próximo passo deste pagamento não é suportado. |
api_error | overlay_not_ready | A janela do pagamento não abriu; tente de novo. |
api_error | unknown | Ocorreu um erro inesperado. |
Respostas da API
Como o SDK traduz a resposta da API em type e code. A message do servidor nunca é lida.
Na criação de cada pm_ (createPaymentMethod):
| Resposta da API | type e code do SDK |
|---|---|
400 card_error com invalid_number, incorrect_number, invalid_expiry_month, invalid_expiry_year, invalid_cvc ou card_not_supported | card_error, o mesmo code |
400 com payer_field_missing, email_invalid ou method_not_supported | invalid_request_error, o mesmo code |
400 com parameter_unknown, parameter_missing ou parameter_invalid | invalid_request_error parameter_invalid |
401 api_key_invalid | invalid_request_error api_key_invalid |
403 permission_denied | invalid_request_error permission_denied |
| 429 | api_error rate_limited |
502, 503, 504, falha de rede, corpo sem o objeto error, sucesso sem um pm_ | api_error api_unavailable |
| 8 s sem resposta | api_error request_timeout |
| qualquer outra | api_error unknown |
Na leitura do pagamento (handleNextAction):
| Resposta da API | O que o SDK faz |
|---|---|
| 200 com o pagamento | segue |
| 200 ilegível | api_error api_unavailable |
| 429 | não é erro: espera o Retry-After (em segundos ou data, no mínimo 1 s; sem ele, 3 s) e lê de novo |
| 404 | invalid_request_error payment_intent_not_found |
| 500 ou mais, falha de rede | api_error api_unavailable |
| 8 s sem resposta | api_error request_timeout |
| 400, 401, 403 e as demais | a tabela da criação |
Na leitura, o erro só encerra o handleNextAction na primeira leitura; nas seguintes, o SDK tenta de novo.
Avisos no console
Os avisos saem só em pt-BR, com o prefixo [Assiny], e nunca trazem o que foi digitado.
| Quando | Aviso |
|---|---|
uma chave sk_ no Assiny() | [Assiny] Chave secreta no navegador: use a chave publicável pk_. |
um locale desconhecido | [Assiny] locale desconhecido: '…'; usando pt-BR. |
um método repetido em paymentMethodTypes | [Assiny] paymentMethodTypes repetido: '…' aparece mais de uma vez e foi deduplicado. |
| um item da aparência fora da lista ou da faixa | [Assiny] Appearance: '…' foi ignorado (fora da lista fechada ou da faixa). |
| uma família ou um peso fora do catálogo | [Assiny] Fonte: '…' foi ignorada (fora do catálogo). |
uma chave fora do contrato em billing_details | [Assiny] billing_details: a chave '…' foi descartada (fora do contrato). |
uma chave desconhecida em fragments.update, createPaymentMethod.params ou handleNextAction | [Assiny] fragments.update: a chave '…' foi ignorada (fora do contrato). (e o mesmo com createPaymentMethod.params e handleNextAction) |