[iOS 10] アプリを Apple Pay に対応させるために必要な実装について
はじめに
こんにちは。モバイルアプリサービス部の平屋です。前回の記事に引き続き、Apple Pay についての情報を紹介していきます。
本記事ではアプリを Apple Pay に対応させる場合に必要な実装を解説していきます。
Apple Pay の概要や環境構築などについては以下の記事などをご覧ください。
- [iOS 10] 開発者のための Apple Pay 概要 | Developers.IO
- [iOS 10] Apple Pay 対応アプリ開発のための環境構築について | Developers.IO
検証環境
- Xcode Version 8.0 (8A218a)
- iPhone 6s, iOS 10.0.2
目次
- [1] PassKit をインポート
- [2] Apple Pay の利用可否をチェックする
- [3] Apple Pay ボタンを表示する
- [4] ペイメントリクエストを作成する
- [5] ペイメントシートを表示させる
- [6] ペイメントシートまわりのイベントをハンドリングする
- さいごに
[1] PassKit をインポート
Apple Pay まわりの処理では PassKit フレームワークのクラスを使用します。PassKit
をインポートします。
import PassKit
[2] Apple Pay の利用可否をチェックする
まずは、Apple Pay を利用できる状態かどうかをチェックします。
Apple Pay 自体が使用できる状態かどうか
PKPaymentAuthorizationViewController
の canMakePayments()
メソッドを使用すれば、Apple Pay 自体が使用できる状態かどうかをチェックできます。ハードウェアが対応していなかったり、機能制限がかかっていたりする場合、このメソッドは false
を返します。
if PKPaymentAuthorizationViewController.canMakePayments() { // Apple Pay に対応している } else { // Apple Pay に対応していない }
クレジットカードが「Wallet」アプリに登録済みかどうか
Apple Pay を利用した決済では、標準の「Wallet」アプリに登録済みのクレジットカードを使用します。
PKPaymentAuthorizationViewController
の canMakePayments(usingNetworks:)
メソッドを使用すれば、クレジットカードが登録済みかどうかをチェックできます。
// 利用可能な決済ネットワーク (MasterCard, Visa など) を取得 let networks = PKPaymentRequest.availableNetworks() if PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: networks) { // 利用可能な決済ネットワークが 1 つ以上ある場合 (クレジットカードが登録済みの場合) } else { // 利用可能な決済ネットワークがない場合 }
[3] Apple Pay ボタンを表示する
Apple Pay ボタンは決済開始のトリガーを提供するボタンです。
実装的には PKPaymentButton
を使用します。type
と style
を指定して PKPaymentButton
を作成します。
private func preparePayButton() { let paymentButton = PKPaymentButton(type: PKPaymentButtonType.plain, style: PKPaymentButtonStyle.black) paymentButton.addTarget(self, action: #selector(ViewController.pay), for: .touchUpInside) self.view.addSubview(paymentButton) self.prepareButtonConstraints(button: paymentButton) }
クレジットカードが未登録の場合
クレジットカードが未登録の場合は type
に PKPaymentButtonType.setUp
を指定して、カード登録を誘導する外観のボタンを表示できます。
private func prepareSetUpButton() { let setUpButton = PKPaymentButton(type: PKPaymentButtonType.setUp, style: PKPaymentButtonStyle.black) setUpButton.addTarget(self, action: #selector(ViewController.setUp), for: .touchUpInside) self.view.addSubview(setUpButton) self.prepareButtonConstraints(button: setUpButton) }
type
が PKPaymentButtonType.setUp
のボタンが押された時に PKPassLibrary
の openPaymentSetup()
メソッドを呼ぶようにします。
func setUp(sender: AnyObject) { PKPassLibrary().openPaymentSetup() }
OS が提供するクレジットカード追加画面に遷移させることができます。
[4] ペイメントリクエストを作成する
ペイメントシートを表示する前に、PKPaymentRequest
を作成し、決済まわりの設定や金額などの情報を格納します。
ここの実装はこちらの記事の手順 [1] に対応します。
func pay(sender: AnyObject) { // PKPaymentRequest作成 let request = PKPaymentRequest() // マーチャント ID を指定 request.merchantIdentifier = "merchant.com.example.myMerchant" // ISO 3166 country code (2文字) を指定 request.countryCode = "JP"; // ISO 4217 currency code を指定 request.currencyCode = "JPY"; // サポートする決済ネットワークを指定 request.supportedNetworks = PKPaymentRequest.availableNetworks() // サポートするプロトコルを指定 request.merchantCapabilities = .capability3DS // capability3DS は必須 // 金額を指定 request.paymentSummaryItems = [ // 商品の金額、送料、割引額、合計の 3 つを表示する場合 PKPaymentSummaryItem(label: "商品の金額", amount: NSDecimalNumber(string: "1000")), PKPaymentSummaryItem(label: "送料", amount: NSDecimalNumber(string: "100")), PKPaymentSummaryItem(label: "割引額", amount: NSDecimalNumber(string: "100")), PKPaymentSummaryItem(label: "MyMerchant", amount: NSDecimalNumber(string: "1000")) // 合計額 ] // ... }
請求先や配送先の情報が必要な場合は、requiredShippingAddressFields
や requiredBillingAddressFields
プロパティなどに値を指定します。
func pay(sender: AnyObject) { // ... // 請求先や配送先のフィールドのタイプを指定 request.requiredShippingAddressFields = .postalAddress request.requiredBillingAddressFields = .postalAddress // 配送方法 let shippingMethod = PKShippingMethod(label: "Japan Post", amount: NSDecimalNumber(string: "100")) shippingMethod.identifier = "Japan Post" shippingMethod.detail = "到着: 3-4 週後" request.shippingMethods = [shippingMethod] // ... }
[5] ペイメントシートを表示させる
ペイメントシートのビューは PKPaymentAuthorizationViewController
が管理します。PKPaymentRequest
から PKPaymentAuthorizationViewController
を作成し、ペイメントシートを表示させます。
ここの実装はこちらの記事の手順 [2] に対応します。
func pay(sender: AnyObject) { // ... // PKPaymentRequest から PKPaymentAuthorizationViewController を作成し、表示 let viewController = PKPaymentAuthorizationViewController(paymentRequest: request) viewController.delegate = self self.present(viewController, animated: true, completion: nil) }
[6] ペイメントシートまわりのイベントをハンドリングする
PKPaymentAuthorizationViewController
を表示する ViewController を PKPaymentAuthorizationViewControllerDelegate
に適合させると、ペイメントシートまわりのイベントをハンドリングできるようになります。
実装必須のメソッドについて
実装が必須のメソッドは paymentAuthorizationViewController(_:didAuthorizePayment:completion:)
と paymentAuthorizationViewControllerDidFinish(_:)
の 2 つです。
(1) paymentAuthorizationViewController(_:didAuthorizePayment:completion:)
このメソッドはユーザーがペイメントリクエストを承認した時に呼ばれます。
引数 payment
から以下の情報を取得できます。ペイメントトークンのフォーマットはこちらのページに載っています。
- 暗号化済みのペイメントトークン
- 請求先情報 (
PKPaymentRequest
作成時にrequiredBillingAddressFields
プロパティに値を指定した場合) - 配送先情報 (
PKPaymentRequest
作成時にrequiredShippingAddressFields
プロパティに値を指定した場合) - 配送方法 (
PKPaymentRequest
作成時にshippingMethods
プロパティに値を指定した場合)
アプリのバックエンド側に上記の情報を送り、決済処理を進めます。
決済処理が正常終了したタイミングで引数に .success
を指定して completion
を呼びます。
ここの実装はこちらの記事の手順 [5] に対応します。
// ユーザーがペイメントリクエストを承認した時に呼ばれる func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, completion: @escaping (PKPaymentAuthorizationStatus) -> Void) { // 暗号化済みのペイメントトークン // payment.token // ペイメントリクエストの requiredBillingAddressFields に値を指定した場合、値が入る // payment.billingContact // ペイメントリクエストの requiredShippingAddressFields に値を指定した場合、値が入る // payment.shippingContact // ペイメントリクエストの shippingMethods に値を指定した場合、値が入る // payment.shippingMethod // アプリのバックエンド側に上記の情報を送り、決済処理を進める // ... // 決済処理が正常終了した場合は、`completion` に `.success` つっこむ completion(.success) }
(2) paymentAuthorizationViewControllerDidFinish(_:)
このメソッドは決済の全ての処理が終わった時、または決済がキャンセルされた時に呼ばれます。PKPaymentAuthorizationViewController
を閉じる処理を実行します。
func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) { self.dismiss(animated: true, completion: nil) }
実装任意のメソッドについて
実装が任意のメソッドは 4 つです。
(1) paymentAuthorizationViewControllerWillAuthorizePayment(_:)
このメソッドは、ユーザーによるペイメントリクエスト承認が完了する直前に呼ばれます。
func paymentAuthorizationViewControllerWillAuthorizePayment(_ controller: PKPaymentAuthorizationViewController) { // ... }
(2) paymentAuthorizationViewController(_:didSelect:completion:)、第二引数の型 : PKPaymentMethod
このメソッドは支払い方法が変更された時に呼ばれます。
例えば、特定の支払い方法のときに割引をする場合はこのメソッド内で合計金額などを更新します。
func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelect paymentMethod: PKPaymentMethod, completion: @escaping ([PKPaymentSummaryItem]) -> Void) { // ... }
(3) paymentAuthorizationViewController(_:didSelect:completion:)、第二引数の型 : PKShippingMethod
このメソッドは配送方法が変更された時に呼ばれます。
例えば、配送方法によって、配送料が変わる場合は、このメソッド内で配送料などを更新します。
func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelect shippingMethod: PKShippingMethod, completion: @escaping (PKPaymentAuthorizationStatus, [PKPaymentSummaryItem]) -> Void) { // ... }
(4) paymentAuthorizationViewController(_:didSelectShippingContact:completion:)
このメソッドは配送先が変更された時に呼ばれます。
例えば、配送先によって配送方法や配送料が変わる場合は、このメソッド内で配送方法や配送料を更新します。
func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelectShippingContact contact: PKContact, completion: @escaping (PKPaymentAuthorizationStatus, [PKShippingMethod], [PKPaymentSummaryItem]) -> Void) { // ... }
さいごに
本記事ではアプリを Apple Pay に対応させる場合に必要な実装について解説しました。アプリ内での支払いに Apple Pay を採用すれば、決済のフロント部分の実装工数を小さくできそうだと思いました。
2016/10/21 現在、日本ではまだサービスインしていませんが、今後広く普及していくことを期待しています!
参考資料
- Apple Payプログラミングガイド:Apple Payについて
- Apple Pay - Apple Developer
- Getting Started with Apple Pay - Apple Developer
WWDC Documents
- What's New with Wallet and Apple Pay - WWDC 2016 - Videos - Apple Developer
- Apple Pay Within Apps - WWDC 2015 - Videos - Apple Developer
- Emporium: A Simple Shopping Experience with Apple Pay
API Reference
- PKPaymentRequest - PassKit
- PKPaymentAuthorizationViewController - PassKit
- PKPaymentButton - PassKit
- PKPaymentAuthorizationController - PassKit
- PKPaymentAuthorizationViewControllerDelegate - PassKit
- PKPaymentAuthorizationStatus - PassKit
- PKPayment - PassKit