Stripe - 单一方法预构建 UI,STPAPIClient.shared().publishableKey iOS Swift UiKit
Posted
技术标签:
【中文标题】Stripe - 单一方法预构建 UI,STPAPIClient.shared().publishableKey iOS Swift UiKit【英文标题】:Stripe - single method prebuit UI, STPAPIClient.shared().publishableKey iOS Swift UiKit 【发布时间】:2021-10-31 20:24:14 【问题描述】:我关注了这个文档:https://stripe.com/docs/payments/accept-a-payment?platform=ios&ui=payment-sheet
我从我的后端获取这些。
"clientSecret" : "pi_3JUrPkLW44AR......7WElFl", "stripecustomerid" : "cus_K8......pLu4", “paymentids”:“pi_3JVA .....R9VmA” "EphemeralKey" : "ephkey_1JV......kEtnlw"
//PaymentSheet Configuration
let clientSecret = response["clientSecret"].stringValue
let ephemeralSecret = response["EphemeralKey"].stringValue
let cusId = response["stripecustomerid"].stringValue
// MARK: Set your Stripe publishable key - this allows the SDK to make requests to Stripe for your account
STPAPIClient.shared.publishableKey = self.publishableKey
// MARK: Create a PaymentSheet instance
var configuration = PaymentSheet.Configuration()
configuration.merchantDisplayName = "Z*****"
configuration.customer = .init( id: cusId, ephemeralKeySecret: ephemeralSecret)
configuration.returnURL = "payments-example://stripe-redirect"
self.paymentSheet = PaymentSheet(
paymentIntentClientSecret: clientSecret,
configuration: configuration)
在此之后(付款开始)我从条带获取日志:
日志分析:[“product_usage”:[“PaymentSheet”],“app_name”:“Zucraz”,“additional_info”:[],“bindings_version”:“21.8.1”,“apple_pay_enabled”:0,“ocr_type “:“无”,“os_version”:“14.4”,“analytics_ua”:“analytics.stripeios-1.0”,“ui_usage_level”:“部分”,“publishable_key”:“pk_test_51J9Te0LW............tRQbRP2 ", "device_type": "iPhone12,1", "event": "mc_complete_init_customer", "app_version": "3.4"]
调用此方法时 - 显示 PaymentSheet
func openPaymentSheet()
// MARK: Start the checkout process
paymentSheet?.present(from: self) paymentResult in
// MARK: Handle the payment result
switch paymentResult
case .completed:
self.displayAlert("Your order is confirmed!")
case .canceled:
print("Canceled!")
case .failed(let error):
print(error)
self.displayAlert("Payment failed: \n\(error.localizedDescription)")
收到此错误
Error Domain=com.stripe.lib Code=50 "There was an unexpected error -- try again in a few seconds" UserInfo=NSLocalizedDescription=There was an unexpected error -- try again in a few seconds, com.stripe.lib:ErrorMessageKey=No valid API key provided. Set `STPAPIClient.shared().publishableKey` to your publishable key, which you can find here: https://stripe.com/docs/keys, com.stripe.lib:StripeErrorTypeKey=invalid_request_error, com.stripe.lib:StripeErrorCodeKey=
文档中没有定义设置 STPAPIClient.shared().publishableKey。 仍然,我尝试在我的视图控制器中设置 STPAPIClient.shared.publishableKey,但仍然收到错误。
提前致谢
完整的类代码:
导入 UIKit 导入 SwiftyJSON 导入 FirebaseAnalytics 导入条纹 导入 PassKit
类 ReviewOrderViewC: UIViewController,UITableViewDelegate,UITableViewDataSource
@IBOutlet weak var viewForEmptyCart: UIView!
@IBOutlet weak var lblCity: UILabel!
@IBOutlet weak var lblNsmr: UILabel!
@IBOutlet weak var lblAdress: UILabel!
@IBOutlet weak var lblMobile: UILabel!
var responseData : JSON = []
@IBOutlet weak var tblReview: UITableView!
@IBOutlet weak var btnCod: UIButton!
@IBOutlet weak var btnOnlinePayment: UIButton!
@IBOutlet weak var lblApplyCoupon: UILabel!
@IBOutlet weak var viewForApplyCoupon: UIView!
@IBOutlet weak var txtCouponCode: UITextField!
@IBOutlet weak var lblCartTotalAmount: UILabel!
@IBOutlet weak var lblTotalAmount: UILabel!
@IBOutlet weak var viewBlankForCoupn: UIView!
var paymentType = "cod"
var couponCode = ""
@IBOutlet weak var lblEmptyCartText: UILabel!
@IBOutlet weak var lblAddInCartText: UILabel!
@IBOutlet weak var btnContinueSaida: CustomButton!
@IBOutlet weak var lblReviewOrder: UILabel!
@IBOutlet weak var lblMobileText: UILabel!
@IBOutlet weak var btnEditChange: UIButton!
@IBOutlet weak var lblOnlineText: UILabel!
@IBOutlet weak var lblCODText: UILabel!
@IBOutlet weak var lblPaymentMethodText: UILabel!
@IBOutlet weak var lblPriceDetailsText: UILabel!
@IBOutlet weak var lblCartTotalText: UILabel!
@IBOutlet weak var lblTotalAmountText: UILabel!
@IBOutlet weak var btnProcedd: CustomButton!
@IBOutlet weak var lblCouponText: UILabel!
@IBOutlet weak var btnApplyCoupon: UIButton!
@IBOutlet weak var lblDelivery: UILabel!
@IBOutlet weak var lblDeliveryText: UILabel!
@IBOutlet weak var lblDelTime: UILabel!
@IBOutlet weak var lblDiscountText: UILabel!
@IBOutlet weak var lblDiscount: UILabel!
@IBOutlet weak var lblFreeDel: UILabel!
@IBOutlet weak var lblCreditText: UILabel!
@IBOutlet weak var lblCreditPointText: UILabel!
@IBOutlet weak var btnRemoveCoupon: UIButton!
var addressData : JSON = []
var couponAmt = "0"
//For Stripe
var customerContext : STPCustomerContext?
var paymentContext : STPPaymentContext?
var isSetShipping = false
var paymentSheet: PaymentSheet?
var clientSecret = ""
var ephemeralKeySecret = ""
var paymentSheetFlowController: PaymentSheet.FlowController!
@IBOutlet weak var buyButton: UIButton!
@IBOutlet weak var paymentMethodButton: UIButton!
@IBOutlet weak var paymentMethodImage: UIImageView!
let publishableKey = "pk_test_51J***************bRP2"
override func viewDidLoad()
super.viewDidLoad()
self.orderReview()
viewForApplyCoupon.isHidden = true
viewBlankForCoupn.isHidden = true
//Add Tap Gesture on Blank view to hide apply Coupon
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
viewBlankForCoupn.addGestureRecognizer(tap)
viewForApplyCoupon.layer.cornerRadius = 8
viewForApplyCoupon.clipsToBounds = true
btnCod.setImage(#imageLiteral(resourceName: "radio"), for: .normal)
// viewForEmptyCart.isHidden = true
lblReviewOrder.text = "reviewOrder".localizableSting()
lblMobileText.text = "mobile".localizableSting() + " :"
btnEditChange.setTitle("edit".localizableSting(), for: .normal)
lblPaymentMethodText.text = "paymentMethod".localizableSting()
lblCODText.text = "cod".localizableSting()
lblOnlineText.text = "online".localizableSting()
lblApplyCoupon.text = "applyCoupon".localizableSting()
lblPriceDetailsText.text = "priceDetails".localizableSting()
lblCartTotalText.text = "cartTotal".localizableSting()
lblTotalAmountText.text = "total".localizableSting()
btnProcedd.setTitle("proceedReview".localizableSting(), for: .normal)
lblEmptyCartText.text = "blankCartText".localizableSting()
lblAddInCartText.text = "addInCartText".localizableSting()
btnContinueSaida.setTitle("continueSaida".localizableSting(), for: .normal)
lblCouponText.text = "coupon".localizableSting()
txtCouponCode.placeholder = "txtCoupon".localizableSting()
btnApplyCoupon.setTitle("apply".localizableSting(), for: .normal)
btnOnlinePayment.isEnabled = true
self.lblDeliveryText.text = "deliveryCharges".localizableSting()
self.lblNsmr.text = self.addressData["fname"].stringValue + " " + self.addressData["lname"].stringValue
self.lblAdress.text = "\(self.addressData["address"].stringValue), \(self.addressData["state"].stringValue), \(self.addressData["city"].stringValue)"
self.lblMobile.text = self.addressData["mobileno"].stringValue
if NetworkManeger.getWalletStatus() == "0"
lblCreditText.isHidden = true
lblCreditPointText.isHidden = true
else
lblCreditText.isHidden = false
lblCreditPointText.isHidden = false
self.intiateStripePayment()
@objc func handleTap(_ sender: UITapGestureRecognizer? = nil)
// handling code
viewForApplyCoupon.isHidden = true
viewBlankForCoupn.isHidden = true
@IBAction func btnCODAction(_ sender: Any)
paymentType = "cod"
btnCod.setImage(#imageLiteral(resourceName: "radio"), for: .normal)
btnOnlinePayment.setImage(#imageLiteral(resourceName: "contact_us_icon-1"), for: .normal)
@IBAction func btnOnlineAction(_ sender: Any)
if self.responseData["totalcost"].floatValue > 0
paymentType = "online"
btnOnlinePayment.setImage(#imageLiteral(resourceName: "radio"), for: .normal)
btnCod.setImage(#imageLiteral(resourceName: "contact_us_icon-1"), for: .normal)
@IBAction func btnApplyCouponAction(_ sender: Any)
//Show blank view and coupon code view
viewForApplyCoupon.isHidden = false
viewBlankForCoupn.isHidden = false
@IBAction func btnApplyCouponCode(_ sender: Any)
//Call after response from API
couponCode = txtCouponCode.text ?? ""
txtCouponCode.resignFirstResponder()
//orderReview()
addCoupon()
viewForApplyCoupon.isHidden = true
viewBlankForCoupn.isHidden = true
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return self.responseData["productdetails"].count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "ReviewOrderTableViewCell", for: indexPath) as! ReviewOrderTableViewCell
let imgURLString = self.responseData["productdetails"][indexPath.row]["imageurl"].stringValue
let newImageUrlStr = imgURLString.replacingOccurrences(of: " ", with: "%20")
let imageUrl = URL(string:newImageUrlStr)
cell.imgCartProduct.af_setImage(withURL:imageUrl!)
cell.lblCartProductName.text = self.responseData["productdetails"][indexPath.row]["productname"].stringValue
cell.lblPrice.text = self.responseData["productdetails"][indexPath.row]["sellingprice"].stringValue + " " + "JD".localizableSting()
cell.lblQuantity.text = self.responseData["productdetails"][indexPath.row]["qty"].stringValue
cell.lblBySaidaText.text = "bySaida".localizableSting()
cell.lblSizeText.text = "size".localizableSting() + " : "
cell.lblSize.text = self.responseData["productdetails"][indexPath.row]["size"].stringValue
cell.lblQtyText.text = "qty".localizableSting() + " : "
cell.btnRemove.addTarget(self, action: #selector(remove(sender:)), for: .touchUpInside)
cell.btnRemove.tag = indexPath.row
return cell
@objc func remove(sender: UIButton)
let altMessage = UIAlertController(title: "ZUCRAZ", message: "Remove this item from cart.", preferredStyle: UIAlertController.Style.alert)
altMessage.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler:
_ in
if NetworkManeger.isConnectedToNetwork()
let cartId = NetworkManeger.getCartId()
let productId = self.responseData["productdetails"][sender.tag]["pid"].stringValue
NetworkManeger.postRequest(remainingUrl: "deleteCartProduct.php", parameters: ["cartid": cartId, "pid": productId]) (response) in
if response["status"].intValue == 200
self.orderReview()
else
NetworkManeger.showAlertWithMsg(vc: self, msg: response["msg"].stringValue)
else
let altMessage = UIAlertController(title: "ZUCRAZ", message: "Please check internet connection!", preferredStyle: UIAlertController.Style.alert)
altMessage.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
self.present(altMessage, animated: true, completion: nil)
))
altMessage.addAction(UIAlertAction(title: "Cancel", style: UIAlertAction.Style.default, handler: nil))
self.present(altMessage, animated: true, completion: nil)
@IBAction func btnBack(_ sender: UIButton)
self.navigationController?.popViewController(animated: true)
@IBAction func btnProceed(_ sender: UIButton)
self.openPaymentSheet()
//MARKS: API HIT
func intiateStripePayment()
NetworkManeger.postRequest(remainingUrl: "stripepaymentinitiate.php", parameters: ["cartid": NetworkManeger.getCartId(), "user_id" : NetworkManeger.getUserId()]) (response) in
if response["status"].intValue == 200
//Get ephmeral Key and clientSecret
self.clientSecret = response["clientSecret"].stringValue
// self.clientSecret = response["paymentintent"][0]["secret"].stringValue
self.ephemeralKeySecret = response["EphemeralKey"][0]["id"].stringValue
let cusId = NetworkManeger.getStripCustomerId()
// MARK: Set your Stripe publishable key - this allows the SDK to make requests to Stripe for your account
STPAPIClient.shared.publishableKey = self.publishableKey
// MARK: Create a PaymentSheet instance
var configuration = PaymentSheet.Configuration()
configuration.merchantDisplayName = "Zucraz"
configuration.customer = .init(
id: cusId, ephemeralKeySecret: self.ephemeralKeySecret)
configuration.returnURL = "payments-example://stripe-redirect"
self.paymentSheet = PaymentSheet(
paymentIntentClientSecret: self.clientSecret,
configuration: configuration)
DispatchQueue.main.async
self.buyButton.isEnabled = true
func openPaymentSheet()
// MARK: Start the checkout process
self.paymentSheet?.present(from: self) paymentResult in
// MARK: Handle the payment result
switch paymentResult
case .completed:
self.displayAlert("Your order is confirmed!")
case .canceled:
print("Canceled!")
case .failed(let error):
print(error)
self.displayAlert("Payment failed: \n\(error.localizedDescription)")
func displayAlert(_ message: String)
let alertController = UIAlertController(title: "", message: message, preferredStyle: .alert)
let OKAction = UIAlertAction(title: "OK", style: .default) (action) in
alertController.dismiss(animated: true)
self.navigationController?.popViewController(animated: true)
alertController.addAction(OKAction)
present(alertController, animated: true, completion: nil)
func orderReview()
self.responseData = []
NetworkManeger.postRequest(remainingUrl: "orderReviewAPI.php", parameters: ["cartid": NetworkManeger.getCartId(), "user_id" : NetworkManeger.getUserId() , "coupondiscount" : couponCode, "applang" : NetworkManeger.getAppLang(), "iswalletused" : NetworkManeger.getWalletStatus(), "address_id" : self.addressData["address_id"].stringValue])
func addCoupon()
NetworkManeger.postRequest(remainingUrl: "cartcouponapply.php", parameters: ["cartid": NetworkManeger.getCartId(), "user_id" : NetworkManeger.getUserId() , "promocode" : couponCode, "cartvalue" : self.responseData["subtotal"].stringValue])
【问题讨论】:
如果您不设置临时密钥,也会出现该错误,不幸的是,该错误有点令人困惑。你能分享你的完整代码吗?包括实际解析服务器响应并使用客户详细信息创建PaymentSheet.Configuration()
的部分?
嗨@karllekko 添加了支付配置代码。
你能记录下例如的值吗? ephemeralSecret
并确保它不是零?您还应该在使用时记录self.publishableKey
,只需进行一些调试以检查这些变量是否意外地为零。
也可能不相关,但您正在配置 self.paymentSheet
但稍后您将展示 paymentSheet
,因此由于它不引用 self
您可能有两个 PaymentSheet 变量实例并且只配置了其中一个?不看完整的代码很难说。
response["EphemeralKey"][0]["id"].stringValue
在我看来不合适。您不需要密钥的 ID,您需要从 API(stripe.com/docs/payments/…) 返回的对象的 secret
值。您拥有的值应该类似于 ek_test_xxx
,而不是 ephkey_xxx
。
【参考方案1】:
不要对错误感到困惑:“将STPAPIClient.shared().publishableKey
设置为您的可发布密钥”。
与此无关。
如果遇到此类错误,请检查您的密钥。
EphemeralKey 必须类似于:ek_test_xxx(秘密)。
【讨论】:
以上是关于Stripe - 单一方法预构建 UI,STPAPIClient.shared().publishableKey iOS Swift UiKit的主要内容,如果未能解决你的问题,请参考以下文章
使用 Stripe,如何为多个客户附加从 Setup Intent API 创建的单一支付方式
如何为 Flutter Web 添加 Firebase 预构建的身份验证 UI?
使用 Try/Catch PHP 方法捕获 Stripe 错误
尽管没有任何错误或异常,为啥 Stripe Google Pay 按钮无法在 UI 上为我呈现?