Skip to content

Commit 516de8d

Browse files
committed
Merge pull request #14 from djvaldez/requests-from-xml
XML and flat name-value pair request support
2 parents 02972ac + 1770b8f commit 516de8d

7 files changed

Lines changed: 317 additions & 89 deletions

File tree

lib/CybsClient.php

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
<?php
2+
3+
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/conf');
4+
5+
/**
6+
* CybsClient
7+
*
8+
* An implementation of PHP's SOAPClient class for making either name-value pair
9+
* or XML CyberSource requests.
10+
*/
11+
class CybsClient extends SoapClient
12+
{
13+
const CLIENT_LIBRARY_VERSION = "CyberSource PHP 1.0.0";
14+
15+
private $merchantId;
16+
private $transactionKey;
17+
18+
function __construct($options=array(), $properties, $nvp=false)
19+
{
20+
$required = array('merchant_id', 'transaction_key');
21+
22+
if (!$properties) {
23+
throw new Exception('Unable to read cybs.ini.');
24+
}
25+
26+
if ($nvp === true) {
27+
array_push($required, 'nvp_wsdl');
28+
$wsdl = $properties['nvp_wsdl'];
29+
} else {
30+
array_push($required, 'wsdl');
31+
$wsdl = $properties['wsdl'];
32+
}
33+
34+
foreach ($required as $req) {
35+
if (empty($properties[$req])) {
36+
throw new Exception($req . ' not found in cybs.ini.');
37+
}
38+
}
39+
40+
parent::__construct($wsdl, $options);
41+
$this->merchantId = $properties['merchant_id'];
42+
$this->transactionKey = $properties['transaction_key'];
43+
44+
$nameSpace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
45+
46+
$soapUsername = new SoapVar(
47+
$this->merchantId,
48+
XSD_STRING,
49+
NULL,
50+
$nameSpace,
51+
NULL,
52+
$nameSpace
53+
);
54+
55+
$soapPassword = new SoapVar(
56+
$this->transactionKey,
57+
XSD_STRING,
58+
NULL,
59+
$nameSpace,
60+
NULL,
61+
$nameSpace
62+
);
63+
64+
$auth = new stdClass();
65+
$auth->Username = $soapUsername;
66+
$auth->Password = $soapPassword;
67+
68+
$soapAuth = new SoapVar(
69+
$auth,
70+
SOAP_ENC_OBJECT,
71+
NULL, $nameSpace,
72+
'UsernameToken',
73+
$nameSpace
74+
);
75+
76+
$token = new stdClass();
77+
$token->UsernameToken = $soapAuth;
78+
79+
$soapToken = new SoapVar(
80+
$token,
81+
SOAP_ENC_OBJECT,
82+
NULL,
83+
$nameSpace,
84+
'UsernameToken',
85+
$nameSpace
86+
);
87+
88+
$security =new SoapVar(
89+
$soapToken,
90+
SOAP_ENC_OBJECT,
91+
NULL,
92+
$nameSpace,
93+
'Security',
94+
$nameSpace
95+
);
96+
97+
$header = new SoapHeader($nameSpace, 'Security', $security, true);
98+
$this->__setSoapHeaders(array($header));
99+
}
100+
101+
/**
102+
* @return string The client's merchant ID.
103+
*/
104+
public function getMerchantId()
105+
{
106+
return $this->merchantId;
107+
}
108+
109+
/**
110+
* @return string The client's transaction key.
111+
*/
112+
public function getTransactionKey()
113+
{
114+
return $this->transactionKey;
115+
}
116+
}

lib/CybsNameValuePairClient.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
include 'CybsClient.php';
4+
5+
/**
6+
* CybsSoapClient
7+
*
8+
* An implementation of SOAPClient class for making CyberSource name-value pair
9+
* requests.
10+
*/
11+
class CybsNameValuePairClient extends CybsClient
12+
{
13+
14+
function __construct($options=array())
15+
{
16+
$properties = parse_ini_file('cybs.ini');
17+
parent::__construct($options, $properties, true);
18+
}
19+
20+
/**
21+
* Runs a transaction from a name-value pair array
22+
*
23+
* @param string $request An array of name-value pairs
24+
* @return string Response of name-value pairs delimited by a new line
25+
*/
26+
public function runTransaction($request)
27+
{
28+
if (!is_array($request)) {
29+
throw new Exception('Name-value pairs must be in array');
30+
}
31+
$nvpRequest = "";
32+
foreach($request as $k => $v) {
33+
$nvpRequest .= ($k . "=" . $v ."\n");
34+
}
35+
return parent::runTransaction($nvpRequest);
36+
}
37+
}

lib/CybsSoapClient.php

Lines changed: 63 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,123 +1,98 @@
11
<?php
22

3-
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/conf');
3+
include 'CybsClient.php';
44

55
/**
66
* CybsSoapClient
77
*
88
* An implementation of PHP's SOAPClient class for making CyberSource requests.
99
*/
10-
class CybsSoapClient extends SoapClient
10+
class CybsSoapClient extends CybsClient
1111
{
12-
private $merchantId;
13-
private $transactionKey;
1412

1513
function __construct($options=array())
1614
{
1715
$properties = parse_ini_file('cybs.ini');
18-
$required = array('merchant_id', 'transaction_key', 'wsdl');
19-
20-
if (!$properties) {
21-
throw new Exception('Unable to read cybs.ini.');
22-
}
16+
parent::__construct($options, $properties);
17+
}
18+
19+
public function simpleXmlToCybsRequest($simpleXml) {
2320

24-
foreach ($required as $req) {
25-
if (empty($properties[$req])) {
26-
throw new Exception($req . ' not found in cybs.ini.');
21+
$vars = get_object_vars($simpleXml);
22+
$request = new stdClass();
23+
foreach(array_keys($vars) as $key) {
24+
$element = $vars[$key];
25+
if ($key == 'comment') {
26+
continue;
27+
}
28+
if (is_string($element)) {
29+
$request->$key = $element;
30+
} else if (is_array($element)) {
31+
$array = $element;
32+
if ($key == "@attributes") {
33+
// Each attribute in the '@attributes' array should
34+
// instead be a property of the parent element.
35+
foreach($array as $k => $value) {
36+
$request->$k = $value;
37+
}
38+
} else {
39+
$newArray = array();
40+
foreach($array as $k => $value) {
41+
$newArray[$k] = $this->simpleXmlToCybsRequest($value);
42+
}
43+
$request->$key = $newArray;
44+
}
45+
} else if ($element instanceof SimpleXMLElement) {
46+
$request->$key = $this->simpleXmlToCybsRequest($element);
2747
}
2848
}
29-
30-
parent::__construct($properties['wsdl'], $options);
31-
$this->merchantId = $properties['merchant_id'];
32-
$this->transactionKey = $properties['transaction_key'];
33-
34-
$nameSpace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
35-
36-
$soapUsername = new SoapVar(
37-
$this->merchantId,
38-
XSD_STRING,
39-
NULL,
40-
$nameSpace,
41-
NULL,
42-
$nameSpace
43-
);
44-
45-
$soapPassword = new SoapVar(
46-
$this->transactionKey,
47-
XSD_STRING,
48-
NULL,
49-
$nameSpace,
50-
NULL,
51-
$nameSpace
52-
);
53-
54-
$auth = new stdClass();
55-
$auth->Username = $soapUsername;
56-
$auth->Password = $soapPassword;
57-
58-
$soapAuth = new SoapVar(
59-
$auth,
60-
SOAP_ENC_OBJECT,
61-
NULL, $nameSpace,
62-
'UsernameToken',
63-
$nameSpace
64-
);
65-
66-
$token = new stdClass();
67-
$token->UsernameToken = $soapAuth;
68-
69-
$soapToken = new SoapVar(
70-
$token,
71-
SOAP_ENC_OBJECT,
72-
NULL,
73-
$nameSpace,
74-
'UsernameToken',
75-
$nameSpace
76-
);
77-
78-
$security =new SoapVar(
79-
$soapToken,
80-
SOAP_ENC_OBJECT,
81-
NULL,
82-
$nameSpace,
83-
'Security',
84-
$nameSpace
85-
);
86-
87-
$header = new SoapHeader($nameSpace, 'Security', $security, true);
88-
$this->__setSoapHeaders(array($header));
49+
return $request;
8950
}
9051

9152
/**
92-
* @return string The client's merchant ID.
53+
* Returns an object initialized with basic client information.
54+
*
55+
* @param string $merchantReferenceCode Desired reference code for the request
56+
* @return stdClass An object initialized with the basic client info.
9357
*/
94-
public function getMerchantId()
58+
public function createRequest($merchantReferenceCode)
9559
{
96-
return $this->merchantId;
60+
$request = new stdClass();
61+
$request->merchantID = $this->getMerchantId();
62+
$request->merchantReferenceCode = $merchantReferenceCode;
63+
$request->clientLibrary = self::CLIENT_LIBRARY_VERSION;
64+
$request->clientLibraryVersion = phpversion();
65+
$request->clientEnvironment = php_uname();
66+
return $request;
9767
}
9868

9969
/**
100-
* @return string The client's transaction key.
70+
* Runs a transaction from an XML string
71+
*
72+
* @param string $filePath The path to the XML file
73+
* @param string $merchantReferenceCode Desired reference code for the request
74+
* @return stdClass An object representation of the transaction response.
10175
*/
102-
public function getTransactionKey()
76+
public function runTransactionFromXml($xml, $merchantReferenceCode)
10377
{
104-
return $this->transactionKey;
78+
$request = $this->createRequest($merchantReferenceCode);
79+
$simpleXml = simplexml_load_string($xml);
80+
$xmlRequest = $this->simpleXmlToCybsRequest($simpleXml);
81+
$mergedRequest = (object) array_merge((array) $request, (array) $xmlRequest);
82+
return $this->runTransaction($mergedRequest);
10583
}
10684

10785
/**
108-
* Returns an object initialized with basic client information.
86+
* Runs a transaction from an XML file
10987
*
88+
* @param string $filePath The path to the XML file
11089
* @param string $merchantReferenceCode Desired reference code for the request
111-
* @return stdClass An object initialized with the basic client info.
90+
* @return stdClass An object representation of the transaction response.
11291
*/
113-
public function createRequest($merchantReferenceCode)
92+
public function runTransactionFromFile($filePath, $merchantReferenceCode)
11493
{
115-
$request = new stdClass();
116-
$request->merchantID = $this->merchantId;
117-
$request->merchantReferenceCode = $merchantReferenceCode;
118-
$request->clientLibrary = "CyberSource PHP 1.0.0";
119-
$request->clientLibraryVersion = phpversion();
120-
$request->clientEnvironment = php_uname();
121-
return $request;
94+
$request = $this->createRequest($merchantReferenceCode);
95+
$xml = file_get_contents($filePath);
96+
return $this->runTransactionFromXml($xml, $merchantReferenceCode);
12297
}
12398
}

lib/conf/cybs.ini

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ merchant_id = your_merchant_id
22
transaction_key = "your_transaction_key"
33

44
; Modify the URL to point to either a live or test WSDL file with the desired API version.
5-
wsdl = "https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.109.wsdl"
5+
wsdl = "https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.109.wsdl"
6+
7+
; Modify the URL to point to either a live or test WSDL file with the desired API version for the name-value pairs transaction API.
8+
nvp_wsdl = "https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_NVP_1.120.wsdl"

samples/AuthFromNameValuePairs.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
// This sample demonstrates how to run an auth request for two items with a flat
3+
// name-value pair structure
4+
5+
// Using Composer-generated autoload file.
6+
require __DIR__ . '/../vendor/autoload.php';
7+
// Or, uncomment the line below if you're not using Composer autoloader.
8+
// require_once(__DIR__ . '/../lib/CybsSoapClient.php');
9+
10+
11+
// Before using this example, you can use your own reference code for the transaction.
12+
$referenceCode = 'your_merchant_reference_code';
13+
14+
$client = new CybsNameValuePairClient();
15+
16+
$request = array();
17+
$request['ccAuthService_run'] = 'true';
18+
$request['merchantID'] = 'dvaldez';
19+
$request['merchantReferenceCode'] = 'MRC-14344';
20+
$request['billTo_firstName'] = 'Jane';
21+
$request['billTo_lastName'] = 'Smith';
22+
$request['billTo_street1'] = '1295 Charleston Road';
23+
$request['billTo_city'] = 'Mountain View';
24+
$request['billTo_state'] = 'CA';
25+
$request['billTo_postalCode'] = '94043';
26+
$request['billTo_country'] = 'US';
27+
$request['billTo_email'] = 'jsmith@example.com';
28+
$request['card_accountNumber'] = '4111111111111111';
29+
$request['card_expirationMonth'] = '12';
30+
$request['card_expirationYear'] = '2019';
31+
$request['purchaseTotals_currency'] = 'USD';
32+
$request['item_0_unitPrice'] = '12.34';
33+
$request['item_1_unitPrice'] = '56.78';
34+
$reply = $client->runTransaction($request);
35+
36+
// This section will show all the reply fields.
37+
print("\nRESPONSE:\n" . $reply);

0 commit comments

Comments
 (0)