[CyberSource logo]


Search documentation:

  Help  Advanced
        Published 05/13/2002 Table of ContentsPreviousNextIndex

Chapter 1

CDK for C/C++ 3.4.0

This appendix explains how to develop CGI, ISAPI, or NSAPI programs in C/C++ to support CyberSource ICS applications, as presented in the following sections:

Installing the CDK for C/C++

If you are going to be installing the Perl libraries, you need to run the install script as a user with write access in the Perl directories:

  1. Unzip or untar the CDK package
  2. Run the install scripts.
  3. For Windows NT, run install.bat
    For UNIX, run install.sh
    The install scripts will create a directory to contain the ics configuration directory and copy all necessary files into that directory and its subdirectories.
    The default directory is C:\opt\ics (for Windows NT) or /opt/ics (for UNIX).
    You may specify an alternate directory as long as you set the environment variable ICSPATH. For example: setenv ICSPATH /opt/ics.
    1. The install scripts will automatically call ECert, which sets up the merchant key files, merchant_id.pvt and merchant_id.crt, and retrieves the Cybersource_SJC_US.crt file.
    2. For Unix: The script will prompt you for a merchant_id.
      For Windows: The merchant_id must be provided on the command line when running install.bat:
      C:\temp\cdkperlc-nt-3_4_0\> install.bat merchant_id [ path ]
      where the merchant_id is your merchant_id and path is the directory where you want to install the files. The path is optional. The default path is c:\opt\ics. If install.bat is run without any parameters, it will display a help message and exit.
      By default, ECert writes the files to [current drive]:\opt\ics\keys (for WIndows NT) or /opt/ics/keys (for Unix).

Requesting ICS Applications

To request CyberSource ICS applications, you must:

Constructing and Sending Messages

Adding Fields to a Message

As discussed in the section "Using Fields to Send Data" in the ICS2 Developer's Guide, available on the CyberSource Small Business Support Center, fields specify information about the request.

To add a field to a message, use the ics_fadd subroutine to specify the name and value of the field.

Example  Adding the value "San Jose" to the bill_city field in the "request" message:

ics_fadd (request, "bill_city", "San Jose");

Syntax for Adding Field Names and Values

Offer Fields

An offer is a single field that contains pairs of field names and values.

Syntax for Offer Fields

Example  An offer with the amount of "$12.95," and the product name of "Fast Software":

ics_fadd (request, "offer0", "amount:12.95^ product_name:Fast Software");

Note  You need to include several additional fields in a real offer.

Extracting Field Values

You can use the following subroutines to extract values from fields:

Note  Although offers contain fields, you cannot use these subroutines to extract values from the fields in an offer. You must write your own code to extract names and values from the fields in an offer.

Printing Field Values

You can print the names and associated values of all the fields returned from CyberSource using the ics_print application. In addition, you can turn on a debugging flag when you create an SCMP message, so that ics_print automatically prints debugging information to stdout whenever you send or receive results using that message. See ics_init for more information.

Sample Request Script

Included with the installation files is the file sample/cgi/transtest.pl. The purpose of the transtest.pl script is to demonstrate how to construct a request and send it. It is a sample program to learn how to create an ICS request message and may be run on a Web server. It presents the user with a form to fill in request parameters. Upon receiving the submitted form, the script builds the ICS request, sends it, and prints the result. Enter your unique merchant_id to execute the test transactions. The only setup required is to copy the script to a cgi-bin directory so that Web server can run it.

Example  Using transtest.pl

  1. Copy transtest.pl to your Web server's cgi-bin directory.
  2. Access the script from a Web browser as http://yourWebServer/cgi-bin/transtest.pl
  3. Note  If you install the CDK to a location other than /opt/ics/ (or C:\opt\ics\ on Windows), you may have to set the ICSPATH environment variable within the script so that it can find the encryption program and keys. For example: $ENV{ICSPATH} = '/home/user/opt/ics';

In addition, the sample/requests/ directory contains example ICS requests in text files (auth.txt, auth_bill.txt, etc.).

Creating and Testing the C/C++ Program

Requesting applications in a C/C++ program

To request applications in your programs, follow these steps:

  1. Create two empty SCMP messages — one for the request you send to the ICS server, and one for the reply you receive from the server.
  2. For example, to create messages named request and reply, your request message must include information about the request and about which ICS applications you want:
    ics_msg* request; request=ics_init(0);
    ics_msg* result; /*do not have to initialize result*/
  3. Add a merchant_id field that contains the name of your merchant key, as specified during the installation of the ICS libraries.
  4. For example:
    ics_fadd(request,"merchant_id", "acme-widgets");
  5. Add a merchant_ref_number field that contains a reference number for the request.
  6. For example::
    ics_fadd(request,"merchant_ref_number", "1234567");
  7. Add an ics_applications field that contains the ICS applications that you want to include in the request. You can choose any of the applications listed in the section "ICS Application Reference" in the ICS2 Developer Guide, available on the CyberSource Small Business Support Center.
  8. For example, to request credit authorization (ics_auth):
    ics_fadd (request, "ics_applications", "ics_auth");
    If you are requesting the applications in a single message, the order of the applications in the ics_applications field is not important. If you are requesting the applications in two or more messages, see the chapter "Using Multiple CyberSource Applications" in the ICS2 Developer's Guide, available on the CyberSource Small Business Support Center.
  9. Look up the required fields for each ICS application you are requesting in the ICS2 Developer's Guide, available on the CyberSource Small Business Support Center.
  10. Add each of the credit card fields, message-level fields, and request-level fields that are required by the applications you are requesting.
  11. If more than one application uses the same field, add the field only once.
    For example, to assign the value "Fred" to the request-level field customer_firstname:
    ics_fadd (request, "customer_firstname", "Fred");
  12. Add an offer field for each product in the current request. There can be several fields in one request. Each field consists of several subfields, some of which are required.
  13. For example, to specify the first two fields for two offers, where the first offer is for a product called Fast Software with an amount of $12.95, and the second offer is for a product called SoftEx with an amount of $99.00:
    ics_fadd(request, "offer0", "amount:12.95^product_name:Fast Software");
    ics_fadd(request, "offer1", "amount:99^product_name:SoftEx);
  14. Use the application ics_send to send the message to the ICS server.
  15. For example:
    result=ics_send(request);
    By default, ics_send sends all messages are sent to the ics2test.ic3.com ICS server. Do not change the server name unless directed to do so by CyberSource or if you are testing your programs.
    CyberSource looks in the following places to determine which CyberSource ICS server to send the message to (in order of priority):
  16. Check the fields in the reply message for status and information, as described in the chapter "Interpreting Returned Messages" in the ICS2 Developer's Guide, available on the CyberSource Small Business Support Center.
  17. If you want to reuse the messages to request new ICS applications in a different request, clear the memory associated with the messages using ics_destroy.
  18. For example:
    ics_destroy(request);
    ics_destroy(result);
    request=ics_init(0);
  19. Test your program, as described in the chapter "Testing Your System" in the ICS2 Developer's Guide, available on the CyberSource Small Business Support Center.
  20. Note  For details on how to use individual CyberSource ICS applications, see the section "ICS Application Reference" in the ICS2 Developer's Guide, available on the CyberSource Small Business Support Center.

Compiling Your C/C++ Programs

When you compile your C/C++ programs, consider the following topics.

Compiling and Linking Under UNIX

For an example of how to compile a C or C++ program to use the ICS libraries, see the sample makefile.

The steps below show how to use the ICS C/C++ libraries under the currently supported UNIX platforms.

  1. Include ics.h in the program:
  2. #include "ics.h"
  3. Link the program with the following:
  4. libics2.a
    libics2.so
    For example, to compile and link the icstest application (included in the SCMP directory) using the GNU C compiler:
    gcc -g icstest.c -lics -lsocket -lnsl -lresolv -o icstest
    To compile a program as a shared library, compile with the libics2.so file instead of libics2.a.
    For other examples on compiling, see the makefile.

Compiling and Linking Under NT

  1. Create a project in the C/C++ compiler you are using.
  2. Link the program with the following:
  3. ics2api.dll
    ics.h

ICS C/C++ Library Reference

The ICS SCMP C/C++ libraries consist of a number of subroutines, which are summarized in Table 1. This section describes these subroutines.

Table 1 Summary of ICS C/C++ Subroutines 
Subroutine
Description
ics_destroy
Clears a used SCMP message.
ics_fadd
Adds a field (a name=value pair) to an SCMP message.
ics_fcount
Returns the quantity of fields in an SCMP message.
ics_fget
Returns the value of the name=value pair at the position in the message specified by index.
ics_fgetbyname
Returns a field from an SCMP message by name.
ics_fname
Returns the name of the name=value pair at the position in the message specified by index.
ics_fremove
Removes a field from an SCMP message.
ics_init
Creates and initializes an SCMP message.
ics_print
Prints the fields of a message to stdout.
ics_send
Sends an encrypted message to the ICS server.



Table 2 ICS C/C++ Data Types 
Data Types
Description
ics_msg
An SCMP message.

ics_destroy



Table 3 ics_destroy Subroutine 
ics_destroy
void ics_destroy (ics_msg* msg)
Action
Frees resources used by an SCMP message that was created by ics_init or by ics_send.
Returns
Nothing.
Description
This call frees any memory used by the specified message. You should destroy messages when your program no longer needs them.

ics_fadd



Table 4 ics_fadd Subroutine 
ics_fadd
int ics_fadd (ics_msg* msg, char* name, char* value)
Action
Adds the name and value of a field to the specified SCMP message.
Returns
The number of fields in the message after the field is added, or -1 if the field cannot be added because the entire message exceeds 32kB limit.
Description
Adds a field to an existing message. A field consists of the name and value of the field (also called a name-value pair).
Adding a field that is already in the message overwrites that message. You can also use ics_fremove to remove a field before you add it again.
Example
To add a field named customer_firstname with the value Jesse to a message named request:
qty = ics_fadd (request, "customer_firstname", "Jesse");

ics_fcount



Table 5 ics_fcount Subroutine 
ics_fcount
int ics_fcount (ics_msg* msg)
Action
Counts the number of fields in the specified message.
Returns
The number of fields in the specified message.
Description
Use ics_fcount to get the total number of fields in the message. Then use ics_fget and ics_fname to iterate through all the fields in the message.

ics_fgetbyname



Table 6 ics_fgetbyname Subroutine 
ics_fgetbyname
char* ics_fgetbyname (ics_msg* msg, char* name)
Action
Extracts the value of a field from a message by its field name.
Returns
A pointer to the value portion of the name-value pair of the field with the specified name, or a null pointer if no field name exists in the specified message.
Description
Use this to access a value in ics_msg, e.g., ics_fgetbyname (msg, "ics_rcode")

ics_fget



Table 7 ics_fget Subroutine 
ics_fget
char* ics_fget (ics_msg* msg, int index)
Action
Extracts the value of the field that is stored in msg at the position indicated by index.
Returns
Returns the value portion of the name=value pair at the position in the message specified by index.
Description
Use this to get all of the field values in an ics_msg by iterating from 0 to ics_fcount(msg)-1.

Example  Using ics_fget to get all of the field names in an ics_msg

int i, c;  
char *name, *value;  
c = ics_fcount(msg);  
for (i = 0; i < c; i++) {  
name = ics_fname(msg, i);  
value = ics_fget(msg, i);  
printf("%s=%s\n", name, value);  
}  

ics_fname

Table 8 ics_fname Subroutine
ics_fname
char *ics_fname (ics_msg* msg, int index)
Action
Extracts the name of the field that is stored in msg at the position indicated by index.
Returns
The name portion of the name=value pair at the position in the message specified by index.
Description
Use this to get all of the field names in an ics_msg by iterating from 0 to ics_fcount(msg)-1.

Example  Using ics_fname to get all of the field names in an ics_msg

int i, c;  
char *name, *value;  
c = ics_fcount(msg);  
for (i = 0; i < c; i++) {  
name = ics_fname(msg, i);  
value = ics_fgetbyname(msg, name);  
printf("%s=%s\n", name, value);  
}  

ics_fremove



Table 9 ics_fremove Subroutine 
ics_fremove
int ics_fremove (ics_msg* msg, char* name)
Action
Removes the field with the specified name from the specified message.
Returns
The number of fields in the message after the field is removed, or -1 if the field is not removed or does not exist in the specified message.
Description
Use this call to change the value of a field. Remove the field, then add it using ics_fadd.

ics_init



Table 10 ics_init Subroutine 
ics_init
ics_msg* ics_init (int debug_flag)
Action
Creates and initializes a new instance of an SCMP message.
Returns
A pointer for a new message, or a null pointer if it cannot allocate space for the message (minimum 68 bytes). It uses more space depending on the number of required and optional fields for different applications and the number of line items in the request.
Description
Free this pointer and its associated memory using ics_destroy when the program no longer needs the pointer.
The debug_flag parameter is required (example: int debug_flag = 0). This parameter can contain one of the following values:
  • 0: Debugging information cannot be displayed (default).
  • 1: (ICS_DEBUG) Requests that debugging information be sent to stdout whenever ics_send is called with this message. You can use 1 or ICS_DEBUG.
  • 2: (ICS_TRACE) Writes debugging information to a log file. New logging information is appended to the existing older log file, but does not overwrite it. You can use 2 or ICS_TRACE.
Log filenames are:
  • For UNIX: /opt/ics/tmp/icsapilog.txt
  • For Windows NT: icsapilog.txt in the root directory in the current drive from which the program is run.
Debugging information includes:
  • Some variable values
  • The fields of the message being sent
  • The encrypted data being sent
  • Some data about where the message was sent
  • The encrypted data received as a result
  • The fields of the decrypted result

Example  Using ics_init to get debugging information

The following sample code creates an SCMP message named request:

#include	 "ics.h" 
int main (int argc, char* argv []); 
{ 
ics_msg *request; 
ics_msg *result; 
request = ics_init (ICS_DEBUG); 
... 
... # request message is filled here  
... 
result = ics_send (request); 

Because debugging is turned on, ics_send sends information similar to the following to stdout:

-- request to: ics2test.ic3.com:80 -- 
server_host=ics2test.ic3.com 
server_port=80 
ics_applications=ics_auth 
merchant_id=ICS2Test 
customer_firstname=John 
customer_lastname=Doe 
customer_email=nobody@cybersource.com 
customer_phone=650-965-6000 
bill_address1=1295 Charleston Rd. 
bill_city=Mountain View 
bill_state=CA 
bill_zip=94043 
bill_country=US 
customer_cc_number=4111111111111111 
customer_cc_expmo=12 
customer_cc_expyr=2015 
merchant_ref_number=12 
currency=USD 
offer0=offerid:0^amount:4.59 

When a response is received from the ICS server, ics_send sends information similar to the following to stdout:

-- response -- 
ics_send request: 
server_host=ics2test.ic3.com 
server_port=80 
ics_applications=ics_auth 
merchant_id=ICS2Test 
customer_firstname=John 
customer_lastname=Doe 
customer_email=nobody@cybersource.com 
customer_phone=650-965-6000 
bill_address1=1295 Charleston Rd. 
bill_city=Mountain View 
bill_state=CA 
bill_zip=94043 
bill_country=US 
customer_cc_number=4111111111111111 
customer_cc_expmo=12 
customer_cc_expyr=2015 
merchant_ref_number=12 
currency=USD 
offer0=offerid:0^amount:4.59 
ics_version=v2.01 
client_lib_version=NT4.0/WIN32/C/3.4.0 
ics_send: sending request; timeout_basis=991993961      timeout=991994071 
getting ICS2Test's certificate from C:\opt\ics\keys\ICS2Test.crt 
getting ICS2Test's private key from get_secret_key_func 
getting ICS2Test's private key from C:\opt\ics\keys\ICS2Test.pvt 
getting CyberSource_SJC_US's certificate from C:\opt\ics\keys\CyberSource_SJC_US.crt 
allocating 544 bytes for clearBuf 
clearBufLen=543 
allocating 2589 bytes for encodedBuf 
before 1st base64_encode: cryptBufLen=1538 bytes 
after 1st base64_encode: strlen encodedBuf=2077 bytes 
encodedBuf before headers 2077 
encodedBuf after headers 2348 
before preparePKCSMessage 
after preparePKCSMessage 
allocating 4495 bytes for encodedBuf 
before 2nd base64_encode: input buf=2951 bytes 
after 2nd base64_encode: encoded buf=3985 bytes 
ics_send server_host: ics2test.ic3.com 
ics_send server_port: 80 
ics_send version: v2.01 
ics_send svrproc: ics.pl 
ics_send sender: ICS2Test 
ics_send recipient: CyberSource_SJC_US 
before gethostbyname(ics2test.ic3.com) 
after gethostbyname 
Content-Length=3530 
read 3530 bytes 
ics_send received result... 
allocating 2548 bytes for decrypt buf 
base64_decode returned 2483 
auth_auth_avs=Y 
auth_auth_response=A 
ics_rmsg=Request was processed successfully. 
ics_rflag=SOK 
auth_auth_amount=4.59 
auth_rcode=1 
auth_rmsg=ok 
auth_auth_code=123456 
auth_auth_time=2001-06-07T215328Z 
ics_rcode=1 
auth_rflag=SOK 
request_id=9919939610000167904032 
client_lib_version=NT4.0/WIN32/C/3.4.0 
-- end -- 
successful ICS order, rcode = 1 

ics_print



Table 11 ics_print Subroutine 
ics_print
int ics_print (ics_msg* msg)
Action
Prints the fields of a message, one field on each line, to stdout.
Returns
An unused integer.
Description
This call is useful for debugging, but you will not use it in most applications.

ics_send



Table 12 ics_send Subroutine 
ics_send
ics_msg* ics_send (ics_msg* msg)
Action
Sends an encrypted message to the ICS server.
Returns
If the call is successful, returns a pointer to an message that contains the results of the request. Otherwise, returns NULL.
Description
The message's destination is determined as described in the chapter "Testing Your System" in the ICS2 Developer's Guide, available on the CyberSource Small Business Support Center.
Each message consists of one field specifying the applications to be performed, and several data fields required by the requested applications.
The returned message includes status fields and calculated data fields. The applications and fields are described in the section "ICS Application Reference" in the ICS2 Developer's Guide.

Sample C Program

Example  How a C-language CGI program can send messages to the ICS server to request credit card authorization. To request these services, you use the CyberSource ICS application ics_auth.

  1. For credit card authorization, the ics_auth application requires the following fields in the message:
  2. The message itself has two required fields:
  3. The offer field (offer0) has the following required field:
  4. To send the message requesting ics_auth and ics_score, and to process the results:
  5. #include "ics.h"
    main()
    {
    /* Allocate request and result message space */
    ics_msg* request;
    ics_msg* result;
    {
    /*Initialize request message*/
    request = ics_init (0);
    if (request == NULL){
    /* Initialization failed, do something appropriate */
    }
    /* add your merchant encryption key*/
    ics_fadd (request, "merchant_id", "electron-hut-inc");
    /* List the applications you want */
    ics_fadd (request, "ics_applications", "ics_auth, ics_score");
    /*insert code here to read user's information from your Web page */
    ics_fadd (request, "customer_firstname", "John");
    ics_fadd (request, "customer_lastname", "Doe");
    ics_fadd (request, "customer_email", "nobody@cybersource.com");
    ics_fadd (request, "customer_phone", "6509656000");
    ics_fadd (request, "bill_address1", "1295 Charleston Road");
    ics_fadd (request, "bill_city", "Mountain View");
    ics_fadd (request, "bill_state", "CA");
    ics_fadd (request, "bill_zip", "94043");
    ics_fadd (request, "bill_country", "US");
    ics_fadd (request, "currency", "USD");
    ics_fadd (request, "customer_cc_number", "4111111111111111");
    ics_fadd (request, "customer_cc_expmo", "09");
    ics_fadd (request, "customer_cc_expyr", "2005");
    / * Insert code to read user's product selection from Web page and fill in data from your database */
    ics_fadd (request, "offer0", "amount:10.99");
    if ((result = ics_send(request)) == NULL) {
    printf ("ics error: unable to send request.\n");
    }
    if (ics_fgetbyname (result, "ics_rcode")) < 0) {
    printf ("ics error: %s\n",
    ics_fgetbyname (result, "ics_err"));
    /* see the chapter "Interpreting Returned Messages in the ICS2 Developer's Guide" for example of */
    /* recommended error handling code */
    }
    else{
    /* Use ics_print for debugging only */
    ics_print (result);
    }
    ics_destroy (request);
    ics_destroy (result);
    ...
    }

Retry Request

Retry Request allows you to get information about a request that has timed out. For more information, see the section on "Retry Request" in the ICS2 Developer's Guide, available on the CyberSource Small Business Support Center.

Three parameters allow you to control how a retry request works.

How Retry Request Works

When retry request is enabled, the CDK for C/C++ will:

  1. Encrypt and send the initial request.
  2. Wait until retry_start has expired or return the response if one was received.
  3. If retry_start has expired, the client will encrypt and send the request again.
  4. The client will wait for a response until the full timeout has expired, counting from the time that the initial request was sent.
  5. The client will then return the response, if one was received, or it will return a timeout error.

Enabling Retry Request

Retry request is disabled by default. To enable retry, set retry_enabled to "yes" in the request message. The value "yes" is case-insensitive.

Example  To enable retry_enabled include the following code:

ics_fadd(msg, "retry_enabled", "yes");

Controlling Timeout

Two fields control when retry request occurs and how long the entire ics_send function will block.

Example  To enable retry_start with a value of 30 seconds include the following code:

ics_fadd(msg, "retry_start", "30");

Setting the Timeout Value

The timeout value controls the time allowed for the entire ICS request. This time begins when the initial request is sent. The default for a timeout value is 90 seconds. The timeout value can be set in a request message.

Example  To enable timeout with a value of 60 seconds include the following code:

ics_fadd(msg, "timeout", "60");

Important  The timeout value must be set at six seconds or more. The timeout value must also be greater than the retry_start value by a three-second differential. Setting the timeout value is critical because a retry request will not occur if it is set too low.

Testing Retry Request

For more information on testing a retry request, see the chapter "Testing Your System" in the ICS2 Developer's Guide, available on the CyberSource Small Business Support Center.


Copyright © 2002 CyberSource Corporation.
TOC PREV NEXT INDEX