I'm using AuthnetXML class from http://www.johnconde.net/blog/tutorial-integrate-authorize-net-xml-api-universal-php-class/ -- generally works great, but I have noticed a problem with creation of associative array which class then converts to XML. Usage examples show associative array creation like:
$xml->createTransactionRequest(array(
'refId' => rand(1000000, 100000000),
'transactionRequest' => array(
'transactionType' => 'authCaptureTransaction',
'amount' => 5,
'payment' => array(
'creditCard' => array(
'cardNumber' => '4111111111111111',
'expirationDate' => '122016',
'cardCode' => '999',
),
),
'order' => array(
'invoiceNumber' => '1324567890',
'description' => 'this is a test transaction',
),
'lineItems' => array(
'lineItem' => array(
'itemId' => '1',
'name' => 'vase',
'description' => 'Cannes logo',
'quantity' => '18',
'unitPrice' => '45.00',
),
),
'tax' => array(
'amount' => '4.26',
'name' => 'level2 tax name',
'description' => 'level2 tax',
),
'duty' => array(
'amount' => '8.55',
'name' => 'duty name',
'description' => 'duty description',
),
'shipping' => array(
'amount' => '4.26',
'name' => 'level2 tax name',
'description' => 'level2 tax',
),
'poNumber' => '456654',
'customer' => array(
'id' => '18',
'email' => 'someone@blackhole.tv',
),
'billTo' => array(
'firstName' => 'Ellen',
'lastName' => 'Johnson',
'company' => 'Souveniropolis',
'address' => '14 Main Street',
'city' => 'Pecan Springs',
'state' => 'TX',
'zip' => '44628',
'country' => 'USA',
),
'shipTo' => array(
'firstName' => 'China',
'lastName' => 'Bayles',
'company' => 'Thyme for Tea',
'address' => '12 Main Street',
'city' => 'Pecan Springs',
'state' => 'TX',
'zip' => '44628',
'country' => 'USA',
),
'customerIP' => '192.168.1.1',
'transactionSettings' => array(
'setting' => array(
'settingName' => 'allowPartialAuth',
'settingValue' => 'false',
),
'setting' => array(
'settingName' => 'duplicateWindow',
'settingValue' => '0',
),
'setting' => array(
'settingName' => 'emailCustomer',
'settingValue' => 'false',
),
'setting' => array(
'settingName' => 'recurringBilling',
'settingValue' => 'false',
),
'setting' => array(
'settingName' => 'testRequest',
'settingValue' => 'false',
),
),
'userFields' => array(
'userField' => array(
'name' => 'MerchantDefinedFieldName1',
'value' => 'MerchantDefinedFieldValue1',
),
'userField' => array(
'name' => 'favorite_color',
'value' => 'blue',
),
),
),
));
However, that results in XML to be submitted to Authorize.Net like:
<createTransactionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
<merchantAuthentication>
<name>yourloginid</name>
<transactionKey>yourtransactionkey</transactionKey>
</merchantAuthentication>
<refId>92347199</refId>
<transactionRequest>
<transactionType>authCaptureTransaction</transactionType>
<amount>5</amount>
<payment>
<creditCard>
<cardNumber>5424000000000015</cardNumber>
<expirationDate>122016</expirationDate>
<cardCode>999</cardCode>
</creditCard>
</payment>
<order>
<invoiceNumber>1324567890</invoiceNumber>
<description>this is a test transaction</description>
</order>
<lineItems>
<lineItem>
<itemId>1</itemId>
<name>vase</name>
<description>Cannes logo</description>
<quantity>18</quantity>
<unitPrice>45.00</unitPrice>
</lineItem>
</lineItems>
<tax>
<amount>4.26</amount>
<name>level2 tax name</name>
<description>level2 tax</description>
</tax>
<duty>
<amount>8.55</amount>
<name>duty name</name>
<description>duty description</description>
</duty>
<shipping>
<amount>4.26</amount>
<name>level2 tax name</name>
<description>level2 tax</description>
</shipping>
<poNumber>456654</poNumber>
<customer>
<id>18</id>
<email>someone@blackhole.tv</email>
</customer>
<billTo>
<firstName>Ellen</firstName>
<lastName>Johnson</lastName>
<company>Souveniropolis</company>
<address>14 Main Street</address>
<city>Pecan Springs</city>
<state>TX</state>
<zip>44628</zip>
<country>USA</country>
</billTo>
<shipTo>
<firstName>China</firstName>
<lastName>Bayles</lastName>
<company>Thyme for Tea</company>
<address>12 Main Street</address>
<city>Pecan Springs</city>
<state>TX</state>
<zip>44628</zip>
<country>USA</country>
</shipTo>
<customerIP>192.168.1.1</customerIP>
<transactionSettings>
<setting>
<settingName>testRequest</settingName>
<settingValue>false</settingValue>
</setting>
</transactionSettings>
<userFields>
<userField>
<name>favorite_color</name>
<value>blue</value>
</userField>
</userFields>
</transactionRequest>
</createTransactionRequest>
Notice there is only one setting element in XML and only one userField element in XML -- in each case only the last specified in associative array is created in XML. Can anyone advise how to fix?
05-17-2012 10:18 AM
The problem is that you can't have duplicate keys at the same level in and array. If you do the last one entered wins and the rest are overwritten.
So you need a way to represent repeating items from XML in and array. I decide to use the JSON methods to keep it simple. A quick wat to convert Simple XML to and array is to pass it through JSON.
$array = json_decode( json_encode( $simpleXML), true);
That will convert XML like this:
<transactionSettings> <setting> <settingName>allowPartialAuth</settingName> <settingValue>false</settingValue> </setting> <setting> <settingName>duplicateWindow</settingName> <settingValue>0</settingValue> </setting> <setting> <settingName>emailCustomer</settingName> <settingValue>false</settingValue> </setting> <setting> <settingName>recurringBilling</settingName> <settingValue>false</settingValue> </setting> <setting> <settingName>testRequest</settingName> <settingValue>false</settingValue> </setting> </transactionSettings>
To an array like this:
array( 'transactionSettings' => array( 'setting' => array( 0 => array('settingName' =>'allowPartialAuth' , 'settingValue' => 'false',), 1 => array('settingName' => 'duplicateWindow', 'settingValue' => '0', ), 2 => array('settingName' => 'emailCustomer', 'settingValue' => 'false', ), 3 => array('settingName' => 'recurringBilling', 'settingValue' => 'false',), 4 => array( 'settingName' => 'testRequest', false, ), ) );
So you need to modify AuthNetXML.class to recognize this format. Just replace your setParameters() method with:
private function setParameters($xml, $array) { if (is_array($array)) { $first = true; foreach ($array as $key => $value) { if (is_array($value)) { if( is_numeric($key) ) { if($first){ $xmlx = $xml; $first = false; } else { $parent = $xml->xpath('parent::*'); $xmlx = $parent[0]->addChild($xml->getName()); } } else { $xmlx = $xml->addChild($key); } $this->setParameters($xmlx, $value); } else { $xml->$key = $value; } } } }
08-06-2012 11:55 AM
A little more then a week ago I made a modification to the core code which addresses this issue. You can now addd as kany line items as you wasnt and they won't get lost. You can get the new code and working sample code from the AuthnetXML github repository.
09-03-2012 09:58 PM