web-dev-qa-db-ja.com

Apple SwiftUIで支払う

大きなプロジェクトで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)
}
3
user2805119

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
    }
}

私はViewModeldelegateとして機能するように使用しています。これをstructのフィールドにlet request: PKPaymentRequestの後に追加し、デリゲートを設定する必要があります。 PKPaymentAuthorizationViewControllerを作成します

0
Departamento B