본문 바로가기
👨‍💻 프로그래밍/책잇아웃(포트폴리오)

👜 Apple Wallet Pass, Spring Boot에서 개발하기

by 개발자 진개미 2023. 6. 2.
반응형

기본적인 구조

모르는 분야의 개발을 시작할 때 가장 먼저 해야 할 일은 공식 문서를 보는 것이라고 생각합니다. 그래서 저도 애플의 공식 문서를 참고해 우선 Apple Wallet의 기본적인 구조를 이해해 보려고 했습니다.

우선, .pkpass라는 파일을 아이폰, 맥북, 아이패드 등의 애플 기기에서 열면 Apple WalletPass가 추가됩니다. .pkpass는 폴더를 압축한 파일이라고 생각하면 되고, 그 폴더의 구조는 아래와 같습니다.

 

보시면, 핵심적인건 3가지 입니다.

  1. 리소스 파일 (icon, thumbnail, logo 등 이미지)
  2. 설정 파일 (pass.json)
  3. 리소스 파일, 설정 파일의 번역본 (영어, 한국어 등)

 

즉, Apple Wallet Pass를 개발하는 방법은 위 3가지를 준비하고, 보안을 구성하는게 끝입니다.


보안 구성하기

Apple Wallet은 민감한 정보를 포함하는 경우가 많기 때문에 보안이 엄격합니다. Apple Wallet Pass를 만들면 보안을 보장하기 위해 sign을 해야 하고, sign이 유효하지 않으면 Apple Wallet Pass를  추가할 수 없습니다. 보안을 위해서 필요한건 3가지 입니다. 

  • 애플 개발자 계정에서 발급한 개인 인증서
  • 개인 인증서의 암호
  • 애플의 인증서

개인 인증서를 발급 받기 위해서는 애플 개발자 계정에 가입해야 합니다. 1년에 13만원 정도인데, 개발자로서 투자한다 생각하고 그냥 가입했습니다.


 

애플 개발자 계정에서 개인 인증서 발급하기

우선, 애플 개발자 계정에 간 후 Account 페이지에 가서 Certificates에 들어갑니다.

 

그리고 Certificate를 만들 때 Pass Type ID Certificate를 선택하고 과정을 따라 주시면 (중간에 암호를 입력하셔야 하는데 이 암호가 바로 개인 인증서의 private key라고 생각하시면 됩니다.)

 

pass.cer 파일을 얻을 수 있습니다.

 


애플의 인증서 얻기

원래 애플의 인증서는 iOS에 포함되어 있었지만 iOS 13부터 삭제되서 이제는 직접 포함시켜야 된다고 합니다. SDK에 따라서는 이미 내부에 포함되서 필요 없는 경우도 있지만 제가 쓸 예정인 jpasskit에는 포함되어 있지 않아 직접 구했습니다. 애플 인증서 목록에 가셔서 Worldwide Developer Relations - G3을 다운로드 받아 주시면 됩니다.


Java 비공식 SDK : jpasskit

이제 발급받은 정보들을 가지고 애플 공식 문서에 나온대로 폴더 구조를 만들면 .pkpass 파일을 만들 수 있습니다. 물론 이 과정을 직접 다 구현해도 되지만, 혹시나 SDK가 없을까 해서 찾아봤더니 각 진영에 적절한 SDK가 있었습니다. (물론 애플 답게 Swift를 제외하고 공식은 없었습니다) 그 중, 가장 활발히 사용되고 있고, 최근까지 유지보수가 되고 있는 jpasskit을 선택했습니다.

 

GitHub - drallgood/jpasskit: jPasskit is an Java™ implementation of the Apple™ PassKit Web Service.

jPasskit is an Java™ implementation of the Apple™ PassKit Web Service. - GitHub - drallgood/jpasskit: jPasskit is an Java™ implementation of the Apple™ PassKit Web Service.

github.com

 

jpasskit에서는 pass.json을 PKPass라는 Java의 class로 표현하고, PKPass의 Builder method와, 각종 Pass Type을 Class로 지원합니다.

return PKPass.builder()
        .formatVersion(1)

        .pass(genericPass)
        .barcodes(List.of(barcode))

        .passTypeIdentifier(passTypeIdentifier)
        .teamIdentifier(teamIdentifier)
        .organizationName(organizationName)

        .serialNumber(serialNumber)
        .description(description)
        .logoText(logoText)

        .backgroundColor(primaryColor)
        .foregroundColor(textColor)

        .build();

 

적절한 설정 값을 넣고 PKPass를 보안 정보들을 가지고 sign 해 주면 .pkpass 파일이 완성됩니다.

public byte[] getAppleWalletPass(PKPass pkPass) throws IOException, CertificateException, PKSigningException {
    PKSigningInformation pkSigningInformation = new PKSigningInformationUtil()
            .loadSigningInformationFromPKCS12AndIntermediateCertificate(
                    privateCertificatePath,
                    passKeyPassword,
                    appleCertificatePath
            );

    IPKPassTemplate pkPassTemplateFolder = new PKPassTemplateFolder(templatePath);

    return pkFileBasedSigningUtil.createSignedAndZippedPkPassArchive(pkPass, pkPassTemplateFolder, pkSigningInformation);
}

Spring Boot Controller에서 .pkpass 내보내기

Controller에서 파일 타입을 .pkpass로 지정한 뒤, Header에서도 .pkpass라는걸 명시해 주면 .pkpass라고 인식합니다.

@GetMapping(value = "apple-wallet/{membershipId}", produces = "application/vnd.apple.pkpass")
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.valueOf("application/vnd.apple.pkpass"));
headers.set("Content-Disposition", "attachment; filename=appleWalletPass.pkpass");

반응형

댓글