1. 개요 및 Zero-DB 아키텍처
WalletGateway는 기업 고객이 자체 백엔드에서 복잡한 Apple PKCS#7 암호화 서명이나 Google Cloud REST API 규격을 직접 구현하지 않고도, 간단한 JSON API 호출 한 번으로 모바일 지갑 패스를 발급할 수 있게 지원하는 엔터프라이즈 게이트웨이 서비스입니다.
게이트웨이는 고객의 승객 정보, 멤버십 번호 등 개인식별정보(PII)를 영구 저장하지 않습니다. 메모리에서 서명된 바이너리(.pkpass) 스트림 생성 즉시 데이터는 완전히 소멸됩니다.
2. [1단계] Apple & Google 플랫폼 인증서 발급
패스 발급을 위해 플랫폼 개발자 계정에서 서명 키를 준비해야 합니다.
A. Apple Wallet (.p12 및 .p8)
- Apple Developer Portal에 접속하여 Pass Type ID를 생성합니다 (예:
pass.com.acme.wallet). - CSR 파일을 업로드하여 Pass Type ID Certificate를 발급받은 후 Keychain Access에서
.p12형태로 내보냅니다. - Keys 메뉴에서 Apple Push Notifications service (APNs) 키(
.p8)를 생성하고 Key ID와 Team ID를 기록합니다.
B. Google Wallet (service_account.json)
- Google Pay & Wallet Console에서 신규 비즈니스 계정을 만들고 Issuer ID를 확인합니다.
- GCP Console에서 서비스 계정을 생성하고 비공개 키 JSON(
service_account.json)을 다운로드합니다.
3. [2단계] 콘솔 인증서 & 템플릿 등록
준비된 키를 관리자 콘솔에 등록하고 발급할 패스 디자인을 생성합니다.
- 인증서 업로드: 인증서 관리 (Credentials) 메뉴에서
.p12파일과 비밀번호, Googleservice_account.json을 등록합니다. - 템플릿 디자인: 템플릿 설정 (Templates) 메뉴에서 배경색, 항공편/좌석 등의 동적 필드 키값, 바코드 규격을 지정하여 고유
templateId(예:tpl_boarding_v1)를 발급받습니다.
4. [3단계] Pass 발급 REST API & landingPageUrl
귀사의 백엔드 서버(Spring Boot, Node.js, Python 등)에서 게이트웨이 엔드포인트로 JSON 요청을 보냅니다.
응답으로 반환되는 landingPageUrl을 귀사의 카카오 알림톡 버튼 링크나 안내 문자(SMS) 본문에 포함하여 고객에게 전송하세요.
curl -X POST "https://api.walletgateway.io/api/v1/passes/issue" \
-H "X-Wallet-Client-Id: your_client_id" \
-H "X-Wallet-Secret-Key: your_secret_key" \
-H "X-Wallet-Env: PROD" \
-H "Content-Type: application/json" \
-d '{
"templateCode": "TMPL-C5AE0425",
"serialNumber": "ORDER-202611-0001",
"userInfo": {
"name": "홍길동",
"phoneNumber": "010-1234-5678",
"email": "user@example.com"
},
"barcode": {
"format": "PKBarcodeFormatCode128",
"message": "1234-5678-9012",
"altText": "1234 5678 9012"
},
"associatedApp": {
"appStoreId": 382431792,
"appLaunchUrl": "koreanair://main"
},
"locations": [
{
"latitude": 37.4602,
"longitude": 126.4407,
"relevantText": {
"ko": "인천공항 제2터미널 근처입니다. 모바일 탑승권을 준비하세요.",
"en": "Near Terminal 2. Please show your boarding pass."
}
}
],
"fields": {
"passengerName": "HONG GILDONG",
"flight": "KE001",
"gate": "24A",
"seat": "12K"
}
}'
{
"success": true,
"code": "SUCCESS",
"data": {
"serialNumber": "ORDER-202611-0001",
"landingPageUrl": "https://wallet.ntssoft.com/p/8f9a2b1c4d...", /* <- 문자/알림톡 버튼 링크 */
"downloadPassUrl": "https://wallet.ntssoft.com/p/8f9a2b1c4d.../download.pkpass",
"googleSaveUrl": "https://pay.google.com/gp/v/save/...",
"billingStatus": "BILLED",
"issuedAt": "2026-11-10T11:00:00"
}
}
5. [4단계] 실시간 푸시 갱신 및 패스 폐기(Revoke)
탑승구가 변경되거나 포인트 잔액이 갱신되었을 때, 혹은 이용권이 환불/취소되었을 때 고객의 스마트폰 지갑을 즉각 제어합니다.
1) 패스 폐기 처리 (Revoke API)
* 호출 즉시 패스 상태가 REVOKED로 바뀌고, 연결된 모든 아이폰으로 APNs 푸시가 전송되어 지갑 화면에서 무효화 처리됩니다.
2) 수동 실시간 APNs 푸시 전송 (Push API)
3) POS 스캔용 고화질 1D/2D 바코드 렌더링 (Barcode API)
* format 옵션: CODE_128 (선형 바코드), QR_CODE (2D), PDF_417 (항공 탑승권)
6. 주요 HTTP 상태 코드 및 트러블슈팅
| HTTP Code | Error Code | 원인 및 조치 방법 |
|---|---|---|
| 200 OK | SUCCESS | 서명 완료 및 바이너리 스트림 정상 반환 |
| 400 Bad Request | FIELD_VALIDATION_ERROR | 템플릿에서 필수 지정된 동적 필드가 JSON에 누락됨 |
| 401 Unauthorized | INVALID_API_KEY | X-API-Key 헤더가 비어있거나 화이트리스트 IP와 불일치 |
| 404 Not Found | TEMPLATE_NOT_FOUND | 콘솔에 등록되지 않은 templateId 전달 |