Guia para integrar o SDK @lina-openx/web-lina-pay-sdk em páginas web de e-commerce com Next.js (última versão) e ShadCN-UI.
Esta Skill orienta a criação de páginas de e-commerce web com integração do SDK @lina-openx/web-lina-pay-sdk, seguindo boas práticas de arquitetura no Next.js e padrões de UI com ShadCN-UI.
Use esta Skill quando o usuário pedir:
app/) com separação clara entre:
src/features/checkout/ para casos de uso, tipos e integrações;src/lib/lina-pay/ para wrapper do SDK e helpers.process.env e validação de variáveis.idle, loading, success, error, retry.src/
app/
(store)/
products/
cart/
checkout/
components/
ui/ # shadcn-ui
checkout/
features/
checkout/
application/
domain/
infrastructure/
lib/
lina-pay/
client.ts
mapper.ts
types.ts
npm i @lina-openx/web-lina-pay-sdksrc/lib/lina-pay/client.ts.getPaymentRequest (SUCESSO quando PAGO, FALHA caso contrário);Antes de usar o SDK, você pode configurar as URLs base para diferentes ambientes (homologação ou produção):
import { configure } from "@lina-openx/web-lina-pay-sdk";
// Configurar para produção
configure({
iamBaseUrl: "https://iam.linaob.com.br",
apiBaseUrl: "https://embedded-payment-manager.linaob.com.br",
});
// Configurar para homologação (padrão)
configure({
iamBaseUrl: "https://iam.linaob.com.br",
apiBaseUrl: "https://embedded-payment-manager.linaob.com.br",
});
configure(config: Partial<LinaPayConfig>)Configura as URLs base do SDK para diferentes ambientes.
Parâmetros:
config: Objeto parcial com as configurações:
iamBaseUrl (string, opcional): URL base do serviço de IAMapiBaseUrl (string, opcional): URL base da API de pagamentosExemplo:
configure({
iamBaseUrl: "https://iam.prod.linaob.com.br",
apiBaseUrl: "https://embedded-payment-manager.prod.linaob.com.br",
});
createPaymentRequest(credentials, payload)Cria uma solicitação de pagamento e redireciona para o portal de inicialização do pagamento.
Parâmetros:
credentials: Objeto com credenciais do subtenant:
subtenantId (string): ID do subtenantsubtenantSecret (string): Secret do subtenantpayload: Objeto CreatePaymentRequest com:
details (string): Detalhes do pagamentotxId (string): ID da transação (opcional)redirectUri (string): URI de redirecionamentocpfCnpj (string): CPF ou CNPJ do clientevalue (number): Valor do pagamentocreditor (objeto): Detalhes do crédito
personType (string): Tipo de pessoa ('PESSOA_JURIDICA' | 'PESSOA_NATURAL')cpfCnpj (string): CPF ou CNPJ do clientename (string): Nome do clienteaccountNumber (string): Número da contaaccountIssuer (string): Emissor da contaaccountIspb (string): ISPB da contaaccountType (string): Tipo de conta ('CACC' | 'SVGS')Retorna: Promise<CreatePaymentResponse> com id e redirectUrl
Exemplo:
const consent = await createPaymentRequest(
{
subtenantId: 'seu-subtenant-id',
subtenantSecret: 'seu-subtenant-secret'
},
{
"details": "Detalhes do pagamento",
"redirectUri": "https://redirect-demo-opal.vercel.app",
"cpfCnpj": "08116143018",
"value": 0.01,
"creditor": {
"personType": "PESSOA_JURIDICA",
"cpfCnpj": "50685362006773",
"name": "Ralph Bragg"
"accountNumber": "11188222",
"accountIssuer": "0001",
"accountIspb": "99999004",
"accountType": "SVGS",
}
}
)
getPaymentRequest(credentials, id)Após o usuário concluir (ou sair) do fluxo no portal Lina, a aplicação white-label recebe o retorno na URL configurada em redirectUri do createPaymentRequest. Nessa rota, use getPaymentRequest do @lina-openx/web-lina-pay-sdk para obter o estado atual da solicitação e montar a tela de resultado.
Função (conforme skill web-lina-pay-sdk):
(credentials: LinaPayCredentials, id: string) => Promise<PaymentRequestData>id: o mesmo identificador retornado por createPaymentRequest (persistir na sessão ou receber por query string no retorno, conforme contrato do redirect do produto).GET …/requests/:id, obtém o token internamente e devolve PaymentRequestData. Na consulta, a API costuma preencher mais campos do que na criação (status, value, creditor, debitor, payments, datas, etc.) — ver distinção createPaymentRequest vs getPaymentRequest em web-lina-pay-sdk/SKILL.md e tipos em web-lina-pay-sdk/reference.md.Regra de interface (obrigatória nesta skill):
PAGO (tipo PaymentItemStatus nos itens de payments).PAGO (incluindo pendências, erros, expirado, ou ausência de itens/payments vazio até haver conclusão com PAGO).Onde checar PAGO: nos itens retornados em payments (cada item tem status). Exemplo de critério para uma solicitação com um ou mais itens:
import { getPaymentRequest } from "@lina-openx/web-lina-pay-sdk";
/** Resposta do GET costuma incluir `payments` com `status` por item — ver `reference.md` do skill web-lina-pay-sdk */
type EnrichedPaymentRequest = {
payments?: Array<{ status: string }>;
};
function isPaidSuccess(data: EnrichedPaymentRequest): boolean {
const items = data.payments ?? [];
return items.some((p) => p.status === "PAGO");
}
Arquitetura no Next.js:
getPaymentRequest no servidor (Server Component, Route Handler ou Server Action) com subtenantId / subtenantSecret vindos de process.env, para não expor credenciais no client.GET /api/payment-requests/[id] (handler interno que chama o SDK), ou um Server Component assíncrono que chama o SDK diretamente e repassa apenas dados necessários para componentes de UI (ShadCN: Alert, Card, tipografia de sucesso/erro).LinaPayError (try/catch, instanceof LinaPayError, statusCode) e mapear para mensagem amigável na variante FALHA.Exemplo mínimo (Route Handler + decisão SUCESSO/FALHA):
// app/api/payment-requests/[id]/route.ts
import { getPaymentRequest, LinaPayError } from "@lina-openx/web-lina-pay-sdk";
import { NextResponse } from "next/server";
export async function GET(
_request: Request,
context: { params: Promise<{ id: string }> }
) {
const { id } = await context.params;
if (!id) {
return NextResponse.json({ error: "missing id" }, { status: 400 });
}
try {
const data = await getPaymentRequest(
{
subtenantId: process.env.LINA_SUBTENANT_ID!,
subtenantSecret: process.env.LINA_SUBTENANT_SECRET!,
},
id
);
const items = "payments" in data && Array.isArray((data as { payments?: unknown }).payments)
? (data as { payments: Array<{ status: string }> }).payments
: [];
const outcome = items.some((p) => p.status === "PAGO") ? "SUCESSO" : "FALHA";
return NextResponse.json({ outcome, data });
} catch (e) {
if (e instanceof LinaPayError) {
return NextResponse.json(
{ outcome: "FALHA", statusCode: e.statusCode, message: e.message },
{ status: e.statusCode ?? 500 }
);
}
throw e;
}
}
A página de retorno consome esse JSON (ou equivalente via Server Component) e renderiza UI distinta para outcome === "SUCESSO" vs outcome === "FALHA", exibindo os campos de data relevantes para o usuário.
Button, Input, Form, Dialog, Alert).Quando esta Skill for acionada, seguir este fluxo:
@lina-openx/web-lina-pay-sdk.getPaymentRequest, regra SUCESSO/PAGO vs FALHA e UI ShadCN-UI.