Create Token
Apple Pay in Apps
如欲了解最新版號 SDK 以及各版號之間的差異性,請參考 Github Release Page : TapPay iOS Github
支援 iOS 10 以上
iOS16 及 iPadOS 16 以上支援在 Safari、Chrome、 Edge、 Firefox 等瀏覽器上使用 Apple Pay。其餘版本僅能於 Safari 使用 Apple Pay。
Environment
請先依照以下步驟設定環境:
1. 下載 TPDirect.framework 並加入您的專案
2. 將 PassKit.framework 加入您的專案
3. 在 Xcode 中將 Apple Pay 打開,並加入 Apple Merchant ID
4. 利用 TPDSetup 設定環境
5. 為提高偽卡交易的準確度,若可以請開啟IDFA功能
TPDSetup
+ (instancetype _Nonnull)setWithAppId:(int)appId
withAppKey:(NSString *_Nonnull)appKey
withServerType:(TPDServerType)serverType;
class func setWithAppKey(_ appKey: String, withAppId appId: Int32, with serverType: TPDServerType) -> Self
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[TPDSetup setWithAppId:"APP_ID" withAppKey:@"APP_KEY" withServerType:TPDServer_SandBox];
return YES;
}
...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
TPDSetup.setWithAppId("APP_ID", withAppKey: "APP_KEY", with: TPDServerType.sandBox)
return true
}
名稱 | 類別 | 內容 |
---|---|---|
appID | int | 驗證識別碼 |
appKey | String | 驗證金鑰 |
serverType | TPDServerType | 使用的伺服器種類 測試時請使用 Sandbox 環境(TPDServerType.Sandbox) 實體上線後請切換至 Production 環境(TPDServerType.Production) |
為提高偽卡交易的準確度,若可以請開啟IDFA功能
Codes
- 將 PassKit 跟 TPDirect frameworks 加入您的專案
#import <PassKit/PassKit.h>
#import <TPDirect/TPDirect.h>
import PassKit
import TPDirect
2. 依照順序實作以下類別:
TPDApplePay
@interface ViewController () <TPDApplePayDelegate>
@property (nonatomic, strong) TPDApplePay *applePay;
@end
class ViewController: UIViewController {
var applePay : TPDApplePay!
}
TPDApplePayDelegate
@protocol TPDApplePayDelegate <NSObject>
@required
// Send To The Delegate After Receive Prime and prime expiry millis.
- (void)tpdApplePay:(TPDApplePay *)applePay didReceivePrime:(NSString *)prime withExpiryMillis:(long)expiryMillis withCardInfo:(TPDCardInfo *)cardInfo withMerchantReferenceInfo:(NSDictionary *)merchantReferenceInfo;
// Send To The Delegate After Apple Pay Payment Processing Succeeds.
- (void)tpdApplePay:(TPDApplePay *)applePay didSuccessPayment: (TPDTransactionResult *)result;
// Send To The Delegate After Apple Pay Payment Processing Fails.
- (void)tpdApplePay:(TPDApplePay *)applePay didFailurePayment: (TPDTransactionResult *)result;
@optional
// Send To The Delegate After Apple Pay Payment's Form Is Shown.
- (void)tpdApplePayDidStartPayment:(TPDApplePay *)applePay;
// Send To The Delegate After User Selects A Payment Method.
// You Can Change The PaymentItem Or Discount Here.
- (TPDCart *)tpdApplePay:(TPDApplePay *)applePay didSelectPaymentMethod: (PKPaymentMethod *)paymentMethod cart:(TPDCart *)cart;
// Send To The Delegate After User Selects A Shipping Method.
// Set shippingMethods ==> TPDMerchant.shippingMethods.
- (void)tpdApplePay:(TPDApplePay *)applePay didSelectShippingMethod: (PKShippingMethod *)shippingMethod;
// Send To The Delegate After User Authorizes The Payment.
// You Can Check Shipping Contact Here, Return YES If Authorized.
- (BOOL)tpdApplePay:(TPDApplePay *)applePay canAuthorizePaymentWithShippingContact:(PKContact *)shippingContact;
// Send To The Delegate After User Cancels The Payment.
- (void)tpdApplePayDidCancelPayment:(TPDApplePay *)applePay;
// Send To The Delegate After Apple Pay Payment's Form Disappeared.
- (void)tpdApplePayDidFinishPayment:(TPDApplePay *)applePay;
@end
public protocol TPDApplePayDelegate : NSObjectProtocol {
// Send To The Delegate After Receive Prime.
public func tpdApplePay(_ applePay: TPDApplePay!, didReceivePrime prime: String!, withExpiryMillis expiryMillis: Int, withCardInfo cardInfo: TPDCardInfo, withMerchantReferenceInfo merchantReferenceInfo: [AnyHashable : Any]!)
// Send To The Delegate After Apple Pay Payment Processing Succeeds.
public func tpdApplePay(_ applePay: TPDApplePay!, didSuccessPayment result: TPDTransactionResult!)
// Send To The Delegate After Apple Pay Payment Processing Fails.
public func tpdApplePay(_ applePay: TPDApplePay!, didFailurePayment result: TPDTransactionResult!)
// Send To The Delegate After Apple Pay Payment's Form Is Shown.
optional public func tpdApplePayDidStartPayment(_ applePay: TPDApplePay!)
// Send To The Delegate After User Selects A Payment Method.
// You Can Change The PaymentItem Or Discount Here.
@available(iOS 9.0, *)
optional public func tpdApplePay(_ applePay: TPDApplePay!, didSelect paymentMethod: PKPaymentMethod!, cart: TPDCart!) -> TPDCart!
// Send To The Delegate After User Selects A Shipping Method.
// Set shippingMethods ==> TPDMerchant.shippingMethods.
@available(iOS 8.0, *)
optional public func tpdApplePay(_ applePay: TPDApplePay!, didSelect shippingMethod: PKShippingMethod!)
// Send To The Delegate After User Authorizes The Payment.
// You Can Check Shipping Contact Here, Return YES If Authorized.
@available(iOS 9.0, *)
optional public func tpdApplePay(_ applePay: TPDApplePay!, canAuthorizePaymentWithShippingContact shippingContact: PKContact!) -> Bool
// Send To The Delegate After User Cancels The Payment.
optional public func tpdApplePayDidCancelPayment(_ applePay: TPDApplePay!)
// Send To The Delegate After Apple Pay Payment's Form Disappeared.
optional public func tpdApplePayDidFinishPayment(_ applePay: TPDApplePay!)
}
名稱 | 使用時機 |
---|---|
didSuccessPayment | 付款成功時呼叫此方法 |
didFailurePayment | 付款失敗時呼叫此方法 |
tpdApplePayDidStartPayment | 付款開始時呼叫此方法 |
didSelectPaymentMethod | 選擇付款方式時呼叫此方法 |
didSelectShippingMethod | 選擇運送方式時呼叫此方法 |
canAuthorizePaymentWithShippingContact | 檢查付款資訊是否正確 |
tpdApplePayDidCancelPayment | 付款取消時呼叫此方法 |
tpdApplePayDidFinishPayment | 付款完成,但結果尚未決定時呼叫此方法 |
didReceivePrime:withExpiryMillis:withCardInfo:withMerchantReferenceInfo | 從 TapPay 獲得 Prime 及 prime 的過期時間時將呼叫此方法 將 Prime 回傳給您的伺服器並透過 Pay by Prime API 完成交易,然後呼叫 showPaymentResult 來顯示結果 |
showPaymentResult | Pay by Prime 成功後 |
TPDTransactionResult
@interface TPDTransactionResult : NSObject
// message, Report Message.
@property (nonatomic, strong) NSString *message;
// status, Result Code, '0' Means Success.
@property (nonatomic, assign) NSInteger status;
// amount
@property (nonatomic, strong) NSDecimalNumber *amount;
// paymentMehod
@property (nonatomic, strong) PKPaymentMethod *paymentMethod;
@end
class TPDTransactionResult : NSObject {
// message, Report Message.
var message: String!
// status, Result Code, '0' Means Success.
var status: Int
// amount
var amount: NSDecimalNumber!
// paymentMehod
var paymentMethod: PKPaymentMethod!
}
在 didSuccessPayment 及 didFailurePayment 中回傳的物件 TPDTransactionResult 將會有以下的值:
名稱 | 內容 |
---|---|
amount | 交易金額 |
status | 交易代碼 |
message | 錯誤訊息 |
paymentMethod | 蘋果的 PKPaymentMethod |
- (void)tpdApplePayDidStartPayment:(TPDApplePay *)applePay {
NSLog(@"=====================================================");
NSLog(@"Apple Pay On Start");
NSLog(@"===================================================== \n\n");
}
- (void)tpdApplePay:(TPDApplePay *)applePay didSuccessPayment: (TPDTransactionResult *)result {
NSLog(@"=====================================================");
NSLog(@"Apple Pay Did Success ==> Amount : %@", [result.amount stringValue]);
NSLog(@"shippingContact.name : %@ %@", applePay.consumer.shippingContact.name.givenName, applePay.consumer.shippingContact.name.familyName);
NSLog(@"shippingContact.emailAddress : %@", applePay.consumer.shippingContact.emailAddress);
NSLog(@"shippingContact.phoneNumber : %@", applePay.consumer.shippingContact.phoneNumber.stringValue);
NSLog(@"===================================================== \n\n");
}
- (void)tpdApplePay:(TPDApplePay *)applePay didFailurePayment: (TPDTransactionResult *)result {
NSLog(@"=====================================================");
NSLog(@"Apple Pay Did Failure ==> Message : %@, ErrorCode : %ld", result.message, (long)result.status);
NSLog(@"===================================================== \n\n");
}
- (void)tpdApplePayDidCancelPayment:(TPDApplePay *)applePay {
NSLog(@"=====================================================");
NSLog(@"Apple Pay Did Cancel");
NSLog(@"===================================================== \n\n");
}
- (void)tpdApplePayDidFinishPayment:(TPDApplePay *)applePay {
NSLog(@"=====================================================");
NSLog(@"Apple Pay Did Finish");
NSLog(@"===================================================== \n\n");
}
- (void)tpdApplePay:(TPDApplePay *)applePay didSelectShippingMethod: (PKShippingMethod *)shippingMethod {
NSLog(@"=====================================================");
NSLog(@"======> didSelectShippingMethod: ");
NSLog(@"Shipping Method.identifier : %@", shippingMethod.identifier);
NSLog(@"Shipping Method.detail : %@", shippingMethod.detail);
NSLog(@"===================================================== \n\n");
}
- (TPDCart *)tpdApplePay:(TPDApplePay *)applePay didSelectPaymentMethod: (PKPaymentMethod *)paymentMethod cart:(TPDCart *)cart {
NSLog(@"=====================================================");
NSLog(@"======> didSelectPaymentMethod: ");
NSLog(@"===================================================== \n\n");
if (paymentMethod.type == PKPaymentMethodTypeDebit) {
[self.cart addPaymentItem:[TPDPaymentItem paymentItemWithItemName:@"Discount"
withAmount:[NSDecimalNumber decimalNumberWithString:@"-1.00"]]];
}
return self.cart;
}
- (BOOL)tpdApplePay:(TPDApplePay *)applePay canAuthorizePaymentWithShippingContact:(PKContact *)shippingContact {
NSLog(@"=====================================================");
NSLog(@"======> canAuthorizePaymentWithShippingContact ");
NSLog(@"shippingContact.name : %@ %@", applePay.consumer.shippingContact.name.givenName, applePay.consumer.shippingContact.name.familyName);
NSLog(@"shippingContact.emailAddress : %@", shippingContact.emailAddress);
NSLog(@"shippingContact.phoneNumber : %@", shippingContact.phoneNumber.stringValue);
NSLog(@"===================================================== \n\n");
return YES;
}
- (void)tpdApplePay:(TPDApplePay *)applePay didReceivePrime:(NSString *)prime withExpiryMillis:(long)expiryMillis withCardInfo:(TPDCardInfo *)cardInfo withMerchantReferenceInfo:(NSDictionary *)merchantReferenceInfo {
// 1. Send Your 'Prime' To Your Server, And Handle Payment With Result
// ...
NSLog(@"=====================================================");
NSLog(@"======> didReceivePrime ");
NSLog(@"Prime : %@", prime);
NSLog(@"apple pay %lu", expiryMillis);
NSLog(@"totalAmount : %@",applePay.cart.totalAmount);
NSLog(@"Client IP : %@",applePay.consumer.clientIP);
NSLog(@"shippingContact.name : %@ %@", applePay.consumer.shippingContact.name.givenName, applePay.consumer.shippingContact.name.familyName);
NSLog(@"shippingContact.emailAddress : %@", applePay.consumer.shippingContact.emailAddress);
NSLog(@"shippingContact.phoneNumber : %@", applePay.consumer.shippingContact.phoneNumber.stringValue);
PKPaymentMethod * paymentMethod = applePay.consumer.paymentMethod;
NSLog(@"Type : %ld", (long)paymentMethod.type);
NSLog(@"Network : %@", paymentMethod.network);
NSLog(@"Display Name : %@", paymentMethod.displayName);
NSLog(@"===================================================== \n\n");
// 2. If Payment Success, applePay.
BOOL paymentResult = YES;
[applePay showPaymentResult:paymentResult];
}
extension ViewController :TPDApplePayDelegate {
func tpdApplePayDidStartPayment(_ applePay: TPDApplePay!) {
print("=====================================================")
print("Apple Pay On Start")
print("=====================================================\n\n")
}
func tpdApplePay(_ applePay: TPDApplePay!, didSuccessPayment result: TPDTransactionResult!) {
print("=====================================================")
print("Apple Pay Did Success ==> Amount : \(result.amount.stringValue)")
print("shippingContact.name : \(applePay.consumer.shippingContact?.name?.givenName) \( applePay.consumer.shippingContact?.name?.familyName)")
print("shippingContact.emailAddress : \(applePay.consumer.shippingContact?.emailAddress)")
print("shippingContact.phoneNumber : \(applePay.consumer.shippingContact?.phoneNumber?.stringValue)")
print("Shipping Method.identifier : \(applePay.cart.shippingMethod.identifier)")
print("Shipping Method.detail : \(applePay.cart.shippingMethod.detail)")
print("=====================================================\n\n")
}
func tpdApplePay(_ applePay: TPDApplePay!, didFailurePayment result: TPDTransactionResult!) {
print("=====================================================")
print("Apple Pay Did Failure ==> Message : \(result.message), ErrorCode : \(result.status)")
print("=====================================================\n\n")
}
func tpdApplePayDidCancelPayment(_ applePay: TPDApplePay!) {
print("=====================================================")
print("Apple Pay Did Cancel")
print("=====================================================\n\n")
}
func tpdApplePayDidFinishPayment(_ applePay: TPDApplePay!) {
print("=====================================================")
print("Apple Pay Did Finish")
print("=====================================================\n\n")
}
func tpdApplePay(_ applePay: TPDApplePay!, didSelect shippingMethod: PKShippingMethod!) {
print("=====================================================")
print("======> didSelectShippingMethod: ")
print("Shipping Method.identifier : \(shippingMethod.identifier)")
print("Shipping Method.detail : \(shippingMethod.detail)")
print("=====================================================\n\n")
}
func tpdApplePay(_ applePay: TPDApplePay!, didSelect paymentMethod: PKPaymentMethod!, cart: TPDCart!) -> TPDCart! {
print("=====================================================");
print("======> didSelectPaymentMethod: ");
print("=====================================================\n\n");
if paymentMethod.type == .debit {
self.cart.add(TPDPaymentItem(itemName: "Discount", withAmount: NSDecimalNumber(string: "-1.00")))
}
return self.cart;
}
func tpdApplePay(_ applePay: TPDApplePay!, canAuthorizePaymentWithShippingContact shippingContact: PKContact!) -> Bool {
print("=====================================================")
print("======> canAuthorizePaymentWithShippingContact ")
print("shippingContact.name : \(applePay.consumer.shippingContact?.name?.givenName) \( applePay.consumer.shippingContact?.name?.familyName)")
print("shippingContact.emailAddress : \(shippingContact.emailAddress)")
print("shippingContact.phoneNumber : \(shippingContact.phoneNumber?.stringValue)")
print("=====================================================\n\n")
return true;
}
tpdApplePay(_ applePay: TPDApplePay!, didReceivePrime prime: String!, withExpiryMillis expiryMillis: Int, withCardInfo cardInfo: TPDCardInfo, withMerchantReferenceInfo merchantReferenceInfo: [AnyHashable : Any]!) {
// 1. Send Your Prime To Your Server, And Handle Payment With Result
// ...
print("=====================================================");
print("======> didReceivePrime");
print("Prime : \(prime!)");
print("Expiry Millis : \(expiryMillis)");
print("total Amount : \(applePay.cart.totalAmount!)")
print("Client IP : \(applePay.consumer.clientIP!)")
print("shippingContact.name : \(applePay.consumer.shippingContact?.name?.givenName) \(applePay.consumer.shippingContact?.name?.familyName)");
print("shippingContact.emailAddress : \(applePay.consumer.shippingContact?.emailAddress)");
print("shippingContact.phoneNumber : \(applePay.consumer.shippingContact?.phoneNumber?.stringValue)");
let paymentMethod = self.consumer.paymentMethod!
print("type : \(paymentMethod.type.rawValue)")
print("Network : \(paymentMethod.network!.rawValue)")
print("Display Name : \(paymentMethod.displayName!)")
print("===================================================== \n\n");
// 2. If Payment Success, applePay.
let paymentResult = true;
applePay.showPaymentResult(paymentResult)
}
}
名稱 | 類別 | 內容 | |||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
prime | String | 交易用的加密字串 | |||||||||||||||||||||||||||||||||
expiryMillis | Int | prime 過期的 millis | |||||||||||||||||||||||||||||||||
cardInfo | TPDCardInfo | 卡片資訊,將會回傳以下幾個值:
|
|||||||||||||||||||||||||||||||||
merchantReferenceInfo | JSONObject | 若商戶在 TapPay 後台使用 Co-brand card management 功能,且交易卡號符合設定時,將會回傳此參數,不支援 JKOPAY 商戶於TapPay後台設定的affiliate code management須限制於20字元內且為半形的英數字
|
PKPaymentButton
@interface ViewController () <TPDApplePayDelegate>
@property (nonatomic, strong) PKPaymentButton *applePayButton;
@end
class ViewController: UIViewController {
var applePayButton : PKPaymentButton!
}
您應在設定付款按鈕前檢查卡片跟機台是否支援 Apple Pay
/**
[TPDApplePay canMakePaymentsUsingNetworks:(NSArray<PKPaymentNetwork> *)]
檢查是否有支援的發卡組織
TPDApplePay setupWthMerchant:(TPDMerchant *) withConsumer:(TPDConsumer *) withCart:(TPDCart *) withDelegate:(id)
將 TPDMerchant, TPDConsumer, TPDCart 帶入初始化 Apple Pay 物件
startPayment
呼叫 Apple Pay Payment Sheet
*/
- (void)paymentButtonSetting {
if ([TPDApplePay canMakePaymentsUsingNetworks:self.merchant.supportedNetworks]) {
self.applePayButton = [PKPaymentButton buttonWithType:PKPaymentButtonTypeBuy style:PKPaymentButtonStyleBlack];
}else{
self.applePayButton = [PKPaymentButton buttonWithType:PKPaymentButtonTypeSetUp style:PKPaymentButtonStyleBlack];
}
[self.view addSubview:self.applePayButton];
self.applePayButton.center = self.view.center;
[self.applePayButton addTarget:self action:@selector(didClickButton:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)didClickButton:(PKPaymentButton *)sender {
// Without Handle Payment
self.applePay = [TPDApplePay setupWthMerchant:self.merchant withConsumer:self.consumer withCart:self.cart withDelegate:self];
[self.applePay startPayment];
}
/**
TPDApplePay.canMakePayments(usingNetworks: [PKPaymentNetwork]!)
檢查是否有支援的發卡組織
TPDApplePay.setupWthMerchant(TPDMerchant!, with: TPDConsumer!, with: TPDCart!, withDelegate: Any!)
將 TPDMerchant, TPDConsumer, TPDCart 帶入初始化 Apple Pay 物件
startPayment
呼叫 Apple Pay Payment Sheet
*/
func paymentButtonSetting() {
if (TPDApplePay.canMakePayments(usingNetworks: self.merchant.supportedNetworks)) {
applePayButton = PKPaymentButton.init(paymentButtonType: .buy, paymentButtonStyle: .black)
} else {
applePayButton = PKPaymentButton.init(paymentButtonType: .setUp, paymentButtonStyle: .black)
}
view.addSubview(applePayButton)
applePayButton.center = view.center
applePayButton.addTarget(self, action: #selector(ViewController.didClickBuyButton(sender:)), for: .touchUpInside)
}
@objc func didClickBuyButton(sender:PKPaymentButton) {
applePay = TPDApplePay.setupWthMerchant(merchant, with: consumer, with: cart, withDelegate: self)
applePay.startPayment()
}
TPDMerchant
@interface ViewController () <TPDApplePayDelegate>
@property (nonatomic, strong) TPDMerchant *merchant;
@end
class ViewController: UIViewController {
var merchant : TPDMerchant!
}
self.merchant = [TPDMerchant new];
self.merchant.merchantName = @"TapPay!";
self.merchant.merchantCapability = PKMerchantCapability3DS;
self.merchant.applePayMerchantIdentifier = @"merchant.apple.pay";
self.merchant.countryCode = @"TW";
self.merchant.currencyCode = @"TWD";
self.merchant.supportedNetworks = @[PKPaymentNetworkAmex, PKPaymentNetworkMasterCard, PKPaymentNetworkVisa, PKPaymentNetworkJCB];
merchant = TPDMerchant()
merchant.merchantName = "TapPay!";
merchant.merchantCapability = .capability3DS;
merchant.applePayMerchantIdentifier = "merchant.apple.pay";
merchant.countryCode = "TW";
merchant.currencyCode = "TWD";
merchant.supportedNetworks = [.amex, .masterCard, .visa, .JCB]
名稱 | 內容 |
---|---|
merchantName | 顯示於 Payment Sheet 欲付給的商家名稱 |
merchantCapability | 欲支援的支付方式,詳細請參考 Apple Pay merchantCapabilities |
applePayMerchantIdentifier | Apple Merchant ID. |
countryCode | 國碼 |
currencyCode | 交易貨幣 |
supportedNetworks | 設定欲支援的信用卡組織 |
supportedNetworks
信用卡組織支援的版本
信用卡組織 | 版本 |
---|---|
American Express | iOS 8.0+ watchOS 3.0+ |
MasterCard | iOS 8.0+ watchOS 3.0+ |
Visa | iOS 8.0+ watchOS 3.0+ |
JCB | iOS 10.1+ watchOS 3.1+ |
TPDConsumer
@interface ViewController () <TPDApplePayDelegate>
@property (nonatomic, strong) TPDConsumer *consumer;
@end
class ViewController: UIViewController {
var consumer : TPDConsumer!
}
self.consumer = [TPDConsumer new];
self.consumer.requiredShippingAddressFields = PKAddressFieldEmail | PKAddressFieldName | PKAddressFieldPhone;
self.consumer.requiredBillingAddressFields = PKAddressFieldPostalAddress;
consumer = TPDConsumer()
consumer.requiredShippingAddressFields = [.email, .name, .phone]
consumer.requiredBillingAddressFields = [.postalAddress]
Name | Content |
---|---|
requiredShippingAddressFields | 設定必填運送資訊欄位 預設為無需要的運送資訊欄位 |
requiredBillingAddressFields | 設定必填帳單資訊欄位 預設為無需要的帳單資訊欄位 |
Apple Pay 指紋認證成功後,可以在 didReceivePrime delegate 中,TPDConsumer.paymentMethod 中取得卡片資訊
可以參考 apple 文件 PKPaymentMethod
名稱 | 內容 |
---|---|
type | 卡片類別 0 : unknown 1 : debit 2 : credit 3 : prepaid 4 : store |
network | 卡別 |
displayName | 卡別及卡片後四碼 |
TPDCart
@interface ViewController () <TPDApplePayDelegate>
@property (nonatomic, strong) TPDCart *cart;
@end
class ViewController: UIViewController {
var cart : TPDCart!
}
/**
[cart addPaymentItem:(TPDPaymentItem *)]
將交易品項加入交易品項列表
*/
self.cart = [TPDCart new];
TPDPaymentItem *book = [TPDPaymentItem paymentItemWithItemName:@"book"
withAmount:[NSDecimalNumber decimalNumberWithString:@"100.00"]];
[self.cart addPaymentItem:book];
/**
cart.add(TPDPaymentItem!)
將交易品項加入交易品項列表
*/
cart = TPDCart()
let book = TPDPaymentItem(itemName: "Initial Charge", withAmount: NSDecimalNumber(string: "100.00"))
cart.add(book)
您可用 TPDPaymentItem
來新增新的物品至您的 TPDCart
中
使用 paymentItemWithItemName
設定顯示物品的金額
TPDCart
中品項的總金額必須大於 0,否則將回傳 error code: 88016
Deferred Payment
self.cart = [TPDCart new];
self.cart.isAmountPending = YES;
self.cart.isShowTotalAmount = NO;
// 設定顯示金額品項
TPDPaymentItem *initialCharge = [TPDPaymentItem paymentItemWithItemName:@"Initial Charge"
withAmount:[NSDecimalNumber decimalNumberWithString:@"100.00"]];
[self.cart addPaymentItem:initialCharge];
// 設定待處理品項
TPDPaymentItem *improvementSurcharge = [TPDPaymentItem pendingPaymentItemWithItemName:@"NT$5 per miles"];
[self.cart addPaymentItem:improvementSurcharge];
cart = TPDCart()
cart.isAmountPending = true
cart.isShowTotalAmount = false
// 設定顯示金額品項
let initialCharge = TPDPaymentItem(itemName: "Initial Charge", withAmount: NSDecimalNumber(string: "100.00"))
cart.add(initialCharge)
// 設定待處理品項
let improvementSurcharge = TPDPaymentItem.pendingPaymentItem(withItemName: "NT$5 per miles")
cart.add(improvementSurcharge)
若要使用 Apple Pay 延後授權 ,請先向 TapPay 客服申請開通此功能(support@cherri.tech)
使用此功能 prime 的時效為取得 prime 後的 30天,實際扣款金額由 pay by prime 設定
TPDCart 中 isAmountPending
屬性決定是否使用延後授權,預設為 false
TPDCart 中 isShowTotalAmount
屬性決定總金額欄位是否顯示總金額或金額待處理,預設為 true
使用 pendingPaymentItemWithItemName
設定品項金額欄位顯示『...』代表為金額待處理
使用延後授權請注意以下規則
TPDCart
中的品項皆為顯示金額
isAmountPending | isShowTotalAmount | 總金額欄位 | Prime 的時效 |
---|---|---|---|
true | true | 顯示品項加總金額 | 30天 |
true | false | 顯示金額待處理 | 30天 |
false | true | 顯示品項加總金額 | 90秒 |
false | false | 不支援,請參考 error code:88013 | X |
TPDCart
中的品項皆為待處理
isAmountPending | isShowTotalAmount | 總金額欄位 | Prime 的時效 |
---|---|---|---|
true | true | 不支援,請參考 error code:88014 | X |
true | false | 顯示金額待處理 | 30天 |
false | true | 不支援,請參考 error code:88015 | X |
false | false | 不支援,請參考 error code:88013 | X |
TPDCart
中的品項包含待處理、顯示金額
isAmountPending | isShowTotalAmount | 總金額欄位 | Prime 的時效 |
---|---|---|---|
true | true | 顯示金額品項加總金額 | 30天 |
true | false | 顯示金額待處理 | 30天 |
false | true | 不支援,請參考 error code:88015 | X |
false | false | 不支援,請參考 error code:88013 | X |
注意事項
因為在 iOS 12 以下的版本 (包含), Apple Pay 延後授權總金額必須大於 0 元
為了達到不同 iOS 版本間相容性, 以下情況 SDK v2.6.0 和以上的版本會把總金額改為 1 並帶入給 Apple 產生交易資料
1.TPDCart
品項皆為『待處理』或品項金額總和為『 0 元』, 且總金額要顯示『金額待處理』(self.cart.isAmountPending = true
)
Example
如果您碰到問題,可參考我們的範例程式
Apple Pay on the Web
如欲了解最新版號 SDK 以及各版號之間的差異性,請參考 Github Release Page : TapPay Web Github
Apple Pay JavaScript API 只有在 iOS 10 以後的機台以及 macOS Sierra (10.12) 以上的 Mac 上才能運作
如有使用 Apple Pay on the Web 商家申請服務,請於 Apple Pay 商家識別碼欄位帶入 TapPay 產出給您的 Apple Pay merchant identifier (您能在Portal > 支付管理 > Apple Pay On The Web 找到此資訊)
Requirements
在 Apple Pay on the Web 中,您必須符合以下要求:
1. 所有包含 Apple Pay 的頁面必須要有 HTTPS , 在正式與測試環境都是必要的。在開發環境可以透過 ngrok 的服務滿足 HTTPS 的需求,可以參考我們的
Ngrok 使用教學
2. 您的網域必須要有合法的 SSL 憑證
3. 您的伺服器必須支援 TLS 1.2 以及下列其中一個密碼套件:
密碼套件值 | 內容 |
---|---|
0xC02F | TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 |
0xC027 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 |
0xC013 | TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA |
0x009E | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 |
0x0067 | TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 |
0x009C | TLS_RSA_WITH_AES_128_GCM_SHA256 |
0x003C | TLS_RSA_WITH_AES_128_CBC_SHA256 |
4. 您的伺服器必須透過 HTTP (TCP over port 443)允許下列的 Apple Pay IP:
IP | 名稱 | 種類 |
---|---|---|
17.171.85.7 | apple-pay-gateway-cert.apple.com | Sandbox |
17.171.78.7 | apple-pay-gateway-nc-pod1.apple.com | Production |
17.171.78.71 | apple-pay-gateway-nc-pod2.apple.com | Production |
17.171.78.135 | apple-pay-gateway-nc-pod3.apple.com | Production |
17.171.78.199 | apple-pay-gateway-nc-pod4.apple.com | Production |
17.171.79.12 | apple-pay-gateway-nc-pod5.apple.com | Production |
17.141.128.7 | apple-pay-gateway-pr-pod1.apple.com | Production |
17.141.128.71 | apple-pay-gateway-pr-pod2.apple.com | Production |
17.141.128.135 | apple-pay-gateway-pr-pod3.apple.com | Production |
17.141.128.199 | apple-pay-gateway-pr-pod4.apple.com | Production |
17.141.129.12 | apple-pay-gateway-pr-pod5.apple.com | Production |
17.171.78.9 | apple-pay-gateway-nc-pod1-dr.apple.com | Production |
17.171.78.73 | apple-pay-gateway-nc-pod2-dr.apple.com | Production |
17.171.78.137 | apple-pay-gateway-nc-pod3-dr.apple.com | Production |
17.171.78.201 | apple-pay-gateway-nc-pod4-dr.apple.com | Production |
17.171.79.13 | apple-pay-gateway-nc-pod5-dr.apple.com | Production |
17.141.128.9 | apple-pay-gateway-pr-pod1-dr.apple.com | Production |
17.141.128.73 | apple-pay-gateway-pr-pod2-dr.apple.com | Production |
17.141.128.137 | apple-pay-gateway-pr-pod3-dr.apple.com | Production |
17.141.128.201 | apple-pay-gateway-pr-pod4-dr.apple.com | Production |
17.141.129.13 | apple-pay-gateway-pr-pod5-dr.apple.com | Production |
SetupSDK
請用以下程式碼在您的 HTML 檔案中設定環境:
請注意版本的差異,避免載入 Web SDK 錯誤
https://js.tappaysdk.com/sdk/tpdirect/v5.14.0
https://js.tappaysdk.com/tpdirect/v5.13.1
使用方式請參考以下範例
<!--
使用 TPDirect.setupSDK("appID" "appKey" 'serverType')
設定 App ID, App Key, Server Type 參數
-->
<head>
<script src="https://js.tappaysdk.com/sdk/tpdirect/v5.14.0"></script>
<script>
TPDirect.setupSDK("appID" "appKey" 'serverType')
</script>
</head>
若使用低於 v5.14.0 之Web SDK版本,請使用以下路徑引用 Web SDK
<script src="https://js.tappaysdk.com/tpdirect/v5.13.1"></script>
<script>
TPDirect.setupSDK(APP_ID, 'APP_KEY', 'sandbox')
</script>
名稱 | 類別 | 內容 |
---|---|---|
appID | int | 驗證識別碼 |
appKey | String | 驗證金鑰 |
serverType | String | 使用的伺服器種類 測試時請使用 Sandbox 環境(sandbox) 實體上線後請切換至 Production 環境(production) |
如欲知 SDK 兼容性,請參考 SDK compatibility
checkAvailability()
/**
使用 TPDirect.paymentRequestApi.checkAvailability() 可以檢查使用者的瀏覽器
是否可以使用 Payment Request API
若回傳 true: 代表支援
若回傳 false: 代表不支援
*/
TPDirect.paymentRequestApi.checkAvailability()
Setup Apple Pay
/**
使用 TPDirect.paymentRequestApi.setupApplePay 設定 Apple Pay 相關參數
*/
TPDirect.paymentRequestApi.setupApplePay({
merchantIdentifier: 'merchant.tech.cherri',
countryCode: 'TW',
})
名稱 (*=必填) | 類別 | 內容 |
---|---|---|
merchantIdentifier* | String | 您於 Apple Developer 註冊的 Merchant Id 若您有使用 Apple Pay on the Web 商家申請服務,請帶入TapPay 產出給您的 Apple Pay merchantIdentifier (您能在Portal > 支付方式 > Apple Pay > Apple Pay on the Web 找到此資訊) |
countryCode | String | 國家代碼 , 預設為 TW |
PaymentRequest
建立一個 paymentRequest 的物件設定交易資訊來索取 Prime
var paymentRequest = {
supportedNetworks: ['AMEX', 'JCB', 'MASTERCARD', 'VISA'],
supportedMethods: ['apple_pay'],
displayItems: [{
label: 'TapPay - iPhone8',
amount: {
currency: 'TWD',
value: '1.00'
}
}],
total: {
label: '付給 TapPay',
amount: {
currency: 'TWD',
value: '1.00'
}
},
shippingOptions: [{
id: "standard",
label: "🚛 Ground Shipping (2 days)",
detail: 'Estimated delivery time: 2 days',
amount: {
currency: "TWD",
value: "5.00"
}
},
{
id: "drone",
label: "🚀 Drone Express (2 hours)",
detail: 'Estimated delivery time: 2 hours',
amount: {
currency: "TWD",
value: "25.00"
}
},
],
options: {
requestPayerEmail: false,
requestPayerName: false,
requestPayerPhone: false,
requestShipping: false,
shippingType: 'shipping'
}
}
名稱 | 類別 | 內容 | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
supportedNetworks | Array | 設定可支援的卡別, 目前支援帶入 “VISA”, “MASTERCARD”, “JCB” 和 “AMEX” | ||||||||||||||||||
supportedMethods | Array | 設定支援的付款方式 | ||||||||||||||||||
displayItems | Array |
|
||||||||||||||||||
total | JSONObject |
|
||||||||||||||||||
shippingOptions | JSONObject |
|
||||||||||||||||||
options | JSONObject |
|
設定好 payment request 物件後, 透過以下方法設定 Payment Request API
/**
使用 TPDirect.paymentRequestApi.setupPaymentRequest 設定 payment request 物件
並在 callback function 回傳物件關於使用者的瀏覽器是否可以使用 Payment Request API 以及是否有卡片進行付款
*/
TPDirect.paymentRequestApi.setupPaymentRequest(paymentRequest, function (result) {
if (!result.browserSupportPaymentRequest) {
console.log('瀏覽器不支援 PaymentRequest')
return
}
if (result.canMakePaymentWithActiveCard === true) {
console.log('該裝置有支援的卡片可以付款')
} else {
console.log('該裝置沒有支援的卡片可以付款')
}
})
setupPaymentRequest 有一個 callback 函式, 裡面會帶有以下物件屬性
名稱 | 類別 | 內容 | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
result | JSONObject |
|
Deferred Payment
若要使用 Apple Pay 延後授權 ,請先向 TapPay 客服申請開通此功能(support@cherri.tech)
使用此功能 prime 的時效為取得 prime 後的 30天,實際扣款金額由 pay by prime 設定
paymentRequest 中 total.isAmountPending
屬性決定是否使用延後授權,預設為 false
paymentRequest 中 total.isShowTotalAmount
屬性決定總金額欄位是否顯示總金額或金額待處理,預設為 true
使用 paymentRequest displayItems 中的 isAmountPending:true
設定品項金額欄位顯示『...』代表為金額待處理
使用延後授權請注意以下規則
displayItems 中設置的品項皆為顯示金額
total.isAmountPending | total.isShowTotalAmount | 總金額欄位 | Prime 的時效 |
---|---|---|---|
true | true | 顯示品項加總金額 | 30天 |
true | false | 顯示金額待處理 | 30天 |
false | true | 顯示品項加總金額 | 90秒 |
false | false | 不支援,TPDirect.paymentRequestApi.setupPaymentRequest 無法初始化 |
X |
displayItems 中設置的品項皆為待處理
total.isAmountPending | total.isShowTotalAmount | 總金額欄位 | Prime 的時效 |
---|---|---|---|
true | true | 不支援,TPDirect.paymentRequestApi.setupPaymentRequest 無法初始化 |
X |
true | false | 顯示金額待處理 | 30天 |
false | true | 不支援,TPDirect.paymentRequestApi.setupPaymentRequest 無法初始化 |
X |
false | false | 不支援,TPDirect.paymentRequestApi.setupPaymentRequest 無法初始化 |
X |
displayItems 中設置的品項包含待處理、顯示金額
total.isAmountPending | total.isShowTotalAmount | 總金額欄位 | Prime 的時效 |
---|---|---|---|
true | true | 顯示金額品項加總金額 | 30天 |
true | false | 顯示金額待處理 | 30天 |
false | true | 不支援,TPDirect.paymentRequestApi.setupPaymentRequest 無法初始化 |
X |
false | false | 不支援,TPDirect.paymentRequestApi.setupPaymentRequest 無法初始化 |
X |
注意事項
因為在 MacOS 10.14.1 以及 iOS 12.1 以下的版本 (包含), Apple Pay 延後授權 total.amount.value
必須大於 0 元
為了達到不同 MacOS 與 iOS 版本間相容性, 以下情況 SDK 會把 total.amount.value
改為 1 並帶入給 Apple 產生交易資料
1.displayItems 品項皆為『待處理』(isAmountPending:true
)或品項金額總和為『 0 元』, 且總金額要顯示『金額待處理』(total.isShowTotalAmount:false
)
2.displayItems 沒有任何品項且總金額要顯示『金額待處理』(total.isShowTotalAmount:false
)
另外請注意如果在 Mac 上面進行付款, 並使用 iPhone 進行指紋、臉部辨識時, 在以上情況中使用者在 iPhone 上看到的金額會是 1 元
shippingOptions
於 paymentRequest 的 ShippingOption 中未加入 detail
shippingOptions: [{
id: "standard",
label: "🚛 Ground Shipping (2 days)",
amount: {
currency: "TWD",
value: "5.00"
}
}]
於 paymentRequest 的 ShippingOption 中加入 detail
shippingOptions: [{
id: "standard",
label: "🚛 Ground Shipping (2 days)",
detail: "Estimated delivery time: 2 days",
amount: {
currency: "TWD",
value: "5.00"
}
}]
Get Prime
/**
使用 TPDirect.paymentRequestApi.getPrime 向 TapPay 取得付款用的 prime
*/
TPDirect.paymentRequestApi.getPrime(function(result) {
console.log('paymentRequestApi.getPrime result', result)
if (result.status !== 0) {
console.error('getPrime failed: ' + result.msg)
return
}
var prime = result.prime
})
Get Prime Result
處理收到的結果,將 Prime 回傳至您的伺服器
再用 Pay by Prime API 來完成付款
{
"prime": String,
// 加上運費的價格
"total_amount": String,
"status": Int,
"msg": String,
"client_ip": String,
"payer": {
"name": String,
"phone": String,
"email": String
},
"shippingAddress": {
"country": String,
"addressLine": ArrayString,
"region": String,
"city": String,
"dependentLocality": String,
"postalCode": String,
"sortingCode": String,
"languageCode": String,
"organization": String,
"recipient": String,
"phone": String
},
"shippingOption": String,
"billingAddress": {
"country": String,
"addressLine": ArrayString,
"region": String,
"city": String,
"dependentLocality": String,
"postalCode": String,
"sortingCode": String,
"languageCode": String,
"organization": String,
"recipient": String,
"phone": String
},
"methodName": String ("apple_pay")
"requestId": String,
"card": {
"lastfour": String,
"funding": Int,
"type": Int,
},
"card_info": {
"bincode": String,
"lastfour": String,
"issuer": String,
"issuer_zh_tw": String,
"bank_id": String,
"funding": Int,
"type": Int,
"level": String,
"country": String,
"countrycode": String,
},
"merchant_reference_info": {
"affiliate_codes": ArrayString,
},
"prime_expiry_millis": Number
}
名稱 | 類別 | 內容 | ||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
prime | Stinrg | prime 字串,於 Pay by Prime API 交易時使用 | ||||||||||||||||||||||||||||||||||||
total_amount | String | 總金額 | ||||||||||||||||||||||||||||||||||||
status | Int | 交易代碼,成功的話為0 | ||||||||||||||||||||||||||||||||||||
msg | String | 錯誤訊息 | ||||||||||||||||||||||||||||||||||||
client_ip | String | 消費者的 IP 位置 | ||||||||||||||||||||||||||||||||||||
payer | JSONObject | 消費者資料
|
||||||||||||||||||||||||||||||||||||
shippingAddress | JSONObject | 運送地址
|
||||||||||||||||||||||||||||||||||||
billingAddress | JSONObject | 帳單地址
|
||||||||||||||||||||||||||||||||||||
shippingOption | String | 運送方式 | ||||||||||||||||||||||||||||||||||||
methodName | String | (“apple_pay”) | ||||||||||||||||||||||||||||||||||||
requestId | String | 此交易請求識別碼 | ||||||||||||||||||||||||||||||||||||
card | JSONObject |
|
||||||||||||||||||||||||||||||||||||
card_info | JSONObject | 卡片資訊,將會回傳以下幾個值:
|
||||||||||||||||||||||||||||||||||||
merchant_reference_info | JSONObject | 若商戶在 TapPay 後台使用 Co-brand card management 功能,且交易卡號符合設定時,將會回傳此參數,不支援 JKOPAY 商戶於TapPay後台設定的affiliate code management須限制於20字元內且為半形的英數字
|
||||||||||||||||||||||||||||||||||||
prime_expiry_millis | Number | Prime 到期時間 Web SDK v5.3 版本之後固定回傳 |
Example
如果您碰到問題,可參考我們的範例程式
或是蘋果的 範例網站做為參考
請記得 Apple Pay JavaScript API 只有在 iOS 10 以後的機台以及 macOS Sierra (10.12) 以上的 Mac 上才能運作
Reference
如果您碰到問題,可參考我們的若您想整合更多付款方式,請參考 Payment Request API
Q&A
如果您需要設定 Content Security Policy 中的 frame-src, 請設置以下二個網域:
- js.tappaysdk.com
- fraud.tappaysdk.com