Accept a payment
Use the PaymentRequestIntentBuilder
class to build an Intent to start an activity to guide a user through the payment steps. Depending on the merchant configuration and Intent options set, a successful payment may be either a finalized payment or a tip-adjustable payment. The steps may include tip selection, signature collection, payment confirmation, and receipt selection. You can configure the options through the merchant settings or on the PaymentRequestIntentBuilder
.
Prerequisites
- Read overview of the Clover platform.
- Create a global developer account with a default test merchant account.
- Order a Clover Developer Kit (Dev Kit) and set it up.
- Use the required Android SDK versions.
Build a payment request
You can build a payment request with a few lines of code.
val externalPaymentId = "<posPaymentId>" // should be unique for each request
val amount = 1000L
val context = this
val builder = PaymentRequestIntentBuilder(externalPaymentId, amount)
val intent = builder.build(context)
String externalPaymentId = "<posPaymentId>";
Long amount = 1000L;
Context context = this;
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder(externalPaymentId, amount);
Intent intent = builder.build(context);
Use the Intent to start the activity to process the payment request.
Options set on the builder to provide additional processing instructions include:
- TipOptions—Settings for tips (if tips are enabled for merchant) and settings for signature requirements
- CardOptions—Settings for supported card entry methods and card confirmations
- ReceiptOptions—Settings for receipt screen
- OfflineOptions—Settings to control offline payment options
- TokenizeOptions—Settings for pay and tokenize cards for use in Ecommerce services
TipOptions & SignatureOptions
TipOptions & SignatureOptions are independent options that can be excluded; however, they share the same “location” value (on screen/on paper).
TipOptions
The TipOptions
class provides static helper methods to simplify the creation of TipOptions.
Method | Description |
---|---|
Disable() | Sets the options so that no tip is requested. Creates a final payment that is not tip-adjustable. |
Provided(tipAmount: Long) | If the tip amount is known before the payment request, this adds the tip amount to the payment and the payment is finalized. |
PromptCustomer(baseAmount: Long, tipSuggestions: List<TipSuggestion>) | Sets the amount to calculate the percentage-based tips or override the tip suggestions with fixed amounts or custom percentages. |
NOTE
The merchant’s payment gateway settings must be configured to create tippable payment for a tip-adjustable payment. On some devices, tips are taken prior to the payment and can be supported without merchant payment gateway settings, as the payment is finalized by the gateway.
SignatureOptions
The SignatureOptions
class provides static helper methods to simplify the creation of SignatureOptions.
Method | Description |
---|---|
Disable() | Sets the options so that no signature is requested. |
PromptCustomer() | Overrides the merchant settings for when, and if, to prompt for a signature. |
Example—Disable tip and signature for a payment
val builder = PaymentRequestIntentBuilder("<posPaymentId>", 1500)
builder.tipAndSignatureOptions(
PaymentRequestIntentBuilder.TipOptions.Disable(),
PaymentRequestIntentBuilder.SignatureOptions.Disable(),
null) // preferOnScreen
val intent = builder.build(context)
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder("<posPaymentId>", 1500);
builder.tipAndSignatureOptions(
PaymentRequestIntentBuilder.TipOptions.Disable(),
PaymentRequestIntentBuilder.SignatureOptions.Disable(),
null); //preferOnScreen
Intent intent = builder.build(context);
CardOptions
The CardOptions
class provides a static method to set the supported card entry methods. It also includes options to auto-accept duplicate payment challenges that bypass the challenge prompts, and a cardNotPresent flag which, if false, results in manual card entry only.
Method | Description |
---|---|
Instance(<br> <span style="white-space: nowrap;"> cardEntryMethods : Set<CardEntryMethod>,</span><br> <span style="white-space: nowrap;"> cardNotPresent : Boolean,</span><br> <span style="white-space: nowrap;"> autoAcceptDuplicates : Boolean) | Optionally sets any of these flags to create a CardOptions instance. If null is passed, the default settings for the merchant are used. |
Instance(<br> <span style="white-space: nowrap;"> cardEntryMethods : Set<CardEntryMethod>,</span><br> <span style="white-space: nowrap;"> cardNotPresent : Boolean,</span><br> <span style="white-space: nowrap;">autoAcceptDuplicates : Boolean,</span><br> <span style="white-space: nowrap;"> cashbackOptions : CashbackOptions) | Optionally sets any of these flags to create a CardOptions instance. If null is passed, the default settings for the merchant are used. |
Example—Set the card entry method to Manual only and to auto-accept duplicate challenges
val builder = PaymentRequestIntentBuilder("<posPaymentId>", 1500)
builder.cardOptions(
PaymentRequestIntentBuilder.CardOptions.Instance(
CardEntryMethod.Manual(), // manual only
null, // card not present
true)) // auto-accept duplicates
val intent = builder.build(context)
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder("<posPaymentId>", 1500);
builder.cardOptions(PaymentRequestIntentBuilder.CardOptions.Instance(
CardEntryMethod.Manual(), // manual only
null, // card not present
true)); // auto-accept duplicates
Intent intent = builder.build(context);
ReceiptOptions
The ReceiptOptions
class provides the following options:
Static Method | Description |
---|---|
Default(cloverShouldHandleReceipts: Boolean) | Set whether clover should handle printing or sending SMS/Email receipts. |
SkipReceiptSelection() | Configure the flow to skip the receipt selection. |
Instance(<br><span style="white-space: nowrap;">cloverShouldHandleReceipts : Boolean,</span> <span style="white-space: nowrap;">smsReceiptOption : SmsReceiptOption,</span><br><span style="white-space: nowrap;">emailReceiptOption : EmailReceiptOption,</span><br><span style="white-space: nowrap;">printReceiptOption : PrintReceiptOption,</span><br><span style="white-space: nowrap;">noReceiptOption : NoReceiptOption)</span> | Disable or enable every receipt selection button on the receipt screen. In addition, this can be used to decide if clover should handle the printing or sending of SMS/Email receipts. |
Example—Disable the SMS and email receipt buttons and set cloverShouldHandleReceipts
to true.
cloverShouldHandleReceipts
to true.val externalPaymentId = "<posPaymentId>" // should be unique for each request
val amount = 1000L
val builder = PaymentRequestIntentBuilder(externalPaymentId, amount)
val receiptOptions = PaymentRequestIntentBuilder.ReceiptOptions.Instance(
true, //cloverShouldHandleReceipts = true
PaymentRequestIntentBuilder.ReceiptOptions.SmsReceiptOption.Disable(), //disable SMS receipt button
PaymentRequestIntentBuilder.ReceiptOptions.EmailReceiptOption.Disable(), //disable Email receipt button
PaymentRequestIntentBuilder.ReceiptOptions.PrintReceiptOption.Enable(), //enable Print receipt button
PaymentRequestIntentBuilder.ReceiptOptions.NoReceiptOption.Enable()) //enable No Receipt button
val paymentRequestIntent = builder.receiptOptions(receiptOptions).build(context)
String externalPaymentId = "<posPaymentId>";
Long amount = 1000L;
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder(externalPaymentId, amount);
PaymentRequestIntentBuilder.ReceiptOptions receiptOptions = PaymentRequestIntentBuilder.ReceiptOptions.Instance(
true, //cloverShouldHandleReceipts = true
PaymentRequestIntentBuilder.ReceiptOptions.SmsReceiptOption.Disable(), //disable SMS receipt button
PaymentRequestIntentBuilder.ReceiptOptions.EmailReceiptOption.Disable(), //disable Email receipt button
PaymentRequestIntentBuilder.ReceiptOptions.PrintReceiptOption.Enable(), //enable Print receipt button
PaymentRequestIntentBuilder.ReceiptOptions.NoReceiptOption.Enable()); //enable No Receipt button
Intent intent = builder.receiptOptions(receiptOptions).build(context);
Result on the device
OfflineOptions
The OfflineOptions
class provides a static method to configure three flags for offline payment settings.
NOTE
To use this feature, merchant's payment gateway must be configured for offline payments.
Static Methods | Description |
---|---|
Instance(<br> <span style="white-space: nowrap;"> allowOfflinePayment : Boolean,</span><br> <span style="white-space: nowrap;"> allowOfflinePaymentWithoutPrompt : Boolean,</span><br> <span style="white-space: nowrap;"> forceOfflinePayment : Boolean)</span> | Creates an OfflineOptions instance that is configured to take the payment offline. If needed, can take the payment offline without prompting the merchant and force the payment to be taken offline. The resulting payment returns a value of offline=true , if the payment was taken offline. Offline payments are processed as soon as network connectivity is available. |
Example—Allow an offline payment and disable the allow offline prompt
val builder = PaymentRequestIntentBuilder("<posPaymentId>", 1500)
builder.offlineOptions(
PaymentRequestIntentBuilder.OfflineOptions.Instance(
true, // allow offline
true, // approveOfflineWithoutPrompt
null)) // forceOffline
val intent = builder.build(context)
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder("<posPaymentId>", 1500);
builder.offlineOptions(
PaymentRequestIntentBuilder.OfflineOptions.Instance(
true, //allow offline
true, //approveOfflineWithoutPrompt
null)); //forceOffline
Intent intent = builder.build(context);
Tokenize options
The TokenizeOptions
class contains a single property, suppressConfirmation. However, the presence of TokenizeOptions, regardless of the suppressConfirmation value, indicates that a token should be generated for the payment card. The tokenize option is secondary to the payment, so, a failed tokenization can result in a successful payment but a failed payment cannot result in a successful tokenization.
Value | Description |
---|---|
Instance(suppressConfirmation:boolean) | Creates a TokenizeOptions instance with the confirmation required or not. By default, confirmation is required and is requested. |
NOTE
To use this feature, you must have core-payments installed in your device. Contact support for queries.
Example—Request a payment token with a payment
val builder = PaymentRequestIntentBuilder("<posPaymentId>", 1500)
builder.tokenizeOptions(PaymentRequestIntentBuilder.TokenizeOptions.Instance(
false // suppressConfirmation
));
val intent = builder.build(context)
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder("<posPaymentId>", 1500);
builder.tokenizeOptions(
PaymentRequestIntentBuilder.TokenizeOptions.Instance(
false)); //suppressConfirmation
Intent intent = builder.build(context);
Additional fields
Additional fields on the PaymentRequestIntentBuilder
include:
Field | Description |
---|---|
externalPaymentId: String | Custom external payment identifier (Id) to identify the transaction. |
amount: Long | Total amount paid. |
taxAmount: Long | Amount paid in taxes. This amount must display in the amount field as this is used for reporting purposes. |
externalReferenceId: String | Reference identifier (Id) that can be passed to the merchant's gateway displays in settlement records as the Invoice Number. |
Response details
When the payment flow completes, the response comes through onActivityResult()
.
- When the request is successful, you can retrieve the resulting Payment object with
Intents.EXTRA_PAYMENT
. You can also retrieve the receipt option selected withIntents.EXTRA_RECEIPT_DELIVERY_TYPE
if it was processed or requested usingIntents.EXTRA_RECEIPT_DELIVERY_STATUS
. - If an email or SMS value is entered, that value is retrieved using
Intents.EXTRA_ENTERED_RECEIPT_VALUE
. - If you tokenized the card used, the card is retrieved using
Intents.EXTRA_CARD
. - When the request is unsuccessful, you can retrieve the failure message with
Intents.EXTRA_FAILURE_MESSAGE
.
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PAYMENT_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
val payment: Payment = data.getParcelableExtra(Intents.EXTRA_PAYMENT)
val receiptDeliveryStatus = data.getStringExtra(Intents.EXTRA_RECEIPT_DELIVERY_STATUS)
val receiptDeliveryType = data.getStringExtra(Intents.EXTRA_RECEIPT_DELIVERY_TYPE)
val enteredReceiptValue = data.getStringExtra(Intents.EXTRA_ENTERED_RECEIPT_VALUE)
val card:Card = data.getParcelableExtra(Intents.EXTRA_CARD) //if card was tokenized
} else {
// payment failed, check for error
val failureMessage = data.getStringExtra(Intents.EXTRA_FAILURE_MESSAGE)
}
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PAYMENT_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Payment payment = data.getParcelableExtra(Intents.EXTRA_PAYMENT);
String receiptDeliveryStatus = data.getStringExtra(Intents.EXTRA_RECEIPT_DELIVERY_STATUS);
String receiptDeliveryType = data.getStringExtra(Intents.EXTRA_RECEIPT_DELIVERY_TYPE);
String enteredReceiptValue = data.getStringExtra(Intents.EXTRA_ENTERED_RECEIPT_VALUE);
Card card = data.getParcelableExtra(Intents.EXTRA_CARD); //if card was tokenized
} else {
// payment failed, check for error
String failureMessage = data.getStringExtra(Intents.EXTRA_FAILURE_MESSAGE);
}
}
}
Examples
Custom tips
Example—Create custom tip options of $1.00, $2.00, and 20% and prefer onScreen tips.
val builder = PaymentRequestIntentBuilder("<posPaymentId>", 1500)
var tipSuggestions = listOf<TipSuggestion>(
TipSuggestion.Amount("Thanks!", 100),
TipSuggestion.Amount("Good Job!", 200),
TipSuggestion.Percentage("Great!", 20)
)
var tipOptions = PaymentRequestIntentBuilder.TipOptions.PromptCustomer(null, tipSuggestions)
builder.tipAndSignatureOptions(
tipOptions,
null, // signature options
true) // preferOnScreen
val intent = builder.build(context)
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder("<posPaymentId>", 1500);
List<TipSuggestion> tipSuggestions = Arrays.asList(
TipSuggestion.Amount("Thanks!", 100L),
TipSuggestion.Amount("Good Job!", 200L),
TipSuggestion.Percentage("Great!", 20L));
PaymentRequestIntentBuilder.TipOptions tipOptions = PaymentRequestIntentBuilder.TipOptions.PromptCustomer(null, tipSuggestions);
builder.tipAndSignatureOptions(tipOptions,
null,
true);
Intent intent = builder.build(context);
Custom card entry methods
Example—Set the card entry methods to Manual and near-field communication (NFC) only.
val builder = PaymentRequestIntentBuilder("<posPaymentId>", 1500)
var cardEntryMethods = setOf<CardEntryMethod>(
CardEntryMethod.MANUAL,
CardEntryMethod.NFC)
var cardOptions = PaymentRequestIntentBuilder.CardOptions.Instance(
cardEntryMethods,
null, // card not present
null) // auto accept duplicates
builder.cardOptions(cardOptions)
val intent = builder.build(context)
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder("<posPaymentId>", 1500);
Set<CardEntryMethod> cardEntryMethods = new HashSet<>();
cardEntryMethods.add(CardEntryMethod.MANUAL);
cardEntryMethods.add(CardEntryMethod.NFC);
PaymentRequestIntentBuilder.CardOptions cardOptions = CardOptions.Instance(
cardEntryMethods,
null, //card not present
null); //auto accept duplicates
builder.cardOptions(cardOptions);
Intent intent = builder.build(context);
Minimal interaction
Example—Reduce the screens to only the payment screen. This example disables tips, signatures, and payment confirmations, and skips the receipt screen.
val builder = PaymentRequestIntentBuilder("<posPaymentId>", 1500)
builder.tipAndSignatureOptions(
PaymentRequestIntentBuilder.TipOptions.Disable(),
PaymentRequestIntentBuilder.SignatureOptions.Disable(),
true)
builder.cardOptions(
PaymentRequestIntentBuilder.CardOptions.Instance(
null,
null,
true))
builder.receiptOptions(PaymentRequestIntentBuilder.ReceiptOptions.SkipReceiptSelection())
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder("<posPaymentId>", 1500);
builder.tipAndSignatureOptions(
PaymentRequestIntentBuilder.TipOptions.Disable(),
PaymentRequestIntentBuilder.SignatureOptions.Disable(),
true);
builder.cardOptions(
PaymentRequestIntentBuilder.CardOptions.Instance(
null,
null,
true));
builder.receiptOptions(PaymentRequestIntentBuilder.ReceiptOptions.SkipReceiptSelection());
Intent intent = builder.build(context);
Custom cashback options
Example—Set the CashbackOptions to $10, $15, $20, $25.
val builder = PaymentRequestIntentBuilder("<posPaymentId>", 1500)
val cashbackSuggestions: List<Long> = mutableListOf(10, 15, 20, 25)
val cashbackOptions = PaymentRequestIntentBuilder.CardOptions.CashbackOptions.Suggestions(cashbackSuggestions)
builder.cardOptions(
PaymentRequestIntentBuilder.CardOptions.Instance(
null,
null,
false,
cashbackOptions))
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder("<posPaymentId>", 1500);
List<Long> cashbackSuggestions = Arrays.asList(10L, 15L, 20L, 25L);
PaymentRequestIntentBuilder.CardOptions.CashbackOptions cashbackOptions = PaymentRequestIntentBuilder.CardOptions.CashbackOptions.Suggestions(cashbackSuggestions);
builder.cardOptions(
PaymentRequestIntentBuilder.CardOptions.Instance(
null, //cardEntryMethods
null, //cardNotPresent
false, //autoAcceptDuplicates
cashbackOptions));
Intent intent = builder.build(context);
Disable cashback
Example—Disable the cashback options screen.
val builder = PaymentRequestIntentBuilder("<posPaymentId>", 1500)
val cashbackOptions = PaymentRequestIntentBuilder.CardOptions.CashbackOptions.Disable()
builder.cardOptions(
PaymentRequestIntentBuilder.CardOptions.Instance(
null,
null,
false,
cashbackOptions))
PaymentRequestIntentBuilder builder = new PaymentRequestIntentBuilder("<posPaymentId>", 1500);
PaymentRequestIntentBuilder.CardOptions.CashbackOptions cashbackOptions = PaymentRequestIntentBuilder.CardOptions.CashbackOptions.Disable();
builder.cardOptions(
PaymentRequestIntentBuilder.CardOptions.Instance(
null, //cardEntryMethods
null, //cardNotPresent
false, //autoAcceptDuplicates
cashbackOptions));
Intent intent = builder.build(context);
Updated 2 months ago