0

I'm trying to make a bridge to implement apple pay in react native. I've made two classes, one that will be expose to react native and the other one that implement apple pay methods. My issue is that when I try to build my app, the build failed with the error:

Cannot find protocol declaration for 'PKPaymentAuthorizationControllerDelegate'

that popped in the interface in mobile-swift.h:

SWIFT_CLASS("_TtC7Staging23InternalApplePayHandler")
@interface InternalApplePayHandler : NSObject
- (nonnull instancetype)init SWIFT_UNAVAILABLE;
+ (nonnull instancetype)new SWIFT_UNAVAILABLE_MSG("-init is unavailable");
@end
@class PKPaymentAuthorizationController;
@class PKPayment;
@class PKPaymentAuthorizationResult;
@interface InternalApplePayHandler (SWIFT_EXTENSION(Staging)) <PKPaymentAuthorizationControllerDelegate>
- (void)paymentAuthorizationController:(PKPaymentAuthorizationController * _Nonnull)controller didAuthorizePayment:(PKPayment * _Nonnull)payment handler:(void (^ _Nonnull)(PKPaymentAuthorizationResult * _Nonnull))completion;
- (void)paymentAuthorizationControllerDidFinish:(PKPaymentAuthorizationController * _Nonnull)controller;
@end

This is the class that implement it:

//
// ApplePayHandler.swift
// Mobile
//
// Created by me on 06/06/2025.
//
final class InternalApplePayHandler: NSObject {
 private var paymentController: PKPaymentAuthorizationController?
 private var onSuccess: ((String) -> Void)?
 private var onFailure: ((String, String) -> Void)?
 private var amount: NSNumber
 private var currencyCode: String
 private var countryCode: String
 static func canMakePayment() -> Bool {
 return PKPaymentAuthorizationController.canMakePayments(usingNetworks: [.visa, .masterCard, .amex, .cartesBancaires])
 }
 init(
 amount: NSNumber,
 currencyCode: String,
 countryCode: String,
 onSuccess: @escaping (String) -> Void,
 onFailure: @escaping (String, String) -> Void
 ) {
 self.amount = amount
 self.currencyCode = currencyCode
 self.countryCode = countryCode
 self.onSuccess = onSuccess
 self.onFailure = onFailure
 }
 func start() {
 let request = PKPaymentRequest()
 request.merchantIdentifier = getMerchantIdentifier()
 request.countryCode = countryCode
 request.currencyCode = currencyCode
 request.supportedNetworks = [.visa, .masterCard, .amex, .discover]
 request.merchantCapabilities = .threeDSecure
 request.paymentSummaryItems = [
 PKPaymentSummaryItem(label: "Total", amount: NSDecimalNumber(decimal: amount.decimalValue), type: .final)
 ]
 let controller = PKPaymentAuthorizationController(paymentRequest: request)
 controller.delegate = self
 paymentController = controller
 controller.present { success in
 if !success {
 self.onFailure?("NOT_PRESENTED", "Failed to present Apple Pay sheet")
 self.cleanup()
 }
 }
 }
 private func getMerchantIdentifier() -> String {
 let bundleId = Bundle.main.bundleIdentifier ?? ""
 return bundleId == "MERCHANT_ID" ? "MERCHANT_ID" : "MERCHANT_ID_B"
 }
 private func cleanup() {
 paymentController = nil
 onSuccess = nil
 onFailure = nil
 }
}
extension InternalApplePayHandler: PKPaymentAuthorizationControllerDelegate {
 func paymentAuthorizationController(_ controller: PKPaymentAuthorizationController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) {
 let tokenData = payment.token.paymentData.base64EncodedString()
 onSuccess?(tokenData)
 completion(PKPaymentAuthorizationResult(status: .success, errors: nil))
 cleanup()
 }
 func paymentAuthorizationControllerDidFinish(_ controller: PKPaymentAuthorizationController) {
 controller.dismiss {
 self.onFailure?("CANCELLED", "User cancelled Apple Pay")
 self.cleanup()
 }
 }
}

and this class is used in the other class:

//
// ApplePayManager.swift
// Mobile
//
// Created by me on 03/06/2025.
//
import Foundation
import React
import PassKit
@objc(ApplePayManager)
class ApplePayManager: NSObject {
 private var paymentHandler: InternalApplePayHandler?
 @objc
 func canMakePayment(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
 resolve(InternalApplePayHandler.canMakePayment())
 }
 @objc
 func startPayment(_ amount: NSNumber, currencyCode: String, countryCode: String, resolver resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) {
 paymentHandler = InternalApplePayHandler(
 amount: amount,
 currencyCode: currencyCode,
 countryCode: countryCode,
 onSuccess: { token in
 resolve(token)
 },
 onFailure: { code, message in
 reject(code, message, nil)
 }
 )
 paymentHandler?.start()
 }
 @objc
 static func requiresMainQueueSetup() -> Bool {
 return true
 }
}

and finally this is my ApplePayManager.m:

#import <React/RCTBridgeModule.h>
#import <React/RCTUtils.h>
#import <PassKit/PassKit.h>
#import <PassKit/PKPaymentAuthorizationController.h>
@interface RCT_EXTERN_MODULE(ApplePayManager, NSObject)
RCT_EXTERN_METHOD(canMakePayment:(RCTPromiseResolveBlock)resolve
 rejecter:(RCTPromiseRejectBlock)reject)
RCT_EXTERN_METHOD(startPayment:(nonnull NSNumber *)amount
 currencyCode:(nonnull NSString *)currencyCode
 countryCode:(nonnull NSString *)countryCode
 resolver:(RCTPromiseResolveBlock)resolve
 rejecter:(RCTPromiseRejectBlock)reject)
@end

and I also imported the passKit inside my bridging header #import <PassKit/PassKit.h>

David Pasztor
55.1k9 gold badges99 silver badges132 bronze badges
asked Jun 10, 2025 at 9:21

1 Answer 1

0

Looks like you aren't importing PassKit in your Swift code. Add import PassKit to the top and it should compile.

answered Jun 13, 2025 at 15:07
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.