Print Receipts
This method integrates receipt printing into your application.
In this topic:
Receipt Properties
Commerce SDK comes with the ability to print an EMV compliant receipt utilizing the integration with Star Micronics printers. If this integration is not utilized, it is the integrator’s responsibility to generate the appropriate receipt for both the consumer and the merchant. An appropriate receipt is dependent on items such as industry, card present vs. card not present and card entry method.
Below are data elements that must be included on a receipt for an EMV transaction in order to have an EMV compliant receipt. These data elements are returned to the integrator for use in generating an EMV compliant receipt. The following are data elements that should be included on a transaction receipt:
Data Element | Description |
---|---|
Merchant Name | Name of business that would be recognized by the cardholder (and Merchant ID for UnionPay only). |
Merchant Location | Including place of business (street address) city and state/province. |
Transaction Receipt Type | Purchase, Credit, Cash Back, Cash Disbursement, Refund |
Transaction Amount | Total of all goods/services sold and any tips, taxes, fees, surcharges, adjustments, credits, cash back. |
Transaction Currency | If not included, it is the local currency of the transaction country. |
Transaction Date | Actual day which the products/services were exchanged. |
Item Description | Description of each product or service purchased. |
Authorization Code | Complete authorization code, provided by the Card issuing bank. |
Card Network Name | Examples: American Express, Discover, MasterCard, UnionPay or Visa |
Account Number | Suppressed/truncated PAN or token (card expiration date must be omitted). |
Cardholder Name | As it appears on the Card if present – Discover Cards only (not required in Canada). |
Cardholder Signature | Merchants must retain a copy of a signed receipt for those that require signature. |
Return Policy | Specific information regarding merchant’s return policy (refer to refund policy FAQ below). |
Additionally, these data elements should be included on the receipt for an EMV transaction:
Transaction Tag | Examples/Values |
---|---|
Transaction Status Information (TSI) | E800 (Offline Data Auth; CVM; Card Risk Mgmt; Terminal Risk Mgmt) |
Terminal Verification Results (TVR) | 0200008000 (SDA; Floor Limit Exceeded) |
Authorization Response Code (ARC) | - 00 (Online Approval) - 05 (Online Decline) - Z3 (Unable to Online;Offline Declined) |
Application ID (AID) | - A0000000041010 (Mastercard) - A00000002501 (Amex) |
Application Counter (AC) | 0E9E8197FF2B672A |
Cardholder Verification Method (CVM)
The CVM performed must be identified on the transaction receipt (even if no CVM was performed). Possible values include:
Test/Value | Description |
---|---|
No CVM Required | Appears in the case where neither PIN nor Signature was required (i.e. NO CVM) |
Verified by PIN | Cardholder entered PIN on terminal |
Verified by Signature | Either signature capture is performed on the terminal, or a signature line is printed on the receipt (to be signed) |
Verified by PIN and Signature | Appears in the case where both PIN and Signature were required |
Application Name
When possible, the Application Preferred Name should be rendered on any receipt. If the Preferred Name cannot be rendered on the receipt, the Application Name should be used.
Code Samples
CWS
Request
Property | Description |
---|---|
method string | required | printReceipt |
requestId string | required | Transaction Request ID |
targetType string | required | paymentGatewayConverge |
parameters JSONObject | required | All relevant parameters for printing receipts. |
paymentGatewayId string | required | Payment Gateway ID Unique payment gateway identifier as returned in the openPaymentGateway transaction response. |
transactionId string | optional | Transaction ID Unique transaction identifier of the approved transaction. Note: Set the value to null (default) to print the last successful transaction. |
receiptTerms JSONObject | optional | Terms Map A map of terms to be printed on the receipt. “receiptTerms” : { “CARD” : “CreditCard”, “START” : “Start”, “EXPIRY” : “Expire”, “SALE” : “Sale”, “REFUND” : “Refundent”, “CASH” : “Cashless”, “CHECK” : “Checkered”, “GRATUITY” : “Tipsy”, “TOTAL” : “Totality”, “SUBTOTAL” : “not the whole amount”, “DISCOUNT” : “Discounted”, “TAX” : “Taxi” }, |
accountInfo JSONObject | optional | Account Information Alternate description of the business. “accountInfo” : { “name” : “Pete’s Northside Dive”, “businessEmail” : “support@elavon.com”, “address1” : “8985 Ridgestone Ct”, “city” : “Roswell”, “stateProvince” : “GA”, “postalCode” : “30076” }, |
Example
Request
{
"method" : "printReceipt",
"requestId" : "1581202618",
"targetType" : "paymentGatewayConverge",
"version" : "1.0",
"parameters" : {
"receiptTerms" : {
"CARD" : "CreditCard",
"START" : "Start",
"EXPIRY" : "Expire",
"SALE" : "Sale",
"REFUND" : "Refundent",
"CASH" : "Cashless",
"CHECK" : "Checkered",
"GRATUITY" : "Tipsy",
"TOTAL" : "Totality",
"SUBTOTAL" : "not the whole amount",
"DISCOUNT" : "Discounted",
"TAX" : "Taxi"
},
"transactionId" : null, /* null implies last successful transaction */
"localeLanguage" : "en",
"localeCountry" : "US",
"utcDate" : null,
"paymentGatewayId" : "5af70b73-1c44-40c4-9cef-b0b4af0265b5",
"accountInfo" : {
"name" : "Pete's Northside Dive",
"currencyCode" : "USD",
"businessEmail" : "support@elavon.com",
"address1" : "8985 Ridgestone Ct",
"city" : "Roswell",
"stateProvince" : "GA",
"postalCode" : "30076",
"isGratuitySupported" : false,
"marketSegment" : null
},
"currencyFormatPattern" : "###,###.## USD",
"receiptRequestor" : "CUSTOMER",
"languageInformation" : {
"languageCode" : "EN",
"countryCode" : "US"
}
}
}
/* Reprint a receipt */
{
"method" : "printReceipt",
"requestId" : "1327657496",
"targetType" : "paymentGatewayConverge",
"version" : "1.0",
"parameters" : {
"receiptTerms" : {
"CARD" : "CreditCard",
"START" : "Start",
"EXPIRY" : "Expire",
"SALE" : "Sale",
"REFUND" : "Refundent",
"CASH" : "Cashless",
"CHECK" : "Checkered",
"GRATUITY" : "Tipsy",
"TOTAL" : "Totality",
"SUBTOTAL" : "not the whole amount",
"DISCOUNT" : "Discounted",
"TAX" : "Taxi"
},
"transactionId" : "070316A15-E4D15565-86A8-490F-A5F1-F9996C062800", /* This transaction id */
"localeLanguage" : "en",
"localeCountry" : "US",
"utcDate" : "2016/03/07 11:04:21", /* On this date */
"paymentGatewayId" : "2cdfef04-b699-4880-a294-ef8da0baaee7",
"accountInfo" : {
"name" : "Pete's Northside Dive",
"currencyCode" : "USD",
"businessEmail" : "support@elavon.com",
"address1" : "8985 Ridgestone Ct",
"city" : "Roswell",
"stateProvince" : "GA",
"postalCode" : "30076",
"isGratuitySupported" : false,
"marketSegment" : null
},
"currencyFormatPattern" : "###,###.## USD",
"receiptRequestor" : "CUSTOMER",
"languageInformation" : {
"languageCode" : "EN",
"countryCode" : "US"
}
}
}
Java
You will need to keep ECLTransaction
, ECLTender
and ECLOutcome
from a completed transaction in order to print the last transaction, get the printer to us, and then tell ECLReceiptProcessor
to send the receipt to that printer.
/* Create receipt using last transaction, tender, and outcome. Specify no account information override, customer as requestor, and no language override. */
final ECLReceiptProcessorInterface receiptProcessor = account.getReceiptProcessor();
ECLReceiptInterface receipt = receiptProcessor.createReceiptForCurrentTransaction(lastCompletedTransaction, lastCompletedTender, lastOutcome,
null, ECLReceiptRequestor.CUSTOMER, null);
/* Create receipt processing listener for receipt processor callbacks */
ECLReceiptProcessingListener receiptProcessingListener = new ECLReceiptProcessingListener() {
@Override
public void receiptDidSucceed(ECLReceiptInterface eclReceiptInterface, ECLReceiptOutputType eclReceiptOutputType) {
}
@Override
public void receiptDidFail(ECLReceiptInterface eclReceiptInterface, ECLReceiptOutputType eclReceiptOutputType, ECCError eccError) {
}
@Override
public String receiptShouldProvideLocalizedText(ECLReceiptInterface eclReceiptInterface, ECLReceiptTextIdentifier eclReceiptTextIdentifier) {
return null;
}
@Override
public String receiptShouldProvideLocalizedMoneyText(ECLReceiptInterface eclReceiptInterface, ECLMoney eclMoney) {
return null;
}
@Override
public String receiptShouldProvideLocalizedPercentageText(ECLReceiptInterface eclReceiptInterface, BigDecimal bigDecimal) {
return null;
}
};
/* Search for a printer to use */
ECCError error = account.getPrinters().findDevices(new ECLDevicesSearchingListener() {
/* This will be called during the search each time a printer is found. The deviceSearchDone will be called when searching is completed */
@Override
public void devicesSearchFound(String name, ECLDeviceConnectionType connection)
{
}
/* This method is called when searching is completed */
@Override
public void devicesSearchDone(List<ECLDeviceSearchResult> deviceSearchResults)
{
if (deviceSearchResults.size() == 0)
{
/* No printers found. Need to tell user to connect a printer */
return;
}
/* If there are multiple printers, you could show UI to let user choose which one to use. Here we will just use the first one */
ECLDeviceSearchResult result = deviceSearchResults.get(0);
ECLPrinterInterface printer = account.getPrinters().setDeviceToUse(result.getName(), result.getConnectionTypes());
receiptProcessor.printReceipt(receipt, printer, receiptProcessingListener);
}
}, ECLDeviceConnectionType.enumSetForAll(), FIND_DEVICES_TIMEOUT_IN_SECONDS);
if (error != null)
{
/* There was a problem starting the search. Show UI for error */
}
Objective-C
ECLReceiptProtocol
First you will need to implement the ECLDevicesSearchingDelegate
which you will use to search for a printer and then print the receipt. We will also use the same class for aECLReceiptProcessingDelegate
that we pass when printing the receipt.
/* In your header */
#import <Commerce-Converge/ECLReceiptProcessingDelegate.h>
#import <Commerce-Converge/ECLDevicesSearchingDelegate.h>
@interface ReceiptPrint : NSObject<ECLReceiptProcessingDelegate,ECLDevicesSearchingDelegate>
@property (readonly) id<ECLReceiptProcotol>)receipt;
+ (id)initWithReceipt:(id<ECLReceiptProcotol>)receipt;
@end
/* In your m file */
@implementation ReceiptPrint
+ (id)initWithReceipt:(id<ECLReceiptProcotol>)receiptParam {
self = [super init];
if (self) {
_receipt = receiptParam;
}
return self;
}
+ (void)deviceSearchFound:(id<ECLDevicesProtocol>)devices name:(NSString *)name connection:(ECLDeviceConnectionType)connection {
/* printer was found but lets wait until the search is done.
We could show some progress to the user if we wanted. */
}
/* searchResults array contains ECLDeviceSearchResult */
+ (void)deviceSearchDone:(id<ECLDevicesProtocol>)devices searchResults:(NSArray *)searchResults {
if ([searchResults count] == 0) {
/* no printers. show UI to tell user to connect printer */
return;
}
/* If there are multiple printers available we could show UI to let user choose. Here we will just use the first one to print the receipt . */
ECLDeviceSearchResult *result = searchResults[0];
id<ECLPrinterProtocol> printer = (id<ECLPrinterProtocol>)[account.printers setDeviceToUse:result.name connection:result.connectionTypes];
[account.receiptProcessor printReceipt:_receipt printer:printer delegate:self];
}
/* This will be called when the receipt was successfully printer, emailed, etc. */
+ (void)receiptDidSucceed:(id<ECLReceiptProtocol>)receipt output:(ECLReceiptOutputType)output {
}
/* This will be called when the receipt failed to go to printer, email, etc. */
+ (void)receiptDidFail:(id<ECLReceiptProtocol>)receipt output:(ECLReceiptOutputType)output error:(NSError *)error {
}
/* Commerce does not provide localization so you need to provide the localized text for each of the following methods */
+ (NSString *)receiptShouldProvideLocalizedText:(id<ECLReceiptProtocol>)receipt for:(ECLReceiptTextIdentifier)textIdentifier {
/* return localized text for the ID */
}
+ (NSString *)receiptShouldProvideLocalizedMoneyText:(id<ECLReceiptProtocol>)receipt amount:(ECLMoney *)amount {
/* You can use our provided methods for this */
return [ECLMoneyUtil stringFromMoney:amount withSymbol:NO withSeparators:NO];
}
+ (NSString *)receiptShouldProvideLocalizedPercentageText:(id<ECLReceiptProtocol>)receipt for:(NSNumber *)percentage {
/* return localized text for the percentage */
}
+ (NSString *)receiptShouldProvideLocalizedText:(id<ECLReceiptProtocol>)receipt forTransactionResult:(ECLTransactionResult)result {
/* return localized text for the transaction result */
}
+ (NSString *)receiptShouldProvideLocalizedText:(id<ECLReceiptProtocol>)receipt forCardScheme:(ECLCardTenderScheme)cardScheme {
/* return localized text for the card scheme */
}
@end
Now that we have our printer search delegate and a receipt processing delegate we can print the receipt.
/* Create receipt using last transaction, tender, and outcome. Specify no account information override, customer as requestor, and no language override. */
id<ECLReceiptProcessorProtocol> receiptProcessor = account.receiptProcessor;
id<ECLReceiptProtocol> receipt = [receiptProcessor createReceiptForCurrentTransaction:lastCompletedTransaction using:lastCompletedTender withOutcome:lastOutcome
accountInformation:nil requestor:ECLReceiptRequestor_Customer languageInformation:nil];
/* Search for a printer to use and then our delegate will print the receipt */
NSError *error = [account.printers findDevices:[[ReceiptPrint alloc] initWithReceipt:receipt] connection:allDeviceConnectionsTypes() timeoutInSecond:30];
if (error != nil) {
/* error starting search. Show UI */
return;
}
C#
PrintBackEndArgs
m_PrintPaymentArgs = new PrintPaymentArgs();
m_PrintPaymentArgs.paymentGatewayId = m_PaymentGatewayId;
m_PrintPaymentArgs.accountInfo = null;
m_PrintPaymentArgs.receiptRequestor = ReceiptRequestor.CUSTOMER.ToString();
m_PrintPaymentArgs.languageInformation = null;
m_PrintPaymentArgs.transactionId = null;
m_CWS.StartPrintPaymentReceipt(m_PrintPaymentArgs, MyNotifyCWSEvent, MyPaymentComplete);
/* To reprint */
m_PrintPaymentArgs.transactionId = origTransId;
m_PrintPaymentArgs.utcDate = origDate;
m_CWS.StartPrintPaymentReceipt(m_PrintPaymentArgs, MyNotifyCWSEvent, MyPaymentComplete);