6
votes

I have implemented apple pay in my iOS application using Passkit framework. I did all of these things fully to set up apple pay. I am using sandbox account. I added cards in Wallet application and these cards are testing cards which I copied from this link. This code I am using:

 print("\(((self.grandTotalLabel.text!).replacingOccurrences(of: "$", with: "")))")

        let paymentNetworks = [PKPaymentNetwork.amex]

        if PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: paymentNetworks){

            paymentRequest.supportedNetworks = paymentNetworks
            paymentRequest.merchantCapabilities = .capability3DS
            paymentRequest.requiredShippingAddressFields = [.all]
            paymentRequest.paymentSummaryItems = self.itemToSell(shipping: 10.0)

                            let sameDayShipping = PKShippingMethod(label: "Same day divilery", amount: 12.99)
            sameDayShipping.detail = "Same day divilery Detail"
            sameDayShipping.identifier = "sameDay"

            let twDaysShipping = PKShippingMethod(label: "Two days divilery", amount: 4.99)
            twDaysShipping.detail = "Two days divilery Detail"
            twDaysShipping.identifier = "twoDays"

            let freeShipping = PKShippingMethod(label: "Free shipping divilery", amount: 0.0)
            freeShipping.detail = "Free shipping divilery Detail"
            freeShipping.identifier = "freeShipping"

           // paymentRequest.shippingMethods = [sameDayShipping,twDaysShipping, freeShipping]
            let applePayVC = PKPaymentAuthorizationViewController(paymentRequest: paymentRequest)

            applePayVC?.delegate = self

            self.present(applePayVC!, animated: true) {

                print("ApplePayViewcontroller")

            }
        }
        else{

            print("Please set up for apple pay")

        }




func itemToSell(shipping:Float) -> [PKPaymentSummaryItem]{

        print(Double("\(((self.grandTotalLabel.text!).replacingOccurrences(of: "$", with: "")))") as Any)

        let dishItems = PKPaymentSummaryItem(label: "FoodKonnect", amount: NSDecimalNumber(string: "21.00"))
        let discount = PKPaymentSummaryItem(label: "Discount", amount: 1.0)
        let shipping = PKPaymentSummaryItem(label: "Shipping", amount: NSDecimalNumber(string: "\(shipping)"))

        let totalAmount = dishItems.amount.adding(discount.amount)

        let totalPrice = PKPaymentSummaryItem(label: "FoodKonnect application", amount: totalAmount)

        return [dishItems, discount,shipping, totalPrice]


    }

These all delegates I am using of PKPaymentAuthorizationViewControllerDelegate :

extension CartViewController:PKPaymentAuthorizationViewControllerDelegate{

    func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {

        controller.dismiss(animated: true, completion: nil)

    }

   // @available(iOS 11.0, *)

    func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelectShippingContact contact: PKContact, completion: @escaping (PKPaymentAuthorizationStatus, [PKShippingMethod], [PKPaymentSummaryItem]) -> Void) {
        print("\(#function)")

    }
    @available(iOS 11.0, *)
    func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelect shippingMethod: PKShippingMethod, handler completion: @escaping (PKPaymentRequestShippingMethodUpdate) -> Void) {
        print("\(#function)")

    }



    @available(iOS 11.0, *)
    func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) {


        print("\(#function)")

    }

}

Apple pay viewcontroller is showing and this screen is showing with a processing circle view.

enter image description here

But after few seconds I got this error message:

enter image description here I am not able to figure what exactly I am doing wrong.

3
The name of the app that you censored in the last picture is clearly visible behind the alert.Tamás Sengel
Double check if all the domains used in the process are correct. I used to face a similar error because of the reason.Jagdeep Singh
do you have a solution? I've got the same problem right now.Gabriel.Massana
@Gabriel.Massana are you find the solution ?balkaran singh
@ajeet sharma Found a solution for that?Omar Hassan

3 Answers

8
votes

In each implemented delegate function of PKPaymentAuthorizationViewControllerDelegate that have completion/handler you must call that block with the appropriate parameters and most importantly with appropriate status.

On iOS 11 not calling the block within (approximately) 15-20s, the iOS is killing the Payment with the error you are seeing. On iOS 10, it will let you spin on Processing indefinitely until the completion blocks are called.

I had the same issue and it turned out that I was not calling the handler block at all in one of the edge cases.

1
votes

Recently I faced the same issue and I found a solution.

Everything is fine only we have to update the handler with the success or failure like this:

func paymentAuthorizationViewController(_ controller: 
PKPaymentAuthorizationViewController, didAuthorizePayment payment: 
PKPayment, handler completion: @escaping 
(PKPaymentAuthorizationResult) -> Void) { 

If the payment data are nil or not check for simulator always its nil :

do {
            let jsonResponse = try JSONSerialization.jsonObject(with: paymentStatus.paymentData, options: .mutableContainers)
            print(jsonResponse as! NSDictionary)
            completion(PKPaymentAuthorizationResult(status: .success, errors: nil))
            
        }
        catch let error
        {
            print(error)
            completion(PKPaymentAuthorizationResult(status: .failure, errors: nil))
            
        }

It should solve the problem.

0
votes

There are still cases when you do have completion/handler properly called in PKPaymentAuthorizationViewControllerDelegate functions that expect this handler, but your internal payment API happen to be set to a longer timeout time than ApplePay dialog expects (as of iOS 13 it would timeout in around 30 secs).

In these cases you may get "Apple pay not completed" error in slow networks (try to block your API artificially to simulate such a situation).

A solution might be in proactively dismissing the ApplePay dialog yourself just before it gives up and shows the error. More details on how to do this can be found in this answer to a similar question being discussed.