SeamlessPayCore
Seamless Payments iOS SDK 可让您快速轻松地在 iOS 应用中构建卓越的支付体验。
我们的框架提供了一些可以直接使用的元素,用于收集用户的支付详情。我们还公开了那些 UI 的低级 API,以便您可以构建完全定制的体验。此外,包含低级的 SPAPIClient
,它对应于 Seamless Payments API 中的资源和方法,因此您可以在此层级之上构建任何自定义功能,同时还可以利用 SeamlessPayCore
框架提供的工具。
原生 UI 元素
SPPaymentCardTextField
是一个具有类似 UITextField
属性的文本字段,但专门用于收集借记/信用卡信息。它在内部管理多个 UITextFields
,以便从用户那里无缝收集此信息。它设计为单行使用,在设计方面可以在任何可以使用 UITextField
的地方使用。
示例 UI
要求:SeamlessPay iOS SDK 需要 Xcode 10.1 或更高版本,兼容针对 iOS 11 或更高版本的应用。
示例
要运行示例项目,请克隆仓库,然后首先从Example目录运行pod install
。
安装
SeamlessPayCore 可通过 CocoaPods 获取。要安装,请只需将以下行添加到您的Podfile中
pod 'SeamlessPayCore'
认证
当您的应用程序启动时,请使用SeamlessPay发布密钥(您可以在API密钥页面获取它)配置SDK,以便它可以向SeamlessPay API发起请求。
对于没有自己后端的单页面应用程序,仅使用发布密钥。在这种情况下,您将只能执行/v1/charge操作。使用密钥可以实现所有交易方法(例如,/v1/charge、/v1/refund、/v1/void)。
Objective-C
AppDelegate.m
#import "AppDelegate.h"
@import SeamlessPayCore;
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[[SPAPIClient getSharedInstance]
setSecretKey:@"sk_XXXXXXXXXXXXXXXXXXXXXXXXXX" // can be nil
publicKey:@"pk_XXXXXXXXXXXXXXXXXXXXXXXXXX"
sandbox: TRUE];
// do any other necessary launch configuration
return YES;
}
@end
Swift
import SeamlessPayCore
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
SPAPIClient.getSharedInstance()?.setSecretKey(@"sk_XXXXXXXXXXXXXXXXXXXXXXXXXX", // can be nil
publishableKey: "pk_XXXXXXXXXXXXXXXXXXXXXXXXXX",
sandbox: true)
return true
}
}
创建支付表单
使用SDK提供的SPPaymentCardTextField(一个嵌入UI组件)在客户端安全地收集卡信息。使用以下代码创建卡组件和支付按钮的实例
Objective-C
CheckoutViewController.m
#import "CheckoutViewController.h"
@import SeamlessPayCore;
@interface CheckoutViewController ()
@property (weak) SPPaymentCardTextField *cardTextField;
@property (weak) UIButton *payButton;
@end
@implementation CheckoutViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
SPPaymentCardTextField *cardTextField = [[SPPaymentCardTextField alloc] init];
self.cardTextField = cardTextField;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.layer.cornerRadius = 5;
button.backgroundColor = [UIColor systemBlueColor];
button.titleLabel.font = [UIFont systemFontOfSize:22];
[button setTitle:@"Pay" forState:UIControlStateNormal];
[button addTarget:self action:@selector(pay) forControlEvents:UIControlEventTouchUpInside];
self.payButton = button;
UIStackView *stackView = [[UIStackView alloc] initWithArrangedSubviews:@[cardTextField, button]];
stackView.axis = UILayoutConstraintAxisVertical;
stackView.translatesAutoresizingMaskIntoConstraints = FALSE;
stackView.spacing = 20;
[self.view addSubview:stackView];
[NSLayoutConstraint activateConstraints:@[
[stackView.leftAnchor constraintEqualToSystemSpacingAfterAnchor:self.view.leftAnchor multiplier:2],
[self.view.rightAnchor constraintEqualToSystemSpacingAfterAnchor:stackView.rightAnchor multiplier:2],
[stackView.topAnchor constraintEqualToSystemSpacingBelowAnchor:self.view.topAnchor multiplier:20],
]];
}
- (void)pay {
NSString *cardNumber = _cardTextField.cardNumber;
NSString *exp = _cardTextField.formattedExpirationDate;
NSString *cvc = _cardTextField.cvc;
NSString *zip = _cardTextField.postalCode;
NSLog(@"%@ %@ %@ %@",cardNumber,exp,cvc,zip);
}
@end
Swift
CheckoutViewController.swift
import UIKit
import SeamlessPayCore
class ViewController: UIViewController {
lazy var cardTextField: SPPaymentCardTextField = {
let cardTextField = SPPaymentCardTextField()
return cardTextField
}()
lazy var payButton: UIButton = {
let button = UIButton(type: .custom)
button.layer.cornerRadius = 5
button.backgroundColor = .systemBlue
button.titleLabel?.font = UIFont.systemFont(ofSize: 22)
button.setTitle("Pay", for: .normal)
button.addTarget(self, action: #selector(pay), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.backgroundColor = .white
let stackView = UIStackView(arrangedSubviews: [cardTextField, payButton])
stackView.axis = .vertical
stackView.spacing = 20
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.leftAnchor.constraint(equalToSystemSpacingAfter: view.leftAnchor, multiplier: 2),
view.rightAnchor.constraint(equalToSystemSpacingAfter: stackView.rightAnchor, multiplier: 2),
stackView.topAnchor.constraint(equalToSystemSpacingBelow: view.topAnchor, multiplier: 20),
])
}
@objc
func pay() {
// ...
}
}
创建支付方法和收费
当用户点击支付按钮时,将STPPaymentCardTextField收集的卡信息转换为PaymentMethod令牌。令牌化确保没有敏感的卡数据需要触及您的服务器,从而确保您的集成符合PCI规范。在客户端传递令牌后,将标识符作为源传递给创建收费方的SPAPIClient方法 -createChargeWithToken
Objective-C
- (void)pay {
[[SPAPIClient getSharedInstance] createPaymentMethodWithType:@"CREDIT_CARD"
account:self.cardTextField.cardNumber
expDate:self.cardTextField.formattedExpirationDate
cvv:self.cardTextField.cvc
accountType:nil
routing:nil
pin:nil
address:nil
address2:nil
city:nil
country:nil
state:nil
zip:self.cardTextField.postalCode
company:nil
email:nil
phone:nil
name:@"IOS test"
nickname:nil
verification : TRUE
success:^(SPPaymentMethod *paymentMethod) {
[[SPAPIClient getSharedInstance]
createChargeWithToken:paymentMethod.token
cvv:self.cardTextField.cvc
capture: TRUE
currency:nil
amount:@"1"
taxAmount:nil
taxExempt: FALSE
tip:nil
surchargeFeeAmount:nil
scheduleIndicator:nil
description:@""
order:nil
orderId:nil
poNumber:nil
metadata:nil
descriptor:nil
txnEnv:nil
achType:nil
credentialIndicator:nil
transactionInitiation:nil
idempotencyKey:nil
needSendReceipt:false
success:^(SPCharge *charge) {
// Success Charge:
NSString *success = [NSString
stringWithFormat:@"Amount: $%@\nStatus: %@\nStatus message: "
@"%@\ntxnID #: %@",
charge.amount, charge.status,
charge.statusDescription, charge.chargeId];
}
failure:^(SPError *error) {
// Handle the error
NSString *err = [error localizedDescription];
}];
}
failure:^(SPError *error) {
// Handle the error
NSString *err = [error localizedDescription];
}];
}
Swift
@objc
func pay() {
SPAPIClient.getSharedInstance()?.createPaymentMethod(
withType: "CREDIT_CARD",
account: cardTextField.cardNumber,
expDate: cardTextField.formattedExpirationDate,
cvv: self.cardTextField.cvc,
accountType: nil,
routing: nil,
pin: nil,
address: nil,
address2: nil,
city: nil,
country: nil,
state: nil,
zip: cardTextField.postalCode,
company: nil,
email: nil,
phone: nil,
name: nil,
nickname: nil,
verification: true,
success: { (paymentMethod: SPPaymentMethod?) in
let token = paymentMethod?.token
SPAPIClient.getSharedInstance()?.createCharge(
withToken: token!,
cvv: self.cardTextField.cvc,
capture: true,
currency: nil,
amount: "1",
taxAmount: nil,
taxExempt: false,
tip: nil,
surchargeFeeAmount: nil,
scheduleIndicator: nil,
description: nil,
order: nil,
orderId: nil,
poNumber: nil,
metadata: nil,
descriptor: nil,
txnEnv: nil,
achType: nil,
credentialIndicator: nil,
transactionInitiation: nil,
idempotencyKey: nil,
needSendReceipt: false,
success: { (charge: SPCharge?) in
// Success Charge:
print(charge?.chargeId ?? "charge is nil")
}, failure: { (error: SPError?) in
// Handle the error
print(error?.localizedDescription ?? "")
return
}
)
}, failure: { (error: SPError?) in
// Handle the error
print(error?.localizedDescription ?? "")
return
}
)
}
从'示例APP'开始,了解基本设置和用法。
许可证
SeamlessPayCore 在 MIT 许可证下可用。有关更多信息,请参阅 LICENSE 文件。