Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- Xcode
- Clean Code
- 리펙토링
- collectionview
- Human interface guide
- HIG
- 스위프트
- uiscrollview
- Refactoring
- swiftUI
- Protocol
- Observable
- SWIFT
- UITextView
- ios
- RxCocoa
- claude code
- rxswift
- clean architecture
- 클로드코드
- swift documentation
- UICollectionView
- tableView
- 리팩토링
- MVVM
- map
- uitableview
- 애니메이션
- 클린 코드
- combine
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 5. 애플페이 (Apply Pay) - PassKit을 사용하여 구현하기 (Green, Yellow, Orange 플로우) 본문
iOS 응용 (swift)
[iOS - swift] 5. 애플페이 (Apply Pay) - PassKit을 사용하여 구현하기 (Green, Yellow, Orange 플로우)
jake-kim 2026. 6. 29. 00:34Green, Yellow, Orange 플로우
| 흐름 (Flow) | 진입 경로 | 리스크 수준 | 인증 절차 | 최종 상태 |
| Green-Flow | 발급사 인앱 (In-App) | Low | 앱 로그인으로 대체 | 즉시 활성화 |
| Yellow-Flow | Apple 월렛 직접 입력 | Medium | 발급사 앱 인증 / SMS / ARS | 인증 후 활성화 |
| Orange-Flow | 의심 기기 / 분실 카드 | High | 없음 (거절 또는 강제 차단) | 등록 실패 |
애플페이 (Issuer App 입장)의 기능
발급사(Issuer) 앱 관점에서 애플페이 대응을 할 때 핵심이 되는 개념은 크게 In-App Provisioning과 Verification 두 가지로 나뉨.
1) In-App Provisioning (인앱 프로비저닝)
- 개념: 사용자가 우리 앱 내부에서 "애플 월렛에 추가" 버튼을 눌렀을 때, 안전하게 카드 정보를 암호화하여 Apple Wallet에 카드를 밀어 넣어주는(발급하는) 기능
- 특징:
- 앱 내부에서 PKAddPaymentPassViewController라는 Apple 표준 시트를 띄워 처리하므로 화면 이탈 없이 매끄러운 UX를 제공. (Green-Flow)
- 앱이 카드 번호(PAN) 원장을 가공되지 않은 상태로 다루지 않고, 기기가 생성한 일회성 토큰(Nonce)을 기반으로 발급사 백엔드와 TSP(Visa, Mastercard 등)를 거쳐 암호화된 페이로드 형태로 Apple 서버에 패스스루(Pass-through)하는 구조.
2) Verification (신원 확인 및 인증)
- 개념: 반대로 사용자가 애플 월렛 앱 안에서 직접 카드를 추가하려고 할 때, "이 사람이 진짜 실소유주가 맞는지 확인해라"라며 월렛이 발급사 앱을 깨워 본인 인증을 요구하는 기능. (Yellow-Flow)
- 특징:
- Step-up Authentication이라고도 부르며, 유니버설 링크(Universal Link)를 통해 월렛 앱에서 우리 앱으로 사용자를 전환시킴.
- 우리 앱이 켜지면 Face ID나 간편비밀번호 등으로 본인 확인을 수행한 뒤, 발급사 백엔드를 통해 TSP에 "인증 완료" 신호를 쏘고 다시 shoebox:// 스킴을 통해 사용자를 월렛으로 안전하게 돌려보내 줌.
PassKit을 사용하여 구현하기
Step 0. 권한 설정
- 1) PKPassLibrary: 애플월렛관련 데이터를 가져오기 위한 라이브러리이고 애플 개발자 페이지의 capability에서 Wallet 활성화해야함
- 2) 애플 in-app provisioining 권한
- PKAddPaymentPassViewController를 사용하려면 애플 개발자 페이지 -> Capability -> In-App Provisioning 권한이 필요
- Xcode에서도 entitlements 파일에 아래 설정도 필요
// {your_app}.entitlements
<dict>
<key>com.apple.developer.passkit.in-app-provisioning</key>
<true/>
</dict>
Step 1. 권한 확인 및 Configuration 설정
가장 먼저 현재 디바이스가 카드 등록을 지원하는지 체크하고, 카드 소유자 이름 및 뒤 4자리 정보를 담은 설정을 빌드
*주의) PKAddPaymentPassViewController를 사용하려면 애플 개발자 페이지 -> Capability -> In-App Provisioning 권한이 필요하고,
import PassKit
func startInAppProvisioning() {
// 1. 디바이스가 인앱 프로비저닝을 지원하는지 체크
guard PKAddPaymentPassViewController.canAddPaymentPass() else {
print("이 디바이스는 카드 추가를 지원하지 않거나 제한된 계정임")
return
}
// 2. 발급할 카드의 메타데이터 구성 (암호화 스킴은 보통 ECC_V2 또는 RSA_V2 사용)
guard let configuration = PKAddPaymentPassRequestConfiguration(encryptionScheme: .ECC_V2) else {
return
}
configuration.cardholderName = "홍길동"
configuration.primaryAccountSuffix = "1234" // 카드 뒷 4자리
configuration.localizedDescription = "내 발급사 대표 카드"
// 3. VC 생성 및 델리게이트 위임
guard let addPaymentPassVC = PKAddPaymentPassViewController(requestConfiguration: configuration, delegate: self) else {
print("컨트롤러 생성 실패 - Entitlement 권한 확인 필요")
return
}
// 4. Apple 표준 카드 등록 시트 모달 표시
self.present(addPaymentPassVC, animated: true, completion: nil)
}
Step 2. PKAddPaymentPassViewControllerDelegate 구현
시트가 뜨면 Apple 서버-발급사 서버 간 암호화 핸드셰이크가 일어남. 이 구간이 구현의 핵심
extension CardManagementViewController: PKAddPaymentPassViewControllerDelegate {
// Apple 이 인증서 체인과 Nonce 를 넘겨주며 암호화 데이터를 요청하는 메서드
func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController,
generateRequestWithCertificateChain certificates: [Data],
nonce: Data,
nonceSignature: Data,
completionHandler: @escaping (PKAddPaymentPassRequest) -> Void) {
// 1. 수신한 certificates, nonce, nonceSignature 를 우리 백엔드 API 로 전송
let requestModel = IssuerAmhohwaRequest(
certificates: certificates,
nonce: nonce,
nonceSignature: nonceSignature
)
// 2. 백엔드 통신 (백엔드는 TSP 와 연동하여 암호화된 데이터를 내려줌)
NetworkManager.shared.requestEncryptedPayload(requestModel) { result in
switch result {
case .success(let response):
// 3. 백엔드가 준 데이터를 암호화 요청 객체에 매핑
let addPassRequest = PKAddPaymentPassRequest()
addPassRequest.encryptedPassData = response.encryptedPassData
addPassRequest.activationData = response.activationData
addPassRequest.ephemeralPublicKey = response.ephemeralPublicKey
// 4. 완성된 request 를 completionHandler 에 담아 Apple SDK 에 반환
completionHandler(addPassRequest)
case .failure:
// 에러 발생 시 빈 객체를 던져 실패 처리
completionHandler(PKAddPaymentPassRequest())
}
}
}
// 프로세스가 완전히 끝났을 때 (성공 혹은 취소/실패) 호출되는 메서드
func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController,
didFinishWith pass: PKPaymentPass?,
error: Error?) {
// 우선 띄웠던 모달을 닫아줌
controller.dismiss(animated: true) {
if let error = error {
print("카드 등록 실패 혹은 유저 취소 발생: \(error.localizedDescription)")
return
}
if let successfullyAddedPass = pass {
print("카드 등록 최종 성공: \(successfullyAddedPass.primaryAccountNumberSuffix)")
// UI 상의 '애플 월렛에 추가' 버튼을 숨기거나 완료 상태로 전환하는 비즈니스 로직 수행
}
}
}
}
'iOS 응용 (swift)' 카테고리의 다른 글
| [iOS] 4. 애플페이 (Apply Pay) - 애플월렛과 앱에서 카드등록 개념 (3) | 2026.06.17 |
|---|---|
| [iOS - swift] 애플페이 목차 (1) | 2026.06.10 |
| [iOS] 3. 애플페이 (Apply Pay) - Xcode에 적용하기 (0) | 2026.06.10 |
| [iOS] 2. 애플페이 (Apply Pay) - 사전 설정 2단계 (앱 외적인 세팅) (1) | 2026.05.27 |
| [iOS] 1. 애플페이 (Apply Pay) - 처리해야하는 전체 플로우 (0) | 2026.05.20 |
Comments