SubSovereign
All guides

SubSovereign em Web & React Native — guia de integração

Este guia abrange o SDK JavaScript/TypeScript, que funciona em três ambientes a partir de uma única biblioteca: React Native (iOS + Android), React Native TV e web (com Stripe). Leva o seu app de "não tenho ideia de quem me pagou" a "o meu app desbloqueia as funcionalidades certas para o utilizador certo, verificadas no meu próprio servidor".

O que o SubSovereign faz por si

Os seus utilizadores subscrevem através de uma loja de apps (Apple, Google) ou, na web, através do Stripe. O SubSovereign responde a uma única pergunta para o seu app, de forma fiável: o que é que este utilizador pagou realmente?

  • O seu app pergunta ao SubSovereign pelo direito de acesso do utilizador — o que foi desbloqueado.
  • A validação da recibo é feita no servidor, diretamente com a loja (ou Stripe), para que um cliente adulterado não consiga falsificar uma subscrição.
  • A barreira de pagamento é configurada remotamente, permitindo-lhe alterar preços, períodos de teste e textos sem necessidade de novo envio.
  • É auto-hospedado: funciona na sua infraestrutura, os dados dos seus utilizadores ficam consigo e não há partilha de receitas — fica com 100% do que os seus utilizadores pagam.

Nunca confia no cliente. O cliente pergunta; o servidor decide.

Antes de começar

Precisa de um servidor SubSovereign em execução, de um app registado no painel de controlo (que lhe fornece um appId e uma chave de API), e dos seus níveis de acesso (tier, por exemplo, pro) criados e associados aos produtos que os seus utilizadores compram — produtos da App Store / Google Play para React Native, ou preços do Stripe para web. Trate da compra normalmente (bibliotecas de compras integradas no React Native, Stripe Checkout/Billing na web); o SubSovereign verifica e regista a compra depois.

Passo 1 — Instalar o SDK

npm install @subsovereign/js-sdk
import SubSovereign from '@subsovereign/js-sdk';

Passo 2 — Configurar uma vez, quando o app iniciar

SubSovereign.configure({
  apiKey:  'SUA_CHAVE_API_DO_APP',              // do painel de controlo
  appId:   'seu-id-do-app',                     // do painel de controlo
  baseUrl: 'https://subs.seudominio.com/api/v1', // O SEU servidor auto-hospedado
  userId:  currentUser.id,                      // o seu próprio ID de utilizador estável
  locale:  'pt',                                // a língua do utilizador
});

Utilize um userId estável para o utilizador autenticado — o mesmo valor em todos os locais, para que o acesso o siga entre dispositivos e plataformas. Volte a executar configure se um utilizador diferente fizer login.

Passo 3 — Verificar o que o utilizador pode aceder

A imagem completa vem de checkEntitlements():

try {
  const result = await SubSovereign.checkEntitlements();
  if (result.hasAccess) unlockProFeatures();
  else showFreeExperience();
} catch (err) {
  // Mantenha o utilizador com o último acesso conhecido e tente novamente mais tarde.
  console.warn('Falha na verificação de direito de acesso:', err);
}

Para um controlo simples, existe um auxiliar de conveniência, hasAccess(), que falha fechado (retorna false) em caso de erro de rede, para que um problema momentâneo nunca desbloqueie acidentalmente funcionalidades pagas:

if (await SubSovereign.hasAccess('pro')) unlockProFeatures();

Cada direito de acesso em result.entitlements inclui accessLevelId, isActive, expiresAt, willRenew e a respetiva store. result.fromCache é true se a resposta veio da cache do último acesso durante uma breve interrupção.

Passo 4 — Vender uma subscrição

Mostrar a barreira de pagamento

const paywall = await SubSovereign.getPaywallConfig('web'); // ou 'ios' | 'android' | 'firetv' | 'roku'
if (paywall) renderPaywall(paywall);   // título, funcionalidades, produtos…
else renderFallbackPaywall();

Concluir a compra e, em seguida, validá-la

Efetue a compra da forma habitual para a plataforma e, depois, passe o resultado ao SubSovereign para que o servidor valide e atribua o nível de acesso. Escolha a chamada que corresponde ao local onde a compra foi efetuada:

// Web (Stripe)
await SubSovereign.validateStripeSubscription({
  subscriptionId, productId, accessLevelId: 'pro',
});

// React Native — iOS (StoreKit)
await SubSovereign.validateApplePurchase({ transactionId, productId, accessLevelId: 'pro' });

// React Native — Android (Play Billing)
await SubSovereign.validateGooglePurchase({ purchaseToken, productId, accessLevelId: 'pro' });

Cada uma retorna true assim que o servidor confirmar a compra. Volte a executar checkEntitlements() depois e desbloqueie.

Feature flags

Ative funcionalidades a partir do servidor sem necessidade de novo envio:

const flags = await SubSovereign.getFeatureFlags(); // { newPlayer: true, ... }
if (flags.newPlayer) showNewPlayer();

Passo 5 — Privacidade: RGPD e CCPA

await SubSovereign.recordConsent({ purpose: 'analytics', granted: true });

await SubSovereign.requestErasure();            // "esqueça-me"
const myData = await SubSovereign.exportMyData(); // exportação de dados
await SubSovereign.setDoNotSell(true);          // sinal "Não Vender" do CCPA / GPC

Tratamento de erros

checkEntitlements e as chamadas validate… lançam exceções em caso de falha — envolva-as em try/catch e, em caso de erro, mantenha o utilizador com o último acesso conhecido e tente novamente mais tarde; nunca bloqueie um utilizador pago por um problema momentâneo. Os auxiliares de conveniência (hasAccess, getPaywallConfig, getFeatureFlags) falham fechados, retornando false/null/{}, sendo seguros para chamar inline.

Melhores práticas

  • Verificar no carregamento/início para que o controlo seja feito antes de o utilizador chegar a uma funcionalidade bloqueada.
  • Verificar novamente após a compra para que a IU se atualize imediatamente.
  • Nunca confiar no cliente — pergunte ao servidor; foi ele que verificou o recibo.
  • Um userId por utilizador real, mantido estável entre web e mobile.

Referência rápida

Pretende… Chamar
Configurar o SDK SubSovereign.configure(config)
Ver o que o utilizador desbloqueou await checkEntitlements()EntitlementResult
Controlo simples (falha fechada) await hasAccess('pro')boolean
Mostrar a barreira de pagamento remota await getPaywallConfig(platform)PaywallConfig | null
Validar uma compra do Stripe / Apple / Google await validateStripeSubscription / validateApplePurchase / validateGooglePurchase(…)
Ler feature flags await getFeatureFlags()
RGPD / CCPA recordConsent · requestErasure · exportMyData · setDoNotSell

Próximos passos