I'm playing with Google Apps Script utilizing the ActiveCollab HTTPS API as a way to link Google Forms to specific projects. I can't figure out where to use the access token in the HTTP request when creating a Task in a project.
Maybe I'm missing it, but which API calls in the documentation require the access token as part of the POST request?
The most basic POST request I've sent was:
var token = // token from authentication
{
"name": "Test task",
"token": token
}
...and it returned a 401 error, saying I wasn't authenticated.
So, I tried:
var token = // token from authentication
{
"name": "Test task",
"username": // my username,
"password": // my password,
"token": token
}
...with the same result. So, which calls require a token and does the token go in the POST payload? Or should it be in the POST options?
Update 3/10/2016
I have added the Authorization parameter to the POST request and am now receiving an invalid token error in the response. I've cleared my cache and reauthorized successfully. My test function is below.
function postTicket() {
// Retrieve the stored token after a successful authorization
var token = PropertiesService.getScriptProperties().getProperty("token");
var data = {
"name": "Testing task"
}
var headers = {
Authorization: 'Bearer ' + token
};
var options = {
"method": "post",
"contentType": "application/json",
"headers": headers,
"payload": JSON.stringify(data)
}
try {
var url = BASE_URL + "/projects/8/tasks";
var response = UrlFetchApp.fetch(url, options);
var json = response.getContentText();
var data = JSON.stringify(json)
Logger.log(data);
} catch (e) {
Logger.log(e);
}
}
The logged error is:
returned code
500.{"type":"ActiveCollab\Authentication\Exception\InvalidTokenException","message":"Authorization
token is not valid","code":0
I had the same problem, but after checking Active Collab SDK code i figured out, that we should use these headers:
var headers = {
'X-Angie-AuthApiToken': token
};
By using this code i'm allowed to create tasks via API.
Token needs to be sent using Authorization HTTP header:
Authorization: Bearer TOKEN_THAT_YOU_GOT_FROM_ACTIVE_COLLAB
This means that you need to send the token as part of request header, not payload. Please check the Google Apps documentation for details (I see that fetch has headers object as one of the arguments, so there is support for this type of interaction built into the platform).
Related
Now I am working on a Google Apps Script project with Google Chat API.
My goal is to get a list of members of a specific space.
I use OAuth2 library to get an access token and making a request to a specific space URL,
but I keep getting the following error:
{
"error": {
"code": 403,
"message": "You are not permitted to use this bot",
"status": "PERMISSION_DENIED"
}
}
I am not sure exactly that which bot this message is talking about.
Here is my code:
const PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----\n\....\n-----END PRIVATE KEY-----\n';
const CLIENT_EMAIL = '......#.....iam.gserviceaccount.com';
function getChatService() {
return OAuth2.createService("ChatAPI")
.setTokenUrl("https://accounts.google.com/o/oauth2/token")
.setPrivateKey(PRIVATE_KEY)
.setIssuer(CLIENT_EMAIL)
.setPropertyStore(PropertiesService.getScriptProperties())
.setScope("https://www.googleapis.com/auth/chat.bot");
}
function getChatMembers() {
let service = getChatService();
if (service.hasAccess()) {
let accessToken = service.getAccessToken();
let headers = {
Authorization: "Bearer " + accessToken
}
let params = {
method: "GET",
headers: headers,
muteHttpExceptions: true
}
let url = "https://chat.googleapis.com/v1/spaces/{{spaceName}}/members";
let response = UrlFetchApp.fetch(url, params);
console.log(response.getContentText());
}
else {
console.log(service.getLastError());
}
}
I enabled Google Chat API on Google Cloud Platform and created service account and secretKey with JSON.
PRIVATE_KEY and CLIENT_EMAIL are from the JSON file.
I set GCP project Number to the apps script file.
Do I have to configure anything else?
I really appriciate your support.
Thank you.
Hi I followed this documentation regarding on creating an invoice on stripe
it says here that The ID of the customer who will be billed.
so I created a test customer manually on stripe and now I tried this code
function testDataInvoices()
{
var url = "https://api.stripe.com/v1/invoices";
var params = {
method: "post",
headers: {Authorization: "Basic " + Utilities.base64Encode("sk_testXXXXX:")},
payload:
{
customer: "cus_JLKM93Pc6j2mxB",
}
};
var res = UrlFetchApp.fetch(url, params);
Logger.log(res.getContentText())
}
but I am getting this error
Exception: Request failed for https://api.stripe.com returned code 400. Truncated server response: {
"error": {
"code": "invoice_no_customer_line_items",
Can someone please enlighten me about this stripe I really just new to this API and their API is just only for node.js
#TRIED
I tried following this link
and change my code to this
function testDataInvoices()
{
var url = "https://api.stripe.com/v1/invoices";
var params = {
method: "post",
headers: {Authorization: "Basic " + Utilities.base64Encode("sk_test_XXXXXX:")},
payload:
{
"email": "paul.kevin#senren.page",
"payment_settings": 'pm_1FWS6ZClCIKljWvsVCvkdyWg',
"invoice_settings[default_payment_method]":'pm_1FWS6ZClCIKljWvsVCvkdyWg'
}
};
var res = UrlFetchApp.fetch(url, params);
Logger.log(res.getContentText())
}
and got this error
A few things:
I'm not familiar with Google App Scripts — are you sure it's safe to store a secret key in such a script and you don't need an actual backend server instead? That key has to be kept private since it can be used to do anything on your Stripe account.
In the first case, you get an error because to issue an Invoice, you have to first call /v1/invoiceitems to add some items to the customer. Then when you call /v1/invoices, which will pull those in to charge for them: https://stripe.com/docs/invoicing/integration#create-invoice-code
in the second case you get an error because those are not valid parameters for that endpoint(if you check the link you posted, those parameters are for /v1/customers, not /v1/invoices).
I'd suggest following https://stripe.com/docs/invoicing/integration .
I am using Google Apps Script to make a UrlFetchApp call to a node.js API endpoint. I own both the Google Apps Script code and node.js code & endpoint, so I can watch what is happening.
When I use Postman, it works. But when I use GAS UrlFetchApp, it doesn't work, as req.body in node is empty { }. I even looked at the code that Postman creates for JavaScript Fetch and try to nearly duplicate it, except for things I know GAS' UrlFetchApp needs. I've done quite a few UrlFetchApp calls with GAS to various external endpoints. So, I'm not new, but can't figure this one out.
Here is my Google Apps Script code:
var url = 'https://xxxxxxxxxxx.azurewebsites.net/api/account';
var data = {
"email": address,
"apiKey": 'xxxxxxxxxxxxxxxxxxx'
}
var payLoadInfo = JSON.stringify(data);
var options = {
"method": "GET",
"headers": {'Content-Type': 'application/json'},
// 'Content-Type': 'application/json',
// "contentType": 'application/json',
redirect: 'follow',
"muteHttpExceptions": true,
"body": payLoadInfo,
// "payload": JSON.stringify(data)
// payload: payLoadInfo
};
var response = UrlFetchApp.fetch(url, options);
The commented out parts of "options" are several different ways I've tried to get it to work. I know in the past that I've usually used "payload" instead of "body" like I am this time (Postman suggested it). When I use "payload", it fails completely, not even getting to my node code. I also tried putting the apiKey in the header.
Here is the node.js API endpoint code:
router.get("/account", async (req, res) => {
var apiKey = process.env.API_KEY;
console.log('apiKey = ' + apiKey);
console.log('req.body = ' + JSON.stringify(req.body, null, 2));
console.log('req.body.apiKey = ' + req.body.apiKey);
if (req.body.apiKey != apiKey) {
console.log('apiKey is not equal');
res.status(401).send({ error: "You are not authorized." });
} else {
process the request...
}
When I use "payload" in "options" I get a 500, and the server code never executes.
When I use "body" in "options", I see the server code execute, but the console.log('req.body = ' + JSON.stringify(req.body, null, 2)), just comes back with an empty object {}, and then since req.body.apiKey != apiKey, it consoles "apiKey is not equal" and sends a 401. When using Postman, the req.body object consoles fine, showing the email & apiKey.
No matter what combinations of things I put into options, it fails either with 500 or 401. However, Postman works great with pretty much the same parameters, headers, etc.
Here is what Postman shows for the code:
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Cookie", "ARRAffinity=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; ARRAffinitySameSite=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
var raw = JSON.stringify({"email":"xxxxxxxxxxxxxxxxx#gmail.com","apiKey":"xxxxxxxxxxxxxxxx"});
var requestOptions = {
method: 'GET',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
I even tried including the cookie and "redirect: follow", but none works.
What am I missing?
I got it to work, thanks to help from #Tanaike (see comments above).
It seems that unlike normal "fetch" in node.js, URLFetchApp in Google Apps Script will not send a body along with a GET.
I still used GET, but changed to sending the param in the URL and the apiKey in the header.
I would like to connect a community connector to a google analytics 4 account so that I can easily modify the data and send it to data studio. However, My code is returning an authentication error:
{ error:
{ code: 401,
message: 'Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.',
status: 'UNAUTHENTICATED' } }
I have included the token, but I am unsure if I am making the correct url call or if there is some other issue that I am unaware of. I don't believe I need an API key to connect from community connector to a google API, but I may be wrong. I did create an API key but the result was the same.
function testFetch(){
var url = "https://analyticsdata.googleapis.com/v1alpha:runReport"
var token = ScriptApp.getOAuthToken();
var options = {
"method" : 'POST',
"entity": { "propertyId": "263290444" },
"dateRanges": [{ "startDate": "2020-12-01", "endDate": "2021-03-01" }],
"dimensions": [{ "name": "country" }],
"metrics": [{ "name": "activeUsers" }],
'muteHttpExceptions': true,
headers: {
Authorization: 'Bearer' + token,
},
};
var response = UrlFetchApp.fetch(url, options);
var result = JSON.parse(response.getContentText());
}
Here is a small guide on how to do what you are trying to achieve:
Set explicit OAuth scopes (see documentation) to your Apps Script project manifest (appsscript.json). In this case you need to add the following:
{
...
"oauthScopes": [
"https://www.googleapis.com/auth/script.external_request",
"https://www.googleapis.com/auth/analytics.readonly"
}
}
Then you need to separate the method parameters from the fetch options. The fetch options need to be stringified and added to payload. You also need to set the contentType to JSON.
const options = {
entry: { propertyId: "263290444"},
// etc.
}
const response = UrlFetchApp.fetch(
'https://analyticsdata.googleapis.com/v1alpha:runReport',
{
method: 'POST',
muteHttpExceptions: true,
headers: {
'Authorization': `Bearer ${ScriptApp.getOAuthToken()}`
},
contentType: 'application/json; charset=utf-8',
payload: JSON.stringify(options)
}
)
After that, you may use the response as you were doing before.
Note that Bearer and the token need to be separated by a space, which your code does not have. It's hard to see because of the concatenation and that why I usually use template literals (see documentation).
References
Authorization scopes | Set explicit scopes (Google Apps Script Guides)
UrlFetchApp.fetch(url, params) (Google Apps Script Reference)
Template literals (MDN)
I'm trying to use UrlFetchApp.fetch(url) method in Apps Script to PATCH a groups resource using the Google Groups Settings API.
The code below allows me to GET the groups properties, but I'm unable to figure out the syntax for a PATCH request.
function doSomething (accessToken) {
var options = {
method: "GET",
headers: {
authorization: "Bearer " + accessToken
},
};
var result = UrlFetchApp.fetch("https://www.googleapis.com/groups/v1/groups/test_group_5#student.vis.ac.at", options);
return HtmlService.createHtmlOutput (result.getContentText());
}
A PATCH request needs a Header Override. You actually need to use a PUT request, and then override it to a PATCH request.
var payload = "{\"" + PropertyOne + "\":\"" + "Proptery Value" + "\"}";
Logger.log('payload: ' + payload);
var options = {"method" : "put", "headers": {"X-HTTP-Method-Override": "PATCH"}, "payload" : payload};
if (payload.length > 2) {
UrlFetchApp.fetch("https://www.googleapis.com/groups/v1/groups/test_group_5#student.vis.ac.at", options );
};
The code above won't be exactly what you want, and might not be error free, but the structure of it should be what you need. I'm sure the payload isn't configured correctly, because I don't know what the format is. It looks like the documentation calls it Patch body with an object.
Google Documentation - Group Settings API Patch
Key words: "Apps Script", patch