I'm new to CodeIgniter. I'm using Phil Sturgeon's RestServer and RestClient. I've been trying to make a POST request in my CodeIgniter RestClient controller to update data in my CodeIgniter RestServer, but it never updates data in my database. I think my POST request is not right.
Here is my RestClient POST request in controller:
$result = $this->rest->post('newscontroller/news/format/json',
array('news_id' => $news_id,
'news_title' => $news_title,
'news_category' => $news_category ),
'json');
if(isset($result->status) && $result->status == 'success')
{
$data['message'] ='News has been updated.';
$this->load->view('otherpageview',$data);
}
else
{
$data['message'] ='Something has gone wrong';
$this->load->view('otherpageview',$data);
}
It seems that $result doesn't get any value, because I did echo the $result->status and it has nothing to display. And I've also have this in this controller's constructor :
// Load the rest client spark
$this->load->spark('restclient/2.1.0');
// Load the library
$this->load->library('rest');
// Run some setup
$this->rest->initialize(array('server' => 'http://api.therestserver.com/index.php/'));
And in the RestServer's controller, which is newscontroller, has this method :
function news_post()
{
$news=array(
'news_id' => $this->post('news_id'),
'news_title' => $this->post('news_title'),
'news_category' => $this->post('news_category') );
$result = $this->News_model->UpdateNews($news);
if($result === FALSE)
{
$this->response(array('status' => 'failed'));
}
else
{
$this->response(array('status' => 'success'));
}
}
With the News_model :
public function UpdateNews($news)
{
$this->db->where('news_id',$news->news_id);
$this->db->update('news',$news);
}
I just don't know where I'm doing wrong, because I still don't understand how the POST request and method work. I've read through the tutorial in Nettuts and search about this, but still.. maybe because of my bad English reading-writing. I hope someone can help me out, any help would be appreciated. Thanks a TON! :)
Finally SOLVED this problem!
It was my POST request in the RESTClient controller that is wrong. After doing some searching and lots of trying / changing the codes, this code works for me for POST request in my RESTClient controller :
$news_id = 12; //this is the id of the news that you want to edit
$method = 'post';
$params = array('news_id' => $news_id,
'news_title' => $this->input->post('news_title'),
'news_category' => $this->input->post('news_category') );
$uri = 'newscontroller/news';
$this->rest->format('application/json');
$result = $this->rest->{$method}($uri, $params);
if(isset($result->status) && $result->status == 'success')
{
$data['message'] ='News has been updated.';
$this->load->view('otherpageview',$data);
}
else
{
$data['message'] ='Something has gone wrong';
$this->load->view('otherpageview',$data);
}
With a lot of help from this reference
I post this if anybody needs an example of the right POST request in RESTClient and RESTServer, because I find it hard to look for an example for POST request in RESTClient-Server*** by Phil Sturgeon.
I'm using :
RESTServer (philsturgeon) v.2.6.0
RESTClient (philsturgeon) v.2.1.0
cURL (philsturgeon) v.1.2.1
CodeIgniter v.2.0.3
There was a problem with the way the post was implemented. see issue on github and another issue on github.
You can either patch your code, or get the latest sources.
Basically you find the post function in the RestServer application/libraries/REST_Controller.php and if it does not look like the following then change it to:
public function post($key = NULL, $xss_clean = TRUE)
{
if ($key === NULL)
{
return $this->_post_args;
}
return array_key_exists($key, $this->_post_args) ? $this->_xss_clean($this->_post_args[$key], $xss_clean) : FALSE;
}
Related
I've been searching for this for hours, I hope someone here can help.
I built a subscription based site on Laravel and PayPal subscriptions using the PayPal PHP SDK.
Everything works perfectly except on thing:
I created a webhook for when a user cancels the payment on his end. I'm getting this error:
Got Http response code 400 when accessing https://api.sandbox.paypal.com/v1/notifications/verify-webhook-signature.{"name":"VALIDATION_ERROR","message":"Invalid data provided","debug_id":"7225cebfec35a","information_link":"https://developer.paypal.com/docs/api/webhooks/#errors","details":[{"field":"webhook_id","location":"body","issue":"Required field cannot be blank"}],"links":[]}
Here is my code:
public function webhook()
{
/**
* Receive the entire body that you received from PayPal webhook.
*/
$bodyReceived = file_get_contents('php://input');
// Receive HTTP headers that you received from PayPal webhook.
$headers = getallheaders();
/**
* Uppercase all the headers for consistency
*/
$headers = array_change_key_case($headers, CASE_UPPER);
$signatureVerification = new \PayPal\Api\VerifyWebhookSignature();
$signatureVerification->setWebhookId(env('PAYPAL_WEBHOOK_ID'));
$signatureVerification->setAuthAlgo($headers['PAYPAL-AUTH-ALGO']);
$signatureVerification->setTransmissionId($headers['PAYPAL-TRANSMISSION-ID']);
$signatureVerification->setCertUrl($headers['PAYPAL-CERT-URL']);
$signatureVerification->setTransmissionSig($headers['PAYPAL-TRANSMISSION-SIG']);
$signatureVerification->setTransmissionTime($headers['PAYPAL-TRANSMISSION-TIME']);
$webhookEvent = new \PayPal\Api\WebhookEvent();
$webhookEvent->fromJson($bodyReceived);
$signatureVerification->setWebhookEvent($webhookEvent);
$request = clone $signatureVerification;
try {
$output = $signatureVerification->post($this->apiContext);
} catch(\Exception $ex) {
//This is where it fails
print_r($ex->getMessage());
exit(1);
}
$verificationStatus = $output->getVerificationStatus();
$responseArray = json_decode($request->toJSON(), true);
$event = $responseArray['webhook_event']['event_type'];
if ($verificationStatus == 'SUCCESS')
{
switch($event)
{
case 'BILLING.SUBSCRIPTION.CANCELLED':
case 'BILLING.SUBSCRIPTION.SUSPENDED':
case 'BILLING.SUBSCRIPTION.EXPIRED':
case 'BILLING_AGREEMENTS.AGREEMENT.CANCELLED':
// $user = User::where('payer_id',$responseArray['webhook_event']['resource']['payer']['payer_info']['payer_id'])->first();
$this->updateStatus($responseArray['webhook_event']['resource']['payer']['payer_info']['payer_id'], 0,1);
break;
}
}
echo $verificationStatus;
exit(0);
}
And here is the $this->apiContext:
trait PayPalApiCredentialsTrait {
private $apiContext;
public function setCredentials()
{
$this->apiContext = new \PayPal\Rest\ApiContext(
new \PayPal\Auth\OAuthTokenCredential(
env('PAYPAL_CLIENT_ID'), // ClientID
env('PAYPAL_CLIENT_SECRET') // ClientSecret
)
);
$this->apiContext->setConfig(
array(
'mode' => env("PAYPAL_MODE"),
'log.LogEnabled' => true,
'log.FileName' => '../PayPal.log',
'log.LogLevel' => 'INFO', // PLEASE USE `INFO` LEVEL FOR LOGGING IN LIVE ENVIRONMENTS
)
);
}
}
This is the error I get from the paypal.log:
[01-09-2020 15:54:18] PayPal\Core\PayPalHttpConnection : INFO: POST https://api.sandbox.paypal.com/v1/oauth2/token
[01-09-2020 15:54:18] PayPal\Core\PayPalHttpConnection : INFO: Response Status : 200
[01-09-2020 15:54:18] PayPal\Core\PayPalHttpConnection : INFO: POST https://api.sandbox.paypal.com/v1/notifications/verify-webhook-signature
[01-09-2020 15:54:19] PayPal\Core\PayPalHttpConnection : INFO: Response Status : 400
[01-09-2020 15:54:19] PayPal\Core\PayPalHttpConnection : ERROR: Got Http response code 400 when accessing https://api.sandbox.paypal.com/v1/notifications/verify-webhook-signature. {"name":"VALIDATION_ERROR","message":"Invalid data provided","debug_id":"26b12ee43cddd","information_link":"https://developer.paypal.com/docs/api/webhooks/#errors","details":[{"field":"webhook_id","location":"body","issue":"Required field cannot be blank"}],"links":[]}
I must mention that everything else works fine.
Creating plans, agreements, cancelling the both, showing active plans, and more...
Everything works smoothly.
This is the only thing that I can't seem to fix.
If anyone could figure this out for me, I'd really appreciate it.
Thank you!
The PayPal-PHP-SDK is deprecated and no longer maintained; it should not be used for new integrations. Its implementation of billing plans and subscriptions is old, and not compatible with the current version of the Subscriptions API.
In its place, a direct HTTPS integration (no SDK) should be used for Subscriptions, and for verifying webhooks.
(For the one time payment use case, there is a new v2 Checkout-PHP-SDK https://developer.paypal.com/docs/api/rest-sdks/ )
I understand the process of using nonces when I create my own templates.
But I am developing a ReactJS App which uses ONLY the Wordpress REST API for pulling data, so the user never gets to the index.php, but does Ajax calls to the WP Rest Api.
Now I cannot get the nonce stuff to work.
This is what I have done so far:
I added the following endpoints:
register_rest_route('frontend', '/customer/', array(
'methods' => 'GET',
'callback' => 'get_customer'
));
register_rest_route('frontend', '/customer/', array(
'methods' => 'POST',
'callback' => 'create_user_and_login'
));
These are my functions:
function get_customer()
{
return get_current_user_id();
}
function create_user_and_login(){
// dummy data for testing
$credentials = ['user_login' => 'mail#mymail.de', 'user_password' => 'XXXX', 'remember' => true];
// create a new user/customer via woocommerce
$customerId = wc_create_new_customer($credentials['user_login'], $credentials['user_login'], $credentials['user_password']);
if(is_a($customerId,'WP_Error')) {
return $customerId;
}
// get the user & log in
$user = get_user_by( 'id', $customerId );
if( $user ) {
wp_set_current_user( $customerId);
wp_set_auth_cookie( $customerId );
}
// create new nonce and return it
$my_nonce = wp_create_nonce('wp_rest');
return $my_nonce;
}
If I now run a POST to /customer which triggers create_user_and_login(), the newly created nonce is returned in the ajax response. Then I use the returned nonce to run my next request, a GET to /customer?_wpnonce=MY-NONCE, but I get the error:
{
"code": "rest_cookie_invalid_nonce",
"message": "Cookie nonce is invalid",
"data": {
"status": 403
}
}
I checked the nonce documentation but I could not find a solution for my problem. Could it be that the sessions are out of sync? So that the nonce is created on the wrong session or wp_set_auth_cookie and wp_set_current_user are not called correctly? Or do I have to use the wp_localize_script function? This will get problematic, as I want to have the ReactJS and the Wordpress backend separated.
I got two cookies after the POST, a wordpress cookie and a wordpress_logged_in cookie.
What am I missing?
Check this answer
It seems that when you call $my_nonce = wp_create_nonce('wp_rest'); the nonce is created with the old session cookie, even when you call wp_set_auth_cookie and wp_set_current_user. But in the next request the session is updated, meaning that the nonce is wrong.
As in the answer, add the following hook (functions.php for example) to force an update of the cookie:
function my_update_cookie( $logged_in_cookie ){
$_COOKIE[LOGGED_IN_COOKIE] = $logged_in_cookie;
}
add_action( 'set_logged_in_cookie', 'my_update_cookie' );
I have created a custom module in Drupal 8 that allows a user to authenticate using facebook login. Their access token is checked against one stored in the database and if it matches authenticates the user and if it doesn't then redirects them to a page that allows them to link their Facebook account to a Drupal user.
The button for login is:
<button id="login_fb" onclick="logIt()">Log in with Facebook</button>
The "logit" function with the ajax request to the Drupal controller is:
function logIt()
{
FB.login(function(response) {
if (response.authResponse) {
if(response.authResponse.accessToken)
{
var request = $.ajax({
url: "/user/token",
method: "POST",
data: { access_token : response.authResponse.accessToken},
dataType: "json"
});
request.done(function( msg ) {
window.location.replace(msg['redirect_url']);
});
request.fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});
}
}
}
And the controller code that handles this ajax call is:
public function token() {
$fb_token = $_POST['access_token'];
$query = db_select('user__field_fb_token', 'u');
$query
->fields('u')
->condition('u.field_fb_token_value', $fb_token,'=');
$res = $query->execute();
$res->allowRowCount = TRUE;
$count = $res->rowCount();
//See if anybody has this access token
if($count > 0)
{
$user = $res->fetchAssoc();
//TODO: Refresh access token and update
$login_id = $user['entity_id'];
//Redirect the user to topics
user_login_finalize(user_load($login_id));
$response_arr = array("status" => "authorised","redirect_url" => "/topics");
}
else
{
$_SESSION['access_token'] = $fb_token;
$response_arr = array("status" => "unauthorised","redirect_url" => "/user/auth","token" => $fb_token);
}
$response = new Response();
$response->setContent(json_encode($response_arr));
$response->headers->set('Content-Type', 'application/json');
return $response;
}
The weird thing is that the db_select query always returns 0 and therefore does not authenticate the user account that has this token. However replacing
$fb_token = $_POST['access_token'];
with
$fb_token = '** hard coded access token **';
yields the correct result. I have checked that the post variable being passed in and it is present (that's why I pass it back with the unauthorised response to check that it's not blank).
I think it may have something to do with the async nature of FB.Login method but not sure.
Any help on this matter would be greatly appreciated!
I'm working cakephp web application, I have created a small Ajax function in default ctp file. setup file now I want to send value data to another controller function, in the chrome browser network showing that Ajax posting to desire url but in controller post value didn't show up when I try to echo $_post ['selectedlocation']??
Ajax Default File
var DisplayLocationName = $('#ListingLocation option:selected').val();
$.ajax({
type: "POST",
url: '/listings/home',
data: {selectedlocation:DisplayLocationName },
dataType:"text",
success: function(result) {
}
});
Listing Controller Function
function home()
{
if(!isset($this->params['requested']) || $this->params['requested'] != true)
{
$this->actionId = 'home';
}
$this->viewFile = null;
if($this->params['isAjax'] && isset($_POST['selectedlocation']))
{
echo "erreerreer";
echo $selectloc= $_POST['selectedlocation'];
$this->set('selectloc',$selectloc);
}
}
how do I display Ajax post value in default for testing purposes that, make sure me that Ajax is posting proper values to the controller
You will need to use the logging files to read the post data. This will write the data to the error log and you can view it there.
function home()
{
if(!isset($this->params['requested']) || $this->params['requested'] != true)
{
$this->actionId = 'home';
}
$this->viewFile = null;
if($this->params['isAjax'] && isset($_POST['selectedlocation']))
{
echo "erreerreer";
CakeLog::write('error', $this->request->data('selectedlocation));
echo $selectloc= $_POST['selectedlocation'];
$this->set('selectloc',$selectloc);
}
}
When you want to $_POST a data from an ajax request, you should use:
$form_data = $this->request->data; (cakephp 2.x)
$form_data = $this->params['form'] (cakephp 1.3)
Now you got an array with your $_POSTed data, try to var_dump() it to understand its sctructure if you want.
Does the contacts API still work for anyone? A while back I started getting 403 errors from the API. I run my backup script once a week. Every user that I can't back up, I retry every hour until the next week. Over the span of the week I will end up with a couple of contacts entries, but not a significant amount. This leads me to believe that my code still works since I get some contacts. Anyone have any insight?
Note: I also use the same code/framework to backup Google Drive and Google Calendars for my organization and have not had any issues.
function retrieveAllUserContacts($user)
{
$nextLink = "https://www.google.com/m8/feeds/contacts/$user/full";
$params = array('xoauth_requestor_id' => $user);
while($nextLink != '')
{
$header = array('GData-Version: 3.0');
$result = sendOAuthRequest('GET', $nextLink, $params, $header);
$params = array('xoauth_requestor_id' => $user);
$nextLink = '';
libxml_use_internal_errors(true);
$xmlObj = simplexml_load_string($result);
if($xmlObj === false)
{
echo "adding $user to retry list. Result : " . print_r($result, true) . "\n";
addUserToRetryList($user);
exit(1);
}
foreach($xmlObj->link as $link)
{
if($link['rel'] == 'next')
{
$nextLink = $link['href'];
}
if($nextLink != '')
{
$urlSplit = explode('?', $nextLink);
$nextLink = $urlSplit[0];
$urlParams = explode('&', $urlSplit[1]);
foreach($urlParams as $urlParam)
{
$urlParamSplit = explode('=', $urlParam);
$params[$urlParamSplit[0]] = $urlParamSplit[1];
}
break;
}
}
foreach($xmlObj->entry as $entry)
{//get contacts
...
}
function sendOAuthRequest($httpMethod, $url, $parameters, $header=array())
{
global $CONSUMER_KEY;
global $CONSUMER_SECRET;
$consumer = new OAuthConsumer($CONSUMER_KEY, $CONSUMER_SECRET, NULL);
$request = OAuthRequest::from_consumer_and_token($consumer, NULL, $httpMethod, $url, $parameters);
// Sign the constructed OAuth request using HMAC-SHA1
$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer, NULL);
// Make signed OAuth request to the Contacts API server
if(count($parameters))
{
if(strpos($url, '?') === false)
{
$url .= '?' . implode_assoc('=', '&', $parameters);
}
else
{
$url .= '&' . implode_assoc('=', '&', $parameters);
}
}
$header[] = $request->to_header();
return send_request($request->get_normalized_http_method(), $url, $header);
}
Here is the OAuth Class code : http://pastebin.com/hH4SM9nn I can say that it works for Google Drive and Google Calendar APIs and also that this code worked for over a year without issue.
A number of problems could be causing this. Since your question isn't specific and gives no code sample, here are some of those potential problems:
You have not moved to HTTPS as opposed to HTTP
your GET request specifies a "default" user, where the authority is not always given
You are trying to get too many contacts
There are also issues with authorisation and permissions as of late, one "fix" as such is documented in this StackOverflow answer. It concerns adding not only a google account, but the gmail address associated with that account to the analytics service, via this link.