SubSovereign
All guides

SubSovereign React (웹) — 통합 가이드

이 가이드는 React 웹 앱용 @subsovereign/react (sdk-react/)에 대해 다룹니다. SubSovereign 대시보드에서 디자인한 결제 화면을 실시간 React 컴포넌트로 렌더링하며, 대시보드 미리 보기와 동일한 렌더러를 사용하므로 대시보드에서 승인한 내용이 그대로 배포됩니다.

이 SDK는 결제 화면을 그리는 역할만 하며, 결제나 권한 부여를 처리하지 않습니다. 권한 확인(checkEntitlements()) 및 구매 검증을 위해 웹/JS 데이터 SDK (@subsovereign/js-sdk)와 함께 사용하도록 설계되었습니다.

시작하기 전에

실행 중인 SubSovereign 서버, 대시보드에 등록된 (앱 ID(appId)와 SDK 역할 API 키), 그리고 게시된 결제 화면 (대시보드 → 결제 화면 → 게시)이 필요합니다.

1단계 — 설치

패키지는 sdk-react/에 있으며 아직 npm에 등록되지 않았습니다. 경로 또는 git 의존성으로 추가하거나 프로젝트에 폴더를 복사하세요.

npm install ./sdk-react   # path dependency while it's pre-npm
import { Paywall, usePaywallConfig } from '@subsovereign/react';

2단계 — 게시된 결제 화면 로드

usePaywallConfig는 이 앱/사용자에 대한 구성을 가져옵니다. A/B 변형은 userId 기준으로 서버 측에서 선택되므로 동일한 사용자는 항상 동일한 결제 화면을 보게 됩니다.

const { config, loading, error } = usePaywallConfig({
  apiUrl: 'https://subs.yourdomain.com/api/v1', // YOUR self-hosted server
  appId:  'your-app-id',
  userId: currentUser.id,                        // your own stable user id
  apiKey: 'YOUR_SDK_KEY',
  locale: 'en',                                  // optional, default 'en'
  platform: 'web',                               // optional, default 'web'
});

매개변수 대신 null을 전달하면 가져오기를 건너뛸 수 있습니다(예: 사용자가 로그아웃된 경우).

3단계 — 렌더링

<Paywall
  config={config}
  loading={loading}
  loadingState={<Spinner />}          // optional
  emptyState={<FallbackPaywall />}    // optional — shown when no config is published
  onSelectProduct={(productId) => startCheckout(productId)}
/>

onSelectProduct는 사용자가 상품을 선택할 때 발생합니다. 웹용 Stripe 결제와 연결하세요. 결제가 성공하면 데이터 SDK로 검증하고 권한을 다시 확인하세요.

await SubSovereign.validateStripeSubscription({ subscriptionId, productId, accessLevelId: 'pro' });
const { hasAccess } = await SubSovereign.checkEntitlements();
if (hasAccess) unlockProFeatures();

이미 데이터 SDK를 통해 구성을 가져온 경우, 훅을 건너뛰고 바로 전달할 수 있습니다. 완전한 제어를 원한다면 원시 렌더러 <PaywallRenderer config={config} onSelectProduct={…} />를 사용하세요.

EU 철회 버튼 (준거 패스포트)

EU 소비자에게 온라인으로 구독을 판매하는 경우, EU 지침 2023/2673에 따라 계약 철회 기능을 명확히 레이블링해야 합니다. SDK는 이를 즉시 사용할 수 있도록 제공합니다.

import { WithdrawalButton, useWithdrawalConfig } from '@subsovereign/react';

function CancelSubscription({ user, sub }: { user: { id: string; locale: string }; sub: { id: string } }) {
  // Fetches the withdrawal settings AND the notice's wording in the customer's language.
  const { config, strings, error } = useWithdrawalConfig({
    apiUrl: 'https://subs.yourdomain.com/api/v1',
    appId: 'your-app-id',
    apiKey: 'YOUR_SDK_KEY',
    locale: user.locale,          // the CUSTOMER's language, not your console's
  });
  // Log it: a silent failure here is how a tenant ships English to German customers and never finds
  // out. The customer is never shown this — they get the button, in English.
  if (error) console.warn('SubSovereign: withdrawal settings unavailable', error);
  if (config && config.enabled === false) return null;   // the tenant turned it off

  return (
    <WithdrawalButton
      apiUrl="https://subs.yourdomain.com/api/v1"
      appId="your-app-id"
      apiKey="YOUR_SDK_KEY"
      userId={user.id}
      subscriptionId={sub.id}
      strings={strings}           // ← without this the dialog is ENGLISH for every customer
      locale={user.locale}        // ← and without this the DATE is formatted for the device
      labelKey={config?.labelKey} // ← the label the tenant chose in the console
      appearance="auto"
    />
  );
}

레이블링은 변경할 수 없습니다. 콘솔에서는 철회 기능에 대해 "Withdraw from contract here" 또는 *"Cancel here"*라는 두 가지 레이블을 제공하며, labelKey는 테넌트가 선택한 레이블을 전달합니다. 단어 자체는 서버에서 고객의 언어로 제공됩니다. 자체 텍스트를 전달할 방법은 없습니다. 과거에는 label prop으로 자유 텍스트를 받을 수 있었지만, 이제 콘솔 경고와 함께 무시됩니다. 이는 통계적 고지문이 마케팅으로Softened 될 수 있는 경우와 동일합니다(이는 색상도 전달할 수 없는 이유입니다).

🚩 locale도 전달하세요. 이는 승인 메시지의 타임스탬프를 형식화합니다. 전달하지 않으면 날짜가 장치 기준으로 형식화되어 독일 고객이 미국 브라우저를 사용할 경우 9/3/2026으로 표시될 수 있으며, 이는 9월 3일이 아닌 3월 9일로 읽힐 수 있습니다. 이는 법적 행위의 기록 날짜이므로 모호성을 방지해야 합니다.

🚩 strings를 전달하세요. 그렇지 않으면 통계적 고지문이 모든 사람에게 영어로 표시됩니다. 단어는 요청한 로케일의 SubSovereign 서버에서 제공됩니다. 이는 법적 고지문이 마케팅으로Softened 되지 않도록 하기 위함입니다. 버튼은 전달받은 내용을 렌더링하며, 자체적으로 가져오지 않습니다. 동일한 컴포넌트 계약이 네트워크에 접근할 수 없는 Roku에서도 동작해야 하기 때문입니다. useWithdrawalConfig는 두 환경을 연결하는 유일한 줄입니다.

패치가 실패하더라도 버튼은 영어로 표시되지만, 소비자 앞에 찾기 쉬운 철회 기능을 배치하지 않는 것은 위반이지만, 잘못된 언어로 표시되는 것은 위반이 아닙니다. 훅은 error를 반환하므로 로그에 기록할 수는 있지만, 고객에게는 표시하지 마세요.

외관 — light, dark 또는 auto(기본값)로만 설정 가능합니다. 대화 상자는 자체 카드와 텍스트를 그리므로 어떤 페이지에서도 가독성이 보장됩니다. auto는 방문자의 브라우저 설정을 따르며, 기본 설정을 감지할 수 없는 경우 dark로 설정됩니다. 색상을 전달할 방법은 없습니다. 통계적 고지문의 경우 레이블링과 색상이 모든 테넌트의 모든 고객에게 동일하게 표시되어야 하기 때문입니다. UI의 다른 곳에 규칙을 적용하려면 resolveAppearance(appearance, scheme)가 내보내집니다(scheme'light' | 'dark' | null).

버튼은 눈에 띄는 레이블이 있는 버튼을 표시하고, 한 번 확인한 후 멱등성 있게 제출합니다(네트워크 재시도로 두 번 철회가 생성되지 않음). 승인 메시지를 표시합니다. 버튼 자체는 제출 외의 네트워크 작업은 수행하지 않으므로 config.enabledconfig.jurisdictions에 대한 게이트는 위와 같이 직접 처리해야 합니다. 하위 수준 컴포넌트(fetchWithdrawalConfig, useWithdrawal, submitWithdrawal)는 커스텀 UI용으로 내보내집니다.

빠른 참조

원하시는 작업 사용 방법
게시된 결제 화면 로드 usePaywallConfig(params){ config, loading, error }
렌더링 <Paywall config onSelectProduct … />
완전한 렌더링 제어 <PaywallRenderer config onSelectProduct />
EU 철회 (고객 언어) useWithdrawalConfig({…, locale})strings, locale, labelKey<WithdrawalButton>에 전달
권한 부여 / 검증 웹 & React Native 가이드

다음 단계