#mikep-applepay-ios
1 messages ยท Page 1 of 1 (latest)
what does "we have apple pay elsewhere" mean? Same app? What's different in the code between the two if so?
Yes, within the same app. We have 2 different checkout styles, each with their own checkout model. So 2 different objects conforming to STPApplePayContextDelegate. The code is largely the same, main difference being one is fetching the secret ahead of time, and the new one is fetching inside the didCreatePaymentMethod like the docs show here: https://stripe.com/docs/apple-pay
Ive also tried injecting the secret ahead of time into this new model, but it didn't make a difference.
Hello! Can you share the code from your STPApplePayContextDelegate method implementations that are producing the error?
And the code where you create an instance of STPApplePayContext and call presentApplePay on it?
final class StripeApplePayController: NSObject, STPApplePayContextDelegate {
private var cartId = ""
private let checkoutService = CheckoutService()
typealias StripeApplePayCompletionBlock = (STPPaymentStatus, Error?) -> Void
private var completion: StripeApplePayCompletionBlock?
func startApplePay(paymentSummaryItems: [PKPaymentSummaryItem], cartId: String, completion: @escaping StripeApplePayCompletionBlock) {
self.cartId = cartId
self.completion = completion
let paymentRequest = StripeAPI.paymentRequest(
withMerchantIdentifier: StripeApplePayController.merchantIdentifier,
country: StripeApplePayController.country,
currency: StripeApplePayController.currency
)
paymentRequest.paymentSummaryItems = paymentSummaryItems
paymentRequest.merchantCapabilities = .capabilityCredit
if let applePayContext = STPApplePayContext(paymentRequest: paymentRequest, delegate: self) {
applePayContext.presentApplePay()
}
}
func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: STPPaymentMethod, paymentInformation: PKPayment, completion: @escaping STPIntentClientSecretCompletionBlock) {
checkoutService.fetchCartPaymentIntentClientSecret(cartId: cartId) { result in
switch result {
case .success(let secret):
completion(secret, nil)
case .failure(let error):
completion(nil, error)
}
}
}
func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?) {
self.completion?(status, error)
}
}
(I removed my static variables used in the payment request before I pasted)
That looks correct. Can you share the code where you're creating an instance of this class and calling startApplePay?
yup, heres the code from the view model: ```
private let applePayController = StripeApplePayController()
func payWithApplePay(cartId: String, completion: @escaping (STPPaymentStatus, Error?) -> Void) {
var summaryItems = [PKPaymentSummaryItem]()
summaryItems.append(PKPaymentSummaryItem(label: "Estimated Total", amount: NSDecimalNumber(value: Double(round(100*estimatedTotal)/100))))
summaryItems.append(PKPaymentSummaryItem(label: StripeApplePayController.companyName, amount: NSDecimalNumber(value: Double(round(100*estimatedTotal)/100))))
applePayController.startApplePay(paymentSummaryItems: summaryItems, cartId: cartId) { status, error in
completion(status, error)
}
}
and then the code from the view: ```
Button {
guard let cartId = cartDataStore.cartId else { return }
model.payWithApplePay(cartId: cartId, completion: applePayHandler(status:error:))
} label: {
// Apple Pay Button Style takes care of the label
}
.frame(height: 42)
.buttonStyle(ApplePayButtonStyle(paymentButtonType: .buy))
Hm, interesting. You said this works in the simulator... what version of iOS in the simulator? What version of iOS on device?
iOS 15 on both
I honestly don't know what's wrong or why it would fail like that without any errors. Really strange that applePayContext(_:didCompleteWith:error:) isn't being called.
The error happens after you confirm the payment with Touch/Face ID, right?
yup, double click side button to confirm, scans face, and then payment not completed from the apple pay sheet but no errors from any of the callbacks
almost immediately
Can you share your applePayHandler code?
sure, I think its mostly just view configuration though: ```
private func applePayHandler(status: STPPaymentStatus, error: Error?) {
switch status {
case .success:
navLinkDestination = .confirmation
navLinkActive = true
case .error:
self.cartUpdateError = CheckoutError.unableToProcessYourPayment.description
Log.e(error?.localizedDescription ?? CheckoutError.unableToProcessYourPayment.description)
case .userCancellation:
return
}
}
Have you tried adding a line at the top of that function that logs both status and error?
Or even just to log a THIS CODE RAN string just to confirm it's not getting called?
On the same device can you try the test Apple Pay button on this page and see if it works as expected? https://stripe.com/docs/stripe-js/elements/payment-request-button
I have a breakpoint on didCompleteWith in the model and that hasnt hit either
sure, let me give that a go
that worked
Okay, so that works, it works in another part of your app, it just doesn't work in this particular place, correct?
yeah
๐ค
AND it works on the simulator
(also, ty in advance for your help. I really appreciate it.)
- Can you log
StripeApplePayController.merchantIdentifierand confirm it's set to the expected value just before you use it to initializeSTPApplePayContext?
- Restart the iOS device and try again.
sure let me try those now
okay merchant id looks right, ill try restarting but I had a colleague test on their device also and it didnt work for them either
same behavior
Ah, okay.
also other bit of info, im using the same merchant id across 2 different targets, but I think that should be okay?
it works for our other checkout flow with the same merchant id
That should be fine.
Can you share a (somewhat redacted) screenshot of how your Xcode merchant ID and capability are set up (similar to the screenshot here: https://stripe.com/docs/apple-pay?platform=ios#setup ?
Wondering if the Apple Pay entitlement is wonky.
A colleague mentioned this a while ago:
Apple Pay on simulator works without explicitly enabling the entitlement but to run on device, you need the entitlement and the merchant ID selected in Xcode when you build to device.
hmm redacting all that might be a bit difficult, could I dm it to you?
I have DMs disabled, but can you check and see if the entitlement is enabled and looks correct?
I think I'm out of ideas beyond producing a test case that reproduces the issue and filing an issue at https://github.com/stripe/stripe-ios, but let me think a bit more...
okay ty again
i found it
this line: paymentRequest.merchantCapabilities = .capabilityCredit
if i remove that it works
....hahah
I'm glad you got it working! I'm going to have to research why that's the case later though, as that is not what I would expect!
No problem, have a great day!
you too!
Dropped this in our internal chat to investigate later and my teammate mentioned this:
Dropping this here before I move on - did some quick googling, it sounds like for those capabilities (https://developer.apple.com/documentation/passkit/pkmerchantcapability). capability3DS is required. I wonder if removing the line all together sets it to some default that includes capability3DS and makes it work?
Seems plausible?
ah so are you thinking paymentRequest.merchantCapabilities = [.capability3DS, .capabilityCredit] should work? I can test that in a little bit and let you know
It might, yeah. Worth testing I think!
yup, that worked!