public function actionStripeHook() {
$this->layout = '//layouts/empty';
try {
Stripe::setApiKey(Yii::app() - > params['secret_key']);
$postdata = file_get_contents("php://input");
$event = json_decode($postdata);
$input = #file_get_contents("php://input");
var_dump($input);
$event_json = json_decode($input);
}
}
In Stripe Webhook set this Url,But in this response i got always empty whats wrong in my code.
If you read the note on this page:
http://php.net/manual/en/wrappers.php.php
You will see that in many versions of PHP php://input can only be read once, and will be empty the second time it is read. If you look closely at your code you will notice that you are reading php://input twice. Make sure and only read it once. That is probably your problem.
I'm using Zurmo and trying to create a new account using REST API. I followed this documentation precisely: http://zurmo.org/wiki/rest-api-specification-accounts to pass the required parameters as json array.
This is my php code:
public function actionCreateOrUpdate()
{
$params=$_POST;
$modelClassName=$this->getModelName();
foreach ($params as $param)
{
if (!isset($param))
{
$message = Zurmo::t('ZurmoModule', 'Please provide data.');
throw new ApiException($message);
}
$r=$this->GetParam($param);
$res= array('status' => 'SUCCESS', 'data' => array($r));
print_r(json_encode($res,true));
}
}
function GetParam ($param){
$modelClassName=$this->getModelName();
if (isset($param['mobile_id'] ) && !$param['mobile_id']=='' &&!$param['mobile_id']==null)
{ $id=$param['mobile_id'];
$params=array();
foreach ($param as $k => $v) {
if(!($k=='mobile_id')) {
$params[$k] = $v;}
}
if ($params=null){$message = Zurmo::t('ZurmoModule', 'Please provide data.');
throw new ApiException($message);}
$tableName = $modelClassName::getTableName();
$beans = ZurmoRedBean::find($tableName, "mobile_id = '$id'");
if (count($beans) > 0)
{
$result = $this->processUpdate($id, $params);
}else{
$result = $this->processCreate($params,$id);
}
}
return $result;
}
The problem is that the $_POST method is returning an empty array. While debugging I tried to use print_r($_POST) and it also returned an empty array. I also tried to pass parameters as plain text and got the same result. I tried $_GET method and it worked. I think the problem is in the $_POST method, maybe I need to change something in my .php files. Any ideas please?
You should first hit the api with static data, to check if it works fine, then try to integrate php within that static data. You will need to read the documentation for which action accepts which format, and which method is supported(GET OR POST). Then try die(); , before sending if the array formed is as per the documentation.
I had similar issue when creating Account using REST API from java client. The problem was I did not send the proper POST request.
Another symptom also was on server side print_r(file_get_contents("php://input"),true); php code returned the correct request data.
Specifically the root cause was:
The Content-Type HTTP header was not "application/x-www-form-urlencoded"
The value field value in POST request was not properly encoded ( I used java.net.URLEncoder.encode method to overcome this)
After fixing these it worked.
I'm using PHP 5.3, and trying to develop a simple web service that gets some parameters with POST method and has a response.
function start(){
getAndValidateParams();
global $response;
echo json_encode($response);
}
function getAndValidateParams(){
// token (mandatory)
if(isset($_POST[PARAM_TOKEN])){
echo 'got your token';
}else{
$response[ERROR_CODE] = ERR2_INVALID_TOKEN;
$response[DESCRIPTION] = CODE2_DESC;
}
}
I'm trying to test that with Postman:
The problems:
1. About the Xdebug HTML I saw the following question, If I turn the var_dump off, will it disable usage of var_dump() inside my php code? (I want to be able use it for debugging but not seeing that in the response).
2.Also I have a problem to pass the parameter 'token', I don't see it in getAndValidateParams().
Any help will be appreciated.
I have used your function to just get insight in this and for tesing you can use also there is Advanced REST client in chrome similar to postMAN that you are using --
use the below lines to debug this --
function start(){
$response = getAndValidateParams();
return json_encode($response);
}
// calling function ends here
// statrt another function that is being called
function getAndValidateParams(){
// token (mandatory)
// print_r($_POST);die; // just for debug purpose
if(isset($_POST[PARAM_TOKEN])){
$response[ERROR_CODE] = 0;
$response[DESCRIPTION] = "Success";
$response[DEtail] = $yourdetailarr; // array of data that you want to retuen
}else{
$response[ERROR_CODE] = ERR2_INVALID_TOKEN;
$response[DESCRIPTION] = CODE2_DESC;
}
return $response;
}
/// ends here
check the response here by calling start function .
In PHP I would like to be able to access PUT and DELETE vars globally similar to how GET and POST vars are accessed globally. I originally considered adding the data to $_PUT and $_DELETE respectively in the global namespace, but then I realized that the data for each request is stored in the message body so there's no way for there to be more than one dataset from a POST, PUT, or DELETE request.
Are there any side-effects of overwriting the $_POST variable?
i.e. str_parse( file_get_contents( 'php://input' ), $_POST );
Am I being silly, or is there a better way to access PUT and DELETE data?
Edit to clarify my thinking:
I am very well aware of the source of the data in $_POST, in fact i mentioned it earlier in my question. If a HTTP POST request is sent to the server the data is stored in php://input. If a HTTP PUT or DELETE request is sent to the server, the data is stored in the exact same place, meaning that $_POST will be empty (as no data was POSTed despite data being available.
A GET request, on the other hand, is passed via the query string. This allows simultaneous passing of $_POST and $_GET variables. It is not possible to simultaneously pass POST and PUT or DELETE variables.
If I overwrite $_POST from php://input on PUT and or DELETE requests, there is no data loss.
The alternative of adding:
global $_PUT;
global $_DELETE;
to the beginning of functions seems silly, as I'll only be able to use one at a time anyway.
My first question, which is the one I really want answered, is about what side-effects or issues exist in overwriting $_POST. I can't possibly be the first person to try something as silly as:
$_POST['foo'] = 'bar';
I'm just concerned that if I do anything similar that it might not be preserved across scopes.
You'll see this called "bad practice" all over the internet, but if you really get in to why it is "bad practice", well, the answers get fuzzy. The most concrete reason is the "hit by a bus" scenario so often bandied about - what if the project gets handed off to a new developer?
Hand wringing aside (you can leave comments, after all), there really isn't a compelling reason not to do it like this, but again, there isn't a compelling reason to do it, either. Why not put the values in a $_SESSION key if you want them global? Or make a global variable? Or make a static class to access the PUT/DELETE values through? With all the other optional approaches, I think that overwriting $_POST, while it won't make your server explode, is the most likely to cause you a headache down the road.
I threw this little static class together, you'll want to test this out before relying on it. Use:
//To check if this is a rest request:
Rest::isRest();
//To get a parameter from PUT
$put_var = Rest::put('keyname', false);
//To get a parameter from DELETE
$dele_var = Rest::delete('keyname', false);
class Rest {
static private $put = false;
static private $delete = false;
static private $is_rest = false;
function __construct() {
self::$is_rest = true;
switch ($_SERVER['REQUEST_METHOD']) {
case 'PUT':
parse_str(self::getVars(), self::$put);
break;
case 'DELETE':
parse_str(self::getVars(), self::$delete);
break;
default:
self::$is_rest = false;
}
}
private static function getVars() {
if (strlen(trim($vars = file_get_contents('php://input'))) === 0)
$vars = false;
return $vars;
}
public static function delete($key=false, $default=false) {
if (self::$is_rest !== true)
return $default;
if (is_array(self::$delete) && array_key_exists($key, self::$delete))
return self::$delete[$key];
return $default;
}
public static function put($key=false, $default=false) {
if (self::$is_rest !== true)
return $default;
if (is_array(self::$put) && array_key_exists($key, self::$put))
return self::$put[$key];
return $default;
}
public static function isRest() {
return self::$is_rest;
}
}
Leave Post and Get as it is. it shouldn't be modified as it's for reading purposes only. Create $_PUT and $_DELETE globals:
// globals
$_DELETE = array ();
$_PUT = array ();
switch ( $_SERVER['REQUEST_METHOD'] ) {
case !strcasecmp($_SERVER['REQUEST_METHOD'],'DELETE'):
parse_str( file_get_contents( 'php://input' ), $_DELETE );
break;
case !strcasecmp($_SERVER['REQUEST_METHOD'],'PUT'):
parse_str( file_get_contents( 'php://input' ), $_PUT );
break;
}
Not tested but you should get the idea. I was in the search for a rest framework myself some weeks ago and decided to go with python. Recess (http://www.recessframework.org/) sounds promising though
You shouldn't modify $_POST directly as this represents values coming from the client. Consider it read-only, and do any modifications in user-defined variable.
As a follow up regarding accessing PUT and DELETE data, currently there is no superglobal built in to PHP to access this data directly. As the data is file data, which can be rather large, the usefulness and efficiency of reading the entire file contents in a typical assignment statement $variable = $_PUT['file']; is questionable. Instead, it should be read in chunks. As such, the usage is consistent with reading from any other file input resource.
More on PUT here:
http://php.net/manual/en/features.file-upload.put-method.php
If you create a "request" object, then regardless whether the request comes over HTTP, command line, or through an HTML5 web socket, you will have a uniform way to access request data. You can then make the request object accessible in the global scope, or pass it as an argument to the required functions or methods.
Ideally you would store data that is independent of the request in static or global variables, e.g. settings that are "static" regardless of the request, and data specific to the request in a local variable or object, that could be used by your business logic. If you had a web socket server, for example, it would be easier to handle multiple request objects in a single PHP process. Here is an example that might help:
$headers = getallheaders();
$query = parse_str($_SERVER['QUERY_STRING']);
$data = file_get_contents('php://input');
if(strpos($headers['Content-Type'],'application/x-www-form-urlencoded') !== false)
{
$data = parse_str($data);
}
elseif(strpos($headers['Content-Type'],'application/json') !== false)
{
$data = json_decode($data);
}
elseif(strpos($headers['Content-Type'],'application/soap+xml') !== false)
{
$data = // parse soap
}
elseif(strpos($headers['Content-Type'],'application/xml') !== false)
{
$data = // parse xml
}
// else ...
$request = new Request($_SERVER['REQUEST_METHOD'],$data,$query);
// example business logic
$method = $request->get_request_method();
$obj = new BlogPost();
if($method == 'GET')
{
$obj->id($request->get_query('id'));
$obj->load();
}
elseif($method == 'PUT')
{
$obj->id($request->get_query('id'));
$obj->title($request->get_data('title'));
$obj->body($request->get_data('body'));
$obj->save();
}
elseif($method == 'POST')
{
$obj->title($request->get_data('title'));
$obj->body($request->get_data('body'));
$obj->save();
}
elseif($method == 'DELETE')
{
$obj->id($request->get_query('id'));
$obj->wipe();
}
Regardless of whether it is a PUT, POST, PATCH, or DELETE, there is only one body of data in the HTTP request, so your application does not need a complex $request object. The request object can make your controller (if you are using MVC) very simple.
Can I get a HttpRequest automatically created from the environment? In other words, right now it seems like you have to...
$request = new HttpRequest;
$request->setCookies($_COOKIE);
$request->setHeaders(apache_request_headers());
$request->setPostFields($_POST);
$request->setQueryData($_GET);
$request->setRawPostData(file_get_contents('php://input'));
$request->setUrl($_SERVER['REQUEST_URI'']);
We also need to set the method -- a ridiculous chore, since $_SERVER['REQUEST_METHOD'] is a string and HttpRequest::setMethod takes an int in the HTTP_METH_* series of contants. So you have to set up your own mapping.
I want to like HttpRequest, but it seems cumbersome to use at the moment. I hope I'm missing something.
Edit:
The idea is to make testing cleaner. $_COOKIE and friends are superglobals. How do you test that?
function receiveRequest() {
$code = 'that touches superglobals like' . $_COOKIE['example'];
$response = new HttpResponse;
$response->setStatus(200);
return $response;
}
function testServer() {
$oldCookie = $_COOKIE;
$oldPost = $_POST;
// etc...
$_COOKIE = array('example' => 'stuff');
$_POST = array();
// etc...
$response = receiveRequest();
$_COOKIE = $oldCookie;
$_POST = $oldPost;
// etc...
assert($response->getStatus() === 200);
}
You need to control the state of not just what you use -- $_COOKIE in this example -- but every superglobal. There are about a dozen. It would be a lot cleaner to wrap up all that stuff in HttpRequest.
function receiveRequest(HttpRequest $request) {
$code = 'is purely a function of arguments like' . $request->getCookie('example');
$response = new HttpResponse;
$response->setStatus(200);
return $response;
}
function testServer() {
$request = new HttpRequest;
$request->setCookie('example' => 'stuff');
$response = receiveRequest($request);
assert($response->getStatus() === 200);
}
Then my actual server.php would use the hypothetical static method that I'm looking for.
$request = HttpRequest::generateRequestFromEnvironment($_COOKIE, $_POST, ...);
unset($_COOKIE, $_POST, ...);
$response = receiveRequest($request);
$response->send();
This seems to me like an odd use case - you want to create an HttpRequest to...yourself? Using exactly the parameters you were passed? Why?
The normal case is for requesting another resource, from another host, for which the kind of "automatic setup" you desire is pretty useless. If you really need this situation, it seems trivial to wrap this in a function that's easily reused?
From what you've posted, I think you're using HttpRequest as a container for all the information about the request which triggered your script.
This isn't what it is for - it is for making HTTP requests to other services from within your script. For example, you might request data from the Flickr API