WooCommerce REST API with Google UrlFetchApp header authorization not working - wordpress

CURRENTLY
I am utilising WooCommerce REST API in my Google Scripts with the following working code:
var ck = "ck_longstringlongstringlongstringlongstring";
var cs = "cs_longstringlongstringlongstringlongstring";
var website = "https://www.mywebsite.com.au";
var url = website + "/wp-json/wc/v3/orders?consumer_key=" + ck + "&consumer_secret=" + cs;
var options =
{
"method": "GET",
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
"muteHttpExceptions": true,
};
var result = UrlFetchApp.fetch(url, options);
PROBLEM
To improve security, I want to put consumer key and secret into the header, but I cannot get the following script to work
var url = website + "/wp-json/wc/v3/orders;
let authHeader = 'Basic ' + Utilities.base64Encode(ck + ':' + cs);
var options =
{
"method": "GET",
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
"muteHttpExceptions": true,
"headers": {"Authorization": authHeader},
};
var result = UrlFetchApp.fetch(url, options);
Current result = {"code":"woocommerce_rest_cannot_view","message":"Sorry, you cannot list resources.","data":{"status":401}}
Expected result = JSON of orders
Is it an issue with my code? Or with WooCommerce API or Google Scripts?

There are a few issues with your code.
With UrlFetchApp.fetch() you need to use contentType instead of Content-Type.
However, in this case you don't even need to set it since application/x-www-form-urlencoded is the default. Same goes for the method property; it defaults to GET.
Moreover, if you want to err on the side of caution use Utilities.base64EncodeWebSafe(data, charset) to base64 encode your credentials instead of the non-web-safe version.
let url = website + "/wp-json/wc/v3/orders";
let encoded = Utilities.base64EncodeWebSafe(ck + ':' + cs, Utilities.Charset.UTF_8);
let options = {
"muteHttpExceptions":true,
"headers": {
"Authorization": "Basic " + encoded
}
};
let result = UrlFetchApp.fetch(url, options);
result = JSON.parse(result);

Related

SSJS HTTP POST BASIC AUTH ISSUE

I have seen a few posts about how this can be done using oauth, but I need to use basic auth using SSJS and I can't seem to get it to work. Below is an example of the code I'm using.
<script runat = "server" >
Platform.Load("core", "1.1.5");
try {
var authEndpoint = "https://example.com/api/v2/oauth/token?grant_type=client_credentials";
var contentType = 'application/json';
var user = 'XXX';
var password = 'XXXX';
var headers = 'Authorization: Basic ' + Platform.Function.Base64Encode(user + ':' + password);
var payload = '';
var accessTokenRequest = HTTP.Post(authEndpoint, contentType, payload, headers);
if (accessTokenRequest.StatusCode == 200) {
var tokenResponse = Platform.Function.ParseJSON(accessTokenRequest.Response[0]);
var accessToken = tokenResponse.access_token
Write("Access Token =" + accessToken + "<br>");
};
} catch (error) {
Write(Stringify(error));
}
</script>
I am getting below error
{"message":"Unable to retrieve security descriptor for this frame.","description":"System.InvalidOperationException: Unable to retrieve security descriptor for this frame. - from mscorlib\r\n\r\n"}

Firebase short URLs not redirecting

I created a Google Sheet that uses a Google Script to generate short URLs via Firebase API.
This is the code in the Google Script
function URLShortener(longURL) {
var body = {
"dynamicLinkInfo": {
"domainUriPrefix": "https://go.example.com",
"link" : longURL
},
"suffix": {
"option": "SHORT"
}
};
var key = 'xxxxxxx'
var url = "https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=" + key;
var options = {
'method': 'POST',
"contentType": "application/json",
'payload': JSON.stringify(body),
};
var response = UrlFetchApp.fetch(url, options);
var json = response.getContentText();
var data = JSON.parse(json);
var obj = data["shortLink"];
return obj;
Logger.log(obj)
}
The script works and it generates URLs similar to https://go.example.com/Xdka but these link redirect to https://example.com/Xdka instead of the actual URL that is sent, e.g. https://example.com/final_url.
If I try to generate these short links from the Firebase dashboard the same happens.
Did I misunderstand how these short URLs work or am I missing something?

How to read Media from Attachment using REST API

I have created an Attachment with image:
{
"_rid": "xD4vALTE7QBAAwAAAAAAAA==",
"Attachments": [
{
"contentType": "image/jpeg",
"id": "10b91d7d-2e5e-466e-a896-3ee54baff4dc",
"media": "/media/xD4vALTE7QBAAwAAAAAAALobDgYB",
"_rid": "xD4vALTE7QBAAwAAAAAAALobDgY=",
"_self": "dbs/xD4vAA==/colls/xD4vALTE7QA=/docs/xD4vALTE7QBAAwAAAAAAAA==/attachments/xD4vALTE7QBAAwAAAAAAALobDgY=",
"_etag": "\"00000d37-0000-0000-0000-5a09602a0000\"",
"_ts": 1510563882
}
],
"_count": 1
}
What is the url to the Media object?
When I use the Cosmos .NET SDK method DocumentClient.ReadMediaAsync(string mediaLink) where mediaLink is /media/xD4vALTE7QBAAwAAAAAAALobDgY= then I can get the Media stream and display the image. But this only works when connecting to Cosmos Db Emulator, when doing the same on the Azure Cosmos DB instance, then I get this error:
Unknown server error occurred when processing this request. ActivityId: 53508de6-2456-4213-947e-4361a8118574, Microsoft.Azure.Documents.Common/1.17.99.1, documentdb-dotnet-sdk/1.19.0 Host/32-bit MicrosoftWindowsNT/6.2.9200.0
The Attachment creation with Medial upload works.
I was thinking to try to query the CosmosDB using the Postman, but I cannot figure out the url to get the Media object.
The url to the Media object is: https://[YOUR-DOCDB-HOST]/media/xD4vALTE7QBAAwAAAAAAALobDgYB
I call this as a GET request in Postman with the following Pre-Request Script:
// store our master key for documentdb
var mastKey = [YOUR-DOCUMENTDB-KEY-HERE];
console.log("mastKey = " + mastKey);
// store our date as RFC1123 format for the request
var today = new Date();
var UTCstring = today.toUTCString();
postman.setEnvironmentVariable("RFC1123time", UTCstring);
// define resourceId/Type now so we can assign based on the amount of levels
var resourceId = "[YOUR-RID-HERE]"; // _rid in attachment document
var resType = "media";
// assign our verb
var verb = request.method.toLowerCase();
// assign our RFC 1123 date
var date = UTCstring.toLowerCase();
// parse our master key out as base64 encoding
var key = CryptoJS.enc.Base64.parse(mastKey);
console.log("key = " + key);
// build up the request text for the signature so can sign it along with the key
var text = (verb || "").toLowerCase() + "\n" +
(resType || "").toLowerCase() + "\n" +
(resourceId || "").toLowerCase() + "\n" +
(date || "").toLowerCase() + "\n" +
"" + "\n";
console.log("text = " + text);
// create the signature from build up request text
var signature = CryptoJS.HmacSHA256(text, key);
console.log("sig = " + signature);
// back to base 64 bits
var base64Bits = CryptoJS.enc.Base64.stringify(signature);
console.log("base64bits = " + base64Bits);
// format our authentication token and URI encode it.
var MasterToken = "master";
var TokenVersion = "1.0";
auth = encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + base64Bits);
console.log("auth = " + auth);
// set our auth token enviornmental variable.
postman.setEnvironmentVariable("authToken", auth);
There are two variables: [YOUR-DOCUMENTDB-KEY-HERE] and [YOUR-RID-HERE]. The kicker is, you need to query attachment meta data first to get the _rid value to use in the token when requesting the media.
The authToken and RFC1123time postman variables are used in the Authorization header:

Why am I getting 'invlid-api-key' from AlchemyAPI while using HTTP.call in meteorjs?

I am trying to get the sentiment of a piece of text using th AlchemyAPI in my meteor application. I am using HTTP.call with 'POST' as recommended by the API to make a server to server call, but I am getting an 'invalid-api-key' response.
var alchemyURL = Meteor.settings.alchemyUrl;
var postData = {
'apikey': Meteor.settings.alchemyUrl,
'text': txt,
'outputMode': 'json'
};
var options = {
data: postData
};
var sentimentData = HTTP.call('POST', alchemyURL, options);
console.log(sentimentData);
I have discovered the answer, to this hence posting it in below.
So turns out, Meteor's HTTP package needs to be given the headers for implementing form url-encoding on the data. Also the data object needs to be passed in 'params' and not in 'data' The correct snippet to be used is given below.
var alchemyURL = Meteor.settings.alchemyUrl;
var postData = {
'apikey': Meteor.settings.alchemyUrl,
'text': txt,
'outputMode': 'json'
};
var options = {
params: postData,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
var sentimentData = HTTP.call('POST', alchemyURL, options);
console.log(sentimentData);

creating proxy url with meteorjs

I was wondering how I might achieve the following using Ironrouter in meteorjs:
app.route("/api/tts").get(function(req,res){
res.type('audio/mpeg');
var text = req.query.q;
var request = require('request');
var url = "https://translate.google.pl/translate_tts?ie=UTF-8&q=" + text + "&tl=en&total=1&idx=0&client=t&prev=input";
request.get(url).pipe(res);
});
If you have iron:router installed already, then you already can. All you need to do is install request using meteorhacks:npm.
Then you simply write:
Router.route("/api/tts", function () {
// NodeJS request object
var req = this.request;
// NodeJS response object
var res = this.response;
res.type('audio/mpeg');
var text = req.query.q;
var request = Meteor.npmRequire('request');
var url = "https://translate.google.pl/translate_tts?ie=UTF-8&q=" + text + "&tl=en&total=1&idx=0&client=t&prev=input";
request.get(url).pipe(res);
}, { where: 'server' });
Let me know if that works.
You can't use IronRouter, Meteor routing is done on the client
(the answer from #rclai won't work because the request is still being sent from the client..)
This solution using the WebApp module shipped with Meteor to define server routes is exactly what you need.
e.g. something like this:
import { WebApp } from 'meteor/webapp';
WebApp.connectHandlers.use('/api/tts', (req, res, next) => {
var text = res.query.q;
var url = "https://translate.google.pl/translate_tts?ie=UTF-8&q=" + text + "&tl=en&total=1&idx=0&client=t&prev=input";
HTTP.call("GET", url, {}, function(err, response){
if(err){
res.writeHead(500);
res.end('Failed...');
}
else {
res.end(response.content);
}
});
});

Resources