samsung-wallet-cdata
v1.0.0
Published
Samsung Wallet CDATA (JWT) generator for Node.js - Generate encrypted card data for Samsung Wallet API
Maintainers
Readme
samsung-wallet-cdata
🇰🇷 한국어 | 🇺🇸 English
⚠️ Unofficial - 이 패키지는 Samsung의 공식 라이브러리가 아닙니다.
Samsung Wallet API 연동을 위한 커뮤니티 오픈소스 라이브러리입니다.
Samsung Wallet CDATA(JWT) 생성 라이브러리 for Node.js
Samsung Wallet API 연동을 위한 CDATA를 쉽게 생성할 수 있습니다.
왜 이 패키지가 필요한가?
Samsung은 공식적으로 Java 샘플 코드만 제공합니다:
Node.js 개발자를 위한 공식 라이브러리가 없어서 이 패키지를 만들었습니다.
Samsung 공식 Java 코드 cdata_generation_sample_code_v1.1.2를 Node.js로 포팅했습니다.
설치
npm install samsung-wallet-cdata빠른 시작
const { SamsungWallet } = require('samsung-wallet-cdata');
const fs = require('fs');
// 1. 인스턴스 생성 (설정 한번만)
const wallet = new SamsungWallet({
partnerId: 'YOUR_PARTNER_ID',
certificateId: 'YOUR_CERT_ID',
samsungCert: fs.readFileSync('samsung.crt', 'utf-8'),
partnerKey: fs.readFileSync('partner.key', 'utf-8'),
});
// 2. 티켓 CDATA 생성 (한 줄!)
const cdata = await wallet.createTicket({
title: '콘서트 입장권',
holderName: '홍길동',
startDate: new Date('2026-03-15T19:00:00'),
location: '올림픽 체조경기장',
barcode: 'TICKET-12345',
});
console.log('CDATA:', cdata);카드 타입별 사용법
🎫 티켓 (Event Ticket)
콘서트, 전시회, 스포츠 경기 등의 입장권
const cdata = await wallet.createTicket({
// 필수
title: '뮤지컬 캣츠',
// 선택 (추천)
holderName: '홍길동',
startDate: new Date('2026-03-15T19:00:00'),
endDate: new Date('2026-03-15T22:00:00'),
location: '블루스퀘어 신한카드홀',
barcode: 'TICKET-12345-ABCD',
// 브랜딩
providerName: 'TicketLink',
logoImage: 'https://example.com/logo.png',
mainImage: 'https://example.com/main.png',
bgColor: '#1428A0',
// 좌석 정보
seatClass: 'VIP석',
seatNumber: 'A열 15번',
});💳 멤버십 (Membership Card)
회원권, 포인트 카드, 멤버십 카드
const cdata = await wallet.createMembership({
title: 'VIP 멤버십',
memberName: '홍길동',
memberId: 'M-2026-12345',
tier: 'Gold',
points: 15000,
expiryDate: new Date('2027-12-31'),
providerName: 'My Store',
bgColor: '#FFD700',
barcode: 'MEMBER-12345',
});🎁 쿠폰 (Coupon)
할인 쿠폰, 기프트 카드
const cdata = await wallet.createCoupon({
title: '20% 할인 쿠폰',
description: '전 품목 적용 가능',
discount: '20% OFF',
expiryDate: new Date('2026-12-31'),
providerName: 'My Store',
bgColor: '#FF6B35',
barcode: 'COUPON-2026-SAVE20',
terms: [
'다른 쿠폰과 중복 사용 불가',
'최소 주문금액 30,000원 이상',
],
});✈️ 보딩패스 (Boarding Pass)
항공권, 버스/기차 티켓
const cdata = await wallet.createBoardingPass({
title: 'KE123',
user: 'HONG/GILDONG',
vehicleNumber: 'KE123',
departCode: 'ICN',
arriveCode: 'NRT',
departName: '인천국제공항',
arriveName: '나리타국제공항',
estimatedOrActualStartDate: new Date('2026-03-15T10:30:00'),
departGate: 'A12',
seatNumber: '23A',
seatClass: 'Economy',
providerName: 'Korean Air',
barcodeValue: 'BCBP-DATA-HERE',
});🎴 기프트 카드 (Gift Card)
상품권, 기프트 카드, 스토어 크레딧
const cdata = await wallet.createGiftCard({
title: '커피숍 기프트카드',
providerName: '스타벅스',
cardNumber: 'GC-2026-12345',
pin: '1234',
balance: '50000',
balanceCurrency: 'KRW',
expiryDate: new Date('2027-12-31'),
user: '홍길동',
senderName: '김철수',
message: '생일 축하해요!',
'barcode.value': 'GC-2026-12345',
});🪪 디지털 ID (Digital ID)
사원증, 학생증, 출입증
const cdata = await wallet.createDigitalId({
title: '사원증',
providerName: '삼성전자',
subType: 'employee',
user: '홍길동',
idNumber: 'EMP-2026-12345',
department: '개발팀',
position: '시니어 개발자',
issueDate: new Date('2026-01-01'),
expiryDate: new Date('2027-12-31'),
'barcode.value': 'EMP-2026-12345',
});🚇 선불 교통카드 (Pay As You Go)
교통카드, 선불 통신요금, 유틸리티 페이먼트
const cdata = await wallet.createPayAsYouGo({
title: '지하철 교통카드',
providerName: '서울교통공사',
subType: 'transit',
accountId: 'METRO-2026-12345',
balance: '25500',
balanceCurrency: 'KRW',
user: '홍길동',
'barcode.value': 'METRO-2026-12345',
});📋 일반 카드 (Generic Card)
위 타입에 해당하지 않는 범용 카드
const cdata = await wallet.createGeneric({
title: '주차권',
providerName: '시티파킹',
subtitle: '월간 주차 허가증',
user: '홍길동',
cardNumber: 'PARK-2026-12345',
header1: 'A구역',
body1: 'A구역 종일 주차 가능',
issueDate: new Date('2026-01-01'),
expiryDate: new Date('2026-12-31'),
'barcode.value': 'PARK-2026-12345',
});커스텀 카드 데이터
템플릿을 사용하지 않고 직접 카드 데이터를 구성할 수도 있습니다:
const cardData = {
card: {
type: 'ticket',
subType: 'entrances',
data: [{
refId: 'my-unique-ref-id',
createdAt: Date.now(),
updatedAt: Date.now(),
language: 'en',
attributes: {
title: 'My Custom Ticket',
// ... 기타 속성
},
}],
},
};
const cdata = await wallet.generateCdata(cardData);Add to Samsung Wallet URL 생성
Data Transmit Link (기본 방식)
CDATA에 전체 카드 데이터를 포함하는 방식입니다.
const cdata = await wallet.createTicket({ ... });
// Samsung Wallet 추가 버튼 URL 생성
// 형식: https://a.swallet.link/atw/v3/{cardId}#Clip?cdata={cdata}
const addUrl = wallet.getAddToWalletUrl(cdata, 'YOUR_CARD_ID', {
rdClickUrl: 'https://your-tracking.com/click',
});
console.log('Add to Wallet URL:', addUrl);Data Fetch Link (pdata 방식)
민감한 데이터가 있거나 정적 링크가 필요할 때 사용합니다. 이 방식은 refId만 전달하고, Samsung 서버가 파트너 서버에 Get Card Data API를 호출하여 데이터를 가져옵니다.
// Data Fetch Link URL 생성
// 형식: https://a.swallet.link/atw/v3/{certificateId}/{cardId}#Clip?pdata={refId}
const fetchUrl = wallet.getDataFetchUrl('TICKET-12345', 'YOUR_CARD_ID');
console.log('Data Fetch URL:', fetchUrl);⚠️ 주의: Data Fetch Link 사용 시 파트너 서버에서 Get Card Data API를 구현해야 합니다.
Samsung Server API (카드 상태 관리)
Samsung Wallet에 등록된 카드의 상태를 관리할 수 있습니다.
Update Notification
카드 정보가 변경되었을 때 Samsung에 알림을 보냅니다.
// Send Card State에서 받은 callbackUrl 사용
const callbackUrl = 'https://kr.swallet.link/wltex/cards/YOUR_CARD_ID';
const result = await wallet.sendUpdateNotification(
callbackUrl,
'ticket', // 카드 타입
[{ refId: 'TICKET-12345' }]
);
console.log('Update 결과:', result.ok);Cancel Notification
공연/이벤트 취소 시 Samsung Wallet 카드도 만료 처리합니다.
const result = await wallet.sendCancelNotification(
callbackUrl,
'ticket',
[{
refId: 'TICKET-12345',
eventId: 'EVENT-001',
estimatedOrActualStartDate: Date.now(),
}]
);
console.log('Cancel 결과:', result.ok);Authorization Token 생성
Samsung Server API 호출 시 필요한 인증 토큰을 생성합니다.
const authToken = await wallet.generateAuthToken();
console.log('Auth Token:', authToken);상수 사용
패키지에서 제공하는 상수를 사용하면 타입 안정성을 높일 수 있습니다:
const {
SamsungWallet,
CardType,
CardState,
BarcodeType,
TicketSubType
} = require('samsung-wallet-cdata');
// 카드 타입 확인
console.log(CardType.TICKET); // 'ticket'
console.log(CardType.COUPON); // 'coupon'
// 카드 상태
console.log(CardState.CANCELED); // 'CANCELED'
// 바코드 타입
console.log(BarcodeType.QRCODE); // 'QRCODE'
// 티켓 서브타입
console.log(TicketSubType.CONCERTS); // 'concerts'사용 가능한 상수
| 상수 | 설명 |
|------|------|
| CardType | 카드 타입 (TICKET, COUPON, LOYALTY, BOARDING_PASS, GIFT_CARD, DIGITAL_ID, PAY_AS_YOU_GO, GENERIC) |
| CardState | 카드 상태 (ACTIVE, EXPIRED, CANCELED, DELETED, REDEEMED, SUSPENDED) |
| BarcodeType | 바코드 타입 (QRCODE, BARCODE, SERIAL) |
| BarcodeFormat | 바코드 형식 (QRCODE_SERIAL, QRCODE_URL, BARCODE_SERIAL) |
| BarcodeSubFormat | 바코드 세부 형식 (QR_CODE, CODE_128, CODE_39, EAN_13 등) |
| TicketSubType | 티켓 서브타입 (ENTRANCES, CONCERTS, SPORTS, MOVIES, TRANSIT, OTHERS) |
| BoardingPassSubType | 보딩패스 서브타입 (AIRLINES, TRAINS, BUSES, OTHERS) |
| DigitalIdSubType | 디지털ID 서브타입 (EMPLOYEE, STUDENT, ACCESS, OTHERS) |
| PayAsYouGoSubType | 선불카드 서브타입 (TRANSIT, TELECOM, UTILITY, OTHERS) |
저수준 API (고급 사용자)
직접 암호화/서명 로직을 사용할 수 있습니다:
const {
generateCdata,
readCertificate,
readPrivateKey
} = require('samsung-wallet-cdata');
// 키 로드
const samsungPublicKey = await readCertificate(samsungCertPem);
const partnerPrivateKey = await readPrivateKey(partnerKeyPem);
// CDATA 생성
const cdata = await generateCdata(
partnerId,
certificateId,
samsungPublicKey,
partnerPrivateKey,
JSON.stringify(cardData)
);설정
🔑 인증서 발급 방법
Samsung Wallet API를 사용하려면 파트너 등록 후 인증서를 발급받아야 합니다.
Step 1: 파트너 등록
- Samsung Wallet Partner Portal 접속
- "Sign Up" 클릭하여 계정 생성
- 파트너 신청서 작성
- 승인 대기 (보통 1-3 영업일)
Step 2: Wallet Card 생성
- Partner Portal 로그인
- "Wallet Cards" → "Create Card" 메뉴로 이동
- 카드 타입 선택 (Ticket, Membership, Coupon 등)
- 카드 디자인 및 필드 설정
- 저장 후 Card ID 메모
Step 3: 인증서 생성
- Partner Portal에서 "Certificates" 메뉴로 이동
- CSR (Certificate Signing Request) 생성:
# 개인키 생성 openssl genrsa -out partner.key 2048 # CSR 생성 openssl req -new -key partner.key -out partner.csr partner.csr을 Partner Portal에 업로드- 서명된 인증서와 Samsung 공개 인증서 다운로드
Step 4: 발급받은 정보 정리
승인 후 다음 정보들을 확보하게 됩니다:
| 항목 | 확인 위치 | 파일/값 |
|------|----------|---------|
| Partner ID | Partner Portal → Profile | 1234567890 |
| Certificate ID | Partner Portal → Certificates | cert-xxxxx |
| Card ID | Partner Portal → Wallet Cards | card-xxxxx |
| Samsung 인증서 | Partner Portal → 다운로드 | samsung.crt |
| 파트너 개인키 | 로컬 (Step 3에서 생성) | partner.key |
파일 구조 예시
your-project/
├── certs/
│ ├── samsung.crt # Samsung 공개 인증서
│ └── partner.key # 파트너 개인키 (비밀 유지!)
├── .env
└── ...⚠️ 보안 주의:
partner.key는 절대 버전 관리(Git)에 커밋하지 마세요!
환경 변수 예시
SAMSUNG_WALLET_PARTNER_ID=your-partner-id
SAMSUNG_WALLET_CERTIFICATE_ID=your-cert-id
SAMSUNG_WALLET_CARD_ID=your-card-idTypeScript 지원
TypeScript 타입 정의가 포함되어 있습니다:
import { SamsungWallet, TicketOptions } from 'samsung-wallet-cdata';
const wallet = new SamsungWallet({
partnerId: 'xxx',
certificateId: 'xxx',
samsungCert: '...',
partnerKey: '...',
});
const options: TicketOptions = {
title: 'Concert',
barcode: '12345',
};
const cdata = await wallet.createTicket(options);API 참조
SamsungWallet
| 메서드 | 설명 | 공식 스펙 |
|--------|------|----------|
| constructor(config) | 인스턴스 생성 | - |
| generateCdata(cardData) | 범용 CDATA 생성 | - |
| createTicket(options) | 티켓 CDATA 생성 | Event Ticket |
| createMembership(options) | 멤버십 CDATA 생성 | Loyalty |
| createCoupon(options) | 쿠폰 CDATA 생성 | Coupon |
| createBoardingPass(options) | 보딩패스 CDATA 생성 | Boarding Pass |
| createGiftCard(options) | 기프트카드 CDATA 생성 | Gift Card |
| createDigitalId(options) | 디지털ID CDATA 생성 | Digital IDs |
| createPayAsYouGo(options) | 선불카드 CDATA 생성 | Pay As You Go |
| createGeneric(options) | 일반카드 CDATA 생성 | Generic Card |
| getAddToWalletUrl(cdata, cardId, options) | Data Transmit Link URL 생성 | API Guidelines |
| getDataFetchUrl(refId, cardId, options) | Data Fetch Link URL 생성 | API Guidelines |
| generateAuthToken() | Samsung Server API 인증 토큰 생성 | Security |
| sendUpdateNotification(callbackUrl, cardType, cardDataList) | 카드 업데이트 알림 | API Guidelines |
| sendCancelNotification(callbackUrl, cardType, cancelDataList) | 카드 취소 알림 | API Guidelines |
암호화 스펙
Samsung Wallet API 스펙에 따라:
- JWE: RSA1_5 + A128GCM
- JWS: RS256
라이선스
MIT
