I am having issues utilizing a pay function given by the stripe documentation
Stripe documentation: https://stripe.com/docs/payments/accept-a-payment
All my server side & client side keys are the same testing keys.
I have successfully retrieved a payment intent with the value
pi_1ITiM3KCSIKL5fqUAMGk32Do_secret_cJfvlRxtnnTuU8VIScj8NCz12
Error message:
No such payment_intent: \ 'pi_1ITiM3KCSIKL5fqUAMGk32Do \ '
Not sure why the error message includes: (possibly json issue)
\ '
Any help would be much appreciated on why this is happening.
var paymentIntentClientSecret: String?
func pay() {
guard let paymentIntentClientSecret = paymentIntentClientSecret else {
return;
}
print(paymentIntentClientSecret) // pi_1ITiM3KCSIKL5fqUAMGk32Do_secret_cJfvlRxtnnTuU8VIScj8NCz12
// Collect card details
let cardParams = creditCardField.cardParams//cardTextField.cardParams
let paymentMethodParams = STPPaymentMethodParams(card: cardParams, billingDetails: nil, metadata: nil)
let paymentIntentParams = STPPaymentIntentParams(clientSecret: paymentIntentClientSecret)
print(paymentIntentParams)
paymentIntentParams.paymentMethodParams = paymentMethodParams
// Submit the payment
let paymentHandler = STPPaymentHandler.shared()
paymentHandler.confirmPayment(paymentIntentParams, with: self) { (status, paymentIntent, error) in
switch (status) {
case .failed:
//self.displayAlert(title: "Payment failed", message: error?.localizedDescription ?? "")
print("failed: \(String(describing: error?.localizedDescription))")
break
case .canceled:
//self.displayAlert(title: "Payment canceled", message: error?.localizedDescription ?? "")
print("cancled: \(String(describing: error?.localizedDescription))")
break
case .succeeded:
//self.displayAlert(title: "Payment succeeded", message: paymentIntent?.description ?? "", restartDemo: true)
print("succeeded: \(String(describing: error?.localizedDescription))")
break
#unknown default:
fatalError()
break
}
}
}
Response body:
{
"error": {
"code": "resource_missing",
"doc_url": "https://stripe.com/docs/error-codes/resource-missing",
"message": "No such payment_intent: 'pi_1ITh8QKCSIKL5fqU7VjJqHH0'",
"param": "intent",
"type": "invalid_request_error"
}
}
“No such...” errors are usually caused by either a mismatch in API keys (e.g. using a mixture of your test plus live keys) or by trying to access objects that exist on a different account (e.g. trying to perform an operation from your platform account on an object that was created on a connected account).
Most likely you're using a publishable key from one account and a secret key from another (assuming you're not using Connect).
Related
I am working in autorenewable subscriptions in app purchases with swiftystorekit but i am facing the issue Reciept validation error. I verify all the products in home screen during verify i am facing this issue. I get help from https://github.com/bizz84/SwiftyStoreKit and Videos series https://youtu.be/6ekX7FK0OTY
but i unable to resolve this issue please help me.
Please help.
Code is given below
its go to in error section.
Check error
image
//MARK: - Verify Subscription
func verifyPurchases(id:String,secretkey:String,type: SubscriptionType,validDuration:TimeInterval? = nil){
DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
self.showIndicator(caption: "Loading...")
}
let appleValidator = AppleReceiptValidator(service: .production, sharedSecret: secretkey)
SwiftyStoreKit.verifyReceipt(using: appleValidator) { result in
switch result {
case .success(let receipt):
// Verify the purchase of a Subscription
switch type {
case .simple:
// Verify the purchase of Consumable or NonConsumable
let purchaseResult = SwiftyStoreKit.verifyPurchase(
productId: id,
inReceipt: receipt)
switch purchaseResult {
case .purchased(let receiptItem):
print("\(id) is purchased: \(receiptItem)")
self.hideIndicator()
case .notPurchased:
print("The user has never purchased \(id)")
self.hideIndicator()
}
case .autoRenewable:
let purchaseResult = SwiftyStoreKit.verifySubscription(
ofType: .autoRenewable, // or .nonRenewing (see below)
productId: id,
inReceipt: receipt)
switch purchaseResult {
case .purchased(let expiryDate, let items):
print("\(id) is valid until \(expiryDate)\n\(items)\n")
if id == self.purchasesIds[0]{
self.subsStatus = "Monthly"
self.uploadData(expiryDate:expiryDate)
}else if id == self.purchasesIds[1]{
self.subsStatus = "Yearly"
self.uploadData(expiryDate: expiryDate)
}
self.hideIndicator()
case .expired(let expiryDate, let items):
print("\(id) is expired since \(expiryDate)\n\(items)\n")
self.setData()
self.hideIndicator()
case .notPurchased:
print("The user has never purchased \(id)")
self.setData()
self.hideIndicator()
}
case .nonRenewing:
// validDuration: time interval in seconds
guard let validDuration = validDuration else {return}
let purchaseResult = SwiftyStoreKit.verifySubscription(
ofType: .nonRenewing(validDuration: validDuration),
productId: id,
inReceipt: receipt)
switch purchaseResult {
case .purchased(let expiryDate, let items):
print("\(id) is valid until \(expiryDate)\n\(items)\n")
self.hideIndicator()
case .expired(let expiryDate, let items):
print("\(id) is expired since \(expiryDate)\n\(items)\n")
self.hideIndicator()
case .notPurchased:
print("The user has never purchased \(id)")
self.hideIndicator()
}
}
case .error(let error):
print("Receipt verification failed: \(error)")
self.errorWithMsgTitle(title: "Receipt verification failed", message: "Receipt verification failed: \(error)")
self.hideIndicator()
}
}
}
I can't login and always see this error message:
The verification ID used to create the phone auth credential is invalid
I tried to add my phone like tester, but I wasn't succeed on it.
Sign in method is turn on in Firebase console.
I found the same issue here, but without answer.
I used firebase's docs.
Help me please to figure it out.
Here my code:
func verifyPhone(_ phone: String) -> AsyncTask<String?> {
return AsyncTask<String?>({ observer, lifetime in
guard !lifetime.hasEnded else {
observer.sendInterrupted()
return
}
Auth.auth().languageCode = "ua"
PhoneAuthProvider.provider().verifyPhoneNumber(phone, uiDelegate: nil) { verificationID, error in
if let error = error {
observer.send(error: AppError(error))
return
}
observer.send(value: verificationID)
observer.sendCompleted()
}
})
}
func signInViaPhoneNumber(usingCode smsCode: String) -> AsyncTask<Void> {
return AsyncTask<Void>({ observer, lifetime in
guard !lifetime.hasEnded else {
observer.sendInterrupted()
return
}
guard let verificationCode = UserDefaultsStorage.verificationCode else {
observer.send(error: AppError.logic("Відсутній код верифікації"))
return
}
let credential = PhoneAuthProvider.provider().credential(withVerificationID: smsCode,
verificationCode: verificationCode)
Auth.auth().signIn(with: credential) { result, error in
if let error = error {
observer.send(error: AppError(error))
return
}
guard let firUser = result?.user else {
observer.send(error: AppError.logic("Відсутній юзер"))
return
}
let factory: ModelFactory = ModelFactoryImpl()
let appUser = factory.makeUser(id: firUser.uid, name: firUser.displayName ?? "", phone: firUser.phoneNumber ?? "")
AppService.shared.user = appUser
observer.send(value: ())
observer.sendCompleted()
}
})
}
It's hard for me to see the complete code flow because you are using AsyncTask and delegating all the results outside.
The issue that pops out in your code is the line
PhoneAuthProvider.provider().credential(withVerificationID: smsCode,
verificationCode: verificationCode)
In this method verificationCode should be the code you received via SMS and withVerificationID should be the verificationId that you got in the verifyPhoneNumber callback.
i did all the code regarding to the Stripe and i followed the documentation of the stripe in which i i am calling one api to get the secret key from the server n which is coming..and after that i am passing it ot the "STPPaymentHandler.shared()"..but i am getting the error STPPaymentHandlerActionStatus error Optional("No such setupintent: (null)") a..please help me if you know thank you in advance
below the code which i did
i followed this documentation
https://stripe.com/docs/payments/accept-a-payment
//method to get secrete key
func checkout() {
let apikey = UserDefaults.standard.value(forKey: keyParameter.apikey.rawValue) as! String
let dic = ["apikey":apikey,"amount":"5000"]
Webhelper.sharedInstance.apiPostRequest(apiUrl: GlobalConstant.stripe_token, parameter: dic, success: { (success) in
print("success from the server is \(success)")
do{
let responseResult = try Global.sharedInstance.decode(jwtToken: success)
let message = Global.sharedInstance.getStringValue(responseResult["Message"] as AnyObject)
if let status = responseResult["result"] as? NSNumber {
if status == 1{
let responseDic = responseResult["Secrate"] as! NSDictionary
self.setupIntentClientSecret = responseDic.value(forKey: "clientSecret") as! String
let apikey = responseDic.value(forKey: "publishableKey") as! String
Stripe.setDefaultPublishableKey(apikey)
print(" self.setupIntentClientSecret self.setupIntentClientSecret \(self.setupIntentClientSecret)")
}else if status == 0{
Global.sharedInstance.ShowMessagePopup(Viewobj: self, title: "", Message: message)
}
}
}catch{
print("cought error in the catch \(error.localizedDescription)")
}
}) { (error) in
print("error for the server is \(error.localizedDescription)")
}
}
///this is the method to complete the payment
#objc func pay() {
// Collect card details
let cardParams = self.paymentTextField.cardParams
// Collect the customer's email to know which customer the PaymentMethod belongs to.
let billingDetails = STPPaymentMethodBillingDetails()
billingDetails.email = "sunil#gmial.com"//emailTextField.text
// Create SetupIntent confirm parameters with the above
let paymentMethodParams = STPPaymentMethodParams(card: cardParams, billingDetails: billingDetails, metadata: nil)
print("setupIntentClientSecret inside method\(setupIntentClientSecret)")
let setupIntentParams = STPSetupIntentConfirmParams(clientSecret: setupIntentClientSecret)
setupIntentParams.paymentMethodParams = paymentMethodParams
print("secrete \(setupIntentClientSecret)")
// Complete the setup
let paymentHandler = STPPaymentHandler.shared()
paymentHandler.confirmSetupIntent(withParams: setupIntentParams, authenticationContext: self) { status, setupIntent, error in
print("success from the server is setupIntent\(setupIntent) status \(status) error \(error?.localizedDescription)")
switch (status) {
case .failed:
self.displayAlert(title: "Setup failed", message: error?.localizedDescription ?? "")
// print("\(error?.localizedDescription)")
break
case .canceled:
self.displayAlert(title: "Setup canceled", message: error?.localizedDescription ?? "")
break
case .succeeded:
self.displayAlert(title: "Setup succeeded", message: setupIntent?.description ?? "", restartDemo: true)
break
#unknown default:
fatalError()
break
}
}
}
I am using string in this application perviously but all the things done by backend developer but now stripe change their implementation and give support for European payment change (Supporting 3D Secure Authentication) with SCA so now i need to add library in my local code but i stuck at this place.
I got the client id from server but handle next action will give me error something like this.
Error Domain=STPPaymentHandlerErrorDomain Code=1 "There was an unexpected error -- try again in a few seconds" UserInfo={com.stripe.lib:ErrorMessageKey=The PaymentIntent requires a PaymentMethod or Source to be attached before using STPPaymentHandler., NSLocalizedDescription=There was an unexpected error -- try again in a few seconds}
I did not find any relative document here
Here is my code
//Api called on server for client id
MyAPIClient.sharedClient.createAndConfirmPaymentIntent(paymentResult,
amount: self.paymentContext.paymentAmount,
returnURL: "payments-example://stripe-redirect",
shippingAddress: self.paymentContext.shippingAddress,
shippingMethod: self.paymentContext.selectedShippingMethod) { (clientSecret, error) in
guard let clientSecret = clientSecret else {
completion(.error, error ?? NSError(domain: StripeDomain, code: 123, userInfo: [NSLocalizedDescriptionKey: "Unable to parse clientSecret from response"]))
return
}
STPPaymentHandler.shared().handleNextAction(forPayment: clientSecret, authenticationContext: paymentContext, returnURL: "payments-example://stripe-redirect") { (status, handledPaymentIntent, actionError) in
switch (status) {
case .succeeded:
guard let handledPaymentIntent = handledPaymentIntent else {
completion(.error, actionError ?? NSError(domain: StripeDomain, code: 123, userInfo: [NSLocalizedDescriptionKey: "Unknown failure"]))
return
}
if (handledPaymentIntent.status == .requiresConfirmation) {
// Confirm again on the backend
MyAPIClient.sharedClient.confirmPaymentIntent(handledPaymentIntent) { clientSecret, error in
guard let clientSecret = clientSecret else {
completion(.error, error ?? NSError(domain: StripeDomain, code: 123, userInfo: [NSLocalizedDescriptionKey: "Unable to parse clientSecret from response"]))
return
}
// Retrieve the Payment Intent and check the status for success
STPAPIClient.shared().retrievePaymentIntent(withClientSecret: clientSecret) { (paymentIntent, retrieveError) in
guard let paymentIntent = paymentIntent else {
completion(.error, retrieveError ?? NSError(domain: StripeDomain, code: 123, userInfo: [NSLocalizedDescriptionKey: "Unable to parse payment intent from response"]))
return
}
if paymentIntent.status == .succeeded {
completion(.success, nil)
}
else {
completion(.error, NSError(domain: StripeDomain, code: 123, userInfo: [NSLocalizedDescriptionKey: "Authentication failed."]))
}
}
}
} else {
// Success
completion(.success, nil)
}
case .failed:
completion(.error, actionError)
case .canceled:
completion(.userCancellation, nil)
}
}
My fix was to call paymentManager.confirmPayment(withParams: params, authenticationContext: self) instead of handleNextAction
I know exactly what is happening but I'm unable to fix it. In my mind this works like:
Fetch a document from firestore database where field is a certain string
db.collection("Connections").whereField("UID", isEqualTo: user.uid).whereField("status", isEqualTo: "waitingForUser").addSnapshotListener { (querySnap, error) in
I'm storing let thisStatus: String = data?["status"] as! String and then I've a switch statement which performs tasks based on what the status is now.
If there is a userID with status waitingForUser I need to update the status to onGoing
let document = querySnap?.documents.first
document?.reference.updateData(["status": "onGoing"], completion: { (error) in
I need snapshot listener because I'll be changing status multiple times.
The problem that I'm having is that it runs successfully for the first time but after step 3 it goes to step 1 and there as the condition is false as the status is no longer waitingForUser it's onGoing hence making the program to throw fatal error as there is no data?["status"]. What should I do to make this work I need listener and I need to change status multiple times.
Here is the UPDATED full code block:
db.collection("Connection").whereField("UID2", isEqualTo: user.uid).whereField("status", isEqualTo: "waitingForUser2").addSnapshotListener { (querySnap, error) in
if let error = error {
print("Error: \(error)")
} else {
let data = querySnap?.documents.first?.data()
guard let thisStatus: String = data?["status"] as! String
else { return }
switch thisStatus {
case "waitingForUser2":
//Update the status to onGoing
let document = querySnap?.documents.first
document?.reference.updateData([
"status": "onGoing"
], completion: { (error) in
print("Status is now on going")
})
case "connectionMade":
print("it's connection made")
default:
print("DEFAULT is ON")
}
}