Step 1) I downloaded a fresh copy of PHP SDK from here: http://developer.authorize.net/downloads/
Step 2) I add it to my project and require_once() it whenever it's needed
Step 3) I define the following consts:
define('AUTHORIZENET_SANDBOX', TRUE); // SDK NOTE: SET TO FALSE TO TEST AGAINST PRODUCTION
define('TEST_REQUEST', TRUE); // SDK NOTE: YOU MAY WANT TO SET TO TRUE IF TESTING AGAINST PRODUCTION
define('AUTHORIZENET_API_LOGIN_ID', '123456myLoginID');
define('AUTHORIZENET_TRANSACTION_KEY', '123456myTransactionKey');
Step 4) I go into the doc/CIM.markdown file to get some example code to start with. The simplified set of code I took from the aforementioned file looks like this:
// Create customer profile
$customerProfile = new AuthorizeNetCustomer();
$customerProfile->description = "Description of customer";
$customerProfile->merchantCustomerId = 123;
$customerProfile->email = "user@domain.com";
// Next, create an AuthorizeNetCIM object:
$request = new AuthorizeNetCIM();
// Finally, call the createCustomerProfile method and pass in your
// customer object:
$response = $request->createCustomerProfile($customerProfile);
Step 5) I execute the code above and the Authorize.net PHP SDK chokes with the following exception/error message:
SimpleXMLElement::__construct() [<a href='simplexmlelement.--construct'>simplexmlelement.--construct</a>]: Entity: line 1: parser warning : xmlns: URI AnetApi/xml/v1/schema/AnetApiSchema.xsd is not absolute
*Note: Error originates on line 364 in the following SDK file: /lib/AuthorizeNetCIM.php
Step 6) I run this google search: http://www.google.com/search?hl=en&source=hp&biw=1920&bih=935&q=xmlns%3A+URI+AnetApi%2Fxml%2Fv1%2Fsc...
Step 7) I explore the top few results. The top result: http://community.developer.authorize.net/t5/Integration-and-Testing/ARB-with-SimpleXML-PHP-Issue/td-... says that the fix is to introduce a hack into Authorize.net's PHP SDK by manually ripping out the xmlns attribute. So, I do exactly that in the following SDK file:
/lib/AuthorizeNetCIM.php on line 364.
Authorize.net PHP SDK /lib/AuthorizeNetCIM.php BEFORE tweaking it:
Line 363: $string = '<?xml version="1.0" encoding="utf-8"?><'.$request_type.' xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"></'.$request_type.'>';
Line 364: $this->_xml = @new SimpleXMLElement($string);
Line 365: $merchant = $this->_xml->addChild('merchantAuthentication');
Line 366: $merchant->addChild('name',$this->_api_login);
Line 367: $merchant->addChild('transactionKey',$this->_transaction_key);
Line 368: ($this->_refId ? $this->_xml->addChild('refId',$this->_refId) : "");
Authorize.net PHP SDK /lib/AuthorizeNetCIM.php AFTER tweaking it:
Line 363: $string = '<?xml version="1.0" encoding="utf-8"?><'.$request_type.' xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"></'.$request_type.'>';
Line 364: $string = '<?xml version="1.0" encoding="utf-8"?><'.$request_type.'></'.$request_type.'>'; // I ADDED THIS LINE TO REMOVE THE xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd" ATTRIBUTE
Line 365: $this->_xml = @new SimpleXMLElement($string);
Line 366: $merchant = $this->_xml->addChild('merchantAuthentication');
Line 367: $merchant->addChild('name',$this->_api_login);
Line 368: $merchant->addChild('transactionKey',$this->_transaction_key);
Line 369: ($this->_refId ? $this->_xml->addChild('refId',$this->_refId) : "");
Step 8) I execute the code again (with the hack introduced into the SDK as recommended by this form)
SUCCESS!! The suggested hack has gotten us further into the SDK only to expose this, very similar error:
simplexml_load_string() [<a href='function.simplexml-load-string'>function.simplexml-load-string</a>]: Entity: line 1: parser warning : xmlns: URI AnetApi/xml/v1/schema/AnetApiSchema.xsd is not absolute
*Note: Error originates on line 29 in the following SDK file: /lib/shared/AuthorizeNetXMLResponse.php
Step 9) I do the google search thing again. I get to a number of threads on this forum that all say to use str_replace() to dynamically remove the relative xmlns attribute from the Authorize.net's web API XML response. So, I do just that. Code is as follows:
Authorize.net PHP SDK /lib/shared/AuthorizeNetXMLResponse.php BEFORE tweaking it:
Line 25: public function __construct($response)
Line 26: {
Line 27: $this->response = $response;
Line 28: if ($response) {
Line 29: $this->xml = @simplexml_load_string($response);
Line 30:
Line 31: // Remove namespaces for use with XPath.
Line 32: $this->xpath_xml = @simplexml_load_string(preg_replace('/ xmlns:xsi[^>]+/','',$response));
Line 33: }
Line 34: }
Authorize.net PHP SDK /lib/shared/AuthorizeNetXMLResponse.php AFTER tweaking it:
Line 25: public function __construct($response)
Line 26: {
Line 27: $response = str_replace('xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"', '', $response); I ADDED THIS HACK AS SUGGESTED BY THIS FORUM TO REMOVE THE xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd" ATTRIBUTE FROM THE RESPONSE
Line 28: $this->response = $response;
Line 29: if ($response) {
Line 30: $this->xml = @simplexml_load_string($response);
Line 31:
Line 32: // Remove namespaces for use with XPath.
Line 33: $this->xpath_xml = @simplexml_load_string(preg_replace('/ xmlns:xsi[^>]+/','',$response));
Line 34: }
Line 35: }
Step 10) I execute the code again
SUCCESS!! The PHP SDK is no longer choking on XML namespace issues. HOWEVER, new errors have now cropped up!! In the original code I posted above (that's being used to drive this entire test/overview), you'll notice the last line is exactly:
$response = $request->createCustomerProfile($customerProfile);
The new error is now contained in the API XML response. So, I add the following code to my application:
var_dump($response);
exit;
Step 11) Execute again so we can see what's going on. The following is what's printed out:
object(AuthorizeNetCIM_Response)#38 (3) { ["xml"]=> object(SimpleXMLElement)#39 (1) { ["messages"]=> object(SimpleXMLElement)#37 (2) { ["resultCode"]=> string(5) "Error" ["message"]=> object(SimpleXMLElement)#41 (2) { ["code"]=> string(6) "E00045" ["text"]=> string(55) "The root node does not reference a valid XML namespace." } } } ["response"]=> string(329) "<?xml version="1.0" encoding="utf-8"?><ErrorResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ><messages><resultCode>Error</resultCode><message><code>E00045</code><text>The root node does not reference a valid XML namespace.</text></message></messages></ErrorResponse>" ["xpath_xml"]=> object(SimpleXMLElement)#40 (1) { ["messages"]=> object(SimpleXMLElement)#37 (2) { ["resultCode"]=> string(5) "Error" ["message"]=> object(SimpleXMLElement)#41 (2) { ["code"]=> string(6) "E00045" ["text"]=> string(55) "The root node does not reference a valid XML namespace." } } } }
I am at a loss as to what to do. Once you start googling for E00045 you fall into an abyss of worthless results. One of the top ones is an Authorize.net page telling you that "E00045" means "The root node does not reference a valid XML namespace. ". (same as what code error says). How do I resolve this error? What do I do next? Should I abandon the SDK and just manually write out all my needed XML calls and send direct via curl?? I need some help!!! I've put a lot of time into this and want to use the SDK. Any help would be greatly appreciated.
Last few notes: I did try switching the xmlns attr value to https://api.authorize.net/xml/v1/request.api (absolute as oppossed to SDK default of relative). Absolute URL retrieved from page 18 in the CIM_XML_guide.pdf. This did not fix the error.
To be clear: My objective is to create a CIM customer profile for a business when they sign up for an account on my website.
06-19-2011 06:14 PM
Hey there,
Sorry for the delay, but this one stumped us for a bit. I checked with our developers though and they say that this error is actually a warning that is usually suppressed in the SDK because it's harmless. Authorize.Net uses a relative namespace path which the SDK's XML library complains about. You can just ignore the message--it shouldn't block the SDK from functioning.
Usually the error control operator in PHP (http://php.net/manual/en/language.operators.errorcontrol.php) disables that warning. But if you're using a custom error handler, then that will still be passed along with a flag that tells you the error was supposed to be suppressed. If you're using a custom error handler, then it probably isn't checking to see that the error is listed as suppressed before responding.
So ultimately, you should still be able to the SDK no problem.
Hope that helps.
Thanks,
Michelle
Developer Community Manager
06-29-2011 03:26 PM
This has been frustrating me for some time, as well. What I don't get is why the API hasn't been updated to use an absolute namespace. Heck, I don't really understand why you need the namespace at all for these requests. :-/
I went through all the same internet searches as the original poster to no avail. Simply ignoring these warnings as advised is not an option for large applications / conscientious developers. It clutters the logs where you may need to watch for legitimate errors and in some frameworks displays these confusing warning messages to customers.
That said, I finally found a workaround. It took me hours to figure out, because something was going inscrutably wrong with my attempts to use str_replace() on the XML generated by SimpleXMLElement::asXML to add the xmlns attribute in after generating my XML despite some serious debugging. As it turns out, the solution is quite simple: don't include the xmlns attribute in your construction of the SimpleXMLElement object and use SimpleXMLElement::addAttribute after the fact to add it.
So, instead of this:
$element = new SimpleXMLElement('<createCustomerProfileRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"/>');
Do this:
$element = new SimpleXMLElement('<createCustomerProfileRequest/>');
$element->addAttribute('xmlns', 'AnetApi/xml/v1/schema/AnetApiSchema.xsd');
The PHP examples can easily be updated to use this method as well. To avoid these errors when parsing the response, I simply strip the xmlns attribute out of the response before parsing it with SimpleXML using the following:
$result = str_replace(' xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"', '', $result);
($result in that example is the raw XML as returned by Authorize.Net.)
I'll add that it's not like this is some small PHP library that only a few people would use to manipulate XML. This is the solution in PHP that I'd expect people to use. Getting it right is going to save many developers a lot of time (and their clients a lot of money).
10-27-2011 01:05 AM