@v7-pay/sdk
v0.4.16
Published
V7 Pay API SDK for JavaScript/TypeScript. Use in backend (createSession, getSession) and frontend (tokenizeCard).
Readme
@v7-pay/sdk
V7 Pay API SDK for JavaScript/TypeScript. Covers all API methods plus tokenization (frontend-only).
Installation
npm install @v7-pay/sdkUsage
Auth (backend)
import { getAccessToken } from "@v7-pay/sdk";
const { access_token, refresh_token } = await getAccessToken(
baseUrl,
clientId,
clientSecret,
);Sessão com renovação automática (app)
createAuth mantém a sessão viva sozinho: renova o access token quando ele vence (ou está prestes
a vencer) e só falha com SessionExpiredError quando o refresh token também morreu — o único
momento em que o app deve mostrar a tela de login.
import { createAuth, SessionExpiredError } from "@v7-pay/sdk";
import * as SecureStore from "expo-secure-store";
const auth = createAuth({
baseUrl,
// O refresh token vive 30 dias e vale mais que o access token: armazenamento seguro do SO.
// Keychain (iOS) / Keystore (Android). NÃO use AsyncStorage nem localStorage.
storage: {
async load() {
const raw = await SecureStore.getItemAsync("v7pay.tokens");
return raw ? JSON.parse(raw) : null;
},
async save(tokens) {
await SecureStore.setItemAsync("v7pay.tokens", JSON.stringify(tokens));
},
async clear() {
await SecureStore.deleteItemAsync("v7pay.tokens");
},
},
onSessionExpired: () => navigation.reset({ routes: [{ name: "Login" }] }),
});
await auth.login(clientId, clientSecret);
// Authorization preenchido, renovação transparente e um retry automático em token_expired.
const res = await auth.authorizedFetch(`${baseUrl}/api/v1/transactions`);
await auth.logout(); // revoga a sessão no servidor e limpa o storageDetalhes que importam:
- Uma renovação por vez. Vinte requests que esbarrem no token vencido ao mesmo tempo compartilham o mesmo request de refresh — sem isso, as rotações se invalidariam entre si e a sessão cairia sozinha.
- Rotação de uso único. Cada renovação devolve um refresh token novo; guarde sempre o último.
createAuthjá faz isso pelostorage. - Só renova em
token_expired. Um 401 de escopo insuficiente ou assinatura inválida não é retentado — não adianta token novo, e gastaria uma rotação por request morto. - Vencimento absoluto. A rotação não estende a sessão: passados os 30 dias do login, é login de novo.
Para controlar o fluxo na mão, use refreshAccessToken(baseUrl, refreshToken) e
revokeRefreshToken(baseUrl, refreshToken).
Plans (backend)
import { listPlans, createPlan, getPlan, deletePlan } from "@v7-pay/sdk";
const { data: plans } = await listPlans(baseUrl, accessToken, {
limit: 50,
offset: 0,
});
const plan = await createPlan(baseUrl, accessToken, {
name: "Pro",
amount: 9990,
interval: "MONTHLY",
});
const p = await getPlan(baseUrl, accessToken, planId);
await deletePlan(baseUrl, accessToken, planId);Checkout sessions (backend)
import {
createSession,
listSessions,
getSession,
cancelSession,
} from "@v7-pay/sdk";
const session = await createSession(baseUrl, accessToken, {
amount: 9990,
currency: "BRL",
successUrl: "https://merchant.example/obrigado",
cancelUrl: "https://merchant.example/tente-novamente",
});
// Redirect: window.location = `${baseUrl}/checkout/${session.id}`
// After success/cancel the hosted checkout sends the buyer to successUrl / cancelUrl.
const { data: sessions } = await listSessions(baseUrl, accessToken);
const s = await getSession(baseUrl, accessToken, sessionId);
await cancelSession(baseUrl, accessToken, sessionId);Buyers (backend)
import { listBuyers, createBuyer, attachBuyerCard } from "@v7-pay/sdk";
const { data: buyers } = await listBuyers(baseUrl, accessToken, { limit: 50 });
const buyer = await createBuyer(baseUrl, accessToken, {
firstName: "João",
lastName: "Silva",
email: "[email protected]",
phone: "11999999999",
});
// tokenId comes from tokenizeCard (frontend only). Requires cards:write.
const card = await attachBuyerCard(baseUrl, accessToken, buyer.id, tokenId);Bank accounts (backend)
import { getBankAccount, createBankAccount } from "@v7-pay/sdk";
const bankAccount = await getBankAccount(baseUrl, accessToken);
const { id } = await createBankAccount(baseUrl, accessToken, {
holderName: "Empresa LTDA",
bankCode: "001",
routingNumber: "1234",
accountNumber: "12345-6",
accountType: "checking",
});Subscriptions (backend)
import {
listSubscriptions,
getSubscription,
updateSubscription,
cancelSubscription,
suspendSubscription,
reactivateSubscription,
} from "@v7-pay/sdk";
const { data: subscriptions } = await listSubscriptions(baseUrl, accessToken, {
limit: 50,
offset: 0,
});
const sub = await getSubscription(baseUrl, accessToken, subscriptionId);
await updateSubscription(baseUrl, accessToken, subscriptionId, { plan: newPlanId });
await suspendSubscription(baseUrl, accessToken, subscriptionId);
await reactivateSubscription(baseUrl, accessToken, subscriptionId);
await cancelSubscription(baseUrl, accessToken, subscriptionId);Transactions (backend)
import {
createTransaction,
listTransactions,
voidTransaction,
} from "@v7-pay/sdk";
const { data: transactions } = await listTransactions(baseUrl, accessToken, {
limit: 50,
});
// Charge a stored card. Requires transactions:write. cardId is card.id from attachBuyerCard.
const charged = await createTransaction(baseUrl, accessToken, {
buyerId: buyer.id,
amountCents: 9900,
method: "card",
cardId: card.id,
});
// Or issue a boleto (expirationDate optional, YYYY-MM-DD, default D+3).
const boleto = await createTransaction(baseUrl, accessToken, {
buyerId: buyer.id,
amountCents: 9900,
method: "boleto",
});
const voided = await voidTransaction(baseUrl, accessToken, transactionId);Transfers (backend)
import { listTransfers, listTransferTransactions } from "@v7-pay/sdk";
const { data: transfers } = await listTransfers(baseUrl, accessToken, {
limit: 50,
sort: "time-descending",
status: "succeeded",
});
const { data: txInTransfer } = await listTransferTransactions(baseUrl, accessToken, transferId);Receivables (backend)
import { listReceivables } from "@v7-pay/sdk";
const { data: receivables } = await listReceivables(baseUrl, accessToken, {
limit: 50,
page: 1,
sort: "time-descending",
status: "pending",
});Future transfers (backend)
import { listFutureTransfers } from "@v7-pay/sdk";
const { data: futureTransfers } = await listFutureTransfers(baseUrl, accessToken, {
expectedOnRangeGte: Date.now(),
expectedOnRangeLte: Date.now() + 7 * 24 * 60 * 60 * 1000,
});Tokenize (frontend only, PCI-safe)
Card payments use credit card only (no debit).
import { tokenizeCard } from "@v7-pay/sdk";
const { tokenId } = await tokenizeCard(baseUrl, {
sessionId: "...",
holderName: "...",
cardNumber: "...",
expirationMonth: "MM",
expirationYear: "YYYY",
securityCode: "...",
});Send tokenId to your backend and call attachBuyerCard, then createTransaction to charge the stored card (no card data on the server).
Charge a stored card (backend)
- Frontend:
tokenizeCard(needs an open checkoutsessionId) →tokenId - Backend:
attachBuyerCard(baseUrl, accessToken, buyerId, tokenId)→card.id - Backend:
createTransaction(..., { buyerId, amountCents, method: "card", cardId: card.id })
cardId is the V7 BuyerCard id, not the tokenization token. Reuse card.id for later charges without tokenizing again.
API summary
| Method | Endpoint | Context |
| ------------------- | ------------------------------------- | ---------------------------- |
| getAccessToken | POST /api/auth/token | Backend |
| refreshAccessToken| POST /api/auth/token | Backend / app |
| revokeRefreshToken| POST /api/auth/token/revoke | Backend / app |
| createAuth | POST /api/auth/token (+ renovação) | App |
| listPlans | GET /api/v1/plans | Backend |
| createPlan | POST /api/v1/plans | Backend |
| getPlan | GET /api/v1/plans/{id} | Backend |
| deletePlan | DELETE /api/v1/plans/{id} | Backend |
| createSession | POST /api/v1/checkout/sessions | Backend |
| listSessions | GET /api/v1/checkout/sessions | Backend |
| getSession | GET /api/v1/checkout/sessions/{id} | Backend |
| cancelSession | DELETE /api/v1/checkout/sessions/{id} | Backend |
| listBuyers | GET /api/v1/buyers | Backend |
| createBuyer | POST /api/v1/buyers | Backend |
| attachBuyerCard | POST /api/v1/buyers/{id}/cards | Backend (cards:write) |
| getBankAccount | GET /api/v1/bank-accounts | Backend |
| createBankAccount | POST /api/v1/bank-accounts | Backend |
| listSubscriptions | GET /api/v1/subscriptions | Backend |
| getSubscription | GET /api/v1/subscriptions/{id} | Backend |
| updateSubscription| PUT /api/v1/subscriptions/{id} | Backend |
| cancelSubscription| DELETE /api/v1/subscriptions/{id} | Backend |
| suspendSubscription | POST /api/v1/subscriptions/{id}/suspend | Backend |
| reactivateSubscription | POST /api/v1/subscriptions/{id}/reactivate | Backend |
| listTransactions | GET /api/v1/transactions | Backend |
| createTransaction | POST /api/v1/transactions | Backend (transactions:write) |
| voidTransaction | POST /api/v1/transactions/{id}/void | Backend (transactions:write) |
| listTransfers | GET /api/v1/transfers | Backend (transfers:read) |
| listTransferTransactions | GET /api/v1/transfers/{id}/transactions | Backend (transfers:read) |
| listReceivables | GET /api/v1/receivables | Backend (receivables:read) |
| listFutureTransfers | GET /api/v1/future-transfers | Backend (future_transfers:read) |
| tokenizeCard | GET tokenize-config + direct tokenization | Frontend only (PCI-safe) |
