Link to home
Start Free TrialLog in
Avatar of prowebinteractiveinc
prowebinteractiveinc

asked on

web application to accept and return XML

I need build a web application in PHP to receive and reply in XML

Basically, I need to build a payment gateway

website accepting credit cards or .NET App => GATEWAY (ME) => Financial institution => GATEWAY (ME) => website accepting credit cards or .NET App

Website or .NET app processing credit card payments sends XML to Gateway
Gateway Receives XML
Financial inst. receives XML and then replies back in XML to Gateway
Gateway sends same XML response string from financial inst. to web .NET app
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

As a practical matter, the financial institution will dictate the format and content of the communications, so you will rely on their documentation to prepare your XML string.  You will also need to learn about PCI Compliance.
http://en.wikipedia.org/wiki/Payment_Card_Industry_Data_Security_Standard

The general design of a web service looks something like this.  In the example, there is a GET method request (you will need to use POST) and the query is sent in clear text, not XML, but the principles are still the same.

<?php // RAY_REST_get_last_name.php
error_reporting(E_ALL);


// DEMONSTRATE HOW A RESTFUL WEB SERVICE WORKS
// INPUT FIRST NAME, OUTPUT FAMILY NAME
// CALLING EXAMPLE:
// file_get_contents('http://laprbass.com/RAY_REST_get_last_name.php?key=ABC&resp=XML&name=Ray');


// OUR DATA MODEL CONTAINS ALL THE ANSWERS - THIS COULD BE A DATA BASE - AS SIMPLE OR COMPLEX AS NEEDED
$dataModel
= array
( 'Brian'   => 'Portlock'
, 'Ray'     => 'Paseur'
, 'Richard' => 'Quadling'
, 'Dave'    => 'Baldwin'
)
;

// RESPONSE CAN BE PLAIN TEXT OR XML FORMAT
$alpha = NULL;
$omega = NULL;
if ( (isset($_GET["resp"])) && ($_GET["resp"] == 'XML') )
{
    // PREPARE THE XML WRAPPER
    $alpha = '<response>';
    $omega = '</response>';
}


// TEST THE 'API KEY' - THIS COULD BE A DATA BASE VALIDATION LOOKUP - AS SIMPLE OR COMPLEX AS NEEDED
$key = (!empty($_GET["key"])) ? $_GET["key"] : FALSE;
if ($key !== 'ABC')
{
    echo $alpha . 'BOGUS API KEY' . $omega;
    die();
}


// LOOK UP THE FAMILY NAME
$name = (!empty($_GET["name"])) ? $_GET["name"] : 'UNKNOWN';

// IF THE NAME FROM THE URL IS FOUND IN THE DATA MODEL
if (array_key_exists($name, $dataModel))
{
    // RETURNS THE APPROPRIATE FAMILY NAME FROM THE DATA MODEL
    echo $alpha . $dataModel[$name] . $omega;
    die();
}

// RETURNS THE UNKNOWN NAME INDICATOR
else
{
    echo $alpha . 'UNKNOWN' . $omega;
    die();
}

Open in new window

The PHP processing of XML is often done with the SimpleXML extension.  You make an object from the XML and use iterators to access each of the parts.  For an example, see:
http://www.laprbass.com/RAY_xml_example_131.php

<?php // RAY_xml_example_131.php
error_reporting(E_ALL);
echo "<pre>\n";

// SHOW HOW TO ISOLATE THE DATA FIELDS
// value1 is equal to:   $value1[0], $value1[1]
// value2 is equal to:   $value2[0], $value2[1]

// TEST DATA
$xml = <<<EOXML
<files>
<values>
  <value1>VALUE1</value1>
  <value2>VALUE2</value2>
</values>
<values>
  <value1>VALUE1</value1>
  <value2>VALUE2</value2>
</values>
</files>
EOXML;

// MAKE AN OBJECT
$obj = SimpleXML_Load_String($xml);

// ACTIVATE THIS TO VISUALIZE THE OBJECT
// var_dump($obj);

// ITERATE OVER THE OBJECT TO VISUALIZE THE INTERNALS
foreach($obj as $thing)
{
    // ACTIVATE THIS TO SEE EACH THING
    var_dump($thing);
}

// GET THE DATA INTO ARRAYS
$value1 = array();
$value2 = array();

// ITERATE OVER THE OBJECT TO EXTRACT THE VALUES
foreach ($obj as $thing)
{
    if (isset($thing->value1)) $value1[] = (string)$thing->value1;
    if (isset($thing->value2)) $value2[] = (string)$thing->value2;
}

// ACTIVATE THIS TO SEE THE ARRAYS
// var_dump($value1);
// var_dump($value2);

// SHOW THE OUTPUT
echo "value1 is equal to:   $value1[0], $value1[1] \n";
echo "value2 is equal to:   $value2[0], $value2[1] \n";

Open in new window

HTH, ~Ray
Avatar of prowebinteractiveinc
prowebinteractiveinc

ASKER

Hi Ray

as for PCI compliance, Im fine, Im aware.

I already have everything setup on an actual website to send payments, in XML
The problem is Im creating a .NET application. and sending right to the bank is working right now except the bank accepts XML string Posts from only one IP on the merchant account for security purposes - so what I need to do, is from the .NET application send it to my website as a gateway that already sends requests to the bank, and then take the same request from the bank and send it back to the .NET application. this way I am taking out the IP filter issue I have with the bank and make my own filters on my website / gateway.

this is an example of the XML im sending directly to the financial institution from my .NET app and I get a response back from the server saying that im sending requests from invalid IP: so I know everythig is work to this point. maybe with the xml Im showing you below you will have an idea of what I need to do in PHP to read the info, parse put in db and then send to bank. retrieve from bank, save results in db then send back to .NET app

xxxRequestMode=X&xxxRequestData=<?xml version='1.0' encoding='UTF-8'?><TranxRequest><MerchantNumber>11111111</MerchantNumber><Products>299.95::1::100::Test Product 1::{TEST}</Products><xxxName>Jason Trudeau</xxxName><xxxCompany>ABC Corp</xxxCompany><xxxAddress>4 Corporate Sq</xxxAddress><xxxCity>TestVille</xxxCity><xxxState>NY</xxxState><xxxZipCode>123456</xxxZipCode><xxxCountry>US</xxxCountry><xxxPhone>800-555-1234</xxxPhone><xxxEmail>merchant@website.com</xxxEmail><xxxCard_Number>4505530000000000</xxxCard_Number><xxxCCMonth>09</xxxCCMonth><xxxCCYear>2009</xxxCCYear><CVV2>123</CVV2><xxxTransType>00</xxxTransType><xxxAuthentication>Y</xxxAuthentication></TranxRequest>

Open in new window

How you send it to the bank would be part of the question.  Is it a POST-method request?

Here is a code sample showing how PHP can process the XML and extract elements for storage in a data base.
http://www.laprbass.com/RAY_temp_prowebinteractive.php

<?php // RAY_temp_prowebinteractive.php
error_reporting(E_ALL);
echo "<pre>";

$xml = <<<ENDXML
<?xml version='1.0' encoding='UTF-8'?>
<TranxRequest>
<MerchantNumber>11111111</MerchantNumber>
<Products>299.95::1::100::Test Product 1::{TEST}</Products>
<xxxName>Jason Trudeau</xxxName>
<xxxCompany>ABC Corp</xxxCompany>
<xxxAddress>4 Corporate Sq</xxxAddress>
<xxxCity>TestVille</xxxCity>
<xxxState>NY</xxxState>
<xxxZipCode>123456</xxxZipCode>
<xxxCountry>US</xxxCountry>
<xxxPhone>800-555-1234</xxxPhone>
<xxxEmail>merchant@website.com</xxxEmail>
<xxxCard_Number>4505530000000000</xxxCard_Number>
<xxxCCMonth>09</xxxCCMonth>
<xxxCCYear>2009</xxxCCYear>
<CVV2>123</CVV2>
<xxxTransType>00</xxxTransType>
<xxxAuthentication>Y</xxxAuthentication>
</TranxRequest>
ENDXML;

// MAKE AN OBJECT
$obj = SimpleXML_Load_String($xml);

// VISUALIZE THE OBJECT
var_dump($obj);

// USE OOP NOTATION TO GET DATA FROM THE OBJECT
$n = (string)$obj->xxxName;
$c = (string)$obj->xxxCompany;
$e = (string)$obj->xxxEmail;
echo PHP_EOL . "<b>$n</b> WORKS AT <i>$c</i> AND USES EMAIL <u>$e</u>";

Open in new window

HTH, ~Ray
Yes its a POST

and I built the.NET to POST as well, but like I said, I want it to POST to me instead, then I (website) will post to bank

Below is my PHP file POSTing to the bank
	function sendrequest($transId, $transTypeId, $myCardNumber, $myExpMth, $myExpYr, $myCVV, $paymentAmount, $customerId)
	{
		$method = "POST";
		$url = transactionPostUrl($transTypeId);
		$vars = "xxxRequestMode=X&xxxRequestData=" . urlencode(buildRequest($transId, $transTypeId, $myCardNumber, $myExpMth, $myExpYr, $myCVV, $paymentAmount, $customerId)); //sendrequest($transactionId, 1, $varTransTypeId, $cardNumber, $expMonth, $expYear, $cvv);
		
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: text/xml"));
		curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		if ($method == 'POST') {
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
		}
		$data = curl_exec($ch);
		curl_close($ch);	


		$fileName = $transId ."_" . date('Ymd_His') . ".xml";
		$filePath = $_SERVER['DOCUMENT_ROOT'] . "/trans_response_xml_format/" . $fileName;
//		echo $filePath;

		if(!$fp = fopen($filePath, "w"))
		{
			echo "file not created";
		}
		else
		{
			fwrite($fp, $data);
			fclose($fp);
			chmod ($filePath, 0755);
		}


		$xml = simplexml_load_string($data);

		@mysql_query("UPDATE is_transactions SET trans_Type='" . $xml->xxxTransType . "',
												  ip_address='" . $xml->xxxMerchantIPAddress . "',
												  ip_host='" . gethostbyaddr($xml->xxxMerchantIPAddress) . "',
												  cardHolderName='" . $xml->xxxName . "',
												  trans_amount='" . $xml->TotalAmount . "',
												  card_type='" . $xml->CardType . "',
												  receipt_number='" . $xml->ReceiptNumber . "',
												  approval_code='" . $xml->Page . "',
												  verbiage='" . $xml->Verbiage . "',
												  token='" . $xml->Token . "',
												  xmlFile='" . $fileName . "'
												  WHERE transId=" . $xml->YourVariableName);							
							
		return $xml->YourVariableName;							

	}

Open in new window

so basically I want to be accepting and breaking down XML the exact same way the bank is in PHP
ASKER CERTIFIED SOLUTION
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
no issue, I have changed the POST to my sever, Im parsing the information, works great... now! how do I send info back to .NET application ?
how do I send info back to .NET application ?
You would make a GET or POST request to the URL of a script on the .NET server.
Ok im know the bank is posting back to me but how do they know the URL to send back to ?
how do they know the URL to send back to ?
Uhh, you would probably tell them, right?
Avatar of hielo
Ok im know the bank is posting back to me but how do they know the URL to send back to ?
If I am understanding you correctly, what you meant was "...how do they know where to send the response to".
From what you described, since your .Net app goes to your website, then the bank is only seeing the website script.  So it will only respond to requests originating from your website (due to the IP restriction you described).  So if you deploy you app to 10 machines, and all of them send request simultaneously, your website sees 10 different clients, but since your website routes the requests to the bank, the bank sees one client only (making 10 requests).

how do I send info back to .NET application ?
@Ray: I believe his "confusion" arises from the fact that when he sends the post request using his sendrequest() function, the function returns just a "node" from the xml result that the bank sends him -- return $xml->YourVariableName;

Most likely his application needs the entire XML.

@prowebinteractiveinc: If in fact I am right about you needing/wanting the entire xml response, then I would suggest that in sendrequest() function you change

...
$data = curl_exec($ch);
curl_close($ch);
...

Open in new window


to:

...
$data = curl_exec($ch);
$_POST['bankData']=$data;
curl_close($ch);
...

Open in new window



That way the full xml response from the bank is available outside your function.  Now,  let's say that your .Net app is POSTing to http://site.com/payment.php.  In payment.php you are probably doing something similar to:
<?php
//do some pre-processing
//iterate through $_POST and extract values to pre-fill variables.  
//Perhaps emit a db transaction so you get a transaction id
...

//send the request:
echo sendrequest($transId, $transTypeId, $myCardNumber, $myExpMth, $myExpYr, $myCVV, $paymentAmount, $customerId);

?>

Open in new window


After the suggestion I made earlier, you would now need:

...
//send the request:
sendrequest($transId, $transTypeId, $myCardNumber, $myExpMth, $myExpYr, $myCVV, $paymentAmount, $customerId);

echo $_POST['bankData'];
exit;

?>

Open in new window