Stripe - 单一方法 prebuit UI, STPAPIClient.shared().publishableKey iOS Swift UiKit

Stripe - single method prebuit UI, STPAPIClient.shared().publishableKey iOS Swift UiKit

我关注了这个文档: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” “临时密钥”:“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)

在此之后(支付启动)我从 stripe 获取日志:

日志分析:["product_usage": ["PaymentSheet"], "app_name": "Zucraz", "additional_info": [], "bindings_version": "21.8.1", "apple_pay_enabled": 0, "ocr_type": "none", "os_version": "14.4", "analytics_ua": "analytics.stripeios-1.0", "ui_usage_level": "部分", "publishable_key": "pk_test_51J9Te0LW....... .tRQbRP2", "device_type": "iPhone12,1", "事件": "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。 仍然,我尝试在 viewcontroller 中设置 STPAPIClient.shared.publishableKey,仍然出现错误。

提前致谢

完成class代码:

导入 UIKit 导入 SwiftyJSON 导入 FirebaseAnalytics 进口条纹 导入 PassKit

class 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]) { }
}

不要被错误混淆:“将 STPAPIClient.shared().publishableKey 设置为您的可发布密钥”。

与此无关。

如果出现此类错误,请检查您的密钥。

EphemeralKey 必须类似于:ek_test_xxx(秘密)。