Advanced Flows¶
Cancel the Transaction¶
The POS should use the TransactionManager.abort()
method to
cancel the transaction in progress. The corresponding PaymentCompletedEvent.getStatus()
will return StatusCode.ABORTED
to indicate that it was aborted.
If the event does not have this status, then it’s possible that calling abort
did not happen in time, and the POS should either reverse the transaction
using the TransactionManager.processVoid()
method, or simply accept the completed result.
Inline Tipping with Tip Options¶
The merchant would like the customer to select a tip from a pre-configured menu, determining how much gratuity should be added to the purchase. This menu can be presented before the card is presented, or after, depending on the POS’ preference.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Override // Overridden from the CommerceListenerAdapter public void handleUserInputEvent(UserInputEvent event) { if (UserInputEvent.RECEIVED_TYPE.equals(event.getType())) { Values valueFromCustomer = event.getValues(); if (event.getInputType() == InputType.MENU_OPTIONS) { if (event.getStatus() == StatusCode.SUCCESS) { int selectedIndex = valueFromCustomer.getSelectedIndices()[0]; // Use selected index to determine which button they selected. // In this example, index 0 is 20%, 1 is 15%, etc. } // else handle error } // else handle other input response } // else handle input request from POI } final String header = "Please select a tip"; final String[] buttons = new String[] { "20%", "15%", "10%", "None" }; mTransactionManager.presentUserOptions(header, buttons); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Overridden from the CommerceListenerAdapter override fun handleUserInputEvent(event: UserInputEvent) { if (UserInputEvent.RECEIVED_TYPE.equals(event.getType())) { val valueFromCustomer = event.getValues() if (event.getInputType() == InputType.MENU_OPTIONS) { if (event.getStatus() == StatusCode.SUCCESS) { val selectedIndex = valueFromCustomer.getSelectedIndices()[0] // Use selected index to determine which button they selected. // In this example, index 0 is 20%, 1 is 15%, etc. } // else handle error } // else handle other input response } // else handle input request from POI } val header = "Please select a tip" val buttons = arrayOf("20%", "15%", "10%", "None") mTransactionManager.presentUserOptions(header, buttons) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Overridden from the VFICommerceListenerAdapter override func handle(_ event: VFIUserInputEvent?) { var valueFromCustomer = event?.getValues() if (VFIInputType.MENUOPTIONS == event?.getInputType()) { if (VFIStatusCodeSuccess == event?.getStatus()) { var selectedIndex = valueFromCustomer?.getSelectedIndices()[0] // Use selected index to determine which button they selected. // In this example, index 0 is 20%, 1 is 15%, etc. } // else handle error } // else handle other input response } let header = "Please select a tip" let buttons = ["20%", "15%", "10%", "None"] sdk.getTransactionManager()?.presentUserOptions(header, buttonLabels: buttons) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | private readonly EventHandler<UserInputEvent> user_input_event_handler_; private void HandleEvent(UserInputEvent event) { if (event.Type == UserInputEvent.RECEIVED_TYPE) { Values value_from_customer = event.ResponseValues; if (event.InputType == InputType.MENU_OPTIONS) { if (event.Status == StatusCode.SUCCESS) { int selected_index = value_from_customer.SelectedIndices[0]; // Use selected index to determine which button they selected. // In this example, index 0 is 20%, 1 is 15%, etc. } // else handle error } // else handle other input response } // else handle input request from POI } // ... // Link event handler after initialization is complete but before requesting input user_input_event_handler_ = async (sender, args) => { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => HandleEvent(args)); }; payment_sdk_.TransactionManager.HandleUserInputEvent += user_input_event_handler_; // ... // Present the tip options. string header = "Please select a tip"; string[] buttons = new string[] {"20%", "15%", "10%", "None"}; payment_sdk_.TransactionManager.PresentUserOptions(header, buttons); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // Overridden from the CommerceListenerAdapter void handleUserInputEvent ( const std::shared_ptr<verifone_sdk::UserInputEvent>& event) override { if (event->getType() == verifone_sdk::UserInputEvent::RECEIVED_TYPE) { auto values = event->getValues(); if (event->getInputType() == InputType::MENU_OPTIONS) { if (event->getStatus() == StatusCode::SUCCESS) { auto selected_indices = event->getValues()->getSelectedIndices(); // Use selected indices to determine which button they selected. // In this example, index 0 is 20%, 1 is 15%, etc. } // else handle error } // else handle other input response } // else handle input request from POI } // ... std::vector<std::string> options = {"20%", "15%", "10%", "None"}; auto status = psdk->getTransactionManager()->presentUserOptions( "Please select a tip", options); if (status->getStatus() == verifone_sdk::StatusCode::SUCCESS) { //operation initiated successfully } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public void HandleUserInputEvent(UserInputEvent sdk_event) { if (sdk_event.Type == UserInputEvent.RECEIVED_TYPE) { Values value_from_customer = sdk_event.Values; if (sdk_event.InputType == VerifoneSdk.InputType.MENU_OPTIONS) { if (sdk_event.Status == 0) { int selected_index = value_from_customer.SelectedIndices[0]; // Use selected index to determine which button they selected. // In this example, index 0 is 20%, 1 is 15%, etc. } // else handle error } // else handle other input response } // else handle input request from POI } // ... // Present the tip options. string header = "Please select a tip"; string[] buttons = new string[] {"20%", "15%", "10%", "None"}; payment_sdk_.TransactionManager.PresentUserOptions(header, buttons); |
See also
CommerceListener.handleEvent(event)
UserInputEvent.Values
Handling Requests for User Input from the Payment Application¶
There will be times when the POI requires input from the cashier. In these
cases, the CommerceListener
will receive an event of type
UserInputEvent.REQUEST_TYPE
. The event contains a
RequestParameters
object,
which contains all of the different values and type of request that should be
displayed to the cashier. Any time the response is required by the request, the
listener must display this information to the cashier for the current flow to
proceed. The receiving application must construct a new
Values
object,
populating it with the data received from the cashier, then attach it to the
response object from UserInputEvent.generateResponse()
, and send it
back to the payment application using
TransactionManager.sendEventResponse(response)
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @Override // Overridden from the CommerceListenerAdapter public void handleUserInputEvent(UserInputEvent event) { if (UserInputEvent.REQUEST_TYPE.equals(event.getType())) { RequestParameters requestParameters = event.getRequestParameters(); UserInputEventResponse response = event.generateUserInputEventResponse(); // Based on requestParameters.getInputType(), present the appropriate dialog. // Keep track of the response, it is needed once the input is collected. } } // Send back the response once the input is collected. Values responseValues = response.getResponseValues(); // Set the appropriate value on the values object based on the input type. response.setValues(responseValues); mTransactionManager.sendInputResponse(response); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Overridden from the CommerceListenerAdapter override fun handleUserInputEvent(event: UserInputEvent) { if (UserInputEvent.REQUEST_TYPE.equals(event.getType())) { val requestParameters = event.getRequestParameters() val response = event.generateUserInputEventResponse() // Based on requestParameters.getInputType(), present the appropriate dialog. // Keep track of the response, it is needed once the input is collected. } } // Send back the response once the input is collected. val responseValues = response.getResponseValues() // Set the appropriate value on the values object based on the input type. response.setValues(responseValues) mTransactionManager.sendInputResponse(response) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Overridden from the VFICommerceListenerAdapter override func handle(_ event: VFIUserInputEvent?) { if (VFIUserInputEventREQUESTTYPE == event?.getType()) { var requestParameters: VFIRequestParameters? = event?.getRequestParameters() var response: VFIUserInputEventResponse? = event?.generateResponse() // Based on requestParameters.getInputType(), present the appropriate dialog. // Keep track of the response, it is needed once the input is collected. } } // Send back the response once the input is collected. let responseValues = response?.getValues() // Set the appropriate value on the values object based on the input type. response?.setValues(responseValues) sdk.getTransactionManager()?.sendInputResponse(response) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | private readonly EventHandler<UserInputEvent> user_input_event_handler_; private void HandleUserInputvent(UserInputEvent event) { if (event.Type.Value == UserInputEvent.REQUEST_TYPE) { var request_parameters = event.RequestParameters; var response = event.GenerateUserInputEventResponse(); // Based on requestParameters.getInputType(), present the appropriate dialog. // Keep track of the response, it is needed once the input is collected. } } // ... // Link event handler after initialization is complete but before requesting input user_input_event_handler_ = async (sender, args) => { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => HandleEvent(args)); }; payment_sdk_.TransactionManager.HandleUserInputEvent += user_input_event_handler_; // ... // Send back the response once the input is collected. var responseValues = response.ResponseValues; // Set the appropriate value on the values object based on the input type. response.ResponseValues(responseValues); transaction_manager_.SendInputResponse(response); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // Overridden from the CommerceListenerAdapter void handleUserInputEvent ( const std::shared_ptr<verifone_sdk::UserInputEvent>& event) override { if (event->getType() == verifone_sdk::UserInputEvent::REQUEST_TYPE && event_->getStatus() == verifone_sdk::StatusCode::SUCCESS) { auto request_parameters = event->getRequestParameters(); auto response = event->generateUserInputEventReponse(); // Based on requestParameters.getInputType(), present the appropriate dialog. // Keep track of the response, it is needed once the input is collected. } } // ... // Send back the response once the input is collected. auto responseValues = response->getResponseValues(); // Set the appropriate value on the values object based on the input type. response->setResponeValues(responseValues); psdk->getTransactionManager()->sendInputResponse(response); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public void HandleUserInputEvent(UserInputEvent sdk_event) { if (sdk_event.Type == UserInputEvent.REQUEST_TYPE) { var request_parameters = sdk_event.RequestParameters; var response = sdk_event.GenerateUserInputEventResponse(); // Based on requestParameters.getInputType(), present the appropriate dialog. // Keep track of the response, it is needed once the input is collected. } } // ... // Send back the response once the input is collected. var responseValues = response.ResponseValues; // Set the appropriate value on the values object based on the input type. response.ResponseValues(responseValues); payment_sdk_.TransactionManager.SendInputResponse(response); |
See also
CommerceListener.handleEvent(event)
UserInputEvent.generateResponse()
UserInputEvent.RequestParameters.getInputType()
Manually Keying In Card Information¶
This section describes the procedure for the merchant to manually key in
the card information when making a payment.
This is required when the card reader is unable
to read the card information due to a device malfunction in reading the
chip or magnetic strip.
In these cases, the Payment.setRequestedCardPresentationMethods()
must
be called with the parameter PresentationMethod.KEYED
.
The card information will then be keyed into the terminal.
1 2 3 4 5 6 7 8 9 10 11 | // Please note that creating Payment also creates AmountTotals Payment payment = Payment.create(); ArrayList<PresentationMethod> presentationMethods = new ArrayList<PresentationMethod>(); presentationMethods.add(PresentationMethod.KEYED); payment.setRequestedPaymentType(PaymentType.CREDIT); payment.getRequestedAmounts.setSubtotal(ConversionUtility.parseAmount(8.00) .setTax(ConversionUtility.parseAmount(1.00)) .setGratuity(ConversionUtility.parseAmount(1.00)) .setTotal(ConversionUtility.parseAmount(10.00)); payment.setTransactionType(TransactionType.PAYMENT); payment.setRequestedCardPresentationMethods(presentationMethods); |
1 2 3 4 5 6 | // Please note that creating Payment also creates AmountTotals val payment = Payment.create() payment.setRequestedCardPresentationMethods({PresentationMethod.KEYED}) // Configure amounts and other payment properties before starting. transactionManager.startPayment(payment) // Listener receives the PaymentCompletedEvent. |
1 2 3 4 5 6 | var payment = VFIPayment.create() payment?.setRequestedCardPresentationMethods([ NSNumber(value: VFIPresentationMethod.KEYED.rawValue)]) // Configure amounts and other payment properties before starting. sdk.getTransactionManager()?.start(payment) // Listener receives the PaymentCompletedEvent. |
1 2 3 4 5 6 7 | var payment = new Payment { RequestedCardPresentationMethods = new List<PresentationMethod> { PresentationMethod.KEYED } // Configure amounts and other payment properties before starting. }; transactionManager.StartPayment(payment); // Listener receives the PaymentCompletedEvent. |
1 2 3 4 5 | auto payment = verifone_sdk::Payment::create(); payment->setRequestedCardPresentationMethods({verifone_sdk::PresentationMethod::KEYED}); // Configure amounts and other payment properties before starting. transaction_manager->startPayment(payment); // Listener receives the PaymentCompletedEvent. |
1 2 3 4 | var payment = Payment.Create(); payment.RequestedCardPresentationMethods = new List<PresentationMethod> { PresentationMethod.KEYED }; payment_sdk_.TransactionManager.StartPayment(payment); // Listener receives the PaymentCompletedEvent. |
Handling External Changes to the Basket/Amount¶
It is possible for external apps to request changes to the basket and/or amount during four triggers:
Listener Event |
CP ID |
CP Trigger Class |
---|---|---|
CP_SYSTEM_REQUESTS_BASKET_ADJUSTMENT |
||
CP_SYSTEM_REQUESTS_LOYALTY |
||
CP_SYSTEM_REQUESTS_AMOUNT_ADJUSTMENT |
||
None |
CP_SYSTEM_REQUESTS_PAYMENT_AMOUNT_ADJUSTMENT |
The first 3 require “adjudication”, that is, the POS can decide to accept or reject any of the modifications performed during these triggers. This can be done either automatically or by presenting an appropriate UI to the cashier, depending on the preference of the POS.
To accept or reject the modifications, get a Response object using the
generateResponse() method, then set the accepted modifications on the
response object. Any modifications not set on the response will be rejected. Send
back the response using TransactionManager.sendEventResponse(response)
.
Note
The CP_SYSTEM_REQUESTS_PAYMENT_AMOUNT_ADJUSTMENT
,
is included in the payment response, since it cannot be rejected by the POS.
BasketAdjustedEvent¶
Sent when a CP App decides that the cart is eligible for a specific deal or interacts with the customer to collect a donation amount. The CP App adds the offer(s) or donation(s) which are then sent back to the POS after the Payment App collects them from all of the CP Apps.
Use BasketAdjustedEvent.getAdjustments()
to retrieve the adjustments
requested by the CP App(s). Iterate through the Offer(s)
and
Donation(s)
in the BasketAdjustment
, either
removing them from the current object or adding them to a separate new
BasketAdjustment
. In either case, get the appropriate
BasketAdjustedEvent.Response
from BasketAdjustedEvent.generateResponse()
,
and Response.setFinalAdjustments()
to identify the accepted adjustments and the new total amount for the payment.
If no adjustments are accepted, simply send back the BasketAdjustedEvent.Response
without setting the final adjustments.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Override // Overridden from the CommerceListenerAdapter public void handlBasketAdjustedEvent( BasketAdjustedEvent event) { if (BasketAdjustedEvent.TYPE.equals(event.getType())) { BasketAdjustment adjustments = event.getAdjustments(); // Keep this response object to fill in with the accepted adjustments. BasketAdjustedEventResponse response = event.generateBasketEventResponse(); // Either decide directly which adjustments are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted adjustments. response.setFinalAdjustments(adjustments, amountTotals); transactionManager.sendEventResponse( BasketAdjustedEventResponse.asCommerceResponse(response)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Overridden from the CommerceListenerAdapter override fun handleBasketAdjustedEvent(event: BasketAdjustedEvent) { if (BasketAdjustedEvent.TYPE.equals(event.getType())) { val adjustments = event.getAdjustments() // Keep this response object to fill in with the accepted adjustments. val response = basketAdjustedEvent.generateBasketEventResponse() // Either decide directly which adjustments are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted adjustments. response.setFinalAdjustments(adjustments, amountTotals) transactionManager.sendEventResponse( BasketAdjustedEventResponse.asCommerceResponse(response)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Overridden from the VFICommerceListenerAdapter override func handle(_ event: VFIBasketAdjustedEvent?) { if (VFIBasketAdjustedEventTYPE == event?.getType()) { adjustments = event?.getAdjustments() // Keep this response object to fill in with the accepted adjustments. response = event?.generateResponse() // Either decide directly which adjustments are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted adjustments. response?.setFinalAdjustments(adjustments, amountTotals: amountTotals) transactionManager?.sendEventResponse( VFIBasketAdjustedEventResponse.asCommerceResponse(response)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private void HandleBasketAdjustedvent(BasketAdjustedEvent event) { if (event.Type.Value == BasketAdjustedEvent.TYPE) { var adjustments = event.Adjustment; var response = event.GenerateBasketAdjustedEventResponse(); // Based on requestParameters.getInputType(), present the appropriate dialog. // Keep track of the response, it is needed once the input is collected. } } // Sometime later, send back the response after selecting the accepted adjustments. response.SetFinalAdjustments(adjustments, amount_totals); CommerceResponse commerceResponse = response as CommerceResponse; payment_sdk_.TransactionManager.SendEventResponse(commerceResponse); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // Overridden from the CommerceListenerAdapter void handleBasketAdjustedEvents( const std::shared_ptr<verifone_sdk::BasketAdjustedEvents>& event) override { if (event->getType() == BasketAdjustedEvents::TYPE) { auto basket_adjustments = event->getAdjustments(); auto response = event->generateBasketAdjustedEventResponse(); // Based on requestParameters.getInputType(), present the appropriate dialog. // Keep track of the response, it is needed once the input is collected. } } // Sometime later, send back the response after selecting the accepted adjustments. response->setFinalAdjustments(adjustments, amount_totals); psdk->getTransactionManager()->sendEventResponse( std::dynamic_pointer_cast<verifone_sdk::CommerceResponse>(response)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | private void HandleBasketAdjustedvent(BasketAdjustedEvent sdk_event) { if (sdk_event.Type == BasketAdjustedEvent.EVENT_TYPE) { var adjustments = sdk_event.Adjustments; var response = sdk_event.GenerateBasketAdjustedEventResponse(); // Based on requestParameters.getInputType(), present the appropriate dialog. // Keep track of the response, it is needed once the input is collected. } } // Sometime later, send back the response after selecting the accepted adjustments. response.SetFinalAdjustments(adjustments, amount_totals); CommerceResponse commerceResponse = BasketAdjustedEventResponse.AsCommerceResponse(response); mw.Dispatcher.Invoke(() => { mw.payment_sdk_.TransactionManager.SendEventResponse(commerceResponse); }); |
LoyaltyReceivedEvent¶
This is sent when a CP App collects loyalty information about the customer, and
finds that they are eligible for a reward of some kind. The CP App adds the
Offer
that they are eligible for, which is communicated back to the POS
to decide if it can be applied to the current order or not.
Use LoyaltyReceivedEvent.getLoyaltyAdjustments()
to get each adjustment
grouped by CP App, or use LoyaltyReceivedEvent.getLoyaltyOffersList()
to get all of the adjustments aggregated in a single list, without regard to the
CP App. Get the appropriate LoyaltyReceivedEvent.Response
from
LoyaltyReceivedEvent.generateResponse()
and
LoyaltyReceivedEvent.Response.setLoyaltyOffers(offers)
to identify
the accepted offers.
Update the final amount using Payment.setRequestedAmountTotals()
on either the original payment object or the one returned from
LoyaltyReceivedEvent.Response.getResponsePayment()
. If using a payment
object other than the one returned from the response, set this payment on the
response using LoyaltyReceivedEvent.Response.updatePayment(payment)
.
Finally, it is optional to use
LoyaltyReceivedEvent.Response.selectLoyaltyIdentifier(identifier)
to
select which loyalty ought to be associated with the current Transaction
.
This can allow the system to auto-populate the email address and/or phone number
if receiving a receipt using either of these, or for some other prompts that may
require this information from the user.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Override // Overridden from the CommerceListenerAdapter public void handlLoyaltyReceivedEvent( LoyaltyReceivedEvent event) { if (LoyaltyReceivedEvent.TYPE.equals(event.getType())) { // Offers per loyalty app LoyaltyAdjustment[] loyaltyAdjustments = event.getLoyaltyAdjustments(); // Aggregated offers ArrayList<Offer> offers = event.getLoyaltyOffersList(); // Keep this response object to fill in with the accepted adjustments. LoyaltyReceivedEventResponse response = event.generateResponse(); // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted offers. response.setLoyaltyOffers(offers); Payment payment = response.getResponsePayment(); // update amount totals to changedAmountTotals based on accepted offers payment.setRequestedAmountTotals(changedAmountTotals); transactionManager.sendEventResponse( LoyaltyReceivedEventResponse.asCommerceResponse(response)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // Overridden from the CommerceListenerAdapter override fun handleLoyaltyReceivedEvent(event: LoyaltyReceivedEvent) { if (LoyaltyReceivedEvent.TYPE.equals(event.getType())) { // Offers per loyalty app val loyaltyAdjustments = event.getLoyaltyAdjustments() // Aggregated offers val offers = event.getLoyaltyOffersList() // Keep this response object to fill in with the accepted adjustments. val response = event.generateLoyaltyReceivedEventResponse() // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted offers. response.setLoyaltyOffers(offers) val payment = response.getResponsePayment() // update amount totals to changedAmountTotals based on accepted offers payment.setRequestedAmountTotals(changedAmountTotals) transactionManager.sendEventResponse( LoyaltyReceivedEventResponse.asCommerceResponse(response)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | var loyaltyAdjustments: [VFILoyaltyAdjustment]? var offers: [VFIOffer]? var response: VFILoyaltyReceivedEventResponse? var payment: VFIPayment? var transactionManager: VFITransactionManager? // Overridden from the VFICommerceListenerAdapter override func handle(_ event: VFILoyaltyReceivedEvent?) { if (VFILoyaltyReceivedEventTYPE == event?.getType()) { // Offers per loyalty app loyaltyAdjustments = event?.getLoyaltyAdjustments() // Aggregated offers offers = event?.getLoyaltyOffersList() // Keep this response object to fill in with the accepted adjustments. response = event?.generateResponse() // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } // Sometime later, send back the response after selecting the accepted offers. response?.setLoyaltyOffers(offers) payment = response?.getResponsePayment() // update amount totals to changedAmountTotals based on accepted offers payment.setRequestedAmountTotals(changedAmountTotals) transactionManager?.sendEventResponse( VFILoyaltyReceivedEventResponse.asCommerceResponse(response)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | private readonly EventHandler<LoyaltyReceivedEvent> loyalty_event_handler_; private void HandleEvent(LoyaltyReceivedEvent event) { if (event.Type.Value == LoyaltyReceivedEvent.EVENT_TYPE) { // Offers per loyalty app Array<LoyaltyAdjustments> loyalty_adjustments = event.GetLoyaltyAdjustments(); // Aggregated offers ArrayList<Offer> offers = event.GetLoyaltyOffers(); // Keep this response object to fill in with the accepted adjustments. LoyaltyReceivedEventResponse response = event.GenerateLoyaltyReceivedEventResponse(); // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // ... // Link event handler after initialization is complete loyalty_event_handler_ = async (sender, args) => { await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => HandleEvent(args)); }; payment_sdk_.TransactionManager.HandleLoyaltyReceivedEvent += loyalty_event_handler_; // ... // Send back the response after selecting the accepted offers. response.SetLoyaltyOffers(offers); Payment payment = response.ResponsePayment(); // update amount totals to changed_amount_totals based on accepted offers payment.RequestedAmounts(changed_amount_totals); CommerceResponse commerceResponse = response as CommerceResponse; payment_sdk_.TransactionManager.SendEventResponse(commerceResponse); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // Overridden from the CommerceListenerAdapter void handleLoyaltyReceivedEvent( const std::shared_ptr<verifone_sdk::LoyaltyReceivedEvent>& event) override { if (event->getType() == LoyaltyReceivedEvent::TYPE) { // Offers per loyalty app auto loyalty_adjustments = event->getLoyaltyAdjustments(); // Aggregated offers auto offers = event->getLoyaltyOffersList(); // Keep this response object to fill in with the accepted adjustments. auto response = event->generateLoyaltyReceivedEventResponse(); // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted offers. response->setLoyaltyOffers(offers); auto payment = response->getResponsePayment(); payment->setRequestedAmountTotals(changed_amount_totals); psdk->getTransactionManager()->sendEventResponse( std::dynamic_pointer_cast<verifone_sdk::CommerceResponse>(response)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public void HandleLoyaltyReceivedEvent(LoyaltyReceivedEvent sdk_event) { if (sdk_event.Type == LoyaltyReceivedEvent.EVENT_TYPE) { // Offers per loyalty app IList<VerifoneSdk.LoyaltyAdjustment> loyalty_adjustments = sdk_event.LoyaltyAdjustments; // Aggregated offers IList<Offer> offers = sdk_event.LoyaltyOffersList; // Keep this response object to fill in with the accepted adjustments. LoyaltyReceivedEventResponse response = sdk_event.GenerateLoyaltyReceivedEventResponse(); // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // ... // Send back the response after selecting the accepted offers. response.SetLoyaltyOffers(offers); response.LoyaltyOffers = offers; Payment payment = response.ResponsePayment; // update amount totals to changed_amount_totals based on accepted offers payment.RequestedAmounts = changed_amount_totals; CommerceResponse commerceResponse = LoyaltyReceivedEventResponse.AsCommerceResponse(response); mw.Dispatcher.Invoke(() => { mw.payment_sdk_.TransactionManager.SendEventResponse(commerceResponse); }); |
Note
Use LoyaltyReceivedEvent.getLoyaltyAdjustments()
to get more
information about the customer, including the LoyaltyIdentifier
information that is being used for the specific loyalty program. This
information can streamline further interactions with the customer.
AmountAdjustedEvent¶
This is sent to allow CP Apps to change the amount, generally based on the payment
type such as the card bin range, or based on some interaction with the customer.
These can increase or decrease the overall amount, depending on the value in the
AmountAdjustment
, and it can be either determined by a percentage
AmountAdjustment.getAdjustmentPercentage()
or by a fixed amount
AmountAdjustment.getAdjustmentValue()
, depending on which is set.
Use AmountAdjustedEvent.getAdjustments()
to get the proposed changes, and
AmountAdjustedEvent.generateResponse()
to get the AmountAdjustedEvent.Response
.
Iterate through the AmountAdjustment(s)
, and add the
accepted adjustment(s) to the response using
AmountAdjustedEvent.Response.setAdjustments(adjustments)
.
Update the final amount using Payment.setRequestedAmountTotals(updatedTotals)
on either the original payment object or the one returned from
AmountAdjustedEvent.Response.getPayment()
. If using a payment
object other than the one returned from the response, set this payment on the
response using AmountAdjustedEvent.Response.updatePayment(payment)
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @Override // Overridden from the CommerceListenerAdapter public void handlAmountAdjustedEvent( AmountAdjustedEvent event) { if (AmountAdjustedEvent.TYPE.equals(event.getType())) { // Offers per loyalty app AmountAdjustment[] amountAdjustments = event.getAdjustments(); // Keep this response object to fill in with the accepted adjustments. AmountAdjustedEventResponse response = event.generateAmountAdjustedEventResponse(); // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted offers. response.setAdjustments(amountAdjustments); Payment payment = response.getPayment(); payment.setRequestedAmountTotals(changedAmountTotals); transactionManager.sendEventResponse( AmountAdjustedEventResponse.asCommerceResponse(response)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | // Overridden from the CommerceListenerAdapter override fun handleAmountAdjustedEvent(event: AmountAdjustedEvent) { if (AmountAdjustedEvent.TYPE.equals(event.getType())) { // Offers per loyalty app val amountAdjustments = event.getAdjustments() // Keep this response object to fill in with the accepted adjustments. val response = event.generateAmountAdjustedEventResponse() // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted offers. response.setAdjustments(amountAdjustments) val payment = response.getPayment() payment.setRequestedAmountTotals(changedAmountTotals) transactionManager.sendEventResponse( AmountAdjustedEventResponse.asCommerceResponse(response)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | var amountAdjustments: [VFIAmountAdjustment]? var response: VFIAmountAdjustedEventResponse? var payment: VFIPayment? var transactionManager: VFITransactionManager? var changedAmountTotals: VFIAmountTotals? // Overridden from the VFICommerceListenerAdapter override func handle(_ event: VFIAmountAdjustedEvent?) { if (event?.getType() == VFIAmountAdjustedEventTYPE) { // Offers per loyalty app amountAdjustments = event?.getAdjustments() // Keep this response object to fill in with the accepted adjustments. response = event?.generateResponse() // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted offers. response.setAdjustments(amountAdjustments) payment = response.getPayment() payment?.setRequestedAmounts(changedAmountTotals) transactionManager?.sendEventResponse( VFIAmountAdjustedEventResponse.asCommerceResponse(response)) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | private void HandleAmountAdjustedEvent(AmountAdjustedEvent event) { if (event.Type.Value == AmountAdjustedEvent.EVENT_TYPE) { // Offers per loyalty app Array<LoyaltyAdjustments> amount_adjustments = event.GetAdjustments(); // Keep this response object to fill in with the accepted adjustments. AmountAdjustedEventResponse response = event.GenerateAmountAdjustedEventResponse(); // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted offers. response.SetAdjustments(amount_adjustments); response.Payment.RequestedAmounts(changed_amount_totals); CommerceResponse commerceResponse = response as CommerceResponse; payment_sdk_.TransactionManager.SendEventResponse(commerceResponse); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // Overridden from the CommerceListenerAdapter void handleAmountAdjustedEvent( -const std::shared_ptr<verifone_sdk::AmountAdjustedEvent>& event) override { if (event->getType() == AmountAdjustedEvent::TYPE) { // Offers per loyalty app auto amount_adjustments = event->getAdjustments(); // Keep this response object to fill in with the accepted adjustments. auto response = event->generateAmountAdjustedEventRepsonse; // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } ... // Sometime later, send back the response after selecting the accepted offers. response->setAdjustments(amount_adjustments); auto payment = response->getPayment(); payment->setRequestedAmountTotals(changed_amount_totals); psdk->getTransactionManager()->sendEventResponse(std::dynamic_pointer_cast <verifone_sdk::CommerceResponse>(response)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | private void HandleAmountAdjustedEvent(AmountAdjustedEvent sdk_event) { if (sdk_event.Type == AmountAdjustedEvent.EVENT_TYPE) { // Offers per loyalty app IList<AmountAdjustment> amount_adjustments = sdk_event.Adjustments; // Keep this response object to fill in with the accepted adjustments. AmountAdjustedEventResponse response = sdk_event.GenerateAmountAdjustedEventResponse(); // Either decide directly which offers are accepted, or allow // the cashier to review and decide. } } // Sometime later, send back the response after selecting the accepted offers. response.Adjustments(amount_adjustments); response.Payment.RequestedAmounts = changed_amount_totals; CommerceResponse commerceResponse = AmountAdjustedEventResponse.AsCommerceResponse(response); mw.Dispatcher.Invoke(() => { mw.payment_sdk_.TransactionManager.SendEventResponse(commerceResponse); }); |
See also
CommerceListener.handleEvent(event)
BasketAdjustedEvent.Response
LoyaltyReceivedEvent.Response
AmountAdjustedEvent.Response
Verifone Confidential
This documentation is protected by law from any form of duplication unless prior permission is obtained from the officers of Verifone.
Verifone Payment SDK v3.55.5