The goal is to just make a successful Apple Pay payment and be done with this API integration. I'm literally on the brink of success but I have just one more bug I can't figure out.
func startApplePayCheckout() {
let backendUrlForIntent = "https://us-central1-xxxxx-41f12.cloudfunctions.net/createPaymentIntent"
guard let user = Auth.auth().currentUser else { return }
getUsersStripeCustomerID { (customerid) in
if let id = customerid {
// Create a PaymentIntent as soon as the view loads
let costAsAnInt = self.actualCostOfEvent.text?.replacingOccurrences(of: "$", with: "").replacingOccurrences(of: ".", with: "")
let costForStripe = Int(costAsAnInt!)
let url = URL(string: backendUrlForIntent)!
let json: [String: Any] = [
"amount": costForStripe! + (self.gothereFee * Int(self.stepperValue.value)),
"currency": "CAD",
"customer": id,
"setup_future_usage": "on_session",
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: json)
let task = URLSession.shared.dataTask(with: request, completionHandler: { [weak self] (data, response, error) in
guard let response = response as? HTTPURLResponse,
response.statusCode == 200,
let data = data,
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String : Any],
let clientSecret = json["clientSecret"] as? String else {
let message = error?.localizedDescription ?? "Failed to decode response from server."
self?.displayCancelledAlert(title: "Error Loading Page", message: message)
return
}
guard let paymentIntentID = json["paymentIntentID"] as? String else { return }
self?.db.document("student_users/\(user.uid)/events_bought/\(self?.nameToUseInAPICall)").setData(["stripePaymentIntentID": paymentIntentID], merge: true, completion: { (error) in
if let error = error {
print("There was an error setting the paymentIntentID in the document: \(error)")
} else {
print("PaymentIntentID successfully stored!")
}
})
print("Created PaymentIntent")
self?.paymentIntentClientSecret = clientSecret
})
task.resume()
}
}
I call this right when the Apple Pay sheet is presented. The print statements work fine, the clientSecret gets retrieved. Now when I actually try to pay, I still get a "Payment Not Completed", this is what I have in the didCreatePaymentMethod
function:
func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: STPPaymentMethod, paymentInformation: PKPayment, completion: @escaping STPIntentClientSecretCompletionBlock) {
guard let paymentIntentClient = paymentIntentClientSecret else {
print("There is an issue with the clientSecret")
return
}
let error = NSError(domain: backendUrl, code: 400, userInfo: [NSLocalizedDescriptionKey: "The payment cannot go through for some reason!"])
let paymentIntentParams = STPPaymentIntentParams(clientSecret: paymentIntentClient)
paymentIntentParams.paymentMethodId = paymentMethod.stripeId
let paymentHandler = STPPaymentHandler.shared()
paymentHandler.confirmPayment(paymentIntentParams, with: self) { (status, intent, error) in
switch status {
case .canceled:
print("Payment Canceled")
break
case .failed:
print("Payment Failed")
break
case .succeeded:
print("Payment Succeeded")
break
default:
break
}
}
completion(paymentIntentClient, error)
}
EDIT
So with this implemented, the payment actually charges now when I check in the logs, but for the actual Apple Pay itself, it never shows the success message in the Apple Pay sheet. Here is what I have in the didCompleteWithStatus
method:
func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?) {
guard status == .success else {
print("Payment couldn't go through")
return
}
}
So the weird thing that's going on is that, the first method ends up being successful and the charge is shown in the API Call logs, but the didCompleteWith...
method always finishes with an error status and a "Payment Not Completed" on the Apple sheet and for the life of me I cannot understand why.
applePayContext:didCompleteWithStatus:error:
delegate method try logging bothstatus
anderror
and add the details to your message. – Justin Michaelerror
and feeding it to thecompletion
handler. If you remove thelet error = NSError...
line does it work as expected? – Justin Michael