Integrate our products into your software. Let's make payment happen together!
Look at all the possibilitiesThis guide will walk you through the process to do a payment using the opiPaymentApi The method we will use for this is:
void payment(ExternalTerminal terminal,Payment payment,PaymentDelegate paymentDelegate)
next up we will construct our request objects.
The ExternalTerminal object contains everything regarding the terminal setup. The creation can be done manually as the code snippet beneath shows or using the paymentTerminalDiscoveryService which we recommend as this does this construction for you. \ When you retrieve your terminal you will be informed which protocol your terminal uses. FYI, OPI-NL & OPI-DE are terminal communication-protocols which your terminal uses
ExternalTerminal externalTerminal = ExternalTerminal.builder() .ipAddress(ipAddress) // can be found using getting-started guide .port(terminalPort) // 4100 for OPI-NL & 20002 for OPI-DE .compatibilityPort(compatibilityPort) // 4102 for OPI-NL & 20007 for OPI-DE .socketMode(socketMode) // Dual-Socket for OPI-NL & Single-Socket for OPI-DE & OPI-NL .terminalType(terminalType) // EnumType which contains terminal protocol combined attended/unattended type .languageCode(LanguageCode.EN) // determines the language of the CashierDisplay messages (optional) .printerStatus(PrinterStatusType) // EnumType which contains the printer status: Available, Unavailable, PaperEmpty and PaperLow. Only for OPI-NL .shiftNumber(shiftNumber) // ShiftNumber is used to create a total during a specific shift. .merchantEmailAddress(merchantEmailAddress) // Passes the merchant email address to the terminal so the merchant receipt will be sent to it (OPI-NL via E-ReceiptServer, OPI-DE via OAM server) .customerEmailAddress(customerEmailAddress) // Passes the customer email address to the terminal so the customer receipt will be sent to it (OPI-NL via E-ReceiptServer, OPI-DE via OAM server) .supportMifareCards(true/false) // Indicates if you also want to read MiFare cards when performing a Sale, PreAuthorisation or CardDetection on an unattended OPI-NL terminal .receiptMode(ReceiptMode) // Pass to the terminal how you want to receive your receipts: Default (During the payment), Off (No receipts are send back), ReceiptsInResponse (Terminal send receipts with the end result). This is for OPI-DE terminals only .build();
The Payment object contains everything about the payment you want to be executed on the terminal.
Money money = new Money(new BigDecimal("0.05"), Currency.getInstance("EUR")); Payment payment = Payment .builder() .type(Payment.Type.SALE) .amount(money) .build();
This is the callback mechanism which we use to pass the responses asynchronously to the integrator.
PaymentDelegate paymentDelegate = new PaymentDelegate() { @Override public void onPaymentSuccess(PaymentResult result) { // The payment is completed successful! // The paymentResult contains all information about the transaction } @Override public void onError(Error error) { // The payment failed // The Error object contains information about what went wrong } @Override public void printMerchantReceiptAndSignature(PaymentReceipt receipt) { // Code to handle the MerchantReceipt } @Override public void printCustomerReceiptAndSignature(PaymentReceipt receipt) { //Code to handle CustomerReceipt } @Override public void printDccOffer(PaymentReceipt receipt) { //Code to handle DCC (Dynamic Currency Conversion) receipt } @Override public void printJournalReceipt(PaymentReceipt receipt) { // Code to handle JournalReceipt // This is OPI-NL terminal-protocol specific } @Override public void storeEJournal(String journal) { // Code to store the E-Journal // This is OPI-NL terminal-protocol specific } @Override public void cardUID(String cardUID) { // This is OPI-NL Unattended terminal specific } };
For more information about all possible errorcodes please click here
Now that all our request objects are ready, we can create an instance of the api we want to use. For this guide this will be the paymentApi
PaymentApi paymentService = new eu.ccvlab.mapi.api.PaymentService();
Last but not least, we will execute the specific method payment method which will cause our payment to happen.
paymentService.payment(externalTerminal, payment, paymentDelegate);
When a transaction is completed you’ll receive a result object via the onPaymentSuccess method or via the onError method.
The result object contains all the information about the transaction. For OPI-DE terminals there are some extra fields that are sent back from the terminal:
To retrieve these fields from the result object you will need to cast the result object to a PaymentResultDE object.
Casting in the onPaymentSuccess method:
@Override public void onPaymentSuccess(PaymentResult result) { // The payment is completed successful! // The paymentResult contains all information about the transaction PaymentResultDE paymentResultDE = (PaymentResultDE) result; paymentResultDE.actionCode(); paymentResultDE.returnCode(); paymentResultDE.answerCode(); }
Casting in the onError method:
@Override public void onError(Error error) { // The payment failed // The Error object contains information about what went wrong if (error.result() != null) { PaymentResultDE paymentResultDE = (PaymentResultDE) error.result(); paymentResultDE.actionCode(); paymentResultDE.returnCode(); paymentResultDE.answerCode(); } }
During a payment it could occur that an extra interaction with the integrator is required.
The possible user interactions are:
When an identification and/or signature is needed from the cardholder this will indicated with the following methods on terminals with communication-protocl:
OPI-NL:
OPI-DE:
When an identification and/or signature is needed from the cardholder, the POS needs to create a dialog containing the corresponding message.
Although it is mandatory to show this text at least six seconds to the cashier, it is advised to keep this box available on the screen until the cashier presses/clicks it away.
Example snippet for ask customer signature on an OPI-NL configured terminal:
PaymentDelegate paymentDelegate = new PaymentDelegate() { @Override public void askCustomerSignature(Callback callback) { //Show dialog with corresponding message callback.proceed(); } };
Corresponding example for OPI-DE configured terminal:
PaymentDelegate paymentDelegate = new PaymentDelegate() { @Override public void askCustomerSignature(SignatureAsked signatureAsked) { //Show dialog with corresponding message signatureAsked.signatureAsked(); } };
The DeliveryBox functionality can be used to indicate if the goods are delivered before completing the transaction. If the goods cannot be dispensed the transaction will be aborted.
During the payment flow, the integrator-app needs to deliver the goods and services. The following PaymentDelegate method is called to perform the delivery.
PaymentDelegate delegate = new PaymentDelegate() { ... @Override public void onDeliverGoodsOrServices(DeliveryBoxCallback deliveryBoxCallback) { // Deliver your goods // Call the deliveryBoxCallback.proceed(boolean) once you know that your delivery was successful or noet. deliveryBoxCallback.proceed(true); } ... }; paymentService.payment(terminal, payment, delegate); ...