Stripe ApplePayContext fails to present payment sheet on iOS 14 - ios

I'm trying to implement Apple Pay payment throught Stripe and PassKit. I've done the following to create an STPAppleyPayContext, and use its presentApplePay(on:completion:) method to display the Apple Pay payment sheet.
let merchantId = "A_VALID_MERCHANT_ID_HERE"
let currency = "usd"
let country = "US"
let paymentReq = Stripe.paymentRequest(withMerchantIdentifier: merchantId, country: country, currency: currency)
// Configure the line items on the payment request
let charge = NSDecimalNumber(value: 1000)
let summaryItems = [PKPaymentSummaryItem(label: "Service", amount: charge)]
paymentReq.paymentSummaryItems = summaryItems
if let applePayContext = STPApplePayContext(paymentRequest: paymentReq, delegate: self) {
print("--- presenting apple pay sheet")
applePayContext.presentApplePay(on: self, completion: nil)
} else {
print("--- failed to create STPApplePayContext, may be a problem with the Apple Pay config")
}
In the logs, "--- presenting apple pay sheet" was printed, so I believe applePayContext.presentApplePay(on:completion:) was successfully called. However, no sheet was presented, and I can't find any error logs.
The exact same code worked when we build the App on iOS 13, but it doesn't work on iOS 14. I am wondering if it is related some update to the Apple Pay system in iOS 14, or something else went wrong.

Related

Apple pay sheet not showing up for Apple app reviewer

My app keeps getting rejected by the App Review team due to the fact that the Apple Pay button in my app is unresponsive on their device when they tap it. The Apple Pay sheet shows up perfectly fine on my device but never completes the payment (error says my debit card number is invalid, my card works perfectly fine everywhere else, not sure how to fix this, but not the main issue here).
I am not worried about paying with Apple Pay on my app simply because I will not be the one using my app but I do want to ensure it works for everybody else since Apple is bringing it up as a reoccurring issue.
Here is my function for presenting the Apple Pay sheet:
{
guard let cost = actualCostOfEvent.text else { return }
guard let name = nameOfEvent else { return }
let text = cost
let textWithout$ = text.replacingOccurrences(of: "$", with: "")
guard let finalCost = Double(textWithout$) else { return }
let fee = finalCost / Double(12.0)
let roundedFee = floor(fee * 100) / 100.0
let total = finalCost + roundedFee
let paymentRequest = StripeAPI.paymentRequest(withMerchantIdentifier: "merchant.xxxxx.xxxxx.xxxxx",
country: "CA",
currency: "CAD")
paymentRequest.supportedNetworks = [.visa, .masterCard, .interac, .amex, .discover]
paymentRequest.paymentSummaryItems = [
PKPaymentSummaryItem(label: name , amount: NSDecimalNumber(value: finalCost)),
PKPaymentSummaryItem(label: "Service Fee", amount: NSDecimalNumber(value: roundedFee)),
PKPaymentSummaryItem(label: "XXXXXX", amount: NSDecimalNumber(value: total))
]
guard let applePayController = STPApplePayContext(paymentRequest: paymentRequest, delegate: self) else { return }
if StripeAPI.canSubmitPaymentRequest(paymentRequest) {
applePayController.presentApplePay {
self.startApplePayCheckout()
}
}
}
I can't seem to figure out why the Apple Pay sheet doesn't show up for the App reviewer, any suggestions or things needed to be changed? If not, I will just have to submit an appeal.
I have reproduced your code, and it works perfectly fine; the ApplePay sheet is displayed for me. You may want to confirm with Apple what iOS version they are testing and submit an appeal.
A few notes just in case:
You don’t need to check if StripeAPI.canSubmitPaymentRequest(paymentRequest). When you initialized STPApplePayContext it automatically did the check for you: https://github.com/stripe/stripe-ios/blob/master/Stripe/STPApplePayContext.swift#L87
If you are using a test key, you can complete the payment as long as your real card information is correct. You won’t be charged while using a test key.

How to add AppClip to Siri's Nearby Suggestions?

In the video Configure and link your app clips Apple shows it's possible to have your AppClip being suggested by Siri based on the user's location.
I can't find this in the docs https://developer.apple.com/documentation/app_clips
Is this purely based on which location other users are using this app, or is this something a developer can configure (maybe based on a geocode region)?
According to an Apple App Clips engineer I spoke to at WWDC, in order to get your App Clip published onto Apple Maps, you need to have a registered business registered with Apple. This can be done since iOS 10, via Apple Maps Connect, and registering as a small business.
The Nearby Siri suggestion is based on location data and only appears when your App Clip is associated with a place card on Apple Maps so you do not have control over this. It's definitely possible to get the user location after downloading the App Clips, as showed in the following demo but from your question I presumed you wanted to present the App Clip suggestion before downloading (isn't in the developer's control).
If you want to register an App Clip to a location, you need to wait till App Clips are fully usable and publishable on the App Store. When TestFlight and App Store Connect get support for app clips later this year, you'll be able to invoke an app clip from NFC, QR codes, Maps and more. So you would need to register your business with Apple, register your placecard in Apple Maps and then enable App Clips to get the suggestion.
There is a sample code documentation page that has Widgets and App Clip in the code: https://developer.apple.com/documentation/swiftui/fruta_building_a_feature-rich_app_with_swiftui
In the link above in the App Clip code section, there is a payload that has latitude and longitude configurable. Siri should automatically suggest the App Clip based on the location you put in the latitude and longitude.
#if APPCLIP
func handleUserActivity(_ userActivity: NSUserActivity) {
guard let incomingURL = userActivity.webpageURL,
let components = NSURLComponents(url: incomingURL, resolvingAgainstBaseURL: true),
let queryItems = components.queryItems else {
return
}
if let smoothieID = queryItems.first(where: { $0.name == "smoothie" })?.value {
model.selectSmoothie(id: smoothieID)
}
guard let payload = userActivity.appClipActivationPayload,
let latitudeValue = queryItems.first(where: { $0.name == "latitude" })?.value,
let longitudeValue = queryItems.first(where: { $0.name == "longitude" })?.value,
let latitude = Double(latitudeValue), let longitude = Double(longitudeValue) else {
return
}
let region = CLCircularRegion(center: CLLocationCoordinate2D(latitude: latitude,
longitude: longitude), radius: 100, identifier: "smoothie_location")
payload.confirmAcquired(in: region) { inRegion, error in
if let error = error {
print(error.localizedDescription)
return
}
DispatchQueue.main.async {
model.applePayAllowed = inRegion
}
}
}
#endif
The code snippet is from the documentation from link above.
The documentation doesn't go in specific details yet but from what you can read here:
https://developer.apple.com/documentation/app_clips
and here https://developer.apple.com/documentation/app_clips/configuring_your_app_clip_s_launch_experience
under "Review Advanced App Clip Experiences"
You should be able to associate your app clip with a physical location, which will be available in AppStore Connect and with this set, Siri suggestions should be able to pick up your App Clip based on the user location

iOS ApplePay PKPaymentAuthorizationViewController not appearing in Xcode11/iOS 13

Our application has had ApplePay implemented for a number of years. Just recently I hit the button to trigger it to only find out the pay sheet from PKPaymentAuthorizationViewController doesn't appear. It won't slide up in a sandbox (i.e. simulator or device connected to Xcode) environment, but putting a breakpoint shows that it is being created successfully. It's been awhile since I've tested this, but I am suspecting something change with Xcode11 or iOS 13.
My code is pretty standard Apple Pay, but posted below.
let item = PKPaymentSummaryItem()
item.label = "Our Label"
let price = NSDecimalNumber(mantissa: UInt64(totalPrice), exponent: -2, isNegative: false)
item.amount = price
items.append(item)
request.paymentSummaryItems = items
if let applePayController = PKPaymentAuthorizationViewController(paymentRequest: request) {
applePayController.delegate = self
present(applePayController, animated: true)
}
This will happen if the merchantID used by your PKPaymentRequest is not listed in mobile.entitlements. Or if the MerchantID is not enabled by your app's provisioning profile.
View Controller
PKPaymentRequest *request = [[PKPaymentRequest alloc] init];
request.merchantIdentifier = "com.your.app.merchandId"
mobile.entitlements
<dict>
<key>com.apple.developer.in-app-payments</key>
<array>
<string>com.your.app.merchandId</string>
</array>
</dict>
I was facing the same issue, where Apple Pay suddenly stopped working in our app. We've also been supporting this for at least halve a year now.
Using the latest Xcode (Xcode 11.2, Beta 2 (11B44)), it seems to work again.
I'm guessing it was a Xcode bug then. Even though it's not listed in Xcode's release notes for Xcode 11.1 or Xcode 11.2 beta 2.
I have pasted your snippet into my app, which uses ApplePay and I have run it on a test device which is sandboxed and has ApplePay enabled and the ApplePay button didn't work.
What I found it quite surprising.
When you look at the docs for PKPaymentSummaryItem it has only two initialisers:
init(label: String, amount: NSDecimalNumber)
init(label: String, amount: NSDecimalNumber, type:PKPaymentSummaryItemType)
And neither has default values, but you are initialising one with an empty initialiser. Surprisingly there are no errors or warnings and it even comes up in code completion.
So I changed the initialiser:
let item = PKPaymentSummaryItem(label: "Our Label",
amount: NSDecimalNumber(mantissa: UInt64(totalPrice),
exponent: -2,
isNegative: false))
request.paymentSummaryItems = [items]
if let applePayController = PKPaymentAuthorizationViewController(paymentRequest: request) {
applePayController.delegate = self
present(applePayController, animated: true)
}
And it works (on device only - not simulator)!
That made my wonder so I just changed your item from let to var and it works as well. I would still go with the documented initialiser.

How can implement live stripe apple pay in swift? Stripe test key is working fine but not live, how can I fix it?

I'm using stripe apple pay for payment. I have integrated stripe apple pay and it is working fine with test stripe key. But when I use live stripe key it shows an error:
Apple pay not completed "total" was not able to complete the payment.
I'm following stripe doc and this blog to integrate apple pay. Done with these steps:
1: Register for an Apple Merchant ID
2: Create a new Apple Pay certificate
3: Integrate with Xcode
When click on apple pay button, this code will run:
let paymentNetworks:[PKPaymentNetwork] = [.amex, .discover, .masterCard, .visa]
if PKPaymentAuthorizationViewController.canMakePayments(usingNetworks: paymentNetworks) {
let request = PKPaymentRequest()
request.merchantIdentifier = constants.merchantIdentifier
//request.supportedCountries = ["GB"]
request.countryCode = "GB"
request.currencyCode = "GBP"
request.supportedNetworks = paymentNetworks
//request.requiredShippingContactFields = [.name, .postalAddress]
// This is based on using Stripe
request.merchantCapabilities = .capability3DS
let total = PKPaymentSummaryItem(label: "Total", amount: NSDecimalNumber(decimal: Decimal(floatLiteral: Double(totalWithDeliveryCharges))), type: .final)
request.paymentSummaryItems = [total]
let authorizationViewController = PKPaymentAuthorizationViewController(paymentRequest: request)
if let viewController = authorizationViewController {
viewController.delegate = self
present(viewController, animated: true, completion: nil)
}
}
else {
self.showAlert("Alert", "Device does not support apple pay.")
}
My output is :-
Apple pay not completed "total" was not able to complete the payment.
But actual output is
Processing complete
Done.
I forget to refresh apple pay merchant id in XCode after stripe apple pay certificate added.
Follow the image and just click on refresh merchant id button to get rid of this error.
Make sure you have added stripe apple pay certificate by following this step.

Uber button doesn't display price, but only time

This is my first time using Uber api. I followed the instructions clearly, but it never really mentioned how to display price estimate in the button. My code magically displays the time( dunno why or how). Please explain how to display price as well. Both server token and client ID have been integrated in the info.plist file.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = RideRequestButton()
view.addSubview(button)
button.center = view.center
let ridesClient = RidesClient()
let dropOffLocation = CLLocation(latitude: 20.301647, longitude: 85.819135)
let pickUpLocation = CLLocation(latitude : 20.323706, longitude: 85.814981)
let builder = RideParametersBuilder()
builder.pickupLocation = pickUpLocation
builder.pickupNickname = "Home"
builder.dropoffLocation = dropOffLocation
builder.dropoffNickname = "Mayfair Lagoon, Bhubaneswar"
var productID = ""
ridesClient.fetchProducts(pickupLocation: pickUpLocation) { (product, response) in
productID = product[1].productID
print("🥒\(productID)")
}
ridesClient.fetchPriceEstimates(pickupLocation: pickUpLocation, dropoffLocation: dropOffLocation) { (price, response) in
print(price[0].estimate!,"🍚")
}
ridesClient.fetchTimeEstimates(pickupLocation: pickUpLocation) { (time, response) in
print("🥕",time[0].estimate,"🥕")
}
builder.productID = productID
button.setContent()
button.rideParameters = builder.build()
button.loadRideInformation()
}
}
Button will Deeplink into the Uber App and will simply open up the app. In order to see real-time fare estimates and pickup ETA information you will need to pass additional parameters to it. The Ride Request Button can accept optional parameters to pre-load some information into the ride request. You can see how to do it in the Uber documentation. Also this is explained here on the GitHub
Please, check out StackOverflow thread here.
It is explained and documented how to manage this issue.
Please check it out below link
Display ETA and estimated money option for my "Ride there with Uber" button

Resources