This section explains how to request CyberSource services using the C/C++ SDK.
Requesting CyberSource Services
To request CyberSource services, you must create these items:
nA system that collects the information required for the CyberSource services
nC/C++ programs to assemble the order information into request, send the request to the CyberSource server, and process the reply information
The CyberSource services use the SCMP API, which consists of name-value pairs. The name-value pair API fields you use for credit card orders are described in the Credit Card Services Using the SCMP API (PDF | HTML). The instructions in this section show you how to write C/C++ programs that correctly use SCMP API name-value pairs.
The code in the examples in this section is incomplete. For complete sample programs, see the test programs in the sample/icstest directory of the SDK.
Constructing and Sending Requests
To access any CyberSource services, you must create and send a request that holds the required information. The example in this section shows basic code for requesting CyberSource services. In this example, John Doe is buying three different items, and you are requesting credit card authorization. For the list and description of all the CyberSource C functions, see C Functions.
Adding Header Files and Variables
Include the header file and declare the request and result variables:
#include "ics.h" ics_msg *icsorder; ics_msg *res; |
Creating the Request
Next, create a new request:
icsorder = ics_init(0); |
Adding Services to the Request
Next, add the service that you want using the ics_fadd() function:
ics_fadd(icsorder, "ics_applications", "ics_auth"); |
You can request multiple services by using commas to separate the service names. For example, you can request both credit card authorization and capture together, a sale, by using the following code:
ics_fadd(icsorder, "ics_applications", "ics_auth,ics_bill"); |
Adding Request-Level Fields
Next, add request-level fields using the ics_fadd() function. The fields include basic information about the customer and your company. You can include embedded spaces in the values, but if you include multiple consecutive spaces, only one of the spaces is retained when the request is processed.
ics_fadd(icsorder, "merchant_id", merchant_id); ics_fadd(icsorder, "customer_firstname", "John"); ics_fadd(icsorder, "customer_lastname", "Doe"); ics_fadd(icsorder, "customer_cc_number", "4111111111111111"); |
The example above shows only a partial list of the fields required for the request.
Adding Offer-Level Fields
After specifying request information, add information about the individual items being purchased with the offer-level fields. The offer information is contained in a single field that contains pairs of field names and values. Name-value pairs are separated by carets (^), and names and values are separated by colons (:). Therefore, the values cannot contain carets and colons. You can include embedded spaces in the values, but if you include multiple consecutive spaces, only one of the spaces is retained when the request is processed.
You can include multiple offers in one request.
ics_fadd(icsorder, "offer0", "quantity:1^amount:45.95"); ics_fadd(icsorder, "offer1", "quantity:3^amount:14.99"); ics_fadd(icsorder, "offer2", "quantity:1^amount:25.95"); |
For a full list of the offer fields for the CyberSource credit card services, see Credit Card Services Using the SCMP API (PDF | HTML).
You next send the request to CyberSource:
res = ics_send(icsorder); |
Handling the Reply Flags and Error Messages
After the CyberSource server processes your request, the server returns a reply consisting of name-value pairs. The fields vary, depending on which services you requested and the results of the request.
To use the reply information, you must integrate it into your system and any other system that uses that data. This includes storing the data and passing it to any other services that need the information.
You must write an error handler to handle the reply flags and error messages that you receive from CyberSource. Do not show the flags or error messages directly to customers. Instead, present an appropriate response that tells customers the result.
|
Because CyberSource may add reply fields and reason codes at any time, you should parse the reply data according to the names of the fields instead of their order in the reply. |
The main reply fields to evaluate for the request are as follows:
nics_rcode — a one-digit code indicating the result of the entire request:
l1 indicates the request is successful
l0 indicates the request is declined
l-1 indicates an error occurred
nics_rflag — a one-word description of the result of the entire request:
lSOK indicates the request was successful
lA flag starting with the letter D if the request was declined, such as DMISSINGFIELD
lA flag starting with the letter E if there was an error, such as ESYSTEM
nics_rmsg — a message that explains the reply flag. Do not show this message to customers or use it to write the error handler.
You also receive similar fields for each service you request, indicating the result of the service. The names of the fields are <service>_rcode, <service>_rflag, and <service>_rmsg. For example, the service for credit card authorization (ics_auth) returns auth_rcode, auth_rflag, and auth_rmsg.
|
CyberSource reserves the right to add new reply flags at any time. Write your error handler so that it can process these new reply flags without problems. |
Receiving the Reply
Receive the reply (in the same statement used to send the request):
res = ics_send(icsorder); |
Handling the Reply
Next, evaluate the request’s reply code and reply flag:
if (res == NULL) { /* This happens only if ics_send cannot */ /* allocate memory for the reply. */ /* Log an error, notify customer of problem, and return. */ return; } ics_print(res); printf("-- end --\n");
rcode = ics_fgetbyname(res, "ics_rcode"); rflag = ics_fgetbyname(res, "ics_rflag"); rmsg = ics_fgetbyname(res, "ics_rmsg"); status = atoi(rcode); switch (status) { case -1: /* Error occurred; Notify customer and ask to try again. */ break;
case 0: /* Request declined, evaluate rflag for reason why. */ if (strcmp(rflag, "DINVALIDDATA") == 0) { /* Notify customer that request included invalid data. */ } else if (strcmp(rflag, "DMISSINGFIELD") == 0) { /* Notify customer that request is missing a required field.*/ } else if (strcmp(rflag, "DCARDREFUSED") == 0) { /* Card declined by the bank. Notify customer */ /* unable to process order. */ } else { /* Handle remaining declined reply flags here. */ /* Write handler to handle new reply flags */ /* created by CyberSource. */ } break; case 1: /* Successful transaction; perform any local process */ /* and notify customer of success. */ break; default: /* Unexpected result; notify customer. */ } |
Destroying the Request
Finally, destroy the used request and reply:
ics_destroy(icsorder); ics_destroy(res); |
When you request multiple services in one request, CyberSource processes the services in a specific order. When a service fails, CyberSource does not process the subsequent services in the request.
For example, in the case of a sale (a credit card authorization and a capture requested together), if the authorization service fails, CyberSource does not process the capture service. The reply you receive only includes reply fields for the authorization.
Many CyberSource services include “ignore” fields that tell CyberSource to ignore the result from the first service when deciding whether to run the subsequent services. In the case of the sale, even though the issuing bank gives you an authorization code, CyberSource might decline the authorization based on the AVS or card verification results. Depending on your business needs, you might choose to capture these types of declined authorizations anyway. You can set the ignore_avs field to "yes" in your combined authorization and capture request:
ics_fadd(msg, "ignore_avs", "yes"); |
This tells CyberSource to continue processing the capture even if the AVS result causes CyberSource to decline the authorization. In this case you would then get reply fields for both the authorization and the capture in your reply.
|
You are charged only for the services that CyberSource performs. |
Timeouts and Automatic Retries
Retries and timeouts control how long the client waits for a reply from the CyberSource server after it sends a request, and whether and when the client automatically resends the request (called a retry). If you find that you are not receiving replies to some of your requests, you can troubleshoot the problem by adjusting how your code handles retries and timeouts.
|
When the client retries, the retry request has the same request ID as the original request. |
Three parameters allow you to control how retry requests and timeouts work:
nretry_enabled — indicates whether you want to send a retry request if you do not initially get a reply. Retry request is disabled by default.
nretry_start — controls how long (in seconds) you want to wait for the initial request to be sent and replied to by CyberSource. A retry request is sent if a reply is not received by the time this expires. The default value is 30.
ntimeout — controls the total amount of time (in seconds) you want to wait for a response before a timeout error is returned (whether retry was attempted or not). The default value is 110.
|
Retry is not attempted if the difference between the timeout and retry_start values is less than 3 seconds. |
How a Transaction without Retry Works
When retry is disabled, the SDK proceeds as follows:
1Encrypts and sends the initial request. The timeout count starts at 0 seconds.
2Receives a response from the CyberSource server in the allotted by the timeout parameter.
If the response does not come back from the CyberSource server in the allotted time, a timeout error is returned.
How a Transaction with Retry Works
When retry is enabled, the SDK proceeds as follows:
1Encrypts and sends the initial request. The timeout and the retry_start counts start at 0 seconds.
2Waits until retry_start has expired or returns the response if one was received, whichever comes first.
3If retry_start has expired and no response has been received, the client encrypts and sends the request again, using the same request ID as the initial request. The timeout clock continues counting. The request and the response automatically include an additional field to indicate that this request is a retry.
4The client returns a response if one is received, or waits until the full timeout has expired. (The timeout clock started counting at the time that the initial request was sent.)
5If no response was received before the timeout expired, a timeout error is returned.
For example, if retry_start is set at 30 seconds, and no response has been received in that 30 seconds, then the client sends a retry request.
The client then waits for the duration of the remaining timeout time (timeout minus retry_start). For example, if timeout is set at 110 seconds, the client then waits for a length of time equal to 110 seconds minus 30 seconds. If no response is received in that 80-second interval, then a timeout error is returned.
Evaluating the Retry Reply Fields
You evaluate the success of the retry request using the ics_retry field. The field returns one of the following values:
n1 — The retry request was successful using the original data; no reprocessing was necessary.
The CyberSource server has a record of the response in its database. CyberSource does not reprocess the request and sends the original response to you.
n0 — The retry request was successful using data from reprocessing the request.
The CyberSource server has no record of the request. CyberSource reprocesses the request and sends you the response.
n-1 — The retry request was unsuccessful due to a processing error.
The CyberSource server has a record of the request, but the response is not in its database. CyberSource does not reprocess the request. Do not resend the request, because you might duplicate the transaction. Use Transaction Search in the Business Center to search for the transaction.
Setting Retry and Timeout Parameters
You can set the retry field values using the ics_fadd() function.
Enabling Retry
The retry_enabled value controls whether the client sends a retry request when no initial response is received. Retry is disabled by default. Enable retry_enabled with the following code:
ics_fadd(msg, "retry_enabled", "yes"); |
Setting the retry_start Value
The retry_start value controls how long the client waits before sending a retry request. The default value is 30 seconds. The minimum value is 3 seconds, which is acceptable for testing, but not for running live transactions. Start with the default value of 30 seconds and lower the value to 15 seconds if appropriate. The following code example sets the retry_start value to 15 seconds:
ics_fadd(msg, "retry_start", "15"); |
Setting the timeout Value
The timeout value controls the maximum time you want to wait to send the request and receive the response. This time begins when the client sends the initial request. The default value is 110 seconds and must not be less than the minimum value of 6 seconds when retry is enabled. The following code example sets the timeout value to 90 seconds
ics_fadd(msg, "timeout", "90"); |
|
The timeout value must not be set at less than 6 seconds when retry is enabled. The timeout value must also be greater than the retry_start value by at least 3 seconds. You receive an error and the system sends no retry request when the timeout or retry_start values are too low or invalid. |
The client’s automatic retry capability described above in Timeouts and Automatic Retries does not automatically retry in the case of system errors, only timeouts. You must design your transaction management system to include a way to correctly handle CyberSource system errors. System errors occur when you successfully receive a reply and the reply’s ics_rflag=ESYSTEM. For more information about the ics_rflag, see Handling the Reply Flags and Error Messages. Depending on which payment processor is handling the transaction, the ESYSTEM error may indicate a valid CyberSource system error or a processor rejection due to invalid data. In either case, CyberSource recommends that you do not design your system to retry sending a transaction many times when an ESYSTEM error occurs.
Instead, CyberSource recommends that you retry sending the request only two or three times with successively longer periods of time between each retry. For example, after the first system error response, wait 30 seconds and then retry sending the request. If you receive the same error a second time, wait one minute before you send the request again. Depending on the situation, you may decide you can retry sending the request after a longer time period. Determine what is most appropriate for your business situation.
If after several retry attempts you are still receiving a system error, it is possible that the error is actually being caused by a processor rejection and not a CyberSource system error. In that case, CyberSource recommends that you either:
nSearch for the transaction in the Business Center, look at the description of the error on the Transaction Detail page, and call your processor to determine why they are rejecting the transaction.
nContact CyberSource Customer Support to confirm whether your error is truly caused by a CyberSource system issue.
If TSYS Acquiring Solutions is your processor, you may want to follow the first suggestion because there are several common TSYS Acquiring Solutions processor responses that are returned to you as system errors and that only TSYS Acquiring Solutions can address.