大きなプロジェクトでPassKitとSwiftUIを使用するのはこれが初めてです。 Apple Pay SwiftUIを実装しようとしていますが、ネイティブに実装する方法がまだないため、PKPaymentAuthorizationViewControllerをUIViewControllerRepresentableでラップしてみましたが、それを適切に行う。
ビューは正しく表示され、クリックして支払うと機能するようです。ビューをisPresentingApplePay boolにバインドすることでウィンドウの表示を制御します(以下を参照)。問題は、ウィンドウを閉じる必要があるときに発生します。 cancel
ボタンをタップしてもビューは閉じません。場合によっては、paymentAuthorizationViewControllerDidFinishデリゲート関数も呼び出さないことがあります。同じことが起こります後支払いを送信します。時々、didFinishデリゲートが呼び出されますが、ビューは却下されません。バインディング変数isPresentingApplePayを渡して、didFinishからfalseに設定してみましたが、何も実行されません。ビューを非表示にする唯一の方法は、Apple支払いウィンドウの任意の部分外側をタップすることです。
誰かが私が間違っていることを知っていますか?私が完全に欠けているものはありますか?
if statement
の下にビューをバインドすると、ボタンを押したときにAppleペイウィンドウが適切に表示されます
これが私のPKPaymentAuthorizationViewControllerラッパーです。
import Foundation
import PassKit
import SwiftUI
struct ApplePayController: UIViewControllerRepresentable {
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var userData: UserData
@Binding var purchase: Purchase
@Binding var isPresenting: Bool
let items: [PKPaymentSummaryItem]
func updateUIViewController(_ uiViewController: PKPaymentAuthorizationViewController, context: Context) {
}
typealias UIViewControllerType = PKPaymentAuthorizationViewController
func makeUIViewController(context: Context) -> PKPaymentAuthorizationViewController {
let applePayManager = ApplePayManager(items: items)
let apm = applePayManager.paymentViewController()!
apm.delegate = context.coordinator
return apm
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject, PKPaymentAuthorizationViewControllerDelegate {
var parent: ApplePayController
init(_ parent: ApplePayController) {
self.parent = parent
}
func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {
controller.dismiss(animated: true) {
self.parent.isPresenting = false
}
}
func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) {
print("did authorize payment")
}
func paymentAuthorizationViewControllerWillAuthorizePayment(_ controller: PKPaymentAuthorizationViewController) {
print("Will authorize payment")
}
}
class ApplePayManager: NSObject {
let currencyCode: String
let countryCode: String
let merchantID: String
let paymentNetworks: [PKPaymentNetwork]
let items: [PKPaymentSummaryItem]
init(items: [PKPaymentSummaryItem],
currencyCode: String = "USD",
countryCode: String = "US",
merchantID: String = "xxx.merchant.xxx",
paymentNetworks: [PKPaymentNetwork] = [PKPaymentNetwork.amex, PKPaymentNetwork.masterCard, PKPaymentNetwork.visa]) {
self.items = items
self.currencyCode = currencyCode
self.countryCode = countryCode
self.merchantID = merchantID
self.paymentNetworks = paymentNetworks
}
func paymentViewController() -> PKPaymentAuthorizationViewController? {
if PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: paymentNetworks) {
let request = PKPaymentRequest()
request.currencyCode = self.currencyCode
request.countryCode = self.countryCode
request.supportedNetworks = paymentNetworks
request.merchantIdentifier = self.merchantID
request.paymentSummaryItems = items
request.merchantCapabilities = [.capabilityCredit, .capabilityDebit]
return PKPaymentAuthorizationViewController(paymentRequest: request)
}
return nil
}
}
}
これは私がUIViewでそれを表示する方法です:
if isPresentingApplePay {
ApplePayController(purchase: self.$currentOrder.purchase, isPresenting: $isPresentingApplePay, items: self.createOrder(with: self.currentOrder.purchase)).environmentObject(self.userData)
}
PKPaymentAuthorizationViewController
を表示するために機能するバージョンは、次の場所にあります。 SwiftUIのみのプロジェクトでPKPaymentAuthorizationViewControllerを適切に表示する方法
私が使用しているラッパーは次のようになります。
import PassKit
import SwiftUI
struct ApplePayWrapper: UIViewControllerRepresentable {
typealias UIViewControllerType = PKPaymentAuthorizationViewController
let request: PKPaymentRequest
func makeUIViewController(context: Context) -> PKPaymentAuthorizationViewController {
let applePayController = PKPaymentAuthorizationViewController(paymentRequest: request)
return applePayController!
}
func updateUIViewController(_ uiViewController: PKPaymentAuthorizationViewController, context: Context) {
// Nothing
}
}
私はViewModel
をdelegate
として機能するように使用しています。これをstruct
のフィールドにlet request: PKPaymentRequest
の後に追加し、デリゲートを設定する必要があります。 PKPaymentAuthorizationViewController
を作成します