Sobre a documentação
Esta documentação tem como objetivo instruir a implementação da API de pagamentos Global Pays. Para realizar a integração com o gateway de pagamentos da Global Pays é necessário um programador com conhecimentos básicos em comunicação REST e manipulação de arquivos Json.
Autenticação
A autenticação é feita através do fornecimento de seu Token. Ele deve ser transmitido
em
todas as requisições no header token. Caso o Token seja inválido ou não
seja
informado, a API retornará HTTP 401.
Os Tokens são distintos entre os ambientes de Sandbox e Produção, portanto lembre-se de alterá-lo quando mudar a URL.
Atenção
- Seu Token carrega muitos privilégios, portanto certifique-se de mantê-lo protegido. Não informe ele em atendimentos e nem o exponha no front-end da sua aplicação.
- Além disso, não é possível recuperá-lo caso perdido, sendo necessário a geração de um novo.
Validade do Token e limite de requisições
- O Token gerado tem validade de 30 minutos a partir da sua geração. Após esse período ele expira e uma nova requisição deve ser feita para gerar outro.
- Esta rota não deve ser utilizada de forma abusiva, como gerar um Token novo
a cada requisição feita pela sua aplicação. Chamadas excessivas podem
acionar um bloqueio temporário (
HTTP 429 - Too Many Requests). O recomendado é reaproveitar o mesmo Token durante todo o seu período de validade e só solicitar um novo quando ele estiver perto de expirar.
Verificando a validade do Token antes de gerar um novo
A forma correta de evitar o bloqueio por excesso de requisições é armazenar o
Token junto com o campo expirate retornado na resposta, e só solicitar um novo Token quando o horário atual
estiver próximo ou além desse valor. Os exemplos abaixo (PHP e JavaScript)
implementam essa verificação, reaproveitando o Token em cache enquanto ele
ainda for válido:
<?php
/**
* Exemplo compatível com PHP 8.0 ou superior.
*
* Reutiliza o Token armazenado em cache enquanto ele estiver válido.
* Um novo Token é solicitado apenas quando necessário, evitando
* requisições excessivas à rota /auth (HTTP 429).
*/
class ParceladoUsaAuthClient
{
// URL do ambiente Sandbox.
// Em produção, utilize a URL correspondente ao ambiente produtivo.
private const AUTH_URL =
'https://apisandbox.parceladousa.com/v1/paymentapi/auth';
// Armazene o arquivo fora da pasta pública da aplicação.
private const CACHE_FILE = __DIR__ . '/parceladousa_token.json';
// Renova o Token 60 segundos antes do vencimento.
private const SAFETY_MARGIN_SECONDS = 60;
public function __construct(
private string $pubKey,
private string $merchantCode
) {
}
public function getValidToken(): string
{
$cached = $this->readCache();
if (
isset($cached['token'], $cached['expirate']) &&
$this->isStillValid($cached['expirate'])
) {
return $cached['token'];
}
return $this->requestNewToken();
}
private function isStillValid(string $expirate): bool
{
$expiresAt = strtotime($expirate); // "expirate": "Y-m-d H:i:s"
return $expiresAt !== false
&& $expiresAt > time() + self::SAFETY_MARGIN_SECONDS;
}
private function requestNewToken(): string
{
$payload = json_encode([
'pubKey' => $this->pubKey,
'merchantCode' => $this->merchantCode,
]);
if ($payload === false) {
throw new \RuntimeException(
'Não foi possível gerar os dados da autenticação.'
);
}
$ch = curl_init(self::AUTH_URL);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Accept: application/json',
],
CURLOPT_POSTFIELDS => $payload,
CURLOPT_CONNECTTIMEOUT => 10,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
$curlError = curl_error($ch);
$httpCode = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($response === false) {
throw new \RuntimeException(
'Erro de conexão com a API: ' . $curlError
);
}
if ($httpCode === 429) {
throw new \RuntimeException(
'Limite de solicitações de Token excedido (HTTP 429).'
);
}
if ($httpCode < 200 || $httpCode >= 300) {
throw new \RuntimeException(
"Erro ao solicitar o Token (HTTP {$httpCode})."
);
}
$data = json_decode($response, true);
if (
!is_array($data) ||
!isset($data['token'], $data['expirate'])
) {
throw new \RuntimeException(
'A API retornou uma resposta de autenticação inválida.'
);
}
$cache = json_encode([
'token' => $data['token'],
'expirate' => $data['expirate'],
]);
if (
$cache === false ||
file_put_contents(self::CACHE_FILE, $cache, LOCK_EX) === false
) {
throw new \RuntimeException(
'Não foi possível salvar o Token em cache.'
);
}
return $data['token'];
}
private function readCache(): ?array
{
if (!is_file(self::CACHE_FILE)) {
return null;
}
$content = file_get_contents(self::CACHE_FILE);
if ($content === false) {
return null;
}
$data = json_decode($content, true);
return is_array($data) ? $data : null;
}
}
// Exemplo de uso:
$auth = new ParceladoUsaAuthClient(
'SEU_PUBKEY',
'SEU_MERCHANT_CODE'
);
$token = $auth->getValidToken();
/**
* Exemplo compatível com Node.js 18 ou superior.
*
* Reutiliza o Token em memória enquanto ele estiver válido e só solicita um
* novo quando necessário, evitando requisições excessivas à rota /auth
* (HTTP 429). Em ambientes serverless ou com múltiplas instâncias,
* substitua o cache em memória por Redis ou banco de dados.
*/
// URL do ambiente Sandbox.
// Em produção, utilize a URL correspondente ao ambiente produtivo.
const AUTH_URL = 'https://apisandbox.parceladousa.com/v1/paymentapi/auth';
// Renova o Token 60 segundos antes do vencimento.
const SAFETY_MARGIN_MS = 60 * 1000;
const REQUEST_TIMEOUT_MS = 30 * 1000;
let cachedToken = null;
let cachedExpiresAt = null;
async function getValidToken(pubKey, merchantCode) {
if (cachedToken && Date.now() < cachedExpiresAt - SAFETY_MARGIN_MS) {
return cachedToken;
}
return requestNewToken(pubKey, merchantCode);
}
async function requestNewToken(pubKey, merchantCode) {
let response;
try {
response = await fetch(AUTH_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json',
},
body: JSON.stringify({ pubKey, merchantCode }),
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
});
} catch (error) {
throw new Error(`Erro de conexão com a API: ${error.message}`);
}
if (response.status === 429) {
throw new Error('Limite de solicitações de Token excedido (HTTP 429).');
}
if (!response.ok) {
throw new Error(`Erro ao solicitar o Token (HTTP ${response.status}).`);
}
const data = await response.json();
if (!data?.token || !data?.expirate) {
throw new Error('A API retornou uma resposta de autenticação inválida.');
}
// "expirate": "YYYY-MM-DD HH:mm:ss" -> converte para timestamp.
const expiresAt = new Date(data.expirate.replace(' ', 'T')).getTime();
if (Number.isNaN(expiresAt)) {
throw new Error('A data de expiração do Token é inválida.');
}
cachedToken = data.token;
cachedExpiresAt = expiresAt;
return cachedToken;
}
// Exemplo de uso:
const token = await getValidToken('SEU_PUBKEY', 'SEU_MERCHANT_CODE');
Códigos HTTP das respostas
A Global Pays utiliza respostas HTTP convencionais para indicar sucesso ou falha nas requisições. Respostas com status 200 indicam sucesso, status 4xx indicam falhas decorrentes de erros nas informações enviadas, e status 500 indicam erros internos no servidor da Global Pays.
| Código HTTP | Descrição |
|---|---|
| 200 OK | Sua requisição foi bem sucedida. |
| 300 | The pubKey was not informed. |
| 310 | The merchantCode was not informed. |
| 320 | Invalid credentials. |
| 330 | Merchant account not found. |
| 340 | The amount entered must be equal to or greater than 1. |
| 350 | Callback redirection routes not informed. |
| 360 | There was an error calculating the values, if the error persists, please contact support |
| 370 | An error occurred when registering the order, if the error persists contact support. |
| 380 | Order id not entered or not numeric. |
| 390 | Merchant account not found. |
| 400 | Order not found. |
| 410 | Invalid token. |
| 420 | Expired token. |
| 429 | Muitas requisições em um curto período de tempo (rate limit). Aguarde antes de tentar novamente. |
Todos os endpoints da Global Pays recebem e respondem em JSON.
Exemplo de resposta para HTTP 300:
{
"statusCode":300,
"statusType":"error",
"msg":"The pubKey field is required"
}
Ambiente de desenvolvimento e testes
| Produção | Sandbox |
|---|---|
| https://api.tryglobalpays.com/v1 | https://apihml.tryglobalpays.com/v1 |
Atenção
- Para o desenvolvimento de sua integração recomendamos que utilize nosso Sandbox. Para tal, você deve primeiramente ter uma conta junto a Global Pays. Após a criação da conta, vá até a opção integrações no menu lateral e gere sua chave de integração, (essa chave é sua chave de produção) clique no botão 'Criar conta teste' e informe uma senha para seu ambiente de testes. Após criada a conta de teste clique em 'Acessar conta teste', você será direcionado para uma tela de login do nosso ambiente de testes, faça login com o mesmo e-mail e com a senha que informou no momento da criação da conta teste, vá até a opção integração no menu lateral e gere sua chave de integração de testes. . Em Sandbox é possível você testar o envio e recebimento de notificações de email. Portanto você não deve usar emails e celulares reais. Para testar o recebimento de notificações você pode utilizar os seus próprios emails e celulares.
Cartão de crédito para testes
Bandeira: Visa
Número do cartao: 4111111111111111
CVV: 123
Validade: 10/2040
Autenticação
Solicitar Token de acesso
Para gerar seu Token, você deve fazer um requisição usando o seu pubKey, gerado no seu ambiente Sandbox. Você deverá usar seu Token em todas as outras requisições em nossa API.
Lembre-se: o Token gerado tem validade de 30 minutos e esta rota não deve ser
usada de forma abusiva. Chamadas excessivas podem resultar em bloqueio
temporário (HTTP 429). Veja como validar a expiração do Token na seção Autenticação.
Transações
Os status possíveis de uma transação são os seguintes:
open - Transação está aberta para pagamento (ainda não teve interação do cliente).
pending - O cliente gerou um boleto e a transação está aguardando a quitação do mesmo
analysis - Pagamento efetuado mas está em análise para liberação pelo setor de segurança, (este status não significa que a compra está concluída, pois pode não ser aprovada pelo setor de segurança caso seja identificada alguma inconsistência nos dados).
approved - Pagamento efetuado e liberado pelo setor de segurança, (este status significa que a compra está totalmente liberado e será transferido para a conta bancária do merchant registrada em nosso sistema).
delivered - A compra está totalmente liberada e já foi transferida para a conta bancária do merchant registrada em nosso sistema.
canceled - Pagamento efetivado mas cancelado posteriormente à pedido do cliente ou por não atender aos requisitos de segurança.
aborted - A transação foi abortada antes de sua conclusão(ocorre quando o cliente clica no botão cancelar na tela de pagamento).
Criar nova transação
Para realizar a criação de transações é necessário que já tenha sido gerado um TOKEN de acesso, e este deve ser enviado através do header da requisição com Bearer Token
Split de comissão (commissionSplit)
: Caso deseje
acrescer
um valor de comissão ao valor original da compra
para que seja dividido entre outros merchants. obrigatoriamente a soma das comissões
já
devem estar acrescidas ao valor amount principal, pois esta comissão é subtraída do
valor
a ser repassado para o merchant principal.
Rota de Callback (callback)
: A rota de callback é
utilizada para redirecionar o cliente pagador para seu ambiente, será adicionado a
ela
um parâmetro após o endereço fornecido que é o orderId(Id da ordem que está sendo
processada) ficando assim: https://SEUHOST/seuendpoint?orderId=1234.
OBS: Nesse endereço você deve realizar uma consulta para nossa api seguindo a
instrução que está no tópco "CONSULTAR UMA TRANSAÇÃO",
para confirmar se a transação está paga ou foi cancelada, só então direcionar seu
cliente para sua tela de sucesso ou cancelamento.
Atenção
- O link que é retornado em data.url deverá ser inserido no botão de finalização do seu site ou através de algum outro método de redirecionamento que prefira, para que o cliente seja redirecionado para o ambiente de pagamento da Global Pays.
Consultar uma transação
Para recuperar uma transação específica é necessário que você tenha o
ID (orderId) que a Global Pays retornou no momento da criação dela.
Para acompanhar mudanças de status sem precisar consultar esta rota
repetidamente, utilize os Webhooks, que notificam automaticamente sua aplicação a cada mudança de status da
transação. Esta rota também possui limite de requisições (rate limit); uso
abusivo (polling agressivo) pode resultar em bloqueio temporário (HTTP 429 - Too Many Requests).
Inativando uma transação
Para inativar uma transação específica é necessário que você tenha o
ID (orderId) que a Global Pays retornou no momento da criação dela.
Consultando valores
Calcular novo valor
Para calcular o valor total de taxas, impostos e valor total a pagar. Nossa API irá retornar os totais por forma de pagamento, PIX, Boleto e cartão de crédito.
Webhooks
O sistema irá enviar uma notificação HTTP POST sempre que o status de um pedido criado através da API for alterado (aprovado, cancelado, expirado, entregue, etc.), para a URL cadastrada na integração. As notificações são enviadas somente para os pedidos criados a partir da API, e não para vendas feitas manualmente pelo dashboard.
Assim que uma notificação chega, evite depender apenas dela: consulte a rota Consultar uma transação para confirmar o status oficial do pedido antes de liberar o produto ou serviço ao cliente. O Webhook é um aviso de conveniência e não a fonte de verdade.
Como configurar
Para receber notificações, efetue login em sua conta na Global Pays, vá até o menu Integrações, e crie (ou edite) uma integração própria. No formulário exibido, preencha:
- Rota de retorno (webhook): a URL do seu servidor que receberá as notificações via POST.
- Token de autenticação: clique em Gerar token para gerar automaticamente um token seguro, ou defina um token próprio no
formato
whsec_seguido de pelo menos 32 caracteres entre letras, números, hífen e underline. Fora desse formato o token é recusado ao salvar. É este token que permite validar a assinatura das notificações (veja Assinatura de segurança, logo abaixo).
Atenção
- O token completo fica visível apenas enquanto o formulário está aberto.
Copie e guarde-o com segurança antes de salvar, porque depois o painel
passa a mostrar somente uma versão mascarada (
whsec_••••••••••••••••••••••••••••PQzw). - O token novo só entra em vigor quando a integração é salva. A partir desse momento o token anterior deixa de validar, então atualize o valor no seu servidor para continuar reconhecendo as notificações como autênticas.
- Se você não gerar nem informar um token, a integração é salva sem token: as notificações continuam chegando normalmente, porém sem os headers de assinatura descritos abaixo.
Estrutura da notificação
A notificação consiste em uma requisição POST com corpo em JSON, conforme este exemplo:
{
"orderId": 15613,
"order_date": "2023-02-15 12:11:37",
"payment_date": "2023-02-15 19:27:18",
"amount": 598.96,
"invoice": "Invoice text",
"description": "",
"authCode": "99999999999999",
"payment_method": "Cartão de Crédito",
"total_amount_usd": 678.32,
"total_amount_brl": 3833.12,
"netValue": 598.96,
"installment": 6,
"status": "approved",
"expirationDate": "2023-02-20 23:59:59",
"client": {
"name": "Naruto Uzumaki",
"email": "naruto@seudominio.com",
"doc": "99999999999",
"phone": "99999999999",
"cep": "99999999",
"address": "Rua Konoha",
"numberAddress": "1",
"city": "Cidade",
"state": "UF"
},
"last_update": "2023-02-15 19:27:18",
"url_checkout": "",
"discharge": {
"statementUuid": "b1f3c2e4-9a7d-4e21-8f3b-4a6d1c9e0f52",
"date": "2023-02-20",
"dischargeStatus": "concluded"
}
}
Alguns campos merecem atenção:
client: só é preenchido quando o pedido tem um pagamento em andamento ou concluído. Para pedidos ainda open ou aborted, este objeto é retornado vazio ({}).url_checkout: só vem preenchido enquanto o pedido está open; para os demais status, o campo vem vazio.discharge.dischargeStatus: indica o repasse financeiro do pedido: pending (ainda não iniciado), in_progress (em conciliação) ou concluded (repassado ao merchant).
Assinatura de segurança
Toda notificação enviada para uma integração com Token de autenticação configurado carrega três headers adicionais, que permitem confirmar que a requisição foi realmente enviada pela Global Pays e que o corpo não foi alterado no caminho:
| Header | Descrição |
|---|---|
ParceladoUSA-Webhook-Id |
Identificador único do evento (ex.: evt_01HZY6WZTG5V6Q7N9K8XABCDEF). Use-o para evitar processar a mesma notificação duas vezes. |
ParceladoUSA-Webhook-Timestamp |
Timestamp Unix do momento em que a notificação foi enviada. |
ParceladoUSA-Webhook-Signature |
Assinatura HMAC-SHA256 do corpo da requisição, no formato v1={assinatura}. |
Exemplo de requisição completa:
POST /seu-endpoint-configurado HTTP/1.1
Content-Type: application/json
User-Agent: ParceladoUSA-Webhook/1.0
ParceladoUSA-Webhook-Id: evt_01HZY6WZTG5V6Q7N9K8XABCDEF
ParceladoUSA-Webhook-Timestamp: 1700000000
ParceladoUSA-Webhook-Signature: v1=5f3c1e9b7a2d4c6e8f0a1b2c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3e4f5a6
{"orderId":15613,"status":"approved", ...}
A assinatura é calculada com HMAC-SHA256, usando o seu token whsec_... como chave, sobre o seguinte conteúdo:
{timestamp}.{corpo_bruto_da_requisicao}
Importante
A assinatura deve ser calculada sobre o corpo bruto da requisição, exatamente como recebido, sem fazer json_decode seguido de json_encode. Qualquer diferença de espaçamento, quebra de linha ou ordem de chaves produz
uma assinatura diferente e invalida a comparação.
Passo a passo da validação
- Leia o corpo bruto da requisição recebida.
- Obtenha os headers
ParceladoUSA-Webhook-TimestampeParceladoUSA-Webhook-Signature. - Verifique se o timestamp está dentro de uma tolerância razoável do horário atual. Recomendamos 300 segundos (5 minutos). Isso protege contra ataques de replay com requisições antigas capturadas.
- Recalcule o HMAC-SHA256 sobre
{timestamp}.{corpo_bruto}usando seu token. - Compare o resultado com a assinatura recebida usando uma função resistente a
timing attacks (
hash_equalsem PHP,crypto.timingSafeEqualem Node.js). Nunca use==ou===. - Só processe o evento depois da validação passar. Use o
ParceladoUSA-Webhook-Idpara não processar o mesmo evento mais de uma vez, caso a notificação seja reentregue.
<?php
/**
* Exemplo de validação da assinatura de um Webhook recebido.
* Compatível com PHP 8.0 ou superior.
*/
// Token de autenticação gerado na tela de Integrações ("Token de autenticação").
const WEBHOOK_SECRET = 'whsec_SEU_TOKEN_AQUI';
// Tolerância máxima entre o timestamp da requisição e o horário atual.
const TOLERANCE_SECONDS = 300;
function validateWebhookSignature(): array
{
$rawBody = file_get_contents('php://input');
$eventId = $_SERVER['HTTP_PARCELADOUSA_WEBHOOK_ID'] ?? null;
$timestamp = $_SERVER['HTTP_PARCELADOUSA_WEBHOOK_TIMESTAMP'] ?? null;
$signatureHeader = $_SERVER['HTTP_PARCELADOUSA_WEBHOOK_SIGNATURE'] ?? null;
if ($timestamp === null || $signatureHeader === null) {
http_response_code(401);
exit('Assinatura ausente.');
}
if (abs(time() - (int) $timestamp) > TOLERANCE_SECONDS) {
http_response_code(401);
exit('Timestamp fora da tolerância (possível replay).');
}
$expectedSignature = hash_hmac(
'sha256',
$timestamp . '.' . $rawBody,
WEBHOOK_SECRET
);
$receivedSignature = preg_replace('/^v1=/', '', $signatureHeader);
if (!hash_equals($expectedSignature, $receivedSignature)) {
http_response_code(401);
exit('Assinatura inválida.');
}
return [
'eventId' => $eventId,
'payload' => json_decode($rawBody, true),
];
}
$webhook = validateWebhookSignature();
// Utilize $webhook['eventId'] para não processar o mesmo evento duas vezes
// (ex.: gravando os IDs já tratados em banco/cache antes de seguir).
// A partir daqui, o Webhook está autenticado. Processe $webhook['payload'].
/**
* Exemplo de validação da assinatura de um Webhook recebido.
* Compatível com Node.js 18 ou superior (Express + corpo bruto).
*/
import crypto from 'node:crypto';
import express from 'express';
const WEBHOOK_SECRET = 'whsec_SEU_TOKEN_AQUI';
const TOLERANCE_SECONDS = 300;
const app = express();
// Importante: capture o corpo BRUTO da requisição. Não use express.json()
// antes desta rota, pois a assinatura é calculada sobre os bytes originais.
app.post(
'/webhooks/parceladousa',
express.raw({ type: 'application/json' }),
(req, res) => {
const rawBody = req.body.toString('utf8');
const eventId = req.header('ParceladoUSA-Webhook-Id');
const timestamp = req.header('ParceladoUSA-Webhook-Timestamp');
const signatureHeader = req.header('ParceladoUSA-Webhook-Signature');
if (!timestamp || !signatureHeader) {
return res.status(401).send('Assinatura ausente.');
}
const now = Math.floor(Date.now() / 1000);
if (Math.abs(now - Number(timestamp)) > TOLERANCE_SECONDS) {
return res.status(401).send('Timestamp fora da tolerância (possível replay).');
}
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
const receivedSignature = signatureHeader.replace(/^v1=/, '');
const expectedBuffer = Buffer.from(expectedSignature, 'utf8');
const receivedBuffer = Buffer.from(receivedSignature, 'utf8');
const isValid =
expectedBuffer.length === receivedBuffer.length &&
crypto.timingSafeEqual(expectedBuffer, receivedBuffer);
if (!isValid) {
return res.status(401).send('Assinatura inválida.');
}
// Utilize eventId para não processar o mesmo evento duas vezes.
const payload = JSON.parse(rawBody);
// A partir daqui, o Webhook está autenticado.
return res.status(200).send('ok');
}
);
Boas práticas
- Sempre responda com um status HTTP entre 200 e 299 assim que validar e aceitar a notificação, de preferência antes de processar tarefas demoradas.
- Nunca exponha o seu token
whsec_...em código de front-end, repositórios públicos ou logs de aplicação. - Utilize sempre HTTPS na URL de webhook cadastrada, para que o conteúdo não trafegue em texto puro entre nós e o seu servidor.
- Se o seu endpoint não responder ou retornar erro, considere que a notificação pode não ter chegado. Utilize Consultar uma transação periodicamente como rede de segurança para pedidos críticos.