본문으로 건너뛰기

React SDK

React 18/19용 공식 바인딩입니다. Provider + hooks 기반으로 SDK 로드부터 popup checkout, embedded widget까지 선언적으로 다룰 수 있습니다.

호환성

항목지원 버전
React18.x · 19.x (peer dependency)
TypeScript5.0+
Module formatsESM · CJS

설치

pnpm add @nexus-cross/cross-pay-react

사전 준비

모든 예시의 checkoutId / idempotencyKey가맹점 백엔드POST /v1/payments를 호출해 발급받은 뒤 클라이언트로 전달한 값입니다. React 앱은 MERCHANT_API_KEY를 절대 보관하지 않습니다.

복사해서 시작하기

import { CrossPayProvider, CrossPaySDKError, usePayment } from '@nexus-cross/cross-pay-react';

export default function App() {
return (
<CrossPayProvider theme="light" locale="ko">
<CheckoutButton />
</CrossPayProvider>
);
}

function CheckoutButton() {
const { requestPayment, isLoading } = usePayment();

async function handlePay() {
try {
const result = await requestPayment({
checkoutId: 'cs_발급받은_checkout_id',
idempotencyKey: 'ik_발급받은_idempotency_key',
embeddedWallet: true,
});

console.log(result.paymentId, result.status);
} catch (error) {
if (error instanceof CrossPaySDKError && error.code === 'USER_REJECTED') {
return;
}
throw error;
}
}

return (
<button type="button" onClick={handlePay} disabled={isLoading}>
{isLoading ? 'SDK 로드 중...' : '결제'}
</button>
);
}

Provider

CrossPayProvider는 SDK loader 옵션과 기본 UI 옵션을 받습니다.

<CrossPayProvider
src="https://js.crosspay.ai/pay-js/latest/cross-pay.js"
integrity="sha384-abc123..."
theme="auto"
locale="ko"
onError={(error) => console.error(error)}
>
<Checkout />
</CrossPayProvider>
prop설명
src로드할 cross-pay.js URL 오버라이드
integrity고정 스크립트 URL 배포에서 SRI 검증 적용
themeProvider 기본 theme. hook 호출에서 생략하면 주입됨
localeProvider 기본 locale. hook 호출에서 생략하면 주입됨
onErrorSDK 로드 실패를 callback으로 처리. 지정하면 Provider가 에러를 re-throw하지 않음

onError를 생략하면 로드 실패 시 다음 렌더에서 Error를 throw합니다. 이 모드에서는 React Error Boundary로 감싸세요.

function Checkout() {
const { requestPayment, isLoading } = usePayment();

async function handlePay() {
const result = await requestPayment({
checkoutId: 'cs_abc123',
idempotencyKey: 'ik_xyz',
successUrl: 'https://shop.example.com/pay/success',
failUrl: 'https://shop.example.com/pay/fail',
embeddedWallet: false,
});

console.log(result.paymentId, result.status);
}

return <button onClick={handlePay} disabled={isLoading}>결제</button>;
}

embeddedWallet은 Provider prop이 아니라 checkout 호출별 옵션입니다. 기본값은 true입니다.

Widget 모드

import { usePaymentWidget, CheckoutStatus } from '@nexus-cross/cross-pay-react';
import { useEffect, useState } from 'react';

function WidgetCheckout({ checkoutId }: { checkoutId: string }) {
const [embeddedWallet, setEmbeddedWallet] = useState(true);
const { widgets, status, paymentMethodWidget, renderPaymentMethods } = usePaymentWidget();

useEffect(() => {
if (!checkoutId) return;
renderPaymentMethods('#payment-methods', {
checkoutId,
idempotencyKey: 'ik_xyz',
embeddedWallet,
});
}, [checkoutId, embeddedWallet, renderPaymentMethods]);

useEffect(() => {
paymentMethodWidget?.update({ embeddedWallet });
}, [embeddedWallet, paymentMethodWidget]);

async function handlePay() {
const result = await widgets?.submit({ idempotencyKey: 'ik_xyz' });
console.log(result);
}

return (
<>
<label>
<input
type="checkbox"
checked={embeddedWallet}
onChange={(event) => setEmbeddedWallet(event.currentTarget.checked)}
/>
Embedded wallet 표시
</label>
<div id="payment-methods" />
<button onClick={handlePay} disabled={status !== CheckoutStatus.READY}>
결제하기
</button>
</>
);
}

usePaymentWidget은 widget instance 재생성 시 마지막 render 파라미터를 replay합니다. terminal 상태 이후 새 결제를 시작할 때는 반드시 새 checkoutId/idempotencyKey로 다시 렌더링하세요.

에러 표시

import { CrossPayProvider, useCrossPayError } from '@nexus-cross/cross-pay-react';

function App() {
return (
<CrossPayProvider onError={(error) => console.error(error)}>
<Checkout />
</CrossPayProvider>
);
}

function Checkout() {
const error = useCrossPayError();
if (error) return <div>SDK 로드 실패: {error.message}</div>;
return <button type="button">결제</button>;
}

Hooks 레퍼런스

Hook반환 타입설명
useCrossPay()CrossPayInstance | null저수준 인스턴스 직접 접근
useCrossPayLoading()boolean스크립트 로드 중 여부
useCrossPayError()Error | nullSDK 로드 실패 에러 (onError 모드에서 사용)
usePayment(){ requestPayment, isLoading }Popup 결제 편의 hook
usePaymentWidget(options?){ widgets, status, paymentMethodWidget, renderPaymentMethods }Widget 생명주기 관리

재노출 API

@nexus-cross/cross-pay-react는 React 연동에 필요한 SDK API와 주요 shared contract를 함께 재노출합니다.

  • 값: loadCrossPay, clearCrossPay, CrossPaySDKError, ERROR_CODES
  • Hooks/Provider: CrossPayProvider, useCrossPay, useCrossPayError, useCrossPayLoading, usePayment, usePaymentWidget
  • 주요 타입: Amount, CheckoutParams, CheckoutPaymentResult, CrossPayAppearance, CrossPayError, CrossPayInstance, CrossPayLocale, CrossPayTheme, ErrorCode, ErrorType, RenderPaymentMethodsParams, WidgetHandle, WidgetsInstance, WidgetsOptions
  • enums/상수: CheckoutStatus, Currency, PaymentType, ProductCategory, UpdateReason