#etienne-swift-applepay

1 messages · Page 1 of 1 (latest)

tame tapirBOT
light phoenix
#

@tepid peak Hello! I'm happy to help but I'm going to need a lot more specific details than what you said unfortunately.
Step 1: Exact PaymentIntent id
Step 2: Exact iOS client-side code and the exact doc URL you are following
Step 3: Exact error you get, clear logs about where the issue is failing, etc

#

etienne-swift-applepay

tepid peak
#
  1. "pi_3NzNJjIpmrzcezdL2Ig8VGAn"
  2. Client Side Code:

import Foundation
import PassKit
import Stripe

class ApplePayModel : NSObject, ObservableObject, STPApplePayContextDelegate {
@Published var paymentStatus: STPPaymentStatus?
@Published var lastPaymentError: Error?
var clientSecret: String?

func pay(clientSecret: String?, donationAmount: String) {
    self.clientSecret = clientSecret

    // Configure a payment request
    let pr = StripeAPI.paymentRequest(withMerchantIdentifier: "merchant.co.somethingdope.yshuascripture", country: "US", currency: "USD")

    pr.requiredShippingContactFields = []
    pr.requiredBillingContactFields = [.postalAddress]

    // Build payment summary items
    pr.paymentSummaryItems = [
        PKPaymentSummaryItem(label: "Donation", amount: NSDecimalNumber(string: donationAmount)), //Double(donationAmountCents)
        PKPaymentSummaryItem(label: "Dontaion", amount: NSDecimalNumber(string: donationAmount)) //Double(donationAmountCents)
    ]

    // Present the Apple Pay Context:
    let applePayContext = STPApplePayContext(paymentRequest: pr, delegate: self)
    applePayContext?.presentApplePay()
}



func applePayContext(_ context: STPApplePayContext, didCreatePaymentMethod paymentMethod: STPPaymentMethod, paymentInformation: PKPayment, completion: @escaping STPIntentClientSecretCompletionBlock) {
    // Confirm the PaymentIntent
    if (self.clientSecret != nil) {
        // Call the completion block with the PaymentIntent's client secret.
        completion(clientSecret, nil)
    } else {
        completion(nil, NSError())
    }
}

func applePayContext(_ context: STPApplePayContext, didCompleteWith status: STPPaymentStatus, error: Error?) {
    // When the payment is complete, display the status.
    self.paymentStatus = status
    self.lastPaymentError = error
}

}

#

class BackendModel: ObservableObject {
@Published var paymentStatus: STPPaymentHandlerActionStatus?
@Published var paymentIntentParams: STPPaymentIntentParams?
@Published var lastPaymentError: NSError?
var paymentMethodType: String?
var currency: String?

#

func preparePaymentIntent(paymentMethodType: String, currency: String) {
self.paymentMethodType = paymentMethodType
self.currency = currency
// MARK: Fetch the PaymentIntent from the backend
// Create a PaymentIntent by calling the sample server's /create-payment-intent endpoint.
let url = URL(string: backendURL + "create-payment-intent")!
let json: [String: Any] = [
"currency": currency,
"paymentMethodType": paymentMethodType,
"amount": 60
]
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 = """
Failed to decode response from server.
Error: (error?.localizedDescription ?? "N/A")
HTTP Status Code: ((response as? HTTPURLResponse)?.statusCode ?? -1)
Data: (String(data: data ?? Data(), encoding: .utf8) ?? "N/A")
"""
print(message)
return
}
print("Created PaymentIntent")
// MARK: Create the PaymentIntent
DispatchQueue.main.async {
self?.paymentIntentParams = STPPaymentIntentParams(clientSecret: clientSecret)
}
})
task.resume()
}

#

func onCompletion(status: STPPaymentHandlerActionStatus, pi: STPPaymentIntent?, error: NSError?) {
self.paymentStatus = status
self.lastPaymentError = error

    // MARK: Demo cleanup
    if status == .succeeded {
        // A PaymentIntent can't be reused after a successful payment. Prepare a new one for the demo.
        self.paymentIntentParams = nil
        preparePaymentIntent(paymentMethodType: self.paymentMethodType!, currency: self.currency!)
    }
}

}

#

Call Code:
if let paymentStatus = applePayModel.paymentStatus {
HStack {
switch paymentStatus {
case .success:
Image(systemName: "checkmark.circle.fill").foregroundColor(.green)
Text("Payment complete!")
case .error:
Image(systemName: "xmark.octagon.fill").foregroundColor(.red)
Text("Payment failed!")
case .userCancellation:
Image(systemName: "xmark.octagon.fill").foregroundColor(.orange)
Text("Payment canceled.")
@unknown default:
Text("Unknown status")
}
}
}

            }
            .foregroundStyle(themeManager.currentTheme.textColor)
            .padding()
        }
       
            Button(action: {
                backendModel.preparePaymentIntent(paymentMethodType: "card", currency: "usd")
                
                let donationAmount = amount.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
                applePayModel.pay(clientSecret: backendModel.paymentIntentParams?.clientSecret, donationAmount: donationAmount)
            }, label: {
                ZStack {
                    RoundedRectangle(cornerRadius: 25)
                        .frame(height: 50)
                        .foregroundStyle(themeManager.currentTheme.textColor)
                    Text("Give Now")
                    //.font(.title3)
                        .foregroundStyle(themeManager.currentTheme.backgroundColor)
                        .fontWeight(.bold)
                }
            })
#

The exact error i am getting is "Payment Failed"

light phoenix
#

That I'm sorry I didn't expect you to drop dozens of lines of code like this

tepid peak
#

Oh i apologise

#

I will try to explain better

#

This is what i am following

#

My code is identical to this

light phoenix
#

@lofty frigate is taking over for me and will help

lofty frigate
#

Hello! I'm taking over and catching up...

tepid peak
#

Hi Rubeus!

#

My console and stripe dashboard looks like it should be working, however, when I try to make a test payment (in this case $1), I am getting an error from apple pay saying that the payment failed

lofty frigate
#

What's the underlying error logged in the debugger when this happens?

tepid peak
#

LOG ANALYTICS: ["os_version": "17.0", "install": "S", "analytics_ua": "analytics.stripeios-1.0", "network_type": "Wi-Fi", "pay_var": "legacy", "device_type": "iPhone15,2", "event": "stripeios.token_creation", "app_version": "1.0", "ocr_type": "none", "product_usage": ["STPApplePayContext"], "bindings_version": "23.17.0", "token_type": "apple_pay", "publishable_key": "unknown", "additional_info": [], "apple_pay_enabled": 1, "app_name": "Yshua"]

#

other than that the payment intent is showing that it was created successfully

lofty frigate
#

The Payment Intent creation is separate from the Apple Pay payment attempt. I'm asking what errors are showing up in Xcode when this happens?

tepid peak
#

There arn't any, that is what i'm confused about

lofty frigate
#

Can you share a screenshot or video of what you're seeing?

tepid peak
lofty frigate
#

No, sorry. Earlier you said this:

my apple pay gets rejected and says payment failed

Where are you seeing that? Can you share a screenshot of that?

tepid peak
#

Its not in Xcode. Its on my physical device when I try to make a payment. I choose a card to pay with, click pay on the apple pay popup, and then it loads for a second and gets rejected, And then the applePayModel.paymentStatus = case .error:

lofty frigate
#

Can you run the app on your device from Xcode so you can see the debugging console when this error happens?

tepid peak
#

The screenshot I provided is what I receive when this happens

lofty frigate
#

Meaning in Xcode choose your physical device as the target, then run from Xcode, then reproduce the error, then look in Xcode's debug console?

tepid peak
#

that is what i provided. this is why i am confused because the console hasn't trown an error and stripe hasn't either. The only way i can see an error is on my physical device.

Is there something specific you want me to print out, like write a print statement and then recreate the error?

lofty frigate
#

To clarify, is your code above displaying the error? Meaning is Text("Payment failed!") the source of the error you're seeing?

tepid peak
#

wait

#

Yes

#

When this happens the Text box is showing on my device Payment Failed

lofty frigate
#

With or without the !?

tepid peak
#

with

lofty frigate
#

Can you add additional logging to your code to surface the underlying error details?

tepid peak
#

yes i can

#

what exactly would you like to see

#

because after the payment is ran, and gets failed, this block of code switchs the error case and displays the Text("Payment Failed!") with the image:

if let paymentStatus = applePayModel.paymentStatus {
HStack {
switch paymentStatus {
case .success:
Image(systemName: "checkmark.circle.fill").foregroundColor(.green)
Text("Payment complete!")
case .error:
Image(systemName: "xmark.octagon.fill").foregroundColor(.red)
Text("Payment failed!")
case .userCancellation:
Image(systemName: "xmark.octagon.fill").foregroundColor(.orange)
Text("Payment canceled.")
@unknown default:
Text("Unknown status")
}
}
}

lofty frigate
#

Go into your ApplePayModel class and add logging in your didCompleteWith delegate method. There should be an error object passed in there that contains additional details.

tepid peak
#

Task <E78679D1-0EF8-485A-B322-7BC854E35BDC>.<1> finished with error [-1,200] Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSErrorFailingURLStringKey=https://m.stripe.com/6, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <E78679D1-0EF8-485A-B322-7BC854E35BDC>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <E78679D1-0EF8-485A-B322-7BC854E35BDC>.<1>"
), NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://m.stripe.com/6, NSUnderlyingError=0x283879080 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, _kCFNetworkCFStreamSSLErrorOriginalValue=-9816, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9816, _NSURLErrorNWPathKey=satisfied (Path is satisfied), viable, interface: en0[802.11], ipv4, ipv6, dns}}, _kCFStreamErrorCodeKey=-9816}

#

Apple Pay Error: There was an unexpected error -- try again in a few seconds

lofty frigate
#

Where is that from? It's doubtful that's related.

#

Errors with the m.stripe.com domain should not impact functionality.

#

Where is Apple Pay Error: There was an unexpected error -- try again in a few seconds from?

tepid peak
#

I am adding the didCompleteWith error, give me a few moments

lofty frigate
#

Usually that error indicates an unexpected response from Stripe, like a 500, or unparsable JSON. It's very unusual to encounter that one, as those things mostly never happen. Is the device you're testing with able to access the internet without restrictions? Also wondering if the date and time on the device is set correctly?

tepid peak
#

Yes it is, as it is my personal device. Would you like me to try again on another physical device?

lofty frigate
#

If you have another device there yeah, that would be helpful.

tepid peak
#

one moment

lofty frigate
#

What version of iOS are you running on these devices?

tepid peak
#

ios17

#

LOG ANALYTICS: ["publishable_key": "unknown", "bindings_version": "23.17.0", "network_type": "Wi-Fi", "ocr_type": "none", "app_name": "Yshua", "additional_info": [], "pay_var": "legacy", "install": "S", "token_type": "apple_pay", "event": "stripeios.token_creation", "analytics_ua": "analytics.stripeios-1.0", "apple_pay_enabled": 1, "os_version": "17.0.1", "product_usage": ["STPApplePayContext"], "app_version": "1.0", "device_type": "iPhone15,3"]
Apple Pay Error: There was an unexpected error -- try again in a few seconds

#

again, an issue with another device

lofty frigate
#

Did you run into any issues creating your Apple merchant ID or certificate?

tepid peak
#

I did everything according to the stripe docs

lofty frigate
tepid peak
#

Question, if my merchant ID is in red text on the Apple Pay of the Signing & Capabilities, would that persent an issue?

#

yesterday it was white

lofty frigate
#

Ah, yes, that indicates there's some kind of issue there.

tepid peak
#

My developer account is currently being migrated right now, would that impact this?

lofty frigate
#

That could cause the issue you're seeing.

#

Honestly I'm not sure.

#

Probably.

#

When you present the Apple Pay sheet the app reaches out to Apple to try and create an Apple Pay Session using your merchant ID and certificate.

#

If your account is in a wonky state that's probably failing and causing this error.

tepid peak
#

My certificate should be fine though as i submitted the stripe one to my dev account, and then reuploaded the response certificate back to stripe

lofty frigate
#

My guess is the request to create the Apple Pay Session is failing with an unexpected error/response due to your account state.

tepid peak
#

Okay, i will look into it. Regarding my code, if you don't see an issue with my code, then i can probably figure this out myself! Thank you for your help Rubeus!

lofty frigate
#

Yeah, I recommend the network/HTTP debugging as the next step.

tepid peak
#

Okay Great, i will do that right now

lofty frigate
#

That should shed some light on what's actually going on.

tepid peak
#

Okay, I will reach out again if I need your help!