// Example Program: T_LVL23CMP
// Description:
// This is a test program to illustrate how to call the CTI_Run()
// subprocedure to perform a capture utilizing Level II and Level III
// data used/required by FDC Compass. This program demonstrates
// a request for Visa that matches the example on page 54 in the
// LVL2/3 SO API guide provided by CyberSource:
// http://goo.gl/4VZRIF
//
// Fields not used in this request but which may be used by others
// (especially by MasterCard) are commented out.
//
// Note that this example relies on a previous authorization.
//
// To achieve this, generate a unique ID with CTI_NextUniqueId(), and
// then populate and write a record to CTIWSHDR. This example also
// writes one or more records to CTIWSITM to provide that level of
// detail. Then, call CTI_Run() passing in your unique ID as well
// as the other parameters shown.
//
// CTI_Run() will return *On if no error was encountered, or *Off
// if an error occurred. If an error occurred, you should look at
// the fields in ErrorDS to retrieve information about the error.
//
// Otherwise, you can perform a CHAIN against the CTIWSRSP physical
// file, and retrieve the result fields.
Ctl-Opt ActGrp(*Caller) BndDir('CTIBND') Option(*NoDebugIO);
Dcl-F CTIWSHDR Disk(*Ext) Keyed Qualified Usage(*Input:*Output);
Dcl-F CTIWSITM Disk(*Ext) Keyed Qualified Usage(*Input:*Output);
Dcl-F CTIWSRSP Disk(*Ext) Keyed Qualified Usage(*Input);
Dcl-Ds HDR ExtName('CTIWSHDR':*Output) Qualified End-Ds;
Dcl-Ds ITM ExtName('CTIWSITM':*Output) Qualified End-Ds;
Dcl-Ds RSP ExtName('CTIWSRSP':*Input) Qualified End-Ds;
/COPY QRPGLECPY,CTICB
// This is included for demo output purposes.
Dcl-Pr WriteToJobLog Int(10) Extproc('Qp0zLprintf');
pString Pointer Value Options(*String);
End-Pr;
Dcl-C NewLine x'15';
// This stores the unique ID for this API call
Dcl-S UniqueId Like(CTI_UniqueId_t) Inz;
// This holds any error information returned by the API call
Dcl-Ds ErrorDS LikeDS(CTI_ErrorDS_t) Inz(*LikeDS);
// Modify this field to specify different card details
Dcl-S CardNumber Char(20) Inz('4111111111111111');
// Modify this field to use your merchant ID
Dcl-S MerchantId Like(CTI_MerchantId_t) Inz('ikrengel');
// This data structure is used to store details from the point of sale
// payment terminal
Dcl-Ds PosDS LikeDS(CTI_PosDS_t) Inz(*LikeDS);
reset ErrorDS;
// Each API call requires a unique ID
UniqueId = CTI_NextUniqueId();
// Note that CTIWSHDR and CTIWSITM need to be occupied with the
// necessary information first before running this request
clear HDR;
HDR.UID = UniqueId;
HDR.CRTDT = %Timestamp();
HDR.CAPRUN = CTi_TRUE;
HDR.MCHID = MerchantId;
HDR.MCHREFCD = 'MYREFCD132';
HDR.CAPPCHLVL = '3';
// ID from previous authorization
HDR.ATHREQID = '4351671320145000001518';
// required for Visa & MasterCard for best rate
// valid formats are: #####, #####-#### (dash required), or
// ### ### in CA
// If customer takes possession of items at your location, should
// match HDR.SFPSTCD
HDR.STPSTCD = '56001';
// required for best rate in Visa, optional but recommended for
// MasterCard
HDR.STCNTRY = 'US';
HDR.STSTT = 'MN';
HDR.PTCUR = 'USD';
HDR.PTGNDAMT = '919.04';
// This is used if you're sending AMEX (and setting HDR.CCRDTYP to 003)
// and if this is a capture
// Otherwise, if this is a credit request it's not required, but you
// would need to be populating HDR.CRDREQID
//HDR.AMEXTAA1 = 'describe transaction';
// listed as required for all card types for
// "purchase/procurement cards", but is otherwise listed as optional
//HDR.USRPO = 'purchase order number';
// listed as optional for MasterCard, no details for other types
//HDR.ALTTAXAMT = '';
// This is required if you set HDR.ALTTAXAMT to any value, including 0.
// You can also send this without setting HDR.ALTTAXAMT
//HDR.ALTTAXID = '';
// listed as optional for Visa, no details for other types
//HDR.VATTAXAMT = '';
// listed as optional for Visa, no details for other types
// describes the rate of VAT or other taxes for order
// valid range is 0.01 to 0.99 (e.g. 1% to 99%)
//HDR.VATTAXRTE = '';
// listed as optional for Visa, no details for other types
// total discount applied to order
//HDR.PTDSCAMT = '';
// listed as optional for Visa and MasterCard, no details for other
// types
// total charges for any import/export duties in order
//HDR.PTDTYAMT = '';
// listed as optional for Visa and MasterCard, no details for other
// types
// total freight or shipping/handling charges for order. when this
// is set, HDR.PTGNDAMT must also be set
//HDR.PTFGTAMT = '';
// optional for Visa, required for MasterCard for best rate
// valid formats are: #####, #####-#### (dash required), or
// ### ### in CA
//HDR.SFPSTCD = '';
write CTIWSHDR.CTIWSHDRR HDR;
clear ITM;
ITM.PID = UniqueId;
ITM.UID = CTI_NextUniqueId();
ITM.CRTDT = %Timestamp();
// requied for Visa & MasterCard for Level III interchange
// do not use all zeroes or spaces
// text description of item
ITM.PRDNAM = 'File Cabinet';
// Optional for Visa, not listed for other card types
//ITM.COMMCD = '';
// required for Visa & MasterCard for Level III interchange
// do not use all zeroes or spaces
// if you don't provide this, CyberSource sets to 'default'
ITM.PRDCD = 'default';
// required for Visa & MasterCard for Level III interchange
// do not use all zeroes or spaces
// must be a whole number
ITM.QTY = 10;
// required for all card types
// unit cost of item purchased
ITM.UNTPRC = '59.95';
// required for all card types
// total tax to apply to product, cannot be negative
ITM.TAXAMT = '49.46';
// required for all card types for level III interchange
// tax rate applied to item
// valid range is 0.01 to 0.99 (e.g. 1% to 99%)
//ITM.TAXRAT = '';
// required for MasterCard, not listed for other card types
// type of tax being applied
//ITM.TAXTYPAPL = '';
// used to determine order items will appear in request
// to CyberSource
ITM.SEQ# = 1;
// optional for Visa/MasterCard, not listed for other card types
//ITM.DSCAMT = '';
// optional for MasterCard, not listed for other card types
// Y or N indicates if the item is discounted - if you don't set this
// but set a value in ITM.DSCAMT, CyberSource changes this to Y
//ITM.DSCIND = ''; // Y=yes or N=no
// required for MasterCard, not listed for other card types
// Y or N indicates if tax amount is included in line item total
//ITM.GRSNETIND = ''; //Y=yes or N=no
// listed as optional for all card types
// "Field to support an invoice number for a transaction. You
// must specify the number of line items that will include an invoice
// number. By default, the first line item will include an invoice
// number field. The invoice number field can be included for
// up to 10 line items
//ITM.INVNBR = '';
// required for all card types
// do not use all zeroes or spaces
// total amount for item, typically price X quantity
ITM.TOTAMT = '648.96';
// required for all card types for level 3 interchange
// do not use all zeroes or spaces
// unit of measure or unit of measure code for item
//ITM.UOM = '';
write CTIWSITM.CTIWSITMR ITM;
clear ITM;
ITM.PID = UniqueId;
ITM.UID = CTI_NextUniqueId();
ITM.CRTDT = %Timestamp();
ITM.PRDNAM = 'File Folders';
ITM.PRDCD = 'default';
ITM.QTY = 50;
ITM.UNTPRC = '4.99';
ITM.TAXAMT = '20.58';
ITM.SEQ# = 2;
ITM.TOTAMT = '270.08';
write CTIWSITM.CTIWSITMR ITM;
if not CTI_Run( UniqueId : ErrorDS : CardNumber : *Omit : MerchantId );
// If CTI_Run() returns *Off then an error occured.
// You should check ErrorDS subfields for info:
// ErrorDS.Subproc = Name of CTI subprocedure that threw error
// ErrorDS.MessageId = Message ID of the error message
// ErrorDS.Message = Error message description
// ErrorDS.LogFile = Path to a log file created in the IFS that can
// be used for troubleshooting. Log files are generated
// automatically whenever an error occurs. You can also force log
// files to generate by modifying the value of the LOGALL field in
// CTICFGMCH for the provided Merchant ID.
// ErrorDS.Source =
// - CTI_SOURCE_INTERNAL is a general product error.
// This could be due to issues with input data, or the
// inability to access physical files, etc.
//
// - CTI_SOURCE_TRANSMIT is a product error that specifically
// occurred during HTTPS communication with the CyberSource
// webservice. This could be due to issues with your network
// configuration, proxy setup, internet connection, etc.
//
// - CTI_SOURCE_REMOTE is an error message provided by CyberSource.
WriteToJobLog( 'Error Message Id: ' + ErrorDS.MessageId + NewLine );
WriteToJobLog( 'Error Message: ' + ErrorDS.Message + NewLine );
WriteToJobLog( 'Error Source: ' + ErrorDS.Source + NewLine );
// All error information is also written to the file CTIERR.
else;
// If CTI_Run() returned *On the request was successful. You can
// access the results in the CTIWSRSP file using the same UniqueID
// that was used to create the request record in CTIWSRSP.
chain UniqueId CTIWSRSP.CTIWSRSPR RSP;
if %Found(CTIWSRSP);
// For this sample code we're writing the response data to the job
// log, but generally you would extract the data and pass it into
// your own data tables. The CTIWSHDR, CTIWSITM, and CTIWSRSP files
// should not be used for long-term data storage and should instead
// be considered short-term transactional files.
// Authorization Response fields
WriteToJobLog( 'CCAMT: ' + RSP.CCAMT + NewLine );
WriteToJobLog( 'CCATHCD: ' + RSP.CCATHCD + NewLine );
WriteToJobLog( 'CCATHDT: ' + RSP.CCATHDT + NewLine );
WriteToJobLog( 'RSNCD: ' + %Char(RSP.RSNCD) + NewLine );
WriteToJobLog( 'CCRSNCD: ' + RSP.CCRSNCD + NewLine );
WriteToJobLog( 'REQID: ' + RSP.REQID + NewLine );
WriteToJobLog( 'REQTK: ' + RSP.REQTK + NewLine );
WriteToJobLog( 'CCAVSCD: ' + RSP.CCAVSCD + NewLine );
WriteToJobLog( 'CCAVSCDR: ' + RSP.CCAVSCDR + NewLine );
WriteToJobLog( 'CCPRCRSP: ' + RSP.CCPRCRSP + NewLine );
// Capture Response fields
WriteToJobLog( 'MCHREFCD: ' + RSP.MCHREFCD + NewLine );
WriteToJobLog( 'CAPAMT: ' + RSP.CAPAMT + NewLine );
WriteToJobLog( 'RSNCD: ' + %Char(RSP.RSNCD) + NewLine );
WriteToJobLog( 'CAPRSNCD: ' + %Char(RSP.CAPRSNCD) + NewLine );
WriteToJobLog( 'REQID: ' + RSP.REQID + NewLine );
WriteToJobLog( 'REQTK: ' + RSP.REQTK + NewLine );
WriteToJobLog( 'CAPREQDT: ' + RSP.CAPREQDT + NewLine );
WriteToJobLog( 'CAPRECID: ' + RSP.CAPRECID + NewLine );
endif;
endif;
*INLR = *On;
return;