Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

web application to accept and return XML

Posted on 2012-08-13
10
Medium Priority
?
497 Views
Last Modified: 2012-08-17
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
0
Comment
Question by:prowebinteractiveinc
  • 5
  • 4
10 Comments
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 38291645
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
 

Author Comment

by:prowebinteractiveinc
ID: 38291777
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
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 38291956
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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:prowebinteractiveinc
ID: 38292020
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
 
LVL 111

Accepted Solution

by:
Ray Paseur earned 2000 total points
ID: 38292079
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
 

Author Comment

by:prowebinteractiveinc
ID: 38293967
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
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 38294490
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
 

Author Comment

by:prowebinteractiveinc
ID: 38294545
Ok im know the bank is posting back to me but how do they know the URL to send back to ?
0
 
LVL 111

Expert Comment

by:Ray Paseur
ID: 38296274
how do they know the URL to send back to ?
Uhh, you would probably tell them, right?
0
 
LVL 82

Expert Comment

by:hielo
ID: 38305169
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

Featured Post

[Webinar On Demand] Database Backup and Recovery

Does your company store data on premises, off site, in the cloud, or a combination of these? If you answered “yes”, you need a data backup recovery plan that fits each and every platform. Watch now as as Percona teaches us how to build agile data backup recovery plan.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Since pre-biblical times, humans have sought ways to keep secrets, and share the secrets selectively.  This article explores the ways PHP can be used to hide and encrypt information.
There are times when I have encountered the need to decompress a response from a PHP request. This is how it's done, but you must have control of the request and you can set the Accept-Encoding header.
The viewer will learn how to dynamically set the form action using jQuery.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
Suggested Courses

571 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question