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
prowebinteractiveincAsked:
Who is Participating?
 
Ray PaseurCommented:
OK, what is the issue?  Just change the .NET application to post to your URL instead of the bank's URL.  When the URL is activated, run this instruction:

var_dump($_POST);

With that you will be able to see what arrived in the POST request.

Here is a teaching example script that receives a POST and re-POSTs the information.

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


// IF NOTHING IS POSTED YET, PUT UP THE HTML FORM TO RECEIVE THE DATA
if (empty($_POST))
{
    $form = <<<ENDFORM
    <form method="post">
    ENTER TWO THINGS:
    <input name="foo" />
    <input name="bar" />
    <br/><input type="submit" />
    </form>
ENDFORM;

    die($form);
}


// THE EMAIL ADDRESS WE WANT TO SEND TO
$my_email = 'Ray.Paseur@Gmail.com';

// THE SITE WE WANT TO TALK TO - IN THIS CASE, TO MY SITE
$server_url  = "www.your.org";
$server_url  = $_SERVER["HTTP_HOST"];

// THE PAGE INSIDE THE WEB SITE
$request_uri = "/RAY_dump_superglobals.php";

// CONSTRUCT THE SQL STATEMENT
$sql = 'INSERT INTO mytable ( ';
$sql_keys = '';
$sql_vals = '';

// CONSTRUCT THE SQL AND POST STRINGS
$postdata  = '';
foreach ($_POST as $key => $val)
{
    $postdata .= '&' . $key . '=' . urlencode(stripslashes($val));
    $sql_keys .= "`$key`,";
    $sql_vals .= "`$val`,";
}
$postdata = ltrim($postdata, '&');
$sql_keys = rtrim($sql_keys, ',');
$sql_vals = rtrim($sql_vals, ',');
$sql      = $sql . $sql_keys . ' ) VALUES ( ' . $sql_vals . ') ';

// SEND THE EMAIL
mail ($my_email, 'POST STUFF', $sql);

// UPDATE THE DATA BASE HERE
// $res = mysql_query($sql), ETC ETC ETC


// CONSTRUCT THE HEADERS FOR THE RE-POST
$header = '';
$header .= "POST $request_uri HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($postdata) . "\r\n\r\n";

// SHOW WHAT WE ARE GOING TO DO (REMOVE THIS SEGMENT FOR A LIVE SYSTEM)
echo "<pre>\n";
echo "REQUEST DATA FOLLOWS:\n";
var_dump($server_url);
var_dump($request_uri);
var_dump($postdata);
var_dump($header);
echo "</pre>\n";


// OPEN THE SOCKET TO THE PAGE
$fp = fsockopen ($server_url, 80, $errno, $errstr, 30);

// TEST FOR VERIFICATION
if (!$fp)
{
    die("HTTP ERROR $server_url $request_uri fsockopen() FAILED ERRNO=$errno ERRSTR=$errstr");
}

// HTTP OPEN - WRITE HEADER AND REQUEST
fputs ($fp, $header . $postdata);

// HTTP OPEN - READ RESPONSE
$reply = '';
while (!feof($fp))
{
    $reply .= fgets($fp, 1024);
}

// SEE WHAT THE FOREIGN SITE SAID
echo "<pre>\n";
echo htmlentities($reply);
echo "</pre>\n";

// FINIS
echo 'Done!';

Open in new window

I have not tested this script in a long time, but it probably is correct in principle.  There may be ways to use CURL instead of fsockopen().  See if it gives you some ideas!
0
 
Ray PaseurCommented:
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
0
 
prowebinteractiveincAuthor Commented:
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

0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
Ray PaseurCommented:
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
0
 
prowebinteractiveincAuthor Commented:
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
0
 
prowebinteractiveincAuthor Commented:
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 ?
0
 
Ray PaseurCommented:
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.
0
 
prowebinteractiveincAuthor Commented:
Ok im know the bank is posting back to me but how do they know the URL to send back to ?
0
 
Ray PaseurCommented:
how do they know the URL to send back to ?
Uhh, you would probably tell them, right?
0
 
hieloCommented:
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

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.