We are considering the use of Microsoft Dynamics GP 10 Web Services and will want to use PHP to create / update customers and sales... So the question is: Is this possible and if so does anyone know of good documentation out there?
I am not finding anything out there with using PHP, another part of this question would be security credentials and if PHP can correctly pass the needed login and fully interact with GP's web service?
Any ideas or known resources?
For what it's worth, I use a set of stored procedures called eConnect to do GP integrations. It may not be the most elegant solution, but it works fairly good. eConnect is also documented pretty well by Microsoft.
If you choose to use this kind of integration, it is wise to get familiar with the Dexterity Application. Learning the Dexterity Application helps a lot with object and table mappings and it should be a free download from Customer Source.
Here is an example of an eConnect stored procedure to create a customer record:
$sql = "declare #p115 int
set #p115=0
declare #p116 varchar(255)
set #p116=''
exec dbo.taUpdateCreateCustomerRcd
#I_vCUSTNMBR = '123456',
#I_vCUSTNAME = 'Company Name',
#O_iErrorState = #p115 OUTPUT,
#oErrString = #p116 OUTPUT
select #p115, #p116";
To execute it just do something like the following (using PHP ADODB in this example):
gp_execute_sp($sql);
function gp_execute_sp($sql, $transactions = true) {
global $DBGP;
if($transactions)
$DBGP->StartTrans();
$rs = $DBGP->Execute($sql);
if(is_object($rs) && !$rs->EOF) {
if($rs->fields['computed'] != 0) {
if($transactions)
$DBGP->FailTrans();
throw new Exception(get_error_desc($rs->fields['computed']));
}
} elseif(!is_object($rs)) {
if($transactions)
$DBGP->FailTrans();
throw new Exception("Database Connection Error.");
} else {
if($transactions)
$DBGP->FailTrans();
throw new Exception("Stored proceedure did not return a result.");
}
if($transactions)
$DBGP->CompleteTrans();
}
function get_error_desc($value) {
global $DBGP;
if(is_numeric($value)) {
$result = "No Error Available";
$sql = "SELECT ErrorDesc FROM DYNAMICS..taErrorCode WHERE ErrorCode=?";
$rs = $DBGP->execute($sql, array($value));
if(!$rs->EOF) {
$result = $rs->fields['ErrorDesc'];
}
} else {
$result = $value;
}
return $result;
}
I have not yet used Dynamics GP but based on my reding of the developer guide there is a legacy endpoint and a native endpoint but both are SOAP services so I see no reason why you couldn't use PHP's SOAP client.
$client = new SoapClient('http://machine_name:<port_number>/Dynamics/GPService');
$result = $client->GetCompanyList(...);
I do not know what goes at ..., but again there is no reason the above shouldn't be possible since SOAP is designed to work with most languages including PHP, it just won't be as simple as it could be.
EDIT: It may be helpful to use a WSDL to PHP class generator. See: generate php code from wsdl
Related
require_once 'C:/wamp/www/FirstWebsite/CommonFunctions.php';
function SelectRowByIncrementFunc(){
$dbhose = DB_Connect();
$SelectRowByIncrementQuery = "SELECT * FROM trialtable2 ORDER BY ID ASC LIMIT 1";
$result = mysqli_query($dbhose, $SelectRowByIncrementQuery);
$SelectedRow = mysqli_fetch_assoc($result);
return $SelectRowByIncrementQuery;
return $SelectedRow; //HERE is the error <-------------------------------
return $result;
}
$row = $SelectedRow;
echo $row;
if ($row['Id'] === max(mysqli_fetch_assoc($Id))){
$row['Id']=$row['Id'] === min(mysqli_fetch_assoc($Id));#TODO check === operator
}
else if($row['Id']=== min(mysqli_fetch_assoc($Id))){
$row['Id']=max(mysqli_fetch_assoc($Id));#TODO check === operator //This logic is important. DONT use = 1!
Ok, I am trying to write a program for the server end of my website using PHP. Using Netbeans as my IDE of choice I have encountered an error while attempting to write a function which will store a single row in an associative array.
The issue arises when I try to return the variable $SelectedRow. It causes an 'Unreachable Statment' warning. This results in the program falling flat on its face.
I can get this code to work without being contained in a function. However, I don't really feel that that is the way to go about solving my issues while I learn to write programs.
Side Notes:
This is the first question I have posted on SO, so constructive criticism and tips are much appreciated. I am happy to post any specifications that would help an answer or anything else of the sort.
I do not believe this is a so-called 'replica' question because I have failed to find another SO question addressing the same issue in PHP as of yet.
If anybody has any suggestions about my code, in general, I'd be stoked to hear, as I have only just started this whole CS thing.
You can only return one time. Everything after the first return is unreachable.
It's not entirely clear to me what you want to return from that function, but you can only return one value.
The return command cancels the rest of the function, as once you use it, it has served its purpose.
The key to this is to put all of your information in to an array and return it at the end of the function, that way you can access all of the information.
So try changing your code to this:
require_once 'C:/wamp/www/FirstWebsite/CommonFunctions.php';
function SelectRowByIncrementFunc(){
$dbhose = DB_Connect();
$SelectRowByIncrementQuery = "SELECT * FROM trialtable2 ORDER BY ID ASC LIMIT 1";
$result = mysqli_query($dbhose, $SelectRowByIncrementQuery);
$SelectedRow = mysqli_fetch_assoc($result);
$returnArray = array();
$returnArray["SelectRowByIncrementQuery"] = $SelectRowByIncrementQuery;
$returnArray["SelectedRow"] = $SelectedRow;
$returnArray["result"] = $result;
return $returnArray;
}
And then you can access the information like so:
$selectedArray = SelectRowByIncrementFunc();
$row = $selectedArray["SelectedRow"]
And so forth...
after searching for a long time got this great article its really very nice
but i am facing a bit problem here in my stuff as u have used direct mysql query in api i have used stored procedure in here and every time i have to compare two XML before and after even for a single short and sweet query so is there any alternative for this process but which is this secure
please chk this out u will get i more clearly
database testing in php using phpunit,simpletest on api haveing stored procedure
or how shall i compare to xml files before and after api function call(the function contains the stored procedure)
means i am able to get the before state with mysql-dump but the after but not getting the instant after xml state
sorry for the English but tried my best
thanks for the help friend
have to write an unit test test for the api function
public function delete($userId)
{
// this function calls a stored procedure
$sql = "CALL Delete_User_Details(:userId)";
try {
$db = parent::getConnection();
$stmt = $db->prepare($sql);
$stmt->bindParam("userId", $userId);
$stmt->execute();
$id = $stmt->fetchObject();
if ($id == null) {
$delete_response->createJSONArray("DATABASE_ERROR",0);
} else {
$delete_response->createJSONArray("SUCCESS",1);
}
} catch (PDOException $e) {
$delete_response->createJSONArray("DATABASE_ERROR",0);
}
return $delete_response->toJSON();
}
i have writen this unit test for it now want to write an dbunit for it
public function testDeleteUser()
{
$decodedResponse = $response->json();
$this->assertEquals($response->getStatusCode(), 200);
$this->assertEquals($decodedResponse['status']['StatusMSG'], 'SUCCESS');
$this->assertEquals($decodedResponse['status']['Code'], '1');
}
help guyss
u can just simply test it before by calling the query like
$sql = "select * from user";
and compare it with BeforeDeleteUser.xml
And the Call Ur stored procedure
$sql = "CALL Delete_User_Details(:userId)";
And for the after case just repeat the before one again
$sql = "select * from user";
and compare it with AfterDeleteUser.xml
see the logic is very simple if u have 5 Users in BeforeDeleteUser.xml and it results true and after the call of CALL Delete_User_Details(:userId) stored procedure , the AfterDeleteUser.xml should contain only 4 user (or maybe idDelete field to 0 that depends on ur implementation)
I've created a web service with the following code:
class WebUser {
public $USERID;
}
class UseridService
{
public $username = "my_user";
public $password = "my_pw";
public $server = "my_remote_server";
public $databasename = "my_database";
public $tablename = "my_table";
function __construct ()
{
$this->con = mssql_connect($this->server, $this->username, $this->password) or die('Connection failed!');
mssql_select_db($this->databasename);
}
public function getUserid ()
{
$sql = "Select top 10 USERID FROM my_table";
$result = mssql_query($sql);
$rows = array();
while ($row = mssql_fetch_assoc($result))
{
$storage = new WebUser();
$storage->USERID = $row['USERID'];
$rows[] = $row;
}
mssql_close($this->con);
return $rows;
}
}
For now in flash builder 4.5, I want to output the top 10 userids into a List component in my canvas. I can assure everyone that the PHP webservice code I wrote works and returns an array of WebUser() objects with just the USERID string inside.
There is a lot of documentation online for MySQL and how they simply "drag and drop" the webservice into a list and it "magically" works. Despite trying to follow their conventions using MSSQL instead, I simply cannot get it working.
I was hoping if anyone can offer a piece of advice on what to do? Even if it's not an answer itself, does anyone know any online documentation that works specifically with Flashbuilder/PHP/MSSQL?
Go to the source! Adobe Documentation on setting this up:
http://www.adobe.com/devnet/flash-builder/articles/flashbuilder-php-part1.html
They walk you through hooking up a service in Flashbuilder, connecting your data objects, and displaying them.
I know what you're asking asks for MSSQL, but the database you use on the back-end doesn't matter. What matters is serializing your object from the server-side to the client-side (i.e. PHP to AS3) which means matching the objects on both ends or finding a way to convert them (i.e. JSON-encoded objects in a REST-based web service can be de-serialized quite smoothly using the as3core library as an example).
<?php
header('Cache-Control: no-cache, must-revalidate');
header('Content-type: application/json');
$mysql = mysql_connect('corte.no-ip.org', 'hostcorte', 'xxxx');
mysql_select_db('fotosida');
if((isset($_POST['GetPersons'])))
{
if(isset($_POST['ID'])) {
$query = sprintf("SELECT * FROM persons WHERE id='%s'",
mysql_real_escape_string($_POST['ID']));
} else {
$query = "SELECT * FROM persons";
}
$res = mysql_query($query);
while ($row = mysql_fetch_assoc($res)) {
for ($i=0; $i < mysql_num_fields($res); $i++) {
$info = mysql_fetch_field($res, $i);
$type = $info->type;
if ($type == 'real')
$row[$info->name] = doubleval($row[$info->name]);
if ($type == 'int')
$row[$info->name] = intval($row[$info->name]);
}
$rows[] = $row;
}
echo json_encode($rows);
}
mysql_close($mysql);
?>
This works ok for generating a json object based on a database query. Im not very familiar with PHP, so i would like some feedback from you before i proceed with this. Is this a good way of calling the database using ajax? Other alternatives? Frameworks maybe?Are there any security problems when passing database queries like UPDATE, INSERT, SELECT etc using an ajax HTTPPOST? Thanks
To simplify CRUD operations definitely give REST a read.
As mentioned, stop using the # (AKA "shut-up") operator in favor of more robust validation:
if(isset($_GET['key'])){
$value = $_GET['key'];
}
Or some such equivalent.
Using JavaScript/AJAX, aggregate and send your request data, such as IDs and other parameters, from the form fields into a JSON object. Not the built query. The only time the client should be allowed to manipulate directly executed SQL is if you're creating an web based SQL client. Architect your URLs meaninfully (RESTful URLs) so that your HTTP request can be formed as:
GET users/?id=123
DELETE photos/?id=456
Or alternatively:
GET users/?id=123
GET photos/?method=delete&id=456
Server-side, you're going to receive these requests and based on parameters from the session, the request, etc., you can proceed by firing parametrized queries:
switch($method){
case 'get':
$sql = 'SELECT * FROM `my_table` WHERE `id` = :id';
break;
case 'delete':
$sql = 'DELETE FROM `my_table` WHERE `id` = :id';
break;
default:
// unsupported
}
// interpolate data from $_GET['id'] and fire using your preferred
// database API, I suggest the PDO wrapper.
See PDO
Generate output as necessary, and output. Capture on client-side and display.
Always validate and filter user input. Never send and execute raw SQL queries, or concatenate raw user input into SQL queries.
With regard to your question, here's a possible snippet:
(Note -- I haven't tested it, nor rigorously reviewed it, but it should still serve as a guide -- there is a lot of room for improvement, such as refactoring much of this logic into reusable parts; functions, classes, includes, etc.)
header('Cache-Control: no-cache, must-revalidate');
header('Content-type: application/json');
$error = array();
// get action parameter, or use default
if(empty($_POST['action']))
{
$action = 'default_action';
}
else
{
$action = $_POST['action'];
}
// try to connect, on failure push to error
try
{
$pdo = new PDO('mysql:dbname=fotosida;host=corte.no-ip.org', 'hostcorte', 'xxxx');
}
catch(Exception $exception)
{
$error[] = 'Error: Could not connect to database.';
}
// if no errors, then check action against supported
if(empty($error))
{
switch($action)
{
// get_persons action
case 'get_persons':
try
{
if(!isset($_POST['id']))
{
$sql = 'SELECT * FROM `persons`';
$stm = $pdo->prepare($sql);
$stm->execute();
}
else
{
$sql = 'SELECT * FROM `persons` WHERE `id` = :id';
$stm = $pdo->prepare($sql);
$stm->execute(array(
'id' => (int) $_POST['id'],
));
}
$rows = array();
foreach($stm->fetchAll() as $row)
{
$rows[] = $row;
}
}
catch(Exception $exception)
{
$error[] = 'Error: ' . $exception->getMessage();
}
break;
// more actions
case 'some_other_action':
// ...
break;
// unsupported action
default:
$error[] = 'Error: Unsupported action';
break;
}
}
// if errors not empty, dump errors
if(!empty($error))
{
exit(json_encode($error));
}
// otherwise, dump data
if(!empty($rows))
{
exit(json_encode($rows));
}
You can't do that. Sending database queries from the client is a huge security risk! What if he sends DROP TABLE fotosida as query?
You should always validate and sanitize data coming from the client before you do anything with it. Identify your use-cases and provide access to them with a clearly defined interface.
Update: To elaborate a bit about the interface you define. Say you're creating a gallery. Let's assume you have several use-cases:
Get a list of all images
Delete an image from the gallery
Upload an image to the gallery
There are different ways to do this, but the simplest way (for a beginner in PHP programming) is proably to have a PHP script for every case.
So you'll have:
imageList.php?gallery=1 that will return a list of all images in the gallery with ID 1
deleteImage.php?image=46 will delete the image with ID 46
uploadImage.php parameters will be passed via multipart POST and should be a uploaded file and the ID of the gallery where the image should be added to.
All these scripts need to make sure that they are receiving valid parameters. Eg. the ID should be a number, uploaded file needs to be checked for validity etc.
Only expose the needed functionality via your interface. This makes it much more secure and also better understandable for other users.
Like the other answers above, i agree that this is just asking for an injection attack (and probably other types). Some things that you can do to prevent that and enhance security in other ways could be the following:
1 Look for something suspicious with your response handler.
Lack of a query variable in the post, for instance, doesn't make sense, so it should just kill the process.
#$_POST["query"] or die('Restricted access');
2 Use preg_match to sanatize specific fields.
if (!preg_match("/^[a-zA-Z0-9]+$/", $_POST[query])){
die('Restricted access');
}
3 Use more fields, even if they are semi-meaningless and hidden, to add more reasons to kill the process through their absence, or lack of a certain text pattern (optional).
4 You shouldn't send a complete query through the POST at all. Just the elements that are necessary as input from the user. This will let you build the query in PHP and have more control of what actually makes it to the final query. Also the user doesn't need to know your table names
5 Use mysql_real_escape_string on the posted data to turn command characters into literal characters before entering data into a db. This way someone would have a last name of DROP TABLE whatever, instead of actually dropping table whatever.
$firstname = mysql_real_escape_string($_POST[fname]);
$lastname = mysql_real_escape_string($_POST[lname]);
$email = mysql_real_escape_string($_POST[email]);
$sql="INSERT INTO someTable (firstname, lastname, email)
VALUES('$firstname','$lastname','$email')";
6 Last, but not least, be creative, and find more reasons to kill your application, while at the same time giving the same die message on every die statement (once debugging is done). This way if someone is hacking you, you don't give them any feedback that they are getting through some of your obstacles.
There's always room for more security, but this should help a little.
You shouldn't trust your users so much! Always take into account, when working with Javascript, that an user could edit your calls to send what (s)he wants.
Here you are taking the query from the GET parameters and executing it without any kind of protection. How can you trust what $_GET['query'] contains? A way to do this would be to call a php page with some parameters through ajax, validate them using PHP and then execute a query built on the parameters you get, always thinking about what the values of such parameters could be.
I have a JSON API that I need to provide super fast access to my data through.
The JSON API makes a simply query against the database based on the GET parameters provided.
I've already optimized my database, so please don't recommend that as an answer.
I'm using PHP-APC, which helps PHP by saving the bytecode, BUT - for a JSON API that is being called literally dozens of times per second (as indicated by my logs), I need to reduce the massive RAM consumption PHP is consuming ... as well as rewrite my JSON API in a language that execute much faster than PHP.
My code is below. As you can see, is fairly straight forward.
<?php
define(ALLOWED_HTTP_REFERER, 'example.com');
if ( stristr($_SERVER['HTTP_REFERER'], ALLOWED_HTTP_REFERER) ) {
try {
$conn_str = DB . ':host=' . DB_HOST . ';dbname=' . DB_NAME;
$dbh = new PDO($conn_str, DB_USERNAME, DB_PASSWORD);
$params = array();
$sql = 'SELECT homes.home_id,
address,
city,
state,
zip
FROM homes
WHERE homes.display_status = true
AND homes.geolat BETWEEN :geolatLowBound AND :geolatHighBound
AND homes.geolng BETWEEN :geolngLowBound AND :geolngHighBound';
$params[':geolatLowBound'] = $_GET['geolatLowBound'];
$params[':geolatHighBound'] = $_GET['geolatHighBound'];
$params[':geolngLowBound'] =$_GET['geolngLowBound'];
$params[':geolngHighBound'] = $_GET['geolngHighBound'];
if ( isset($_GET['min_price']) && isset($_GET['max_price']) ) {
$sql = $sql . ' AND homes.price BETWEEN :min_price AND :max_price ';
$params[':min_price'] = $_GET['min_price'];
$params[':max_price'] = $_GET['max_price'];
}
if ( isset($_GET['min_beds']) && isset($_GET['max_beds']) ) {
$sql = $sql . ' AND homes.num_of_beds BETWEEN :min_beds AND :max_beds ';
$params['min_beds'] = $_GET['min_beds'];
$params['max_beds'] = $_GET['max_beds'];
}
if ( isset($_GET['min_sqft']) && isset($_GET['max_sqft']) ) {
$sql = $sql . ' AND homes.sqft BETWEEN :min_sqft AND :max_sqft ';
$params['min_sqft'] = $_GET['min_sqft'];
$params['max_sqft'] = $_GET['max_sqft'];
}
$stmt = $dbh->prepare($sql);
$stmt->execute($params);
$result_set = $stmt->fetchAll(PDO::FETCH_ASSOC);
/* output a JSON representation of the home listing data retrieved */
ob_start("ob_gzhandler"); // compress the output
header('Content-type: text/javascript');
print "{'homes' : ";
array_walk_recursive($result_set, "cleanOutputFromXSS");
print json_encode( $result_set );
print '}';
$dbh = null;
} catch (PDOException $e) {
die('Unable to retreive home listing information');
}
}
function cleanOutputFromXSS(&$value) {
$value = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
?>
How would I begin converting this PHP code over to C, since C is both better on memory management (since you do it yourself) and much, much faster to execute?
UPDATE:
Would Facebooks HipHop do all of this automatically for me?
There are better solutions than rewriting this in c. Memcached, adding more memory, tuning php all come to mind.
You need to profile your app to see how much memory is from the php interpreter, and how much is from compressing the output, and pulling the whole sql result set into memory.
Remember that little site called facebook? They use php and get way more traffic than your API. Keep that in mind.
Also think about the maintenance and stability hit you will take compiling this. Any change will now take orders of magnitude longer, and you have to take down the server to deploy. Maybe not an issue, but something to ponder.
I'd bet there are better ways to optimize than what you are thinking. Profiling is the key.
You can write your own Apache module.
Here is a tutorial:
http://threebit.net/tutorials/apache2_modules/tut1/tutorial1.html