can't using post on google script - google-apps-script

hi iam trying to make post using google script , but it does not work,
original site here: https://billing.te.eg/ar-eg , it like you inquiry with code (ex:055) and number (ex:3020100) and it return bill
I try this before using python and it work but it don't work on google script
here is the code working using python:
import json
import requests
url = "https://billing.te.eg/api/Account/Inquiry"
data = {
"AreaCode": "055", # <-- change this
"PhoneNumber": "3020100", # <-- change this
"PinCode": "",
"InquiryBy": "telephone",
"AccountNo": "",
}
with requests.session() as s:
# load cookies
s.get("https://billing.te.eg/ar-eg", verify=False)
resp = s.post(url, data=data, verify=False).json()
print(json.dumps(resp, indent=4))
and this is the code i trying in google script but didn't work :
function landBill() {
var url = "https://billing.te.eg/api/Account/Inquiry"
var data = {"AreaCode": "055", "PhoneNumber": "3020105", "PinCode": "", "InquiryBy": "telephone",
"AccountNo": "", };
var options = {
'method' : 'post',
'contentType': 'application/x-www-form-urlencoded; charset=UTF-8',
// Convert the JavaScript object to a JSON string.
'payload' : JSON.stringify(data),
'muteHttpExceptions': true,
};
var res = UrlFetchApp.fetch(url,options)
var cont = res.getContentText()
Logger.log(cont)
}

On the python code you are doing 2 requests, a GET and a POST
Since they are within a Session object cookies returned by the website are being automatically managed.
That concept however does not exist in built-in libraries of Apps Script, given that it has to be done manually.
Sample Code:
function myFunction() {
// =================== GET ===================
//initiating a request object for the first GET request
var request1 = {
'url': 'https://billing.te.eg/ar-eg',
'method' : 'get',
'muteHttpExceptions': true,
'validateHttpsCertificates': false,
};
// Adding ('validateHttpsCertificates': false,) since it is the equivalent of (verify=false) in the python code
var resGet = UrlFetchApp.fetchAll([request1]); //storing the response to digest cookies
// Digesting the cookies returned by the server (excluding cookies attributes) and adding them to an array to be reused in the POST
var cookies = [];
for (response of resGet) {
var headers = response.getAllHeaders();
for (cookie of headers['Set-Cookie']){
cookies.push(cookie.split(";")[0]);
}
}
// =================== POST ===================
// declaring the payload for the POST
var postData = {
"AreaCode": "055",
"PhoneNumber": "3020100",
"PinCode": "",
"InquiryBy": "telephone",
"AccountNo": "",
};
//Initiating a request object for the POST request and injecting the stored cookies into the HTTP headers
var request2 = {
'url': "https://billing.te.eg/api/Account/Inquiry",
'method' : 'post',
'contentType': 'application/x-www-form-urlencoded',
'muteHttpExceptions': true,
'validateHttpsCertificates': false,
'headers' : {
'Cookie': (cookies.join("; ") + ";"),
},
'payload' : postData,
};
//Storing the POST response
var resPost = UrlFetchApp.fetchAll([request2]);
//Printing POST response content to console
console.log(resPost[0].getContentText());
}

Related

POST requests with the Coinbase Pro API using Google Apps Script

I'm working with the Coinbase Pro API and while it's working well for GET requests I'm getting an "Invalid signature" when I try a POST request to place an order. I suspect that this may be something related to the "body" of the message since this is the only difference with the GET where "body" is empty.
I'm wondering if someone can help me on this.
function SellMarket (product,amount) {
var requestPath = '/orders';
var method = 'POST';
var body = JSON.stringify({
"type": "market",
"side": "buy",
"product_id": product,
//"size": amount,
'size': '1.0'
});
Logger.log('Sell - Body = '+body);
var responseJson = SignAndCallAPI(method, requestPath, body);
Logger.log('Sell Executed = '+responseJson);
}
function SignAndCallAPI(method, requestPath, body) {
var timestamp = Math.floor(Date.now() / 1000).toString();
var what = Utilities.base64Decode(Utilities.base64Encode(timestamp + method + requestPath + body));
var decodedsecret = Utilities.base64Decode(globalvars_CB.secret);
var hmac = Utilities.base64Encode(Utilities.computeHmacSha256Signature(what, decodedsecret));
var options = {
'method' : method,
'muteHttpExceptions' : true,
'headers' : {
'Content-Type': 'application/json',
'CB-ACCESS-KEY' : globalvars_CB.apikey,
'CB-ACCESS-SIGN' : hmac,
'CB-ACCESS-TIMESTAMP' : timestamp,
'CB-ACCESS-PASSPHRASE' : globalvars_CB.passphrase,
}
}
var responseJson = UrlFetchApp.fetch(globalvars_CB.uri+requestPath, options);
return(responseJson);
}
Untested suggestion, I recommend changing this bit in your code (in SignAndCallAPI function):
var options = {
'method' : method,
'muteHttpExceptions' : true,
'headers' : {
'Content-Type': 'application/json',
'CB-ACCESS-KEY' : globalvars_CB.apikey,
'CB-ACCESS-SIGN' : hmac,
'CB-ACCESS-TIMESTAMP' : timestamp,
'CB-ACCESS-PASSPHRASE' : globalvars_CB.passphrase,
}
}
to:
const options = {
method: method,
payload: body,
contentType: 'application/json',
muteHttpExceptions: true,
headers: {
'CB-ACCESS-KEY': globalvars_CB.apikey,
'CB-ACCESS-SIGN': hmac,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-PASSPHRASE': globalvars_CB.passphrase,
},
};
due to the reasons below:
Although you pass body to SignAndCallAPI function and use body in HMAC computation, you don't appear to actually include body in the POST request sent to the server. I was expecting to see it as the value to a payload property of your options object.
UrlFetchApp documentation (https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetchurl,-params) seems to indicate that Content-Type should be specified in the contentType property of your options object (as opposed to explicitly including a Content-Type header).
I've not looked at the Coinbase API documentation in detail (https://docs.pro.coinbase.com/#place-a-new-order), but body seems okay. You'll also want to make sure the HMAC computation for the CB-ACCESS-SIGN request header is as described in the documentation (https://docs.pro.coinbase.com/#signing-a-message).

How to fix Invalid JSON payload error from the Google Ads API

I'm trying to pull a report from the Google Ads API into Google sheets and I can't get the API to recognize my query as a query
Here's the code and error I'm getting:
function basicReport() {
var query = {
"query" : "SELECT campaign.name, campaign.status FROM campaign ORDER BY campaign.id"
};
var body = JSON.stringify(query);
var head = {
'Developer-token' : "<Dev token>",
'login-customer-id' : <Manager ID>,
'Authorization' : "Bearer <Auth token>",
};
var options = {
'method' : 'POST',
'content-type': 'application/json',
'headers' : head,
'payload' : body,
'muteHttpExceptions' : true
};
var response = UrlFetchApp.fetch('https://googleads.googleapis.com/v4/customers/<Customer ID>/googleAds:searchStream', options);
var json = response.getContentText();
var data = JSON.parse(json);
But I constantly get the error:
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"{\"query\":\"SELECT campaign.name, campaign.status FROM campaign ORDER BY campaign.id\"}\": Cannot bind query parameter. Field '{\"query\":\"SELECT campaign' could not be found in request message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"{\"query\":\"SELECT campaign.name, campaign.status FROM campaign ORDER BY campaign.id\"}\": Cannot bind query parameter. Field '{\"query\":\"SELECT campaign' could not be found in request message."
I've run the query in OAuth playground (https://developers.google.com/oauthplayground) and it worked there, so I know the query is ok.
I've tried passing the body as an object not a string, but then I get a 500 error.
In case anyone else is looking for this - I did solve it.
When set in the header, Content-Type has a dash, when set in the options, contentType does not.
function basicReport() {
var query = {
"query" : "SELECT campaign.name, campaign.status FROM campaign ORDER BY campaign.id"
};
var body = JSON.stringify(query);
var head = {
'developer-token' : "<Dev token>",
'login-customer-id' : "<Manager ID>",
'authorization' : "Bearer <Auth token>",
'accept' : 'application/json'
'Content-Type': 'application/json',
};
var options = {
'method' : 'POST',
'headers' : head,
'payload' : body,
'muteHttpExceptions' : true
};
var response = UrlFetchApp.fetch('https://googleads.googleapis.com/v4/customers/<Customer ID>/googleAds:searchStream', options);
var json = response.getContentText();
var data = JSON.parse(json);
Logger.log(data);

Google Sheets - Mailchimp API - Create Template

WHAT I AM TRYING TO DO:
I am trying to create a template (custom HTML) using Mailchimp API according to this documentation.
WHAT I HAVE TRIED SO FAR:
Took raw HTML of the template I created using 'drag-and-drop'. Tested it using 'code-your-own'. Saved in a variable in apps script. Used to the following code, with data set as that variable. I got the following error
{instance=2fb8b5eb-f11c-4260-a958-f16e5bc7c98b, detail=The resource submitted could not be validated. For field-specific details, see the 'errors' array., type=http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/, title=Invalid Resource, errors=[{field=, message=Schema describes object, NULL found instead}], status=400}
I then set the data to simpler HTML as shown below. I got the same error.
I tried using an already created template (accessed through TEMPLATE_ID) and tried to edit that (just the name of the template). I got the same error though I am able to access the template. The changes I made were:
var TEMPLATE_ID = 'MY_TEMPLATE_ID';
var endpoint = 'templates/' + TEMPLATE_ID;
var data = {
'name': 'new test name'
}
In params
'method': 'PATCH'
I also tried to GET method to see the templates, campaigns, lists. I am successfully able to do that.
I looked up the various answers on SO, one of them suggested using mergefields, I tried it too with the same error.
var data = {
'name': 'Test Template',
'html': '<html><head></head><body><p>TEST</p><body></html>',
'mergefields': {}
};
MWE:
function mailchimpCampaign(){
// URL and params for the Mailchimp API
var root = 'https://us19.api.mailchimp.com/3.0/';
var endpoint = 'templates';
var data = {
'name': 'Test Template',
'html': '<html><head></head><body><p>TEST</p><body></html>'
};
var payload = JSON.stringify(data);
// parameters for url fetch
var params = {
'method': 'POST',
'muteHttpExceptions': true,
'headers': {
'Authorization': 'apikey ' + API_KEY,
'content-type': 'application/json'
},
'data': payload
};
try {
// call the Mailchimp API
var response = UrlFetchApp.fetch(root + endpoint, params);
var data = response.getContentText();
var json = JSON.parse(data);
Logger.log(json);
}
catch (error) {
// deal with any errors
Logger.log(error);
};
}
Any help will be appreciated. Thanks.
This is for future readers.
So while I was hitting my head on this error. I tried using UrlFetchApp.getRequest() and it showed me that payload was empty.
The problem was I had to payload instead of data that I was using.
Updated working code:
var params = {
'method': 'POST',
'muteHttpExceptions': true,
'headers': {
'Authorization': 'apikey ' + API_KEY,
'content-type': 'application/json'
},
'payload': payload
};

Slack API chat.update returns 'not_authed' error

I have a google script running as a webapp to handle the backend of a slack app.
The app has been Authenticated and I have the OAUTH token from this.
I can currently post to a channel with button actions using the chat.postMessage using the for-mentioned token.
Actions url points back at my webapp and hook in via doGet, from this response i construct a JSON object.
var response_payload = {
"token" : access_token,
"ts" : message_ts,
"channel" : channel_id,
"text" : "Approved! you are a winner!"
})
response_url = "https://slack.com/api/chat.update";
sendToSlack_(response_url, response_payload)
posted via the following function:
function sendToSlack_(url,payload) {
var options = {
"method" : "post",
"contentType" : "application/json;charset=iso-8859-1",
"payload" : JSON.stringify(payload)
};
return UrlFetchApp.fetch(url, options)
}
however returned is the following:
{"ok":false,"error":"not_authed"}
I can't find any documentation about this error other than the following
Sending JSON to Slack in a HTTP POST request
However this is in regard to a chat.postMessage request of which in my implementation is working correctly.
You need to put token to header instead of json payload if using application/json. Here is doc for this.
So you request should look like this:
POST /api/chat.update HTTP/1.1
Authorization: Bearer xoxp-xxx-xxx-xxx-xxx
Content-Type: application/json;charset=UTF-8
{
"channel": "xxx",
"text": "Hello ~World~ Welt",
"ts": "xxx"
}
Note: there is no token field in payload.
Well according to the link your provided, Slack does not accept JSON data (weird).
Also, after playing around with their tester, Slack seems to be doing a GET request on https://slack.com/api/chat.update with query parameters attached like this:
https://slack.com/api/chat.update?token=YOUR_TOKEN&ts=YOUR_TIME&channel=YOUR_CHANNEL&text=YOUR_TEXT_URL_ENCODED&pretty=1
So use this code:
var response_payload = {
"token" : access_token,
"ts" : message_ts,
"channel" : channel_id,
"text" : "Approved! you are a winner!"
}
function httpGet(theUrl)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
xmlHttp.send( null );
return xmlHttp.responseText;
}
response_url = encodeURI("https://slack.com/api/chat.update?token=" + response_payload['token'] +
"&ts=" + response_payload['ts'] + "&channel=" + response_payload['channel'] + "&text=" + response_payload['text'] +"&pretty=1");
httpGet(response_url);
Ok! thankyou all for your input.. certainly I have learned a little more. After tweeting at slack_api my original code more or less worked as is.. I had to JSON.parse(payload); the payload in order to then access the object parameters within.. the full example is as below.
function post_update(url, payload) {
var options =
{
'method': 'post',
"payload" : payload,
};
var result = UrlFetchApp.fetch(url, options);
return result.getContentText();
}
function doPost(e) {
var payload = e.parameter.payload;
var json = JSON.parse(payload);
response_url = "https://slack.com/api/chat.update";
// get object elements
var action = json.actions[0].value;
var user = json["user"].name;
var message_ts = json["message_ts"];
var channel_id = json["channel"].id;
if (action == 'approved') // payload if action is 'approved'
{
var response_payload = {
"token" : access_token,
"ts" : message_ts,
"channel" : channel_id,
"text" : "Approved! *" + invitation_name + "* has been sent an invite!",
"attachments" : JSON.stringify([{
"text": ":white_check_mark: Approved by #" + user,
}])
}
}
if (action == 'denied') // payload if action is 'denied'
{
var response_payload = {
"token" : access_token,
"ts" : message_ts,
"channel" : channel_id,
"text" : "Denied. *" + invitation_name + "* has been declined an invite",
"attachments" :JSON.stringify([{
"text": ":exclamation: Declined by #" + user,
}])
}
}
post_update(response_url, response_payload);
return ContentService.createTextOutput().setMimeType(ContentService.MimeType.JSON);
}

How to send a JSON payload with UrlFetchApp service?

I'm trying to POST to a web service that is expecting to get JSON as payload using Google Apps Script. I'm using the following code:
var options =
{
"method" : "post",
"contentType" : "application/json",
"headers" : {
"Authorization" : "Basic <Base64 of user:password>"
},
"payload" : { "endDate": "2012-06-03" }
};
var response = UrlFetchApp.fetch("http://www.example.com/service/expecting/json", options);
On the server side I'm getting the following error:
WARN [facade.SettingsServlet] 04 Jun 2012 15:30:26 - Unable to parse request body: endDate=2012-06-03
net.liftweb.json.JsonParser$ParseException: unknown token e
I'm assuming that the server is expecting to get
{ "endDate": "2012-06-03" }
instead of
endDate=2012-06-03
but I don't know how to make the UrlFetchApp do it.
I do not understand the server side error but the 'payload' parameter must be a string as specified here: https://developers.google.com/apps-script/class_urlfetchapp?hl=fr-FR#fetch.
try:
var options =
{
"method" : "post",
"contentType" : "application/json",
"headers" : {
"Authorization" : "Basic <Base64 of user:password>"
},
"payload" : '{ "endDate": "2012-06-03" }'
};
If you set payload as a String, it will be passed directly (as a
UTF-8 string).
If you set payload as an Object, it will be sent like
an HTML form (which means either 'application/x-www-form-urlencoded' if the
fields are simple, or 'multipart/form-data' if the Object includes a
blob/file).
For your use case (the server is expecting to receive JSON), it sounds like Utilities.jsonStringify() is the way to go.
Something like this worked for me in a similar situation:
Instead of creating payload and adding to options, I built the parameters into a string to append to the URL:
var params = "id=2179853&price=62755";
then, I appended params to the url string:
var result = UrlFetchApp.getRequest(url + '?' + params, options);
So, my options was passed containing only the header.
For my project, this worked like a charm.
Here goes the code that should work with some important comments:
function testMe() {
var products_authkey = "------------";
try {
var url = "https://app.ecwid.com/api/v1/---------/product?id=----------&secure_auth_key=" + products_authkey;
//url= "http://requestb.in/----------"; // you can actually debug what you send out with PUTs or POSTs using Requestb.in service
var payload = {
id: "21798583", // id is necessary and should be a string, or it might be sent in scientific representation (with E)
price: 62755
};
payload = JSON.stringify(payload); // the payload needs to be sent as a string, so we need this
var options = {
method: "put",
contentType: "application/json", // contentType property was mistyped as ContentType - case matters
payload: payload
};
var result = UrlFetchApp.getRequest(url, options);
Logger.log(result) // a better way to debug
var result = UrlFetchApp.fetch(url, options); // works perfectly in my case
Logger.log(result)
} catch (e) {
Logger.log(e)
}
}