시나리오 : 컨퍼런스 참가증을 애플월렛으로 받아서 유니크하고 Apple-like한 느낌을 받았다는 소식을 듣고 해보기로 결심했다.
참고로 Apple 월렛 패스는 지갑 앱을 통해 다양한 카드, 포인트, 쿠폰, 탑승권, 티켓 등을 한 곳에 저장하고 사용하는 기능이다.
준비물 : 인증서가 필요해서 Apple Membership가입이 필수요소이다.
이번 포스팅은 로컬에서 패스를 생성하는 포스팅입니다. 서버 API로 패스를 생성하려고 한다면 아래의 포스팅을 참고 부탁드립니다.
2024.08.12 - [iOS 캐기/토이 프로젝트] - [애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기- 개발환경 세팅
2024.08.12 - [iOS 캐기/토이 프로젝트] - [애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기- 구조 작성
2024.08.12 - [iOS 캐기/토이 프로젝트] - [애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기-기능구현
2024.08.13 - [iOS 캐기/토이 프로젝트] - [애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기- 인증서 관련 작업 정리
폴더를 하나 생성하고 pass.json 파일을 생성하고 필요한 내용을 넣어주고 이미지도 필요하면 넣어주고 해당 폴더를 zip 파일로 압축하고 확장자를 .pkpass 로 변경하고 실행하면 된다.(feat. 인증서관련 작업은 zip파일 압축할 때 필요하다.)
한줄요약으로 보면 간단해 보이지만 생각보다 손이가는 부분도 있기에 차근차근 진행해보자.
패스 생성하기
패스를 생성하기 위해서는 아래와 같은 디렉토리 구조로 소스파일과 이미지를 추가하여 정의할 수 있다.
- 아이콘 / 로고와 같은 이미지 파일
- 패스에 표시하는 문자열과 패스를 정의하는 메타데이터가 포함된 pass.json
- 로컬라이제이션도 추가할 수 있다.
지원하는 패스스타일은 5종류이다.
이처럼 패스스타일에 따라서 전면에 표현할 수 있는 필드의 수가 결정된다.
* 텍스트가 너무 많으면 일부 필드는 표시되지 않을 수도 있다고 한다 *
구성요소들을 알아보자.
{
"formatVersion" : 1,
"passTypeIdentifier" : "pass.com.yourdomain.atlasevent",
"serialNumber" : "001",
"teamIdentifier" : "<YOUR TEAM IDENTIFIER>",
"organizationName" : "Atlas Labs",
"description" : "test event coupon"
}
json에 필수로 들어가야하는 키,밸류 이다.
키 | 타입 | 설명 |
formatVersion | 정수 | 파일형식버전, 문자열을 제공하면 파일이 검증되지 않는다. |
passTypeIdentifier | 문자열 | 패스의 식별자, iOS의 번들아이디와 유사하다 |
serialNumber | 문자열 | 패스의 일련번호 , 문자와 숫자조합으로도 자유롭게 생성가능 |
teamIdentifier | 문자열 | Apple 멤버쉽 가입하게되면 할당받는 고유한 10자리 식별자 |
organizationName | 문자열 | 발행한 엔티디의 이름 |
description | 문자열 | 패스에 대한 간단한 설명 |
{
....
"logoText" : "아틀라스 1일 이용권" ,
"foregroundColor" : "rgb(255, 255, 255)" ,
"BackgroundColor" : "rgb(100, 100, 100)" ,
"labelColor" : "rgb(20, 20 , 20)"
}
키 | 타입 | 설명 |
logoText | 문자열 | 로고 이미지 옆에 패스 헤더에 표시되는 텍스트 |
foregroundColor | 문자열 | 텍스트색 |
backgroundColor | 문자열 | 패스의 배경색 |
labelColor | 문자열 | 레이블색 |
{
....
"barcode" : {
"message" : "바코드 메시지" ,
"format" : "PKBarcodeFormatPDF417" ,
"messageEncoding" : "iso-8859-1"
}
}
키 | 타입 | 설명 |
message | 문자열 | 바코드에 포함하려는 데이터 , 고유코드 또는 전달자의 클라이언드 ID등이 될 수 도 있다. |
format | 문자열 | 바코드 형식 이름 (PKBarcodeFormatQR, PKBarcodeFormatPDF417, PKBarcodeFormatAztec 중 택 1) |
messageEncoding | 문자열 | 메시지를 디코등하는데 사용되는 텍스트 인코딩의 이름 latin1이 아닌 언어를 사용하는 경우 UTF8 또는 자신에게 적합한 다른 텍스트 인코딩을 사용하는 것이 좋다.(영어,숫자를 사용하는경우 기본값은 ios-8859-1) |
"coupon" : { // 패스종류 5가지 제공 coupon/storeCard/boardingPass/generic/eventTicket
"primaryFields" : [
{
"key" : "필드 이름",
"label" : "레이블",
"value" : "표현되는 값"
}
]
}
키 | 타입 | 설명 |
key | 문자열 | 필드 이름 |
label | 문자열 | 필드에 수반되는 레이블 |
value | 문자열 | 필드에 표현되는 텍스트 |
더 많은 필드들을 확인하기 위해서는 레퍼런스를 확인하는 것을 권장합니다!
https://developer.apple.com/library/archive/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/TopLevel.html
{
"formatVersion" : 1,
"passTypeIdentifier" : "pass.atlas.event",
"serialNumber" : "XD",
"teamIdentifier" : "팀아이디",
"barcodes" : [
{
"message" : "https://www.udemy.com/user/imdongju-2/",
"format" : "PKBarcodeFormatQR",
"messageEncoding" : "iso-8859-1"
}
],
"organizationName" : "Atlas labs",
"description" : "Atlas labs",
"foregroundColor" : "rgb(255, 255, 255)",
"backgroundColor" : "rgb(55, 117, 50)",
"labelColor" : "rgb(190, 57, 57)",
"eventTicket" : {
"primaryFields" : [
{
"key" : "event",
"label" : "EVENT",
"value" : "아틀라스와 함께 떠나요~"
}
],
"secondaryFields" : [
{
"key" : "timestamp",
"label" : "DATE",
"value" : "RIGHT NOW!"
}
]
}
}
{
"formatVersion" : 1,
"passTypeIdentifier" : "pass.atlas.event",
"serialNumber" : "XD",
"teamIdentifier" : "팀아이디",
"barcodes" : [
{
"message" : "https://www.udemy.com/user/imdongju-2/",
"format" : "PKBarcodeFormatQR",
"messageEncoding" : "iso-8859-1"
}
],
"organizationName" : "Atlas labs",
"description" : "Atlas labs",
"foregroundColor" : "rgb(255, 255, 255)",
"backgroundColor" : "rgb(55, 117, 50)",
"labelColor" : "rgb(190, 57, 57)",
"eventTicket" : {
"primaryFields" : [
{
"key" : "event",
"label" : "EVENT",
"value" : "아틀라스와 함께 떠나요~"
}
],
"secondaryFields" : [
{
"key" : "timestamp",
"label" : "DATE",
"value" : "RIGHT NOW!"
}
],
"backFields" : [
{
"key" : "back-name",
"label" : "NAME",
"value" : "임동주 a.k.a Atlas"
},
{
"key" : "back-role",
"label" : "OCCUPATION",
"value" : "iOS Developer & Instructor"
},
{
"key" : "back-email",
"label" : "EMAIL",
"attributedValue" : "<a href='mailto:atlas9539@gmail.com'>atlas9539@gmail.com</a>"
},
{
"key" : "back-blog",
"label" : "BLOG",
"attributedValue" : "<a href='https://artieee.tistory.com/6'>감자밭 개발자</a>"
},
{
"key" : "back-website",
"label" : "UDEMY",
"attributedValue" : "<a href='https://www.udemy.com/user/imdongju-2/'>@Atlas</a>"
},
{
"key" : "back-instagram",
"label" : "INSTAGRAM",
"attributedValue" : "<a href='https://www.instagram.com/reel/Cq7j5ycrG9e/?igshid=MzRlODBiNWFlZA%3D%3D'>@dev._.artiee</a>"
},
{
"key" : "back-github",
"label" : "GITHUB",
"attributedValue" : "<a href='https://github.com/PotatoArtie'>@아틀라스</a>"
}
]
}
}
패스를 사용하기 위해서는 인증서가 필요하다.
개발자 포털 사이트에서 PassTypeIDs를 선택하고 인증서를 만들어 보자
여기까지왔다면 Certificate Signing Request 파일이 필요할 것이다.
이것도 차근차근 생성해보자.
Choose File을 하여 생성한 Certificate Signing Reques 파일을 추가해 주자.
다운로드 버튼을 클릭하면 pass.cer 파일을 받을 수 있다. 다운받은 .cer 인증서를 두 번 클릭하여 Keychain Access에 설치
패스 매니페스트는 생성해야 하는 또 다른 JSON 파일로 패스 번들에 포함된 모든 파일과 해당 SHA1 체크섬을 뜻한다.
이런 과정은 각설하고 일단 돌아가는걸 보고싶어하는 분들을 위해서 TimOliver/PassKit-Business-Card 에서 편의성있게 만들어 놓으셨다. (Thanks to TimOliver)
필자의 깃헙에도 업데이트되어 있으니 가서 다운로드해보자.
https://github.com/PotatoArtie/Potato-iOS/tree/master/Labs/Playground/WalletEventPass
실행방법
1. pass.json 의 teamID를 입력해준다.
2. Pass-Event-Card-Demo 폴더에서
./signpass -p ExampleCard
실행시키면 ExampleCard 파일이 생성된다. 이 파일을 실행시키면 된다.
실제 어떤 프로세스가 필요한 것이고 진행되고 있는지 차근차근 알아보자. (From Kodeco)
1. 각 파일에 대한 SHA1 체크섬을 직접 생성해보자.
cd ~/desktop/작업중인폴더
openssl sha1 pass.json
결과
SHA1(pass.json)= c24766ef5aa92197eace640fcc4fb584a505a733
manifest.json 파일을 생성하고 키,값을 넣어주자.
manifest.json
{
"pass.json" : "c24766ef5aa92197eace640fcc4fb584a505a733"
...
}
이미지도 동일하게 작업해준다.
manifest.json
{
"strip.png" : "25b4c9ff2bafe056f3e28379db0ef3fb460c718b" ,
"strip@2x.png" : "dee775ed6fb3c7278b84c65853401e760caabc92" ,
"icon.png" : "8eaa0896db93f2165 fa417df3d002ce9c61fcd92" ,
"icon@2x.png" : "555ce7f70f2f44fb7ac9d9f46df5738ec6250f37" ,
"logo.png" : "e8c4edfbcae41d9d88fad7137d8ed30ae5f73e67" ,
"logo@2x.png" : "1f9b1cc4c75b380ade07e9f2b7f37f988d9d14c3" ,
"pass.json" : "<여기에 패스 SHA1을 입력하세요>"
}
그리고 패스를 만들기 위해서 필수로 필요한 서명작업임으로 시작해보자.
우리가 받은 passId 인증서를 키체인에서 찾아 내보내기를 통해 Certificates.p12로 저장한다.
Certificates.p12 파일에는 패스인증서와 개인키가 모두 포함되어 있기 때문에 OpenSSL에는 이러한 항목이 별도의 파일에 필요하므로 .12파일에서 추출해야한다.
//폴더의 파일 목록이 표시되어야하며 여기에는 인증서 파일이 포함되어 있어야합니다.
//동일한 폴더 내에 "passcertificate.pem" 으로 저장된다.
openssl pkcs12 -in Certificates.p12 -clcerts -nokeys -out passcertificate.pem -passin pass:
//키를 별도의 파일로 내보내는 명령어
//키파일을 내보내려면 비밀번호를 제공해야한다.12345는 테스트를 위한 간단하게 설정한것이기 때문에
//프로덕션환경에서는 강력한 비밀번호를 사용하는게 좋다.
openssl pkcs12 -in Certificates.p12 -nocerts -out passkey.pem -passin pass: -passout pass:12345
패스번들에 서명하기위해서는 자체 인증서 발급자인 Apple을 인증하는 WWDR 중간인증서라는 인증서가 하나 더 필요하다. 키체인에서 Apple Worldwide Developer Relations Certification Authority 를 찾는다.
1.인증서를 찾아서 마우스 오른쪽 클릭을 하여 내보니기 옵션을 선택한다.
2. file 포맷을 개인정보 보호 향상 메일(.pem)으로 설정하고
3. 파일명은 WWDR로 하고 저장한다.
이제 진짜 서명할 준비가 되었다.
//Manifest.json에 서명하는데 사용되는 키파일
openssl smime -binary -sign -certfile WWDR.pem -signer passcertificate.pem -inkey passkey.pem -in manifest.json -out signature -outform DER -passin pass:12345
/*
inkey는 manifest.json에 서명하는 데 사용되는 키 파일
in은 입력 파일 이름
outform은 출력 파일 이름
outform은 출력 형식 (분리된 서명을 만들려면 "DER"가 필요)
passin은 키 파일의 암호
*/
마지막단계로 서명을 받은 파일을 .pkpass로 만들어 주기만하면 된다.
// 파일을 .pkpass로 만들어 주기
zip -r freehugcoupon.pkpass manifest.json pass.json signature logo.png logo@2x.png icon.png icon@2x.png strip.png strip@2x.png
이런 과정을 편하게 만들어 둔 팀 올리버상 ... 아리가또 👍👍👍
조금 더 상세한 설명이 필요하신 분들은 코데코사이트에서 참조해보시길 바란다. (저한테도 알려주세요!🙇)
https://www.kodeco.com/2855-beginning-passbook-in-ios-6-part-1-2?page=4
💁♂️ 압축된 파일을 해제해보면 어떨까?
manifest.json 파일과 signature 파일이 추가되어 있는것을 확인 할 수있다.👍👍👍
결과화면
에어드랍으로 실기기에 옮겨도 보았다.
서버를 만들어서 패스를 생성하고자 한다면 아래의 포스팅을 참고하면 된다.
2024.08.12 - [iOS 캐기/토이 프로젝트] - [애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기- 개발환경 세팅
2024.08.12 - [iOS 캐기/토이 프로젝트] - [애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기- 구조 작성
2024.08.12 - [iOS 캐기/토이 프로젝트] - [애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기-기능구현
2024.08.13 - [iOS 캐기/토이 프로젝트] - [애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기- 인증서 관련 작업 정리
마무리
- 우리나라말로 된 자료가 1도 없었지만 아직 우리나라에서 애플월렛을 활용하기 쉽지않아 많은 관심을 받지못해서이지 않을까 생각했다.
- 조금 더 확장해서 컨퍼런스 참가증용도 사용하기 위해서는 인증서를 관리하는 서버를 두고 사용자마다 입장QR등을 생성해서 주면 된다고 한다. (인증서 때문에 애플이 권장하는 방식이기도 하다)
- NFC 지원도 가능하지만 애플에게 별도로 문의해서 관련 인증서를 받아야하는데 쉽게 갈 수 없는 길이라고 한다. 😭
Airdrop으로 모바일 디바이스 to 디바이스로 시도해봤는데 잘 동작했다. 진짜 애플의 이런 애니메이션은 애플 감성에 한 몫 톡톡히 하는것 같다.
깃헙주소
https://github.com/PotatoArtie/Potato-iOS/tree/master/Labs/Playground/WalletEventPass
ref.
https://developer.apple.com/documentation/passkit
https://github.com/TimOliver/PassKit-Business-Card
https://developer.apple.com/documentation/walletpasses
https://www.kodeco.com/2855-beginning-passbook-in-ios-6-part-1-2?page=2#toc-anchor-006
https://developer.apple.com/documentation/walletpasses/creating_the_source_for_a_pass
[애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기- 인증서 관련 작업 정리 (0) | 2024.08.13 |
---|---|
[애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기-기능구현 (0) | 2024.08.12 |
[애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기- 구조 작성 (0) | 2024.08.12 |
[애플월렛 패스] 참가증, 쿠폰, 티켓같은 패스 서버 API 호출로 생성하기- 개발환경 세팅 (0) | 2024.08.12 |
[애플 라이다] LiDAR를 활용한 토이프로젝트 - 01 (0) | 2023.08.18 |
댓글 영역