这是我的代码,它很大程度上基于 Stripe 的基本模板代码:
import UIKit
import StripePaymentSheet
class CheckoutViewController: UIViewController {
private static let backendURL = URL(string: "https://sundealit.com/stripetest")!
private var paymentIntentClientSecret: String?
private lazy var payButton: UIButton = {
let button = UIButton(type: .custom)
button.setTitle("Pay now", for: .normal)
button.backgroundColor = .systemIndigo
button.layer.cornerRadius = 5
button.contentEdgeInsets = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12)
button.addTarget(self, action: #selector(pay), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
button.isEnabled = false
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBackground
view.addSubview(payButton)
NSLayoutConstraint.activate([
payButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16),
payButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16),
payButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -16)
])
self.fetchPaymentIntent()
}
func fetchPaymentIntent() {
let url = Self.backendURL.appendingPathComponent("/create-payment-intent")
let shoppingCartContent: [String: Any] = [
"items": [
["id": "xl-shirt"]
]
]
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = try? JSONSerialization.data(withJSONObject: shoppingCartContent)
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,
let publishableKey = json["publishableKey"] as? String
else {
let message = error?.localizedDescription ?? "Failed to decode response from server."
self?.displayAlert(title: "Error loading page", message: message)
return
}
print("Created PaymentIntent")
print(clientSecret)
print(publishableKey)
self?.paymentIntentClientSecret = clientSecret
StripeAPI.defaultPublishableKey = publishableKey
DispatchQueue.main.async {
self?.payButton.isEnabled = true
}
})
task.resume()
}
func displayAlert(title: String, message: String? = nil) {
DispatchQueue.main.async {
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default))
self.present(alertController, animated: true)
}
}
@objc
func pay() {
guard let paymentIntentClientSecret = self.paymentIntentClientSecret else {
return
}
var configuration = PaymentSheet.Configuration()
configuration.merchantDisplayName = "Example, Inc."
let paymentSheet = PaymentSheet(
paymentIntentClientSecret: paymentIntentClientSecret,
configuration: configuration)
paymentSheet.present(from: self) { [weak self] (paymentResult) in
switch paymentResult {
case .completed:
self?.displayAlert(title: "Payment complete!")
case .canceled:
print("Payment canceled!")
case .failed(let error):
self?.displayAlert(title: "Payment failed", message: error.localizedDescription)
}
}
}
}
但是,在这个基本模板中,用户无法输入送货地址,所以即使他们付了钱,我也不知道将产品运送到哪里。
我在这里查看了 Stripe 的文档,据说它教我如何在 Swift 中将送货地址字段添加到我的移动应用程序中:https://docs.stripe.com/elements/address-element/collect-addresses
但是,第 4 步是最令人困惑的,我应该在代码中的什么位置插入第 4 步中的代码,才能获得与该页面顶部的图像中显示的效果相同的效果?
简而言之,我也需要以某种方式收集用户的送货地址。谢谢!
在此处使用 AddressElement 需要使用 UINavigationController - 您的 CheckoutViewController 中会有一个按钮,按下该按钮会触发 UINavigationController 将用户导航到 AddressElement。这就是参考文档的步骤 4 中显示的内容。