Ionic Framework using JSONP and the WordPress JSON-API - json

I am currently playing with wpIonic (https://github.com/scottopolis/wpIonic) and the sample uses WP-JSON-API V2 (https://wordpress.org/plugins/rest-api/), but I have heavly bespoked another WP API for my needs (https://wordpress.org/plugins/json-api/).
The problem I am having, the wpIonic sample uses JSONP and I am getting the following error
Uncaught SyntaxError: Unexpected token :
http://preview.meeko.me/api/get_posts/?post_type=product&custom_fields=all&_jsonp=JSONP
Object {data: undefined, status: 404, config: Object, statusText: "error"}
The API i am currently using doesn't output JSONP but the DataLoader factory for GET requests does:
.factory('DataLoader', function( $http ) {
return {
get: function(url) {
// Simple index lookup
return $http.jsonp( url );
}
}
})
This is the request to get the post data in my controller:
var postsApi = $rootScope.url + '/api/get_posts/?post_type=product&custom_fields=all&' + $rootScope.callback;
$scope.moreItems = false;
$scope.loadPosts = function() {
// Get all of our posts
DataLoader.get( postsApi ).then(function(response) {
$scope.posts = response.data;
$scope.moreItems = true;
//$log.log(response.data);
}, function(response) {
$log.error(response);
});
}
API & Callback
$rootScope.url = 'http://preview.meeko.me';
$rootScope.callback = '_jsonp=JSON_CALLBACK';
Any guidence in the right direction will be greatly appreciated

Am having the same issues
i think the problem is from json-rest-api as a lot of other people are having the same issues with the V2
using $http.get(....).success().error();
works fine for me!

Related

Error returning json data while setting up Stripe payment gateway. Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0

so I have been struggling with this for a couple of days and need to find a solution. I followed a tutorial on how to setup Stripe payments the code below is where I am getting the error :
var buyBtn = document.getElementById('payButton');
var responseContainer = document.getElementById('paymentResponse');
// Create a Checkout Session with the selected product
var createCheckoutSession = function(stripe) {
return fetch("stripe_charge.php", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
checkoutSession: 1,
}),
}).then(function(result) {
return result.json(); // JSON PASSED FROM HERE
});
};
// Handle any errors returned from Checkout
var handleResult = function(result) {
if (result.error) {
responseContainer.innerHTML = '<p>' + result.error.message + '</p>';
}
buyBtn.disabled = false;
buyBtn.textContent = 'Buy Now';
};
// Specify Stripe publishable key to initialize Stripe.js
var stripe = Stripe('<?php echo STRIPE_PUBLISHABLE_KEY; ?>');
buyBtn.addEventListener("click", function(evt) {
buyBtn.disabled = true;
buyBtn.textContent = 'Please wait...';
createCheckoutSession().then(function(data) { // TO HERE - ERROR IS HERE
if (data.sessionId) {
stripe.redirectToCheckout({
sessionId: data.sessionId,
}).then(handleResult);
} else {
handleResult(data);
}
});
});
So you can see above where I am trying to return the json and where I am receiving it. I have double checked the value that is being returned and it is as followed:
json result being returned
and here is the error I am getting :
checkout.php:1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
From what I can see it seems that somewhere in the return of the data.json(). The data is being changed so that it is not accepted later in the code.
If anyone could help with this or shine some more light on the situation I would greatly appreciate it. I've had a look online loads and can't seem to find anything other than a HTML file is being passed through instead. The issue is that I don't know HOW this is happening even when looking through the debug.
Thanks a lot.
There is a result, yes, but it is not JSON. Your stripe_charge.php request is almost certainly returning an HTML page instead of the JSON you expect. The error is happening when you try to return result.json(). You need to check your network responses and debug your server code.
See here: https://www.codeproject.com/Tips/1239019/Unexpected-token-in-JSON-at-position
It may be cause because you have put your code in a custom folder.
It works for me by just removing the "/" in fetch("/create-checkout-session.php", {method: "POST",})
in the checkout.html.

How can I invoke and use Google Cloud Functions in a Flutter app?

I have created a url scraper function, working and tested on Google Cloud, but I am really drawing a blank on how to invoke it. I have tried two methods, one using the cloud_functions package, and the other using a standard HTTPS get. I've tried looking online, but none of the solutions/guides involve functions with an input from the Flutter app, and an output back to the app.
Here's the structure of the function (which is working alright). I've named this function Parse in Google Cloud Platform.
<PYTHON PACKAGE IMPORTS>
def Parser(url):
<URL PARSE FUNCTIONS>
return source, datetime, imageurl, keyword
def invoke_parse(request):
request_json = request.get_json(silent=True)
file = Parser(request_json['url'])
return jsonify({
"source": file[0],
"datetime": file[1],
"imageurl": file[2],
"keyword": file[3],
})
The first method I tried was using an HTTP CALL to get the function. But that isn't working, even though there are no errors - I suspect it's just returning nothing.
parser(String url) async{ // Here I honestly don't know where to use the url input within the function
var uri = Uri.parse(<Function URL String>);
HttpClient client;
try {
var request = await client.getUrl(uri);
var response = await request.close();
if (response.statusCode == HttpStatus.ok) {
var json = await response.transform(utf8.decoder).join();
Map data = jsonDecode(json) as Map;
source = data['source']; // These are the variables used in the main Flutter app
postedAt = data['datetime'];
_imageUrl = data['image'];
keyword = data['keyword'];
} else {
print('Error running parse:\nHttp status ${response.statusCode}');
}
} catch (exception) {
print('Failed invoking the parse function.');
}
}
That didn't work, so I thought I might alternatively use the cloud_functions package as follows (in lieu of the previous):
parser(String url) async {
var functionUrl = <FUNCTION URL>;
HttpsCallable callable = CloudFunctions.instance.getHttpsCallable(functionName: 'Parse')
..timeout = const Duration(seconds: 30);
try {
final HttpsCallableResult result = await callable.call(
<String, dynamic>{
'url': url,
}
);
setState(() {
source = result.data['source']; //THESE ARE VARIABLES USED IN THE FLUTTER APP
postedAt = result.data['datetime'];
_imageUrl = result.data['image'];
keyword = result.data['keyword'];
});
}
on CloudFunctionsException catch (e) {
print('caught firebase functions exception');
print(e.code);
print(e.message);
print(e.details);
} catch (e) {
print('caught generic exception');
print(e);
}
}
In the latter case, the code ran without errors but doesn't work. My flutter log states the following error:
I/flutter ( 2821): caught generic exception
I/flutter ( 2821): PlatformException(functionsError, Cloud function failed with exception., {code: NOT_FOUND, details: null, message: NOT_FOUND})
which I'm assuming is also an error at not being able to read the function.
Any help on how I should go about processing my function would be appreciated. Apologies if something is a really obvious solution, but I am not familiar as much with HTTP requests and cloud platforms.
Thanks and cheers.
Node Js Backend Function
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp();
exports.test = functions.https.onCall(async (data, context) => {
functions.logger.info("Hello logs: ", {structuredData: true});
functions.logger.info( data.token, {structuredData: true});
}
Flutter frontend
1- pubspec.yaml
cloud_functions: ^1.1.2
2 - Code
HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('test');
final HttpsCallableResult results = await callable.call<Map>( {
'token': token,
});

wp-json API returns 401 on post edit with React and nonce

I am trying to create an admin page in WordPress with React that allows users to manage post content. I have successfully created a delete method in react to work with the API, but I'm having difficulties getting update to work.
// plugin_file.php
add_action('admin_enqueue_scripts', function() {
wp_localize_script('tfw-js', 'wpApiSettings', [
'root' => esc_url_raw( rest_url() ),
'nonce' => wp_create_nonce( 'wp_rest' )
]);
});
The code above dumps this object near the bottom of my page
<script type='text/javascript'>
/* <![CDATA[ */
var wpApiSettings = {"root":"http:website.com\/wp-
json\/","nonce":"9eb4c99f2c"};
/* ]]> */
</script>
Here is the delete method that works as intended
deletePost(post) {
var _this = this;
this.serverRequest =
axios
.delete(wpApiSettings.root + "wp/v2/posts/" + post.id, {
headers: {'X-WP-Nonce': wpApiSettings.nonce},
})
.then(function(result) {
_this.updatePostList();
})
}
However my update method, that uses the same nonce key as delete returns 401 unauthorized. I am unsure if the using the same key is the correct approach, but admin-ajax.php uses the same nonce key so I am guessing it is.
updatePost(post) {
var _this = this;
this.serverRequest =
axios
.put(wpApiSettings.root + "wp/v2/posts/" + post.id, {
headers: {'X-WP-Nonce':wpApiSettings.nonce},
data : {
title: 'test'
}
})
.then(function(result) {
_this.updatePostList();
})
}
Error that is returned
{"code":"rest_cannot_edit","message":"Sorry, you are not allowed to edit this post.","data":{"status":401}}
I would prefer not to use an additional plugin to manage this.
Thanks!
Update:
I got this to work easily using jQuery. Not that big of a deal for me as I am just trying to learn React. Still curious if anyone can fill me in on why axios does not work with the exact same headers & post data. My current solution:
updatePost(post) {
var _this = this;
jQuery.ajax({
type: "POST",
url: wpApiSettings.root + "wp/v2/posts/" + post.id,
data: {
"title": 'test',
},
beforeSend: function( xhr ) {
xhr.setRequestHeader("X-WP-Nonce", wpApiSettings.nonce);
}
}).done(function(response) {
_this.updatePostList();
})
.fail(function() {
alert( "error" );
});
}
Hey so I have been having the same issues getting this work as well, but after a long day of troubleshooting, the fix to this was actually fairly simple and easy to overlook.
axios.put(wpApiSettings.root + "wp/v2/posts/" + post.id,
{ headers: {'X-WP-Nonce':wpApiSettings.nonce}},
{ title: 'test' })
should be
axios.put(wpApiSettings.root + "wp/v2/posts/" + post.id,
{ title: 'test' },
{ headers: {'X-WP-Nonce':wpApiSettings.nonce}})
I can't believe I misssed this, but the headers should be in an object that is always the third parameter of the PUT or POST functions in Axios. If you don't have any data you want to pass as the second parameter you could also use throw an empty string ''.
I didn't realize the parameter positions mattered, but in the Axios documentation, the prototype is axios.put(url[, data[, config]]). I got it figured out with a friend when we realized that we were putting the header object into the request body instead of actually putting it into the header.
Hope this helps!
You have to
axios.defaults.headers.common['X-WP-Nonce'] = wpApiSettings.nonce;
before sending a request. Best practice would be to set it at your constructor.
and always remember to use qs to serialize your object before sending it.

Twitter search API returns no tweets?

I'm using NodeJS and an npm package called oauth to communicate with Twitter's search API. For some reason however, twitter is returning to me an empty array of statuses without any error... What is even more confusing is the fact that using a tool like Postman with the exact same request and keys returns the list of tweets? It makes no sense! Here is my request:
URL: https://api.twitter.com/1.1/search/tweets.json?count=100&q=hello&since_id=577103514154893312&max_id=577103544903462913
Here is my code:
var twitter_auth = new OAuth(
"https://api.twitter.com/oauth/request_token",
"https://api.twitter.com/oauth/access_token",
config.consumer_key,
config.consumer_secret,
"1.0A",
null,
"HMAC-SHA1"
);
var request = twitter_auth.get(
"https://api.twitter.com/1.1/search/tweets.json" + url,
config.access_token,
config.access_token_secret
);
var chunk = "", message = "", that = this;
request.on("response", function(response){
response.setEncoding("utf8");
response.on("data", function(data){
chunk += data;
try {
message = JSON.parse(chunk);
} catch(e) {
return;
}
console.log(message);
if(message.statuses)
{
for(var i = 0; i < message.statuses.length; i++)
{
var tweet = message.statuses[i];
that.termData[term.name].push(tweet);
}
if(message.search_metadata.next_results)
{
that.openRequests.push(that.createNewSearch(message.search_metadata.next_results, term));
}
else
{
that.termCompleted(term);
}
}
else if(message)
{
console.log("Response does not appear to be valid.");
}
});
response.on("end", function(){
console.log("Search API End");
});
response.on("error", function(err){
console.log("Search API Error", err);
});
});
request.end();
The console.log(message) is returning this:
{
statuses: [],
search_metadata: {
completed_in: 0.007,
max_id: 577103544903462900,
max_id_str: '577103544903462913',
query: 'hello',
refresh_url: '?since_id=577103544903462913&q=hello&include_entities=1',
count: 100,
since_id: 577103514154893300,
since_id_str: '577103514154893312'
}
}
Any ideas what is going on? Why is the statuses array empty in my code but full of tweets in Postman?
This issue was described at twittercommunity.com.
Accordingly answer of user rchoi(Twitter Staff):
"Regarding web vs. API search, we're aware that the two return different results at the moment. We made upgrades to the web search. There is no timeline for those
changes to be brought to other parts of our system."
Try to use
https://dev.twitter.com/rest/reference/get/statuses/mentions_timeline
https://dev.twitter.com/rest/reference/get/statuses/user_timeline
if you get empty result with api search functionality.
Please follow this link
https://twittercommunity.com/t/search-tweets-api-returned-empty-statuses-result-for-some-queries/12257/6

Angular.js: $http request with JSON as response doesn't work

it's my first app with Angular.js and I've searched so hardly but I can't find a solution:
I've got a search form that makes a request to a web server which retrieves a JSON object; the problem is that this request fails and the error function begins.
Here my code:
$scope.queryUser = {};
$scope.url = "http://xxxx:8080/MyApp/search.do?index=central&query=";
$scope.search = function(query) {
$scope.queryUser= angular.copy(query);
// Create the http post request
// the data holds the keywords
// The request is a JSON request.
$http.post($scope.url + $scope.queryUser.value).
success(function(data, status) {
$scope.status = status;
$scope.data = JSON.stringify(data);
$scope.result = data; // Show result from server in our <pre></pre> element
console.log(data);
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
console.log($scope.data);
});
and this is a sample response:
{"Workstation, Laptop#Workstation$$Laptop":[{"values":{"instanceid":"OI-4A35F9C31E114FBCB5B7668FC5E1FFB4","classid":"COMPUTERSYSTEM"},"index":"distributed"},{"values":{"instanceid":"OI-6A03793A658E45EE90E589D82B0D0962","classid":"COMPUTERSYSTEM"},"index":"distributed"}]}
Any suggestions?
Thanks in advance
I understood the problem: this is a problem of domain. Making the request calling the same webservlet it works...calling an external server it doesn't work.
DOH! I'm sorry for the question