Performing a Sale

As noted earlier, every transaction is wrapped within a session, so all transactions described from here forward assume that a session has been established with a valid CommerceListener. Multiple payments can occur within a single session, as in the use cases for multi-tender or split-tender, but a session should be ended before a new cart/order is started. See Getting Started to start a session, and state-matters for information on when different commands can be performed.

Setup and Start a Payment

Before initiating a sale transaction, a Payment object must be established with payment type, amount, tax, etc.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// A session must be open to perform a payment

Payment payment = Payment.create();
// Creating a Payment also creates an empty AmountTotals object in the requested amounts.
AmountTotals requestedAmounts = payment.getRequestedAmounts();
requestedAmounts.setSubtotal(ConversionUtility.parseAmount(8.00));
requestedAmounts.setTax(ConversionUtility.parseAmount(1.00));
requestedAmounts.setGratuity(ConversionUtility.parseAmount(1.00));
requestedAmounts.setTotal(ConversionUtility.parseAmount(10.00));
transactionManager.startPayment(payment);
// Listener receives the PaymentCompletedEvent.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// A session must be open to perform a payment

val payment = Payment.create().apply {
    RequestedAmounts.apply {
        Subtotal = Decimal(8.00)
        Tax = Decimal(1.00)
        Gratuity = Decimal(1.00)
        Total = Decimal(10.00)
    }
}
// Creating a Payment also creates an empty AmountTotals object in the requested amounts.
transactionManager.startPayment(payment)
// Listener receives the PaymentCompletedEvent.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// A session must be open to perform a payment

var payment = VFIPayment.create()
// Creating a Payment also creates an empty AmountTotals object in the requested amounts.
var requestedAmounts = payment?.getRequestedAmounts()
requestedAmounts?.setSubtotal(VFIDecimal.init(valueDecimal: Decimal.init(8.00)))
requestedAmounts?.setTax(VFIDecimal.init(valueDecimal: Decimal.init(1.00)))
requestedAmounts?.setGratuity(VFIDecimal.init(valueDecimal: Decimal.init(1.00)))
requestedAmounts?.setTotal(VFIDecimal.init(valueDecimal: Decimal.init(10.00)))
sdk.getTransactionManager()?.start(payment)
// Listener receives the PaymentCompletedEvent.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// A session must be open to perform a payment

var amount_totals = new AmountTotals();
PaymentSDK.Decimal subtotal = new PaymentSDK.Decimal(8.00);
PaymentSDK.Decimal gratuity = new PaymentSDK.Decimal(1.00);
PaymentSDK.Decimal tax = new PaymentSDK.Decimal(1.00);
PaymentSDK.Decimal total = new PaymentSDK.Decimal(10.00);
amount_totals.SetWithAmounts(subtotal, tax, gratuity, total);
var payment = new Payment
{
    RequestedAmounts = amount_totals
};
payment_sdk_.TransactionManager.StartPayment(payment);
// Listener receives the PaymentCompletedEvent.
   // A session must be open to perform a payment

   auto payment = verifone_sdk::Payment::create();
   // Creating a Payment also creates an empty AmountTotals object in the requested amounts.
   payment->getRequestedAmounts()->setSubTotals(8.00)
                                 ->setTax(1.00)
                                 ->setGratuity(1.00)
                                 ->setTotal(10.00);
   psdk->getTransactionManager()->startPayment(payment);
   // Listener receives the PaymentCompletedEvent.


.. code-tab:: c# .NET
   :linenos:

   // A session must be open to perform a payment

   var amount_totals = AmountTotals.Create(false);
   VerifoneSdk.Decimal subtotal = new VerifoneSdk.Decimal(8);
   VerifoneSdk.Decimal gratuity = new VerifoneSdk.Decimal(1);
   VerifoneSdk.Decimal tax = new VerifoneSdk.Decimal(1);
   VerifoneSdk.Decimal total = new VerifoneSdk.Decimal(10);
   amount_totals.SetWithAmounts(subtotal, tax, gratuity, total, null, null, null);
   var payment = Payment.Create();
   payment.RequestedAmounts = amount_totals;
   payment_sdk_.TransactionManager.StartPayment(payment);
   // Listener receives the PaymentCompletedEvent.

Multi-Currency

A payment transaction can be performed with different currencies each time. A specific currency (eg. USD, EUR) may be specified for the transaction by configuring the currency in the transaction object Transaction.setCurrency(). If no currency is set, then it defaults to the local currency. The currency which is set in the transaction object can be overridden by settint it in the payment object Payment.setCurrency().

Handling Precision of Monetary Values

PSDK uses the Decimal class for monetary values. The values are represented by value and scale: please see DecimalBase(). A Decimal object consists of a 64 bit integer value and a 32 bit integer scale. The scale represents the number of digits to the right of the decimal point. For example, 10.99 is represented as a value of 1099 and a scale of 2.

Handle Payment Completed Event

Once the payment has been initiated, the payment application handles everything, including consumer UI, card reader interaction, and host authorization. We just need to wait for the TransactionEvent.TRANSACTION_PAYMENT_COMPLETED event and check the authorization result. The following code snippet is assumed to be within the CommerceListener.handlePaymentCompletedEvent() method of the instance passed into the session. See the AuthorizationResult enumeration for more details on the result types.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@Override // Overridden from the CommerceListenerAdapter
public void handlePaymentCompletedEvent(PaymentCompletedEvent event) {
    if (TransactionEvent.TRANSACTION_PAYMENT_COMPLETED.equals(event.getType())) {
        if (event.getStatus() == StatusCode.SUCCESS) {
            Payment payment = event.getPayment();
            AuthorizationResult authorizationResult = payment.getAuthResult();
            // Confirm the authorization result is AUTHORIZED instead
            // of DECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Overridden from the CommerceListenerAdapter
override fun handlePaymentCompletedEvent(event: PaymentCompletedEvent) {
    if (TransactionEvent.TRANSACTION_PAYMENT_COMPLETED.equals(event.getType())) {
        if (event.getStatus() == StatusCode.SUCCESS) {
            val payment = event.getPayment()
            val authorizationResult = payment.getAuthResult()
            // Confirm the authorization result is AUTHORIZED instead
            // of DECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Overridden from the VFICommerceListenerAdapter
override func handle(_ event: VFIPaymentCompletedEvent?) {
    if (event?.getType() == VFITransactionEventTRANSACTIONPAYMENTCOMPLETED) {
        if (event?.getStatus() == VFIStatusCodeSuccess) {
            let payment = event?.getPayment()
            let authorizationResult = payment?.getAuthResult()
            // Confirm the authorization result is AUTHORIZED instead
            // of DECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
private void HandlePaymentCompletedEvent(PaymentCompletedEvent event)
{
    if (event.Type.Value == TransactionEvent.TRANSACTION_PAYMENT_COMPLETED)
    {
        if (event.Status == StatusCode.SUCCESS)
        {
            Payment payment = event.Payment;
            AuthorizationResult authorization_result = payment.AuthResult;
            // Confirm the authorization result is AUTHORIZED instead
            // of DECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Overridden from the CommerceListenerAdapter
void handlePaymentCompletedEvent(
    const std::shared_ptr<verifone_sdk::PaymentCompletedEvent>& event) override {
    if (event->getType() == TransactionEvent::TRANSACTION_PAYMENT_COMPLETED) {
      if (event->getStatus() == StatusCode::SUCCESS) {
          auto payment = event->getPayment();
          auto auth_result = payment->getAuthResult();
          // Confirm the authorization result is AUTHORIZED instead
          // of DECLINED or some other result.
      }
      // Else handle failure by examining the status code and message.
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
private void HandlePaymentCompletedEvent(PaymentCompletedEvent sdk_event)
{
    if (sdk_event.Type == TransactionEvent.TRANSACTION_PAYMENT_COMPLETED)
    {
        if (sdk_event.Status == 0)
        {
            var payment = sdk_event.Payment;
            AuthorizationResult authorization_result = payment.AuthResult.Value;
            // Confirm the authorization result is AUTHORIZED instead
            // of DECLINED or some other result.
        }
        // Else handle failure by examining the status code and message.
    }
}