Card present payments
You need to set up the Clover Go reader to accept payments. Then, you can use the PayRequest method to accept customer payment when they insert a card or tap the card on the device.
Set up the Clover Go reader to accept payments.
For more information, see Supported payment methods.
Prerequisites
Field descriptions
PayRequest fields
| Object | Type | Description | Required/ Optional |
|---|---|---|---|
| amount | int64; boolean | Total amount payment in cents, including taxes. Format: Cents; Cannot be a negative value. Maximum amount = 999999999 | Required |
| final | Boolean | Indicates how the payment is processed. Values:
| Required |
| capture | Boolean | Indicates how the payment is captured. Values:
| Required |
| externalPaymentId | String | Identifier (id) that the merchant keeps as a payment reference. This is useful to reference multiple payments in an order. Length: Maximum 32 characters | Optional |
| externalReferenceId | String | Also referred to as Invoice Number. Identifier (id) that is passed to the merchant's gateway and displayed in settlement records. Length: Maximum 12 characters | Optional |
| taxAmount | int64; boolean | Tax amount in cents. Included in the total amount but can also be set to display in transaction records and receipts. Format: Cents; cannot be a negative value Length: Maximum 999999999 | Optional |
| tipAmount | int64; boolean | Tip amount in cents, including taxes. Format: Cents; cannot be a negative value Length: Maximum 999999999 If the final flag is false, this value is always null/nil (not zero (0)) If the final flag is true—that is, payment type is Sale—and tipAmount is null/nil, then it is calculated as zero (0). | Optional |
| keyedInCard | KeyedInCard | See Manual entry payments for more information. Value for card reader payments = null/nil. | Required only for a manual card entry. |
PayResponse fields
| Object | Type | Description |
|---|---|---|
| payment | Payment | Payment details auto-populate on successful payment. |
| issues | Array of PaymentIssueEnum | Array of the enum of the concerns related to the payment. The integrator may want to void this payment in some scenarios. Note: Integrator(s) decide how they want to proceed in the case of issues. For example:
|
PaymentIssueEnum
| Object | Description |
|---|---|
| Duplicate_Payment | Payment is detected as a duplicate payment. |
| Offline_Payment | Payment is detected as offline payment. Note: Offline payments are not supported with this version of Clover Go software development kit (SDK). Integrators won't receive this enum. |
| Partial_Payment | Card allowed only partial payment of the full amount requested. |
| Signature_Required | Signature is required for the transaction. |
| AVS_Mismatch | Address Verification Service (AVS) detects an address mismatch. |
| CVV_Mismatch | Card verification value (CVV) detects a CVV mismatch. |
IMPORTANTReview the resulting payment object's amount field to verify that the full amount requested was authorized. In some scenarios, only a partial amount may be authorized, and your app needs to issue further PayRequest instances to reach the full amount or reverse the transaction.
CloverError
CloverError can be any of the following:
| Error type | Description |
|---|---|
| CloverCardError | Transaction failed because of card error—for example, card expired. |
| CloverMerchantBoardingError | Merchant status returns a declined or pending status from the server. |
| CloverNetworkError | Standard HTTP errors that are captured during communications with our servers. |
| CloverReaderError | Errors encountered while communicating with the card reader. |
| CloverTransactionError | Errors encountered while processing a transaction |
| CloverGenericError | Any error that doesn't fall into the error categories above. |
Android card present payment steps
To create a card present payment:
- Connect the card reader and ensure it has more than 2% of battery power.
- Use
PayRequest. - Note the
ChargeCardReaderState.
A successful request returns OnPaymentComplete with the PayResponse. An error such as a timeout returns OnPaymentError. Instead of PaymentChallenge being displayed, the payment proceeds further, and the issues enum array contains any issues received through the process.
The integrator needs to call ReversePayment to cancel the transaction.
If the request fails—for example, if there is a timeout, a CloverError returns. See CloverError for further details.
Response details
ChargeCardReaderState
| Field | Description |
|---|---|
| OnPaymentComplete | Indicates a successful payment. Review the PayResponse for the successful payment details. |
| OnPaymentError | Indicates an error occurred. The payment is voided. See CloverError for error descriptions. |
| OnReaderPaymentProgress | Captures the progress state in between. See PaymentProgressEvent for in-between progress events. |
PaymentProgressEvent
| Field | Description |
|---|---|
| Card_Inserted | Card reader detected that the card is inserted. |
| Card_Removed | Card is removed after the dip. |
| Card_Swiped | Card reader detected that the card is swiped (in case the device supports it). |
| Card_Tapped | Card reader detected that the card is tapped. |
| Contactless_Failed_Try_Again | For some reason, the contactless failed. Retry or try other methods like dip. |
| EMV_Card_Swiped | Card reader detected that Europay, Mastercard, and Visa (EMV) card is swiped, if the device supports EMV. |
| EMV_Dip_Failed_Try_Again | Card dip failed. Try again or try another method, such as contactless. |
| Insert_Or_Tap_Card | Card reader is ready to take the payment. |
| Multiple_Contactless_Cards_Detected | Multiple cards are tried in an attempt to make a payment. |
| Remove_Card | If the card is dipped, the card data is read, and it needs to be removed to proceed. |
| Request_In_Flight | Transaction is started and the state is put in flight. If another transaction is tried while this is in progress, the other transactions fail. Clear the state onPaymentComplete/onPaymentError. |
| Swipe_Failed | Swipe failed in instances where swipe is supported. |
PayRequest example
fun chargeCardReader(charge: PayRequest): Flow<ChargeCardReaderState>For a non-KeyedInCard PayRequest—such as no KeyedInCard details—ensure the card reader is connected and has more than 2% battery power.
PayRequest request = new PayRequest(
amount,
capture,
isFinal,
externalPaymentID,
externalreferenceID,
taxAmount,
tipAmount,
null //since this is a card present payment, keyed in card is null
);
goSdk.chargeCardReader(
activity,
request,
new GoSdkCallback<ChargeCardReaderState>() {
@Override
public void onNext(ChargeCardReaderState cardReaderState) {
if (chargeCardReaderState instanceof ChargeCardReaderState.OnReaderPaymentProgress) {
Log.d(TAG, "Payment in progress");
updateUI(cardReaderState);
} else if (chargeCardReaderState instanceof ChargeCardReaderState.OnPaymentComplete) {
Log.d(TAG, "Payment successful");
updateUI(cardReaderState);
} else if (chargeCardReaderState instanceof ChargeCardReaderState.OnPaymentError) {
Log.d(TAG, "Payment failed");
updateUI(cardReaderState);
} else {
//Something unexpected happened
}
}
@Override
public void onError(@NonNull Throwable e) {
//handle error scenario
}
}
);lifecycleScope.launch {
/*
Capture State
Final/Sale - true
Tippable/Auth - true
Pre-Auth - false
*/
val request = PayRequest(
final = final,
capture = capture,
amount = amount, //Please note that amount is not nullable, unlike taxAmount and tipAmount
taxAmount = taxAmount,
tipAmount = tipAmount,
externalPaymentId = externalID
)
goSdk.chargeCardReader(
request
).collectLatest { cardReaderState ->
when (cardReaderState) {
is ChargeCardReaderState.OnPaymentComplete -> {
println("Payment successful")
updateUI(cardReaderState)
}
is ChargeCardReaderState.OnPaymentError -> {
println("Payment failed")
updateUI(cardReaderState)
}
is ChargeCardReaderState.OnReaderPaymentProgress -> {
println("Payment in progress")
updateUI(cardReaderState)
}
else -> {
//Something unexpected happened
}
}
}
}iOS card present payment steps
To accept payment using a card reader:
- Create a
PayRequestobject. - Pass it to the
CloverPaymentSDK.shared.charge()function.- Successful transaction returns a .complete paymentEvent with the associated payment, and the async stream closes.
- Failed transaction throws an error, and the async stream closes. During transaction processing, .progress paymentEvents is called to provide status and instructions to provide to the customer.
let payRequest = PayRequest(amount: 1000, taxAmount: 80, tipAmount: 200)
do {
for try await paymentEvent in CloverPaymentSDK.shared.charge(payRequest: payRequest) {
switch paymentEvent {
case .complete(let payResponse):
print("Payment complete")
if payResponse.issues.contains(.duplicatePayment) {
print("This payment is a possible duplicate")
}
case .progress(let progressEvent):
switch event {
case .insertOrTapCard: presentAlert(title: "Insert or Tap Card", message: nil)
case .swipeInsertTapCard: presentAlert(title: "Swipe, Insert, or Tap Card", message: nil)
case .removeCard: presentAlert(title: "Remove Card", message: nil)
case .cardInserted: fallthrough
case .cardRemoved: alert?.dismiss(animated: true)
default: break
}
@unknown default: break
}
}
} catch {
print("Payment Error \(error)")
}Updated 3 days ago
