Namespace
Usage
This class holds all the required details about a sale request. Gateway adapters read the fields of this class object while constructing a sale JSON request thatis sent to the payment gateway. The object of this class is made available through commercepayments.paymentGatewayContext by calling getPaymentRequest().
Example
/** * Responsibilities: * - Set merchant and reference details * - Convert amount into minor units (e.g., cents) * - Map payment method types (card, ACH, SEPA, etc.) * - Include stored payment method token for recurring payments * - Optionally include enhanced Level 2/3 data * * @param saleRequest Input request containing payment and shopper details * @return JSON string payload for the payment gateway */ private String buildSaleRequest(commercepayments.SaleRequest saleRequest) { // Resolve currency (fallback to user's default if missing) String currencyIso = saleRequest.currencyIsoCode; if (currencyIso == null) { currencyIso = UserInfo.getDefaultCurrency(); } // Extract payment method commercepayments.SaleApiPaymentMethodRequest paymentMethod = saleRequest.paymentMethod; // Initialize JSON generator JSONGenerator jsonGeneratorInstance = JSON.createGenerator(true); jsonGeneratorInstance.writeStartObject(); // Merchant configuration (from Named Credential) jsonGeneratorInstance.writeStringField('merchantAccount', '{!$Credential.Username}'); // Unique reference using timestamp + random suffix jsonGeneratorInstance.writeStringField( 'reference', String.valueOf(Datetime.now().getTime()) + String.valueOf(Math.random()).substring(2, 8) ); // Amount block jsonGeneratorInstance.writeFieldName('amount'); jsonGeneratorInstance.writeStartObject(); jsonGeneratorInstance.writeStringField( 'value', String.valueOf((saleRequest.amount * 100.0).intValue()) // convert to minor units ); jsonGeneratorInstance.writeStringField('currency', currencyIso); jsonGeneratorInstance.writeEndObject(); // Payment method block jsonGeneratorInstance.writeFieldName('paymentMethod'); jsonGeneratorInstance.writeStartObject(); String shopperReference; String type = 'scheme'; // default = card // Handle stored payment method data (tokenized payments) if (saleRequest.paymentMethodData != null) { String token = saleRequest.paymentMethodData.get('gatewayToken'); String paymentMethodType = saleRequest.paymentMethodData.get('paymentMethodType'); shopperReference = saleRequest.paymentMethodData.get('gatewayReference'); // Map payment method types to gateway-specific values if ('us_bank_account'.equals(paymentMethodType)) { type = 'ach'; } else if ('sepa_debit'.equals(paymentMethodType)) { type = 'sepadirectdebit'; } else if ('au_becs_debit'.equals(paymentMethodType)) { type = 'directdebit_AU'; } else if ('bacs_debit'.equals(paymentMethodType)) { type = 'directdebit_GB'; } jsonGeneratorInstance.writeStringField('type', type); jsonGeneratorInstance.writeStringField('storedPaymentMethodId', token); } // Add enhanced scheme data ONLY for card payments // Note: Gateway might have validations on L2/L3 data so do test them out before using L2/L3 else transactions might fail if (enhancedPaymentData != null && 'scheme'.equals(type)) { jsonGeneratorInstance.writeFieldName('additionalData'); jsonGeneratorInstance.writeStartObject(); populateEnhancedSchemeData(jsonGeneratorInstance, enhancedPaymentData); jsonGeneratorInstance.writeEndObject(); // additionalData } jsonGeneratorInstance.writeEndObject(); // paymentMethod // Recurring / shopper configuration jsonGeneratorInstance.writeStringField('shopperInteraction', 'ContAuth'); jsonGeneratorInstance.writeStringField('recurringProcessingModel', 'UnscheduledCardOnFile'); jsonGeneratorInstance.writeStringField('shopperReference', shopperReference); // Immediate capture jsonGeneratorInstance.writeNumberField('captureDelayHours', 0); jsonGeneratorInstance.writeEndObject(); // root return jsonGeneratorInstance.getAsString(); } /** * Populates Level 2 and Level 3 enhanced scheme data. * * @param jsonGeneratorInstance JSON generator * @param enhancedPaymentData Enhanced payment data input */ private void populateEnhancedSchemeData(JSONGenerator jsonGeneratorInstance, commercepayments.EnhancedPaymentDataInput enhancedPaymentData) { // -------- Level 2 fields -------- if (enhancedPaymentData.totalTaxAmount != null) { jsonGeneratorInstance.writeStringField( 'enhancedSchemeData.totalTaxAmount', toMinorUnits(enhancedPaymentData.totalTaxAmount) ); } if (enhancedPaymentData.shippingAmount != null) { jsonGeneratorInstance.writeStringField( 'enhancedSchemeData.freightAmount', toMinorUnits(enhancedPaymentData.shippingAmount) ); } if (enhancedPaymentData.discountAmount != null) { jsonGeneratorInstance.writeStringField( 'enhancedSchemeData.discountAmount', toMinorUnits(enhancedPaymentData.discountAmount) ); } if (enhancedPaymentData.invoiceNumber != null) { jsonGeneratorInstance.writeStringField( 'enhancedSchemeData.customerReference', enhancedPaymentData.invoiceNumber ); } // -------- Level 3 fields (line items) -------- if (enhancedPaymentData.lineItems != null) { Integer index = 1; for (commercepayments.LineItemInput item : enhancedPaymentData.lineItems) { populateLineItemData( jsonGeneratorInstance, item, 'enhancedSchemeData.itemDetailLine' + index + '.' ); index++; } } // Shipping / destination info if (enhancedPaymentData.shipFromZip != null) { jsonGeneratorInstance.writeStringField( 'enhancedSchemeData.shipFromPostalCode', enhancedPaymentData.shipFromZip ); } if (enhancedPaymentData.shipToZip != null) { jsonGeneratorInstance.writeStringField( 'enhancedSchemeData.destinationPostalCode', enhancedPaymentData.shipToZip ); } if (enhancedPaymentData.shipToCountry != null) { jsonGeneratorInstance.writeStringField( 'enhancedSchemeData.destinationCountryCode', enhancedPaymentData.shipToCountry ); } } /** * Populates Level 3 line item data. * * @param jsonGeneratorInstance JSON generator * @param item Line item input * @param prefix Field prefix for indexed items */ private void populateLineItemData(JSONGenerator jsonGeneratorInstance, commercepayments.LineItemInput item, String prefix) { if (item.sku != null) { jsonGeneratorInstance.writeStringField(prefix + 'productCode', item.sku); } if (item.name != null) { jsonGeneratorInstance.writeStringField(prefix + 'description', item.name); } if (item.quantity != null) { jsonGeneratorInstance.writeStringField(prefix + 'quantity', String.valueOf(item.quantity)); } // Unit price is always written jsonGeneratorInstance.writeStringField( prefix + 'unitPrice', toMinorUnits(item.unitPrice) ); if (item.taxAmount != null) { jsonGeneratorInstance.writeStringField( prefix + 'taxAmount', toMinorUnits(item.taxAmount) ); } if (item.discount != null) { jsonGeneratorInstance.writeStringField( prefix + 'discountAmount', toMinorUnits(item.discount) ); } if (item.commodityCode != null) { jsonGeneratorInstance.writeStringField(prefix + 'commodityCode', item.commodityCode); } if (item.uom != null) { jsonGeneratorInstance.writeStringField(prefix + 'unitOfMeasure', item.uom); } } /** * Converts amount to minor units (e.g., dollars → cents). * * @param amount Decimal amount * @return String representation of minor units */ private static String toMinorUnits(Decimal amount) { if (amount == null) return null; Decimal value = (amount * 100) .setScale(0, System.RoundingMode.HALF_UP); return String.valueOf(value.intValue()); }
SaleRequest Constructors
The following are constructors for SaleRequest.
SaleRequest(amount)
Signature
global SaleRequest(Double amount)
Parameters
-
amount:
Type: Double
Amount of the sale request.
SaleRequest Properties
The following are properties for SaleRequest.
enhancedPaymentData
Supported only for third-party payment gateways; not supported for native payments.
Signature
public commercepayments.EnhancedPaymentDataInput enhancedPaymentData {get; set;}
Property Value
Type: commercepayments.EnhancedPaymentDataInput
paymentInitiationSourceId
Supported only for third-party payment gateways; not supported for native payments. See PaymentInitiationSource object documentation for more information.
Signature
public String paymentInitiationSourceId {get; set;}
Property Value
Type: String
paymentMethod
Signature
global commercepayments.SaleApiPaymentMethodRequest paymentMethod {get; set;}
Property Value
paymentMethodData
This field is populated when SaleInput specifies a saved payment method. Accessible using paymentMethodData on SaleRequest. The map contains these fields from SavedPaymentMethod: GatewayToken, Type, GatewayReference, and StandardEntryCode for direct gateway interaction without querying the database.
Signature
public Map<String,String> paymentMethodData {get; set;}
submittedByMerchant
Signature
public Boolean submittedByMerchant {get; set;}
Property Value
Type: Boolean
SaleRequest Methods
The following are methods for SaleRequest.
equals(obj)
Signature
global Boolean equals(Object obj)
Parameters
-
obj:
Type: Object
Return Value
Type: Boolean
hashCode()
Signature
global Integer hashCode()
Return Value
Type: Integer