Brand configurations
This section contains guidelines for specific brands.
Apple Pay
Apple Pay is easy to set up. It gives customers a simple and secure way to pay using an iPhone or iPad. This guide explains how to process Apple Pay payments with the SDK.
Configuration
To use Apple Pay on a real device, create keys and a certificate.
- Add an Apple Pay merchant ID in Apple Developer Centre.
- In Smart Payments Platform, go to Administration -> Mobile Payment, select Generate keys, and download the CSR (certificate signing request).
- In Apple Developer Centre, select the merchant ID and choose Create Certificate. Upload the CSR from step 2, and download the certificate. See the Apple Pay guide for details.
- Upload the certificate in Smart Payments Platform.
- Turn on Apple Pay in Xcode: enable Apple Pay under Capabilities in Project Settings, then select the merchant ID the app should use.
Add Apple Pay to the app using one of two methods: Ready-to-Use UI or SDK & Your Own UI. Follow the relevant instructions below.
Ready-to-Use UI
- Add
PKPaymentButtonto the view. - Add a button action method to the view controller. The code sample below shows the main steps.
- (IBAction) applePayTapped:(id)sender {
// request checkout ID from your server
// configure OPPCheckoutProvider
// present checkout for specific payment brand and handle callbacks
}@IBAction func applePayTapped(_ sender: Any) {
// request checkout ID from your server
// configure OPPCheckoutProvider
// present checkout for specific payment brand and implement callbacks
}Request checkout ID
To start a payment, create a checkout ID. The app should request a checkout ID from the server. This example uses a sample integration server; adapt it to use a backend API.
NSURLRequest *merchantServerRequest = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://YOUR_URL/?amount=100¤cy=EUR&paymentType=DB"]];
[[[NSURLSession sharedSession] dataTaskWithRequest:merchantServerRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// Ensure that you handle errors
NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
self.checkoutID = JSON[@"checkoutId"];
}] resume];let merchantServerRequest = NSURLRequest(url: URL(string: "https://YOUR_URL/?amount=100¤cy=EUR&paymentType=DB")!)
URLSession.shared.dataTask(with: merchantServerRequest as URLRequest) { (data, response, error) in
// Ensure that you handle errors
if let json = try? JSONSerialization.jsonObject(with: data!, options: []) as? [String: Any] {
let checkoutID = json?["checkoutId"] as? String
}
}.resume()Create and configure checkout provider
Create a PKPaymentRequest object and add it to OPPCheckoutSettings.
Use OPPPaymentProvider to construct a PKPaymentRequest with:
merchantIdentifiercountryCode- Default values:
supportedNetworksincludes all payment networksmerchantCapabilitiesincludesthreeDSecure
If not using the helper method, ensure merchantCapabilities includes threeDSecure. The emv value is not supported.
OPPPaymentProvider *provider = [OPPPaymentProvider paymentProviderWithMode:OPPProviderModeTest];
OPPCheckoutSettings *checkoutSettings = [[OPPCheckoutSettings alloc] init];
PKPaymentRequest *paymentRequest = [OPPPaymentProvider paymentRequestWithMerchantIdentifier:@"YOUR MERCHANT ID" countryCode:@"YOUR MERCHANT COUNTRY CODE"];
paymentRequest.supportedNetworks = ... // set up supported payment networks
checkoutSettings.applePayPaymentRequest = paymentRequest;
OPPCheckoutProvider *checkoutProvider = [OPPCheckoutProvider checkoutProviderWithPaymentProvider:provider
checkoutID:checkoutID
settings:checkoutSettings];let provider = OPPPaymentProvider(mode: OPPProviderMode.test)
let checkoutSettings = OPPCheckoutSettings()
let paymentRequest = OPPPaymentProvider.paymentRequest(withMerchantIdentifier: "YOUR MERCHANT ID", countryCode: "YOUR MERCHANT COUNTRY CODE")
paymentRequest.supportedNetworks = ... // set up supported payment networks
checkoutSettings.applePayPaymentRequest = paymentRequest
let checkoutProvider = OPPCheckoutProvider(paymentProvider: provider, checkoutID: checkoutID!, settings: checkoutSettings)Set button type (optional)
Choose a button type that matches the purchase flow. For design guidance, see Apple Pay button guidelines.
// Set button type to Buy
checkoutSettings.applePayType = PKPaymentButtonTypeBuy;// Set button type to Buy
checkoutSettings.applePayType = PKPaymentButtonType.buySee PKPaymentButtonType documentation for all options. The default value is plain.
Present checkout and handle callbacks
[checkoutProvider presentCheckoutWithPaymentBrand:@"APPLEPAY"
loadingHandler:^(BOOL inProgress) {
// Start or stop loading animation based on inProgress parameter.
} completionHandler:^(OPPTransaction * _Nullable transaction, NSError * _Nullable error) {
if (error) {
// Check code attribute (OPPErrorCode) and NSLocalizedDescription to find the reason.
} else {
if (transaction.redirectURL) {
// Shopper was redirected to the issuer web page.
// Request payment status when shopper returns using transaction.resourcePath or checkout ID.
} else {
// Request payment status for the synchronous transaction using transactionPath.resourcePath or checkout ID.
}
}
} cancelHandler:^{
// Executed if the shopper closes the payment page early.
}];checkoutProvider?.presentCheckout(withPaymentBrand: "APPLEPAY",
loadingHandler: { (inProgress) in
// Executed whenever SDK sends request to the server or receives the answer.
// You can start or stop loading animation based on inProgress parameter.
}, completionHandler: { (transaction, error) in
if error != nil {
// See code attribute (OPPErrorCode) and NSLocalizedDescription to identify the reason of failure.
} else {
if transaction?.redirectURL != nil {
// Shopper was redirected to the issuer web page.
// Request payment status when shopper returns to the app using transaction.resourcePath or just checkout id.
} else {
// Request payment status for the synchronous transaction from your server using transactionPath.resourcePath or just checkout id.
}
}
}, cancelHandler: {
// Executed if the shopper closes the payment page prematurely.
})Use the brand APPLEPAYTKN when the acquirer should handle decryption. Contact the acquirer for details.
Collecting Apple Pay shipping and billing information
Configure the payment request
Use requiredShippingContactFields and requiredBillingContactFields to specify needed information. The Apple Pay form prompts shoppers to enter the requested details.
// Enable requesting shipping information
if (@available(iOS 11.0, *)) {
paymentRequest.requiredShippingContactFields = [NSSet setWithObject:PKContactFieldPostalAddress];
} else {
paymentRequest.requiredShippingAddressFields = PKAddressFieldPostalAddress;
}
// Enable requesting billing information
if (@available(iOS 11.0, *)) {
paymentRequest.requiredBillingContactFields = [NSSet setWithObject:PKContactFieldPostalAddress];
} else {
paymentRequest.requiredBillingAddressFields = PKAddressFieldPostalAddress;
}if #available(iOS 11.0, *) {
paymentRequest.requiredShippingContactFields = Set([PKContactField.postalAddress])
} else {
paymentRequest.requiredShippingAddressFields = .postalAddress
}
if #available(iOS 11.0, *) {
paymentRequest.requiredBillingContactFields = Set([PKContactField.postalAddress])
} else {
paymentRequest.requiredBillingAddressFields = .postalAddress
}Adopt the OPPCheckoutProviderDelegate protocol
To receive callbacks from the Apple Pay form, make sure your view controller adopts the OPPCheckoutProviderDelegate protocol and set the checkoutProvider.delegate property.
// Adopt the OPPCheckoutProviderDelegate protocol
@interface SomeViewController () <OPPCheckoutProviderDelegate>
@end
@implementation SomeViewController
...
- (IBAction)applePayTapped:(id)sender {
// Set a delegate property for the OPPCheckoutProvider instance
self.checkoutProvider.delegate = self;
...
}
@end// Adopt the OPPCheckoutProviderDelegate protocol
class SomeViewController: UIViewController, OPPCheckoutProviderDelegate {
...
@IBAction func applePayTapped(_ sender: UIButton) {
// Set a delegate property for the OPPCheckoutProvider instance
self.checkoutProvider.delegate = self
...
}
}Collecting shipping information
The Apple Pay form calls two delegates when the shopper provides shipping information:
- Shipping contact:
checkoutProvider:applePayDidSelectShippingContact:handler: - Shipping method:
checkoutProvider:applePayDidSelectShippingMethod:handler:
Some shipping methods are not available in all areas or have different costs for different addresses. Update this information by returning a new list of shipping methods and summary items in the completion block.
Shipping contact
- (void)checkoutProvider:(OPPCheckoutProvider *)checkoutProvider
applePayDidSelectShippingContact:(PKContact *)contact
handler:(void (^)(OPPApplePayRequestShippingContactUpdate * _Nonnull))completion {
// You may want to provide different shipping methods based on shipping information
NSArray *shippingMethods = [self shippingMethodsForContact:contact];
// You may want to change amount of transaction (e.g. by adding tax) based on shipping information
self.contact = contact;
[self updateSummaryItems];
OPPApplePayRequestShippingContactUpdate *update = [[OPPApplePayRequestShippingContactUpdate alloc] initWithErrors:nil paymentSummaryItems:self.summaryItems shippingMethods:shippingMethods];
completion(update);
}func checkoutProvider(_ checkoutProvider: OPPCheckoutProvider, applePayDidSelectShippingContact contact: PKContact, handler completion: @escaping (OPPApplePayRequestShippingContactUpdate) -> Void) {
// You may want to provide different shipping methods based on shipping information
let shippingMethods = self.shippingMethods(contact: contact)
// You may want to change amount of transaction (e.g. by adding tax) based on shipping information
self.contact = contact
updateSummaryItems()
let update = OPPApplePayRequestShippingContactUpdate.init(errors: nil, paymentSummaryItems: self.summaryItems, shippingMethods: shippingMethods)
completion(update)
}To support privacy, Peach Payments keeps the shipping information provided in this delegate anonymous. The returned contact contains enough information to calculate shipping costs without revealing sensitive information about the shopper. Full shipping information is available after the shopper authorises the payment in the
checkoutProvider:applePayDidAuthorizePayment:handlerdelegate.
Shipping method
- (void)checkoutProvider:(OPPCheckoutProvider *)checkoutProvider
applePayDidSelectShippingMethod:(PKShippingMethod *)shippingMethod
handler:(void (^)(OPPApplePayRequestShippingMethodUpdate * _Nonnull))completion {
// Change the amount of the transaction based on the shipping method cost
self.shippingMethod = shippingMethod;
[self updateSummaryItems];
OPPApplePayRequestShippingMethodUpdate *update = [[OPPApplePayRequestShippingMethodUpdate alloc] initWithPaymentSummaryItems:self.summaryItems];
completion(update);
}func checkoutProvider(_ checkoutProvider: OPPCheckoutProvider, applePayDidSelect shippingMethod: PKShippingMethod, handler completion: @escaping (OPPApplePayRequestShippingMethodUpdate) -> Void) {
// You may want to change amount of transaction based on shipping method cost
self.shippingMethod = shippingMethod
updateSummaryItems()
let update = OPPApplePayRequestShippingMethodUpdate.init(paymentSummaryItems: self.summaryItems)
completion(update)
}Collecting billing information
Billing information and full shipping information is available after the shopper authorises the payment. Use the checkoutProvider:applePayDidAuthorizePayment:handler delegate to get this data.
- (void)checkoutProvider:(OPPCheckoutProvider *)checkoutProvider
applePayDidAuthorizePayment:(PKPayment *)payment
handler:(void (^)(OPPApplePayRequestAuthorizationResult * _Nonnull))completion {
OPPApplePayRequestAuthorizationResult *result = nil;
// You may want to validate shipping/billing info
if ([self isValidBillingContact:payment.billingContact]) {
// Return success to continue the payment
result = [[OPPApplePayRequestAuthorizationResult alloc] initWithStatus:PKPaymentAuthorizationStatusSuccess
errors:nil];
} else {
NSArray *errors = nil;
if (@available(iOS 11.0, *)) {
// Since iOS 11 you can pass list of errors in billing/shipping info
NSError *error = [PKPaymentRequest paymentBillingAddressInvalidErrorWithKey:CNPostalAddressCountryKey
localizedDescription:@"Some country error message"];
errors = [NSArray arrayWithObject:error];
}
result = [[OPPApplePayRequestAuthorizationResult alloc] initWithStatus:PKPaymentAuthorizationStatusFailure
errors:errors];
}
completion(result);
}func checkoutProvider(_ checkoutProvider: OPPCheckoutProvider, applePayDidAuthorizePayment payment: PKPayment, handler completion: @escaping (OPPApplePayRequestAuthorizationResult) -> Void) {
var result: OPPApplePayRequestAuthorizationResult
// You may want to validate shipping/billing info
if isValidBillingContact(contact: payment.billingContact) {
// Return success to continue the payment
result = OPPApplePayRequestAuthorizationResult.init(status: .success, errors: nil)
} else {
var errors: [Error] = []
if #available(iOS 11.0, *) {
// Since iOS 11 you can pass list of errors in billing/shipping info
let error = PKPaymentRequest.paymentBillingAddressInvalidError(withKey: CNPostalAddressCountryKey, localizedDescription: "Some country error mesage")
errors = [error]
}
result = OPPApplePayRequestAuthorizationResult.init(status: .failure, errors: errors)
}
completion(result)
}Updating the Apple Pay transaction amount
To update the Apple Pay transaction amount:
- Send an updated list of
PKPaymentSummaryItemsin the shipping information delegates. - Update the checkout session with the new amount by a server-to-server call. Do this asynchronously in the
checkoutProvider:continueSubmitting:completion:delegate, which is the last checkout delegate called before submitting the transaction.
- (void)checkoutProvider:(OPPCheckoutProvider *)checkoutProvider
continueSubmitting:(OPPTransaction *)transaction
completion:(void (^)(NSString * _Nullable checkoutID, BOOL abort))completion {
// Update the checkout session with the new amount
completion(transaction.paymentParams.checkoutID, NO);
}func checkoutProvider(_ checkoutProvider: OPPCheckoutProvider, continueSubmitting transaction: OPPTransaction, completion: @escaping (String?, Bool) -> Void) {
// Update checkout session with the new amount
completion(transaction.paymentParams.checkoutID, false)
}Submitting shopper information
Instead of collecting information manually as explained above, use the mSDK to collect and submit it. Configure CheckoutSettings to specify the information to submit.
Configure CheckoutSettings
CheckoutSettingsSet the applePayContactTypes property in CheckoutSettings to specify the information to submit.
OPPCheckoutApplePayContactTypeBillingAddress: The shopper billing address.OPPCheckoutApplePayContactTypeCustomer: The shopper's name, surname, phone, and email.
Use one or both options.
checkoutSettings.applePayContactTypes = OPPCheckoutApplePayContactTypeBillingAddress | OPPCheckoutApplePayContactTypeCustomer;checkoutSettings.applePayContactTypes = [.billingAddress, .customer]Mobile SDK and your own UI
Accepting Apple Pay with a custom UI is like handling card payments. When the shopper approves a payment, the app receives a PKPayment object with encrypted card details. Create OPPApplePayPaymentParams with the payment data and submit a transaction.
Set up an Apple Pay button
Apple Pay is available to a subset of iOS users. Before presenting the Apple Pay option to the current user, you should determine whether Apple Pay is available. You can do it using OPPPaymentProvider helper method.
- (void)viewDidLoad {
[super viewDidLoad];
self.applePayButton.enabled = [OPPPaymentProvider deviceSupportsApplePay];
}override func viewDidLoad() {
super.viewDidLoad()
applePayButton.isEnabled = OPPPaymentProvider.deviceSupportsApplePay()
}Create a PKPaymentRequest
PKPaymentRequestNext, when the shopper taps "pay by Apple Pay", create a PKPaymentRequest object.
Peach Payments provides a helper method in OPPPaymentProvider to create one with the given merchantIdentifier, countryCode, and the following default values:
supportedNetworkscontain all payment networks.merchantCapabilitiescontainthreeDSecure.
If you do not use the helper method, make sure that the merchantCapabilities always contain threeDSecure. The emv value is not supported.
See how to register a merchant ID in Apple Pay documentation.
PKPaymentRequest *request = [OPPPaymentProvider paymentRequestWithMerchantIdentifier:@"YOUR MERCHANT ID" countryCode:@"YOUR COUNTRY CODE"];
// Set currency.
request.currencyCode = "USD";
// Create total item. Label should represent your company.
// It will be prepended with "Pay" (i.e. "Pay Sportswear $100.00")
NSDecimalNumber *amount = [NSDecimalNumber decimalNumberWithMantissa:10000 exponent:-2 isNegative:NO];
request.paymentSummaryItems = @[[PKPaymentSummaryItem summaryItemWithLabel:@"Sportswear" amount:amount]];let request = OPPPaymentProvider.paymentRequest(withMerchantIdentifier: "YOUR MERCHANT ID", countryCode: "YOUR COUNTRY CODE")
// Set currency.
request.currencyCode = "USD"
// Create total item. Label should represent your company.
// It will be prepended with the word "Pay" (i.e. "Pay Sportswear $100.00")
let amount = NSDecimalNumber(mantissa: 10000, exponent: -2, isNegative: false)
request.paymentSummaryItems = [PKPaymentSummaryItem(label: "Sportswear", amount: amount)]Present a PKPaymentAuthorizationViewController
PKPaymentAuthorizationViewControllerNext, create and present a PKPaymentAuthorizationViewController with your payment request. Use the OPPPaymentProvider method to validate the final PKPaymentRequest object.
Your view controller should adopt the
PKPaymentAuthorizationViewControllerDelegateprotocol to respond to user interaction with that view controller.
- (void)applePayTapped {
PKPaymentRequest *request = ...; // See above
if ([OPPPaymentProvider canSubmitPaymentRequest:request]) {
PKPaymentAuthorizationViewController *vc = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:request];
vc.delegate = self;
[self presentViewController:vc animated:YES completion:nil];
} else {
NSLog(@"Apple Pay not supported.");
}
}- (void)applePayTapped {
PKPaymentRequest *request = ...; // See above
if ([OPPPaymentProvider canSubmitPaymentRequest:request]) {
PKPaymentAuthorizationViewController *vc = [[PKPaymentAuthorizationViewController alloc] initWithPaymentRequest:request];
vc.delegate = self;
[self presentViewController:vc animated:YES completion:nil];
} else {
NSLog(@"Apple Pay not supported.");
}
}Lastly, adopt the required PKPaymentAuthorizationViewControllerDelegate methods. In your implementation of paymentAuthorizationViewController:didAuthorizePayment:completion:, create OPPApplePayPaymentParams and submit a debit transaction.
- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didAuthorizePayment:(PKPayment *)payment
completion:(void (^)(PKPaymentAuthorizationStatus))completion {
OPPApplePayPaymentParams *params = [OPPApplePayPaymentParams applePayPaymentParamsWithCheckoutID:checkoutID
tokenData:payment.token.paymentData];
// Check if parameters are valid and submit transaction.
[self.provider submitTransaction:[OPPTransaction transactionWithPaymentParams:params] completionHandler:^(OPPTransaction *transaction, NSError *error) {
if (error) {
// See code attribute (OPPErrorCode) and NSLocalizedDescription to identify the reason of failure.
} else {
// Send request to your server to obtain transaction status.
}
}];
}
- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller {
[controller dismissViewControllerAnimated:YES completion:nil];
}- (void)paymentAuthorizationViewController:(PKPaymentAuthorizationViewController *)controller
didAuthorizePayment:(PKPayment *)payment
completion:(void (^)(PKPaymentAuthorizationStatus))completion {
OPPApplePayPaymentParams *params = [OPPApplePayPaymentParams applePayPaymentParamsWithCheckoutID:checkoutID
tokenData:payment.token.paymentData];
// Check if parameters are valid and submit transaction.
[self.provider submitTransaction:[OPPTransaction transactionWithPaymentParams:params] completionHandler:^(OPPTransaction *transaction, NSError *error) {
if (error) {
// See code attribute (OPPErrorCode) and NSLocalizedDescription to identify the reason of failure.
} else {
// Send request to your server to obtain transaction status.
}];
}
- (void)paymentAuthorizationViewControllerDidFinish:(PKPaymentAuthorizationViewController *)controller {
[controller dismissViewControllerAnimated:YES completion:nil];
} You can also integrate APPLEPAYTKN in same way as an Apple Pay, you just need to pass the brand APPLEPAYTKN while creating OPPApplePayPaymentParams and submit a transaction.
NSError *error;
OPPApplePayPaymentParams *params = [[OPPApplePayPaymentParams alloc] initWithCheckoutID:checkoutID paymentBrand:@"APPLEPAYTKN" tokenData:payment.token.paymentData error:&error];let params = try? OPPApplePayPaymentParams(checkoutID: checkoutID, paymentBrand: "APPLEPAYTKN", tokenData: payment.token.paymentData)Google Pay
Requirements
- A mobile SDK integration (Ready-to-use UI or SDK and your own UI)
- A Google account. When you are ready to deploy your Google Pay integration, sign up to get access and test with production credentials.
Configuration
Open the build.gradle file in the app module and add the following to the dependencies block:
implementation "com.google.android.gms:play-services-wallet:x.x.x"Add Google Pay to your app in one of two ways, depending on whether you use the ready-to-use UI or the SDK with your own UI. The sections below cover these two approaches. Follow the instructions for your chosen approach.
Ready-to-use UI
Add GOOGLEPAY payment brand
GOOGLEPAY payment brandCreate the CheckoutSettings, and add GOOGLEPAY to the payment brands list:
Set<String> paymentBrands = new HashSet<String>();
paymentBrands.add("GOOGLEPAY");
CheckoutSettings checkoutSettings = new CheckoutSettings(checkoutId, paymentBrands, Connect.ProviderMode.TEST);val paymentBrands = hashSetOf("GOOGLEPAY")
val checkoutSettings = CheckoutSettings(checkoutId, paymentBrands, Connect.ProviderMode.TEST)If you integrate Google Pay using the drop-in buttons, set the GOOGLEPAY payment brand in the PaymentButtonFragment.
paymentButtonFragment.setPaymentBrand("GOOGLEPAY");paymentButtonFragment.paymentBrand = "GOOGLEPAY"Configure PaymentDataRequest
PaymentDataRequestCreate JSONObject to configure Google Pay widget with the transaction information, allowed payment methods, and card networks. Use PaymentDataRequestJsonBuilder to create the base paymentDataRequestJson object with all required parameters.
Then, add optional configurations, for example, enable requesting shipping information in the widget. Refer to the Google Pay Payments API documentation for more options.
JSONArray allowedPaymentMethodsJson = new JSONArray()
.put(new CardPaymentMethodJsonBuilder()
.setAllowedAuthMethods(new JSONArray()
.put("PAN_ONLY")
.put("CRYPTOGRAM_3DS")
)
.setAllowedCardNetworks(new JSONArray()
.put("VISA")
.put("MASTERCARD")
.put("AMEX")
.put("DISCOVER")
.put("JCB")
)
.setGatewayMerchantId("yourEntityId")
.toJson()
);
JSONObject transactionInfoJson = new TransactionInfoJsonBuilder()
.setCurrencyCode("USD")
.setTotalPriceStatus("FINAL")
.setTotalPrice("100.00")
.toJson();
JSONObject paymentDataRequestJson = new PaymentDataRequestJsonBuilder()
.setAllowedPaymentMethods(allowedPaymentMethodsJson)
.setTransactionInfo(transactionInfoJson)
.toJson();val allowedPaymentMethodsJson = JSONArray()
.put(CardPaymentMethodJsonBuilder()
.setAllowedAuthMethods(JSONArray()
.put("PAN_ONLY")
.put("CRYPTOGRAM_3DS")
)
.setAllowedCardNetworks(JSONArray()
.put("VISA")
.put("MASTERCARD")
.put("AMEX")
.put("DISCOVER")
.put("JCB")
)
.setGatewayMerchantId("yourEntityId")
.toJson()
)
val transactionInfoJson = TransactionInfoJsonBuilder()
.setCurrencyCode("USD")
.setTotalPriceStatus("FINAL")
.setTotalPrice("100.00")
.toJson()
val paymentDataRequestJson = PaymentDataRequestJsonBuilder()
.setAllowedPaymentMethods(allowedPaymentMethodsJson)
.setTransactionInfo(transactionInfoJson)
.toJson()Set it to the CheckoutSettings.
For
GOOGLEPAYTKN, Peach Payments has introduced a new method,setGateway(@NonNull String gatewayName), in theCardPaymentMethodJsonBuilderclass. You must pass the gateway name provided by your acquirer when using this method.
new CardPaymentMethodJsonBuilder()
.setGateway("example_provider_gateway_name");CardPaymentMethodJsonBuilder()
.setGateway("example_provider_gateway_name")checkoutSettings.setGooglePayPaymentDataRequestJson(paymentDataRequestJson.toString());checkoutSettings.googlePayPaymentDataRequestJson = paymentDataRequestJson.toString()Collecting shopper information
You can collect extra information with the Google Pay widget before submitting the transaction, for example, shipping information.
Configure payment data request
In addition to the previous steps, complete the configuration of the paymentDataRequestJson object to request extra information from the shopper. Refer to the Google Pay API to see the full list of options.
JSONObject paymentDataRequestJson = new PaymentDataRequestJsonBuilder()
.setAllowedPaymentMethods(allowedPaymentMethodsJson)
.setTransactionInfo(transactionInfoJson)
.setShippingAddressRequired(true)
.setEmailRequired(true)
.toJson();val paymentDataRequestJson = PaymentDataRequestJsonBuilder()
.setAllowedPaymentMethods(allowedPaymentMethodsJson)
.setTransactionInfo(transactionInfoJson)
.setShippingAddressRequired(true)
.setEmailRequired(true)
.toJson()Configure receiving callbacks from the checkout
CheckoutActivity may send the callback CheckoutActivity.ACTION_ON_BEFORE_SUBMIT when the shopper submits the payment. To receive it, complete the following steps:
-
Create a broadcast receiver to listen for intents from
CheckoutActivity. The example below shows how to receive thePaymentDataobject with the requested data from the Google Pay widget. Refer to the Payments API for the class definition.public class CheckoutBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (CheckoutActivity.ACTION_ON_BEFORE_SUBMIT.equals(action)) { // Get shopper information for Google Pay PaymentData paymentData = intent.getParcelableExtra(CheckoutActivity.EXTRA_GOOGLE_PAY_PAYMENT_DATA); if (paymentData != null) { // Validate PaymentData, if invalid, abort the transaction // intent.putExtra(CheckoutActivity.EXTRA_TRANSACTION_ABORTED, true); // If aborted, PaymentError with ERROR_CODE_TRANSACTION_ABORTED is returned in CheckoutActivityResult } String checkoutId = intent.getStringExtra(CheckoutActivity.EXTRA_CHECKOUT_ID); ComponentName senderComponentName = intent.getParcelableExtra(CheckoutActivity.EXTRA_SENDER_COMPONENT_NAME); // Return control to CheckoutActivity Intent checkoutIntent = new Intent(CheckoutActivity.ACTION_ON_BEFORE_SUBMIT); checkoutIntent.setComponent(senderComponentName); checkoutIntent.setPackage(senderComponentName.getPackageName()); checkoutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // EXTRA_CHECKOUT_ID is not required if the transaction is aborted checkoutIntent.putExtra(CheckoutActivity.EXTRA_CHECKOUT_ID, checkoutId); context.startActivity(checkoutIntent); } } }class BroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent?) { val action = intent?.action if (CheckoutActivity.ACTION_ON_BEFORE_SUBMIT == action) { // get shopper information for the Google Pay val paymentData: PaymentData? = intent.getParcelableExtra(CheckoutActivity.EXTRA_GOOGLE_PAY_PAYMENT_DATA) if (paymentData != null) { // you can validate the PaymentData here, if data is not valid abort the transaction by adding // intent.putExtra(CheckoutActivity.EXTRA_TRANSACTION_ABORTED, true) // in this case the PaymentError with ERROR_CODE_TRANSACTION_ABORTED will be returned in the CheckoutActivityResult } val checkoutId = intent.getStringExtra(CheckoutActivity.EXTRA_CHECKOUT_ID) val senderComponent = intent.getParcelableExtra<ComponentName>(CheckoutActivity.EXTRA_SENDER_COMPONENT_NAME) // return control back to the CheckoutActivity val checkoutIntent = Intent(CheckoutActivity.ACTION_ON_BEFORE_SUBMIT) checkoutIntent.component = senderComponent checkoutIntent.setPackage(senderComponent!!.packageName) checkoutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) // the EXTRA_CHECKOUT_ID is not required if transaction is aborted checkoutIntent.putExtra(CheckoutActivity.EXTRA_CHECKOUT_ID, checkoutId) context.startActivity(checkoutIntent) } } } -
Declare the broadcast receiver in
AndroidManifest.xml.<receiver android:name=".CheckoutBroadcastReceiver" android:exported="false" />Set
android:exported="false"to ensure components from the same application or applications with the same user ID can send messages to the broadcast receiver. -
Use directed broadcasts for better security. Add
ComponentNameof the receiver to theCheckoutActivityintent.CheckoutSettings settings = new CheckoutSettings(...); ComponentName receiverComponentName = new ComponentName("yourPackageName", "yourReceiverClassName"); Intent intent = checkoutSettings.createCheckoutActivityIntent(this, receiverComponentName); startActivityForResult(intent, CheckoutActivity.REQUEST_CODE_CHECKOUT);val checkoutSettings = CheckoutSettings(...) val receiverComponent = ComponentName("yourPackageName", "yourReceiverClassName") val intent: Intent = checkoutSettings.createCheckoutActivityIntent(this, receiverComponent) startActivityForResult(intent, CheckoutActivity.REQUEST_CODE_CHECKOUT)
Submitting shopper information
Instead of collecting shopper information manually, use mSDK to collect and submit it.
Configure CheckoutSettings
CheckoutSettingsSpecify what information to submit:
GooglePaySubmitType.BILLING: Shopper billing address.GooglePaySubmitType.CUSTOMER: Shopper name, surname, phone, and email.
Use one or both options.
checkoutSettings.setGooglePaySubmit(EnumSet.of(GooglePaySubmitType.BILLING, GooglePaySubmitType.CUSTOMER));checkoutSettings.setGooglePaySubmit(EnumSet.of(GooglePaySubmitType.BILLING, GooglePaySubmitType.CUSTOMER))Configure payment data request
The payment data request should include shopper information in the payment data response.
JSONArray allowedPaymentMethodsJson = new JSONArray()
.put(new CardPaymentMethodJsonBuilder()
.setAllowedAuthMethods(new JSONArray()
.put("PAN_ONLY")
.put("CRYPTOGRAM_3DS")
)
.setAllowedCardNetworks(new JSONArray()
.put("VISA")
.put("MASTERCARD")
)
.setGatewayMerchantId("entityId")
.setBillingAddressRequired(true)
.setBillingAddressParameters("FULL", true)
.toJson()
);
JSONObject paymentDataRequestJson = new PaymentDataRequestJsonBuilder()
.setAllowedPaymentMethods(allowedPaymentMethodsJson)
.setTransactionInfo(transactionInfoJson)
// set shipping address required if you use GooglePaySubmitType.CUSTOMER,
// some data can be taken from it if billing address is missing
.setShippingAddressRequired(true)
.setEmailRequired(true)
.toJson();val allowedPaymentMethods = JSONArray()
.put(CardPaymentMethodJsonBuilder()
.setAllowedAuthMethods(JSONArray()
.put("PAN_ONLY")
.put("CRYPTOGRAM_3DS")
)
.setAllowedCardNetworks(JSONArray()
.put("VISA")
.put("MASTERCARD")
)
.setGatewayMerchantId("entityId")
.setBillingAddressRequired(true)
.setBillingAddressParameters("FULL", true)
.toJson()
)
val paymentDataRequestJson = PaymentDataRequestJsonBuilder()
.setAllowedPaymentMethods(allowedPaymentMethodsJson)
.setTransactionInfo(transactionInfoJson)
// set shipping address required if you use GooglePaySubmitType.CUSTOMER,
// some data can be taken from it if billing address is missing
.setShippingAddressRequired(true)
.setEmailRequired(true)
.toJson()Parameters mapping
| OPP parameter | Google Pay field |
|---|---|
billing.street1 | paymentMethodData.info.billingAddress.address1 |
billing.street2 | paymentMethodData.info.billingAddress.address2 and paymentMethodData.info.billingAddress3 |
billing.city | paymentMethodData.info.billingAddress.locality |
billing.state | paymentMethodData.info.billingAddress.administrativeArea |
billing.postcode | paymentMethodData.info.billingAddress.postalCode |
billing.country | paymentMethodData.info.billingAddress.countryCode |
| OPP parameter | Google Pay field |
|---|---|
customer.givenName | paymentMethodData.info.billingAddress.name (before first space) |
customer.surname | paymentMethodData.info.billingAddress.name (after first space) |
customer.phone | paymentMethodData.info.billingAddress.phoneNumber or shippingAddress.phoneNumber |
customer.email | email |
Confirmation page
Display a final price before processing the transaction. If the amount changes based on data from the Google Pay widget, show a confirmation page with the final price. Configure this in CheckoutActivity.ACTION_ON_BEFORE_SUBMIT.
-
Initialise
OrderSummarywith order details, total amount, and Google PayPaymentDataresponse.PaymentData paymentData = intent.getParcelableExtra(CheckoutActivity.EXTRA_GOOGLE_PAY_PAYMENT_DATA); if (paymentData != null) { LinkedHashMap<String, Double> orderItems = new LinkedHashMap<String, Double>() {{ put("Subtotal", 200.00); put("Shipping", 10.00); }}; OrderSummary orderSummary = new OrderSummary(orderItems, 210.00, paymentData); }val paymentData: PaymentData? = intent.getParcelableExtra(CheckoutActivity.EXTRA_GOOGLE_PAY_PAYMENT_DATA) if (paymentData != null) { val orderItems = linkedMapOf( "Subtotal" to 200.00, "Shipping" to 10.00 ) val orderSummary = OrderSummary(orderItems, 210.00, paymentData) } -
Add
OrderSummaryextra to theCheckoutActivityintent.checkoutIntent.putExtra(CheckoutActivity.EXTRA_ORDER_SUMMARY, orderSummary);checkoutIntent.putExtra(CheckoutActivity.EXTRA_ORDER_SUMMARY, orderSummary) -
Start the checkout activity to return control to the SDK and show the confirmation page.
Mobile SDK and your own UI
Follow this tutorial to integrate Google Pay into your UI.
Use PaymentDataRequestJsonBuilder to create the base paymentDataRequestJson object with all required parameters.
To make a transaction, create the GooglePayPaymentParams with a received token and actual card brand:
PaymentParams paymentParams = new GooglePayPaymentParams(checkoutId, token, cardBrand);val paymentParams = GooglePayPaymentParams(checkoutId, token, cardBrand)Get the actual card brand from
com.google.android.gms.wallet.PaymentData. If it isMASTERCARD, useMASTERas the card brand.
Submit the transaction:
Transaction transaction = null;
try {
transaction = new Transaction(paymentParams);
paymentProvider.submitTransaction(transaction);
} catch (PaymentException ee) {
/* error occurred */
}try {
val transaction = Transaction(paymentParams)
paymentProvider.submitTransaction(transaction)
} catch (ee: PaymentException) {
/* error occurred */
}For
GOOGLEPAYTKN, use the newpaymentBrandparameter introduced in the constructor as the payment brand.
Samsung Pay
Samsung Pay is easy to set up and gives your customers a simple and secure way to pay using their Samsung devices. This guide explains how to process Samsung Pay payments with Peach Payments' SDK.
Requirements
- A mobile SDK integration (Ready-to-use UI or SDK and your own UI).
- An approved Samsung account with service and app configured.
- A
SamsungPaySDKJAR file for the correct region. To download the Samsung SDK, go to the Samsung Pay developer resources - A Samsung device.
To use Samsung Pay, you must create keys and a certificate signing request (CSR). Follow these steps:
- In the Smart Payments Platform, go to Administration > Mobile Payment, select Generate keys, and download the CSR.
- In the Samsung Pay Developer Centre, choose Create new service and upload the CSR.
Configuration
Add SamsungPaySDK JAR.
-
Drag
SamsungPaySDK_2.22.00.jarto thelibsfolder. -
Update the
implementationin thebuild.gradlefile. Add the .JAR with the .AAR:implementation fileTree(include: ["*.aar", "*.jar"], dir: "libs") -
Open the
AndroidManifest.xmlfile and add the following metadata in the application tag:<meta-data android:name="debug_mode" android:value="Y" /> <meta-data android:name="spay_debug_api_key" android:value="debug_api_key" /> <meta-data android:name="spay_sdk_api_level" android:value="2.18" />Set
debug_modetoNafter Samsung's review and when ready to go live.
Adding Samsung Pay to your app depends on whether you use the ready-to-use UI or the SDK and your own UI. Follow the relevant section below.
Ready-to-use UI
Add your
applicationIdto your app in the Samsung Pay Developer account. Otherwise, the Samsung Pay SDK does not return a payment token.
Add the Samsung Pay payment brand
Set<String> paymentBrands = new HashSet<>();
paymentBrands.add("SAMSUNGPAY");
CheckoutSettings checkoutSettings = new CheckoutSettings(checkoutId, paymentBrands, Connect.ProviderMode.TEST);val paymentBrands = hashSetOf("SAMSUNGPAY")
val checkoutSettings = CheckoutSettings(checkoutId, paymentBrands, Connect.ProviderMode.TEST)Create SamsungPayConfig
SamsungPayConfigCreate SamsungPayConfig to configure Samsung Pay widget. It requires serviceId and CustomSheetPaymentInfo.
private SamsungPayConfig getSamsungPayConfig() {
return new SamsungPayConfig(
"serviceId",
getCustomPaymentSheetInfo()
);
}
private CustomSheetPaymentInfo getCustomPaymentSheetInfo() {
return new CustomSheetPaymentInfo.Builder()
.setMerchantName("Sample merchant")
.setCustomSheet(getCustomSheet(getTransactionAmount(), application.getCurrency().name()))
.build();
}
private CustomSheet getCustomSheet(double amount, String currencyCode) {
AmountBoxControl amountBoxControl = new AmountBoxControl("amountControlId", currencyCode);
amountBoxControl.setAmountTotal(amount, AmountConstants.FORMAT_TOTAL_PRICE_ONLY);
CustomSheet customSheet = new CustomSheet();
customSheet.addControl(amountBoxControl);
return customSheet;
}private fun getSamsungPayConfig(): SamsungPayConfig? {
return SamsungPayConfig(
"serviceId",
getCustomPaymentSheetInfo())
}
private fun getCustomPaymentSheetInfo(): CustomSheetPaymentInfo? {
return Builder()
.setMerchantName("Sample merchant")
.setCustomSheet(getCustomSheet(getTransactionAmount(),
application.getCurrency().name()))
.build()
}
private fun getCustomSheet(amount: Double, currencyCode: String): CustomSheet? {
val amountBoxControl = AmountBoxControl("amountControlId", currencyCode)
amountBoxControl.setAmountTotal(amount, AmountConstants.FORMAT_TOTAL_PRICE_ONLY)
val customSheet = CustomSheet()
customSheet.addControl(amountBoxControl)
return customSheet
}Set SamsungPayConfig in CheckoutSettings
checkoutSettings.setSamsungPayConfig(getSamsungPayConfig());checkoutSettings.samsungPayConfig = getSamsungPayConfig()Handle the card information update event
Samsung Pay provides the card information update event when the shopper changes the card in Samsung Pay. It passes the newly selected cardInfo, allowing the custom sheet to reflect the change. To handle this event, create SamsungPayConfig.CardInfoUpdateListener and set it to SamsungPayConfig.
public class SamsungPayCardInfoUpdateListener
implements SamsungPayConfig.CardInfoUpdateListener {
public SamsungPayCardInfoUpdateListener() {
// do nothing
}
public SamsungPayCardInfoUpdateListener(@NonNull Parcel in) {
// do nothing
}
@Override
public void onCardInfoUpdated(@NonNull CardInfo selectedCardInfo,
@NonNull CustomSheet customSheet) {
// update custom sheet using selected card info
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel parcel,
int flags) {
// do nothing
}
public static final Creator CREATOR
= new Creator<SamsungPayCardInfoUpdateListener>() {
@Override
public SamsungPayCardInfoUpdateListener createFromParcel(Parcel in) {
return new SamsungPayCardInfoUpdateListener(in);
}
@Override
public SamsungPayCardInfoUpdateListener[] newArray(int size) {
return new SamsungPayCardInfoUpdateListener[size];
}
};
}class SamsungPayCardInfoUpdateListener() : SamsungPayConfig.CardInfoUpdateListener {
constructor(parcel: Parcel) : this()
override fun onCardInfoUpdated(selectedCardInfo: CardInfo,
customSheet: CustomSheet) {
// update custom sheet using selected card info
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
// do nothing
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator {
override fun createFromParcel(parcel: Parcel): SamsungPayCardInfoUpdateListener {
return SamsungPayCardInfoUpdateListener(parcel)
}
override fun newArray(size: Int): Array {
return arrayOfNulls(size)
}
}
}samsungPayConfig.setCardInfoUpdateListener(new SamsungPayCardInfoUpdateListener());samsungPayConfig.cardInfoUpdateListener = SamsungPayCardInfoUpdateListener()If the total amount changes, use the
ACTION_ON_BEFORE_SUBMITcallback ofCheckoutActivityto send a checkout ID update request with the new amount. Perform this server-to-server.
Handle CustomSheetPaymentInfo before payment
CustomSheetPaymentInfo before paymentThe CheckoutActivity may send the callback when the shopper submits the payment. See Receiving callbacks during checkout process. Use this callback to check CustomSheetPaymentInfo and update the checkout if needed.
public class CheckoutBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
if (CheckoutActivity.ACTION_ON_BEFORE_SUBMIT.equals(intent.getAction())) {
CustomSheetPaymentInfo customSheetPaymentInfo = intent.getParcelableExtra(
CheckoutActivity.EXTRA_SAMSUNG_PAY_PAYMENT_DATA);
// handle Samsung Pay custom sheet payment info
}
}
}class BroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
val action = intent?.action
if (CheckoutActivity.ACTION_ON_BEFORE_SUBMIT == action) {
val customSheetPaymentInfo: CustomSheetPaymentInfo = intent.getParcelableExtra(
CheckoutActivity.EXTRA_SAMSUNG_PAY_PAYMENT_DATA);
// handle Samsung Pay custom sheet payment info
}
}
}Mobile SDK and your own UI
Follow the Samsung Pay SDK documentation to receive the tokenised payment information for an in-app payment.
After you have the tokenised payment information, create SamsungPayPaymentParams and submit the transaction.
PaymentParams paymentParams = new SamsungPayPaymentParams(checkoutId, paymentCredential);
paymentParams.setShopperResultUrl("companyname://result");
try {
OppPaymentProvider paymentProvider = new OppPaymentProvider(context, providerMode);
paymentProvider.submitTransaction(new Transaction(paymentParams), transactionListener);
} catch (PaymentException e) {
// handle payment exception
}val paymentParams = SamsungPayPaymentParams(checkoutId, paymentCredential)
paymentParams.shopperResultUrl = "companyname://result"
try {
val paymentProvider = OppPaymentProvider(context, providerMode)
paymentProvider.submitTransaction(Transaction(paymentParams), transactionListener)
} catch (e: PaymentException) {
// handle payment exception
}Updated about 7 hours ago