T_ATHSUBCR - Authorization and Subscription Creation

**FREE
// Example Program: T_ATHSUBCR
// Description:
//  This is a test program to illustrate how to call the CTI_Run()
//  subprocedure to perform an authorization, and then create a
//  subscription/profile/token with CyberSource to allow for future
//  transactions to not require passing in credit card data directly.
//
//  To achieve this, the 'authorize' subroutine generates a unique
//  ID with CTI_NextUniqueId(), and then populate and write a record
//  to CTIWSHDR. 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.
//
//  Next, the 'subcreate' subroutine uses that response data and
//  repeats the same general process (get unique ID, write record, call
//  CTI_Run()) to convert the authorization into a profile/subscription.

Ctl-Opt ActGrp(*Caller) BndDir('CTIBND') Option(*NoDebugIO);

Dcl-F CTIWSHDR 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 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 these fields to specify different card details
Dcl-S CardNumber Char(20) Inz('4111111111111111');
Dcl-S CardCV Char(4) Inz('1234');

// Modify this field to use your merchant ID
Dcl-S MerchantId Like(CTI_MerchantId_t) Inz('ikrengel');

// This field is used to store the authorization request ID to pass to
//  the second request.
Dcl-S RequestID Char(26);

exsr authorize;

exsr subCreate;

// Write unique ID to job log for easy reference
WriteToJobLog( 'T_ATHSUBCR Unique ID: ' + %Char(UniqueId) + NewLine );

*INLR = *On;
return;

begsr authorize;
  reset ErrorDS;

  WriteToJobLog( 'Begin Authorize' + NewLine );

  // Each API call requires a unique ID
  UniqueId = CTI_NextUniqueId();

  clear HDR;
  HDR.UID = UniqueId;
  HDR.CRTDT = %Timestamp();
  HDR.ATHRUN = CTI_TRUE;
  HDR.MCHID = MerchantId;
  HDR.MCHREFCD = 'MYREFCD134';
  HDR.CCCRDTYP = '001';
  HDR.CCEXPMM = '10';
  // HDR.CCEXPYY needs to contain a four digit year
  //  To make this example stay current, we're automatically
  //  adjusting the year to be currentYear+1
  HDR.CCEXPYY = %Char( %SubDt( %Date() : *Y ) + 1);
  HDR.BTFNAM = 'Jim';
  HDR.BTLNAM = 'Jones';
  HDR.BTST1 = '123 Central';
  HDR.BTCTY = 'Mankato';
  HDR.BTSTT = 'MN';
  HDR.BTPSTCD = '56001';
  HDR.BTCNTRY = 'US';
  HDR.BTEML = 'asdf@asdf.com';
  HDR.PTCUR = 'USD';
  HDR.PTGNDAMT = '12.12';

  write CTIWSHDR.CTIWSHDRR HDR;

  if not CTI_Run( UniqueId : ErrorDS : CardNumber
                : CardCV : MerchantId );
  // If CTI_Run() returns *Off then an error occurred.

  // 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
  //   CTICFGCER 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.
    return;
  endif;

  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 );

    RequestId = RSP.REQID;
  endif;
  WriteToJobLog( 'End Authorize' + NewLine );
endsr;

begsr subCreate;
  reset ErrorDS;

  WriteToJobLog( 'Begin Subscription Create' + NewLine );
  UniqueId = CTI_NextUniqueId();

  clear HDR;
  HDR.UID = UniqueId;
  HDR.MCHID = MerchantId;
  HDR.MCHREFCD = 'MYREFCD134';
  HDR.PSCRTRUN = CTI_TRUE;
  HDR.RSIFREQ = 'on-demand';
  HDR.PSCRTRID = RequestID;

  write CTIWSHDR.CTIWSHDRR HDR;

  if not CTI_Run( UniqueId : ErrorDS : CardNumber
                : CardCV : 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
  //   CTICFGCER 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.
    return;
  endif;

  // 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.

    // Subscription Create Reply 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 );
    WriteToJobLog( 'PRSNCD: ' + %Char(RSP.PRSNCD) + NewLine );
    WriteToJobLog( 'PSUBID: ' + %Char(RSP.PRSNCD) + NewLine );
  endif;
  WriteToJobLog( 'End Subscription Create' + NewLine );
endsr;