LizG
LizG

Reputation: 2530

Apple Pay works on simulator but not on device

I am able to display Apple Pay view controller on simulator but not on device.

Entitlement added and certificate installed.

class ViewController: UIViewController, PKPaymentAuthorizationViewControllerDelegate {

var paymentRequest: PKPaymentRequest! 

override func viewDidLoad() {
    super.viewDidLoad()

}


func rydes(shipping: Double) -> [PKPaymentSummaryItem] {

    let ryde = PKPaymentSummaryItem(label: "Your Fare", amount: 1.00)
    let discount = PKPaymentSummaryItem(label: "Discount", amount: -0.00)
    let shipping = PKPaymentSummaryItem(label: "Shipping", amount: NSDecimalNumber(string: "\(shipping)"))
    let subTotal = ryde.amount.adding(discount.amount)
    let total = PKPaymentSummaryItem(label: "rydes", amount: subTotal)

    return [ryde, discount, shipping, total]

} // rydes() func


    func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didSelect shippingMethod: PKShippingMethod, completion: @escaping (PKPaymentAuthorizationStatus, [PKPaymentSummaryItem]) -> Void) {

        completion(PKPaymentAuthorizationStatus.success, rydes(shipping: Double(shippingMethod.amount)))

    } // paymentAuthorizationViewController( didSelectShippingMethod )



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

        completion(PKPaymentAuthorizationStatus.success)

    } // paymentAuthorizationViewController( didAuthorizePayment )



    func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {

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

    } // paymentAuthorizationViewControllerDidFinish()


@IBAction func applePayPressed(_ sender: Any) {


    print("enable apple pay")

    // send user to Apple Pay to make payment

    let paymentNetworks = [PKPaymentNetwork.visa, .masterCard, .interac, .discover, .amex]
    let merchantId = "merchant.com.xxx"


    if PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: paymentNetworks) {

        paymentRequest = PKPaymentRequest()
        paymentRequest.currencyCode = "CAD"
        paymentRequest.countryCode = "CA"
        paymentRequest.merchantIdentifier = merchantId
        paymentRequest.supportedNetworks = paymentNetworks
        paymentRequest.merchantCapabilities = .capability3DS
        paymentRequest.requiredShippingAddressFields = [.all]
        paymentRequest.paymentSummaryItems = self.rydes(shipping: 0.00)

        // . . .  shipping - not really needed

        let samedayShipping = PKShippingMethod(label: "Same Day", amount: 12.99)
        samedayShipping.detail = "Guaranteed same day delivery."
        samedayShipping.identifier = "sameday"

        let twodayShipping = PKShippingMethod(label: "Two Day", amount: 4.99)
        twodayShipping.detail = "Guaranteed within two days."
        twodayShipping.identifier = "twoday"

        let freeShipping = PKShippingMethod(label: "Same Day", amount: 0.00)
        freeShipping.detail = "Guaranteed same day."
        freeShipping.identifier = "freeShipping"

        paymentRequest.shippingMethods = [samedayShipping, twodayShipping, freeShipping]

        // . . .  shipping - not really needed

        let applePayVC = PKPaymentAuthorizationViewController(paymentRequest: paymentRequest)
        applePayVC.delegate = self
        self.present(applePayVC, animated: true, completion: nil)

    }  else {

        print("Tell the user they need to set up Apple Pay!")
    }

} // applePayPressed func ACTION

}

The above code just returns this line - Tell the user they need to set up Apple Pay!

I am using a iPhone 6s as the device and Apple Pay and Wallet are enabled with a valid debit card and credit card. I am from Canada, so I am in a valid region.

Edited Code

class ViewController: UIViewController, PKPaymentAuthorizationViewControllerDelegate {

var paymentRequest: PKPaymentRequest! // apple pay

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}


func rydes() -> [PKPaymentSummaryItem] {

    let ryde = PKPaymentSummaryItem(label: "Your Fare", amount: 1.00)
    let subTotal = ryde.amount
    let total = PKPaymentSummaryItem(label: "rydes", amount: subTotal)

    return [ryde, total]

} // rydes() func



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

        completion(PKPaymentAuthorizationStatus.success)

    } // paymentAuthorizationViewController( didAuthorizePayment )



    func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) {

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

    } // paymentAuthorizationViewControllerDidFinish()


@IBAction func applePayPressed(_ sender: Any) {

    print("enable apple pay")

    // send user to Apple Pay to make payment

    let paymentNetworks = [PKPaymentNetwork.visa, .masterCard, .interac, .discover, .amex]
    let merchantID = "merchant.com.xxx"

    if PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: paymentNetworks) {
        paymentRequest = PKPaymentRequest()
        paymentRequest.currencyCode = "CAD"
        paymentRequest.countryCode = "CA"
        paymentRequest.merchantIdentifier = merchantID
        paymentRequest.supportedNetworks = paymentNetworks
        paymentRequest.merchantCapabilities = .capability3DS
        paymentRequest.requiredShippingAddressFields = [.all]
        paymentRequest.paymentSummaryItems = self.rydes()

        let applePayVC = PKPaymentAuthorizationViewController(paymentRequest: paymentRequest)
        applePayVC.delegate = self
        self.present(applePayVC, animated: true, completion: nil)

    }  else {

        print("Tell the user they need to set up Apple Pay!")
    }

} // applePayPressed func ACTION

}

entitlements

console print

Upvotes: 5

Views: 5930

Answers (3)

Raquel Smith
Raquel Smith

Reputation: 27

Make sure you have a card added to your Apple Pay wallet on the device you are testing with :) Simple, but was the fix for me.

Upvotes: 1

Sudipto Roy
Sudipto Roy

Reputation: 6795

If you can see the apple pay option on your simulator and are confused about why it is not showing on a real device, then this answer is for you.

Initially, you may not see the apple pay option on real devices because you may not have any cards added to the Wallet app.

In this case, you have to follow Apple Pay - Sandbox Testing - Apple Developer and set up a sandbox account to test apple pay.

Steps:

  1. Go to https://appstoreconnect.apple.com/access/testers and add your tester account. Use a fresh email address that was not used with any Apple services.
  2. From your iPhone, go to settings, sign out from your logged-in Apple ID, and log in to your new tester account.
  3. Select your region, where apple pay is available. E.j. United States (If not already)
  4. Open the Wallet application and add a new card.

Name: Any
Card Number: 3499 569590 41362
Security Code: 1111
Expiration Date: 12/2022

  1. When successfully card added open your iOS app and you can see apple pay now.

Upvotes: 1

Same issue I face during enable of Apple Pay to my application. Make sure you have entered all the valid shipping, service and total payment value inside PKPayment​Summary​Item.

Also total payment value should be greater that 0.0 to show the payment gate way view. If any of the value is 0.0 then don't add as SummaryItem.

Code for Valid PKPaymentSummaryItem:

{
// 12.75 subtotal
NSDecimalNumber *subtotalAmount = [NSDecimalNumber decimalNumberWithMantissa:1275
 exponent:-2 isNegative:NO];
self.subtotal = [PKPaymentSummaryItem summaryItemWithLabel:@"Subtotal" amount:subtotalAmount];

// 2.00 discount
NSDecimalNumber *discountAmount = [NSDecimalNumber decimalNumberWithMantissa:200 exponent:-2 isNegative:YES];
self.discount = [PKPaymentSummaryItem summaryItemWithLabel:@"Discount" amount:discountAmount];

// 12.75 - 2.00 = 10.75 grand total
NSDecimalNumber *totalAmount = [NSDecimalNumber zero];
totalAmount = [totalAmount decimalNumberByAdding:subtotalAmount];
totalAmount = [totalAmount decimalNumberByAdding:discountAmount];
self.total = [PKPaymentSummaryItem summaryItemWithLabel:@"My Company Name" amount:totalAmount];
self.summaryItems = @[self.subtotal, self.discount, self.total];
request.paymentSummaryItems = self.summaryItems;
}

This will try to fix your above issue.

Edit: Just remove below code and check it again or put check condition if value for discount or shipping is greater that 0.0 then you can send shipping and discount as summary item:

    let ryde = PKPaymentSummaryItem(label: "Your Fare", amount: 1.00)
//change some value here:
    let discount = PKPaymentSummaryItem(label: "Discount", amount: -0.00)
    let shipping = PKPaymentSummaryItem(label: "Shipping", amount: NSDecimalNumber(string: "\(shipping)"))
Make sure your subtotal or total is greater that 0.0.
    let subTotal = ryde.amount.adding(discount.amount)
    let total = PKPaymentSummaryItem(label: "rydes", amount: subTotal)

Upvotes: 2

Related Questions