I am trying to do a request to Gate.io cryptocurrency market and getting this error.
{"label":"INVALID_SIGNATURE","message":"Signature mismatch"}
I have managed to find a way to correctly encrypt all the parameters(my output is the same as they presented in their documentation), however, when I add a real secret key I got this error.
Please see the screenshot:
the right-hand side is a signature from their doc, in the GAS log you see my output so these are the same however when I add real timestamp and my real secret then it doesn't work
Screenshot.
Here is the fetch request I am using:
function getDateIo() {
var key = "xxx"
var sec = "xxx"
var timestamp = Math.floor(Date.now() / 1000)
var a = {"contract":"BTC_USD","type":"limit","size":100,"price":6800,"time_in_force":"gtc"}
a = JSON.stringify(a)
var body = {"text":"t-123456","currency_pair":"ETH_BTC","type":"limit","account":"spot","side":"buy","iceberg":"0","amount":"1","price":"5.00032","time_in_force":"gtc","auto_borrow":false}
body = JSON.stringify(body)
console.log(body)
var requestPayload = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_512, "")
requestPayload = requestPayload.map(function(e) {
var v = (e < 0 ? e + 256 : e).toString(16);
return v.length == 1 ? "0" + v : v;
}).join("");
console.log(requestPayload)
var meth = 'GET'
var pat = '/api/v4/futures/orders'
var sign = meth + "\n" + pat + "\n" + "contract=BTC_USD&status=finished&limit=50" + "\n" + requestPayload + "\n" + timestamp;
console.log(sign)
var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_512, sign, sec);
signature = signature.map(function(e) {
var v = (e < 0 ? e + 256 : e).toString(16);
return v.length == 1 ? "0" + v : v;
}).join("");
var params = {
'method': "get",
'headers': {
'Accept': 'application/json',
'Content-Type': 'application/json',
'KEY': key,
'Timestamp': timestamp,
'SIGN': signature,
},
// 'body': body,
'muteHttpExceptions': true,
};
var data = UrlFetchApp.fetch("https://api.gateio.ws/api/v4/futures/orders?contract=BTC_USD&status=finished&limit=50", params);
}
Thanks for any advice
Related
I'm trying to get data from Amazon Selling Partner API, using a signing request.
The documentation of the API for Orders can be found here.
And I'm trying to invoke the GET /catalog/2020-04-01/items/
Here is the code so far:
function getData(){
const hex = bytes => bytes.map(byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
const digestToHex = data => hex(Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, data));
const toBytes = data => Utilities.newBlob(data).getBytes();
var access_token = access_token();
//Time variables
var ACCESS_KEY = "the_key";
var ACCESS_ID = "the_id";
//Time variables
var currentDate = new Date();
var isoDate = currentDate.toISOString();
var yearMonthDay= Utilities.formatDate(currentDate, 'GTM-5', 'yyyyMMdd');
//API variables
var end_point = 'https://sellingpartnerapi-eu.amazon.com';
//Credential variables
var region = "eu-west-1";
var service = "execute-api";
var termination = "aws4_request";
var httpRequestMethod = 'GET';
var canonicalURI = '/catalog/2022-04-01/items/B0BS147PTP';
var canonicalQueryString = '?marketplaceId=A1PA6795UKMFR9';
var canonicalheaders = 'host:' + canonicalURI + '\n' + 'x-amz-access-token:' + access_token + '\n' + 'x-amz-date:' + isoDate;
var signedheaders = 'host;user-agent;x-amz-access-token;x-amz-date';
const canonicalRequest = [httpRequestMethod,canonicalURI,canonicalQueryString,canonicalheaders + "\n",""].join("\n");
const canonical_request = digestToHex(canonicalRequest);
var credential_scope = yearMonthDay + '/' + aws_region + '/' + service + '/' + termination_string;
var string_to_sign = "AWS4-HMAC-SHA256" + '\n' + isoDate + '\n' + credential_scope + '\n' + canonical_request;
Logger.log(string_to_sign)
var kSecret = ACCESS_KEY;
var kDate = Utilities.computeHmacSha256Signature(yearMonthDay, "AWS4" + kSecret);
var kRegion = Utilities.computeHmacSha256Signature(toBytes(aws_region), kDate);
var kService = Utilities.computeHmacSha256Signature(toBytes(service), kRegion);
var kSigning = Utilities.computeHmacSha256Signature(toBytes(termination_string), kService);
const signature = hex(Utilities.computeHmacSha256Signature(toBytes(string_to_sign), kSigning));
Logger.log(signature)
// 4. Request.
var options = {
'method': 'GET',
'headers': {
'x-amz-access-token': access_token,
'x-amz-date': isoDate,
'Authorization': 'AWS4-HMAC-SHA256 Credential=' + ACCESS_ID + '/' + credential_scope + ', SignedHeaders=' + signedheaders + ', Signature=' + signature,
},
}
var getOrders = UrlFetchApp.fetch(end_point + canonicalURI + canonicalQueryString, options);
Logger.log(getOrders);
}
and here is the response I have:
"errors": [
{
"message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access... (use muteHttpExceptions option to examine full response)
I'm trying to call the Amazon SP-API from Google Apps Script.
I was able to retrieve the access-token. However when trying call the
I attempted to follow the advice on this post: Google Apps Script: Getting Orders from Amazon Selling Partner API (Signing Requests)
There seems to be something wrong with the way the signature is being calculated.
(I am able to make this call in Postman.)
However in Goolge Apps Script I'm getting an InvalidSignature response.
This is my code:
function getAsins() {
const hex = bytes => bytes.map(byte => ('0' + (byte & 0xFF).toString(16)).slice(-2)).join('');
const digestToHex = data => hex(Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, data));
const toBytes = data => Utilities.newBlob(data).getBytes();
//Credential variables
var access_token = AccessToken();
const ACCESS_ID = 'AKIEXAMPLEEXAMPLEW5';
const ACCESS_KEY = 'bh8EXAMPLEEXAMPLEWw5SA/EXAMPLE+5EXAMPLEP';
const marketplaceId = 'ATVPDKIKX0DER';
//Time variables
var currentDate = new Date();
var isoDate = currentDate.toISOString();
var isoString = isoDate.replace(/-/g, "").replace(/:/g, "").replace(/(\.\d{3})/, "");
var yearMonthDay = Utilities.formatDate(currentDate, 'GTM-4', 'yyyyMMdd');
//API variables
var end_point = 'https://sellingpartnerapi-na.amazon.com';
var aws_region = "us-east-1";
var service = "execute-api";
var termination_string = "aws4_request";
//CanonicalRequest components:
var asin = 'B07X6C9RMF';
var httpRequestMethod = 'GET';
var canonicalURI = '/catalog/2022-04-01/items/' + asin;
var canonicalQueryString = '?marketplaceIds=' + marketplaceId;
var canonicalheaders = 'host:' + "sellingpartnerapi-na.amazon.com" + '\n' + 'x-amz-access-token:' + access_token + '\n' + 'x-amz-date:' + isoDate;
var signedheaders = 'host;x-amz-access-token;x-amz-date'; //;user-agent
var requestPayloadHashed = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, "");//NEW
requestPayloadHashed = requestPayloadHashed.map(function (e) { return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2) }).join("");//NEW
//Building the canonical request
var canonical_string = httpRequestMethod + '\n' + canonicalURI + '\n' + "MarketplaceIds=" + marketplaceId + '\n' + canonicalheaders + '\n\n' + signedheaders + '\n' + requestPayloadHashed;//UPDATED
var canonical_signature = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, canonical_string);
canonical_request = canonical_signature.map(function (e) { return ("0" + (e < 0 ? e + 256 : e).toString(16)).slice(-2) }).join("");
var credential_scope = yearMonthDay + '/' + aws_region + '/' + service + '/' + termination_string;
var string_to_sign = "AWS4-HMAC-SHA256" + '\n' + isoString + '\n' + credential_scope + '\n' + canonical_request;
var kSecret = ACCESS_KEY;
var kDate = Utilities.computeHmacSha256Signature(yearMonthDay, "AWS4" + kSecret);
var kRegion = Utilities.computeHmacSha256Signature(toBytes(aws_region), kDate);
var kService = Utilities.computeHmacSha256Signature(toBytes(service), kRegion);
var kSigning = Utilities.computeHmacSha256Signature(toBytes(termination_string), kService);
var signature = hex(Utilities.computeHmacSha256Signature(toBytes(string_to_sign), kSigning));
Logger.log('signature: ' + signature)
var options = {
'method': 'GET',
'headers': {
'x-amz-access-token': access_token,
'x-amz-date': isoDate,
'Authorization': 'AWS4-HMAC-SHA256 Credential=' + ACCESS_ID + '/' + credential_scope + ', SignedHeaders=' + signedheaders + ', Signature=' + signature,
},
'muteHttpExceptions': true
}
var asinData = UrlFetchApp.fetch(end_point + canonicalURI + canonicalQueryString, options);
Logger.log(asinData);
}
This is the response I'm getting:
{
"errors": [
{
"message": "The request signature we calculated does not match the signature you provided.
....
....
The String-to-Sign should have been
'AWS4-HMAC-SHA256
20220701T185142Z
20220701/us-east-1/execute-api/aws4_request
9a5fa583759a5ff04d7ce67d01fcf7157e9f8a58c4fbbdd69f91cb7a816f5650'
",
"code": "InvalidSignature"
}
]
}
Any help sorting this out would be greatly appreciated!
I'm only starting on this but I think the Canonical Query String does not include the question mark.
I want to make a script to get Crypto prices updated in a Google Spreadsheets. I don't want to use API connector, rather do it myself end to end. I found a blog post on CMC blog but it doesn't work, I get an error.
Here is the code:
function ohlc_price() {
var sh1=SpreadsheetApp.getActiveSpreadsheet().getSheetByName(“IDs″);
var requestOptions = {method: ‘GET’, uri: ‘https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical’, qs: {‘id’: ‘1’,’time_period’:’daily’,’interval’:’2d’, ‘start_date’: ‘2019-08-15’, ‘end_date’: ‘2019-08-18’},
headers: {‘X-CMC_PRO_API_KEY’: ‘MY APY KEY IS HERE’},
json: true, gzip: true};
var url=”https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?id=1&time_start=2019-06-01&interval=weekly”;
var result= UrlFetchApp.fetch(url, requestOptions);
var txt= result.getContentText();
var d=JSON.parse(txt); for (var i=0; i<10;i++) {sh1.getRange(i+2, 1).setValue(d.data.quotes[i].quote.USD.timestamp); sh1.getRange(i+2, 2).setValue(d.data.quotes[i].quote.USD.low); sh1.getRange(i+2, 3).setValue(d.data.quotes[i].quote.USD.open); sh1.getRange(i+2, 4).setValue(d.data.quotes[i].quote.USD.close); sh1.getRange(i+2, 5).setValue(d.data.quotes[i].quote.USD.high);}
Here is the error message I get:
SyntaxError: Invalid or unexpected token (ligne : 2, fichier : Coin price.gs)
I tried to follow CMC instructions but nothing works...
Can someone explain me what isn't working and why ?
Thx
I expect there is some lacks of quotes or apostrophes, especially after the uri/url. Try this and complete :
function ohlc_price() {
var sh1=SpreadsheetApp.getActiveSpreadsheet().getSheetByName('IDs');
var requestOptions = {
'method' : 'GET',
'uri': 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical’',
'qs': {'id': '1',
'time_period':'daily',
'interval':'2d',
'start_date': '2019-08-15',
'end_date': '2019-08-18'
},
'headers' : {'X-CMC_PRO_API_KEY': 'MY APY KEY IS HERE'},
'json': true,
'gzip': true};
var url = 'https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?id=1&time_start=2019-06-01&interval=weekly”';
var result = UrlFetchApp.fetch(url, requestOptions);
var txt= result.getContentText();
}
Modification points:
There are no properties of uri and qs in the parameter of UrlFetchApp.
In your URL, id=1&time_start=2019-06-01&interval=weekly is used as the query parameter. But in your qs, {‘id’: ‘1’,’time_period’:’daily’,’interval’:’2d’, ‘start_date’: ‘2019-08-15’, ‘end_date’: ‘2019-08-18’} is used. So unfortunately, I cannot understand which do you want to use.
In this modification, interval=weekly, time_start=2019-06-01, and time_end=2019-08-18 are used. When you want to use other values, please modify the script.
In your script, for (var i = 0; i < 10; i++) {} is used for var d = JSON.parse(txt). In this case, when the data length is less than 10, an error occurs.
When above points are reflected to your script, it becomes as follows.
Modified script:
function ohlc_price() {
// This is from https://gist.github.com/tanaikech/70503e0ea6998083fcb05c6d2a857107
String.prototype.addQuery = function (obj) {
return this + Object.keys(obj).reduce(function (p, e, i) {
return p + (i == 0 ? "?" : "&") +
(Array.isArray(obj[e]) ? obj[e].reduce(function (str, f, j) {
return str + e + "=" + encodeURIComponent(f) + (j != obj[e].length - 1 ? "&" : "")
}, "") : e + "=" + encodeURIComponent(obj[e]));
}, "");
}
var url = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical";
var query = { 'id': '1', 'time_period': 'daily', 'interval': 'weekly', 'time_start': '2019-06-01', 'time_end': '2019-08-18' };
var endpoint = url.addQuery(query);
var requestOptions = {
method: 'GET',
headers: { 'X-CMC_PRO_API_KEY': 'MY APY KEY IS HERE' },
};
var result = UrlFetchApp.fetch(endpoint, requestOptions);
var txt = result.getContentText();
var d = JSON.parse(txt);
var sh1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("IDs");
var values = d.data.quotes.map(({ quote: { USD } }) => [USD.timestamp, USD.low, USD.open, USD.close, USD.high]);
sh1.getRange(2, 1, values.length, values[0].length).setValues(values);
}
Note:
In this answer, it supposes that your value of X-CMC_PRO_API_KEY is valid value. Please be careful this.
References:
fetch(url, params)
OHLCV Historical
I'm trying to use the Coinbase API v2 (NOT PRO) to simply pull the contents of my wallet in to my spreadsheet. I have the following:
var url = 'https://api.coinbase.com/v2';
var requestPath = '/accounts';
var api_key = '********';
var secret_key = '********';
// var timestamp = new Date().getTime().toString().slice(0, -3);
var timestamp = Math.floor(Date.now() / 1000).toString();
var method = 'GET';
var message = Utilities.base64Decode(Utilities.base64Encode(timestamp + method + requestPath));
var decoded_secret = Utilities.base64Decode(secret_key);
var signature = Utilities.base64Encode(Utilities.computeHmacSha256Signature(message, decoded_secret));
//previous attempt
/* var signature = Utilities.computeHmacSha256Signature(message, decoded_secret);
signature = signature.map(function(e) {
var v = (e < 0 ? e + 256 : e).toString(16);
return v.length == 1 ? "0" + v : v;
}).join("");*/
var params = {
'method': method,
'headers': {
'Content-Type': 'application/json',
'CB-ACCESS-SIGN': signature,
'CB-ACCESS-TIMESTAMP': timestamp,
'CB-ACCESS-KEY': api_key,
'CB-VERSION': '2021-02-03'
}
};
Logger.log(params);
var res = await UrlFetchApp.fetch(url + requestPath, params);
Unfortunately I am getting the invalid signature error. I feel like I'm close. It could be that I don't have the url/request path going in to the signature correctly.
Creating a Coinbase signature with Apps Script is a bit tricky
As you can see from the documentation for Coinbase API, in Python the signature is built with
signature = hmac.new(self.secret_key, message, hashlib.sha256).hexdigest().
In other words, the signature needs to be hex-encoded.
There is no 1:1 equivalent to hexdigest() in Apps Script, but you can build it manually.
This works for me:
var message = (timestamp + method + requestPath + body);
var byteSignature = Utilities.computeHmacSha256Signature(message, secret);
var signature = byteSignature.reduce(function(str,chr){
chr = (chr < 0 ? chr + 256 : chr).toString(16);
return str + (chr.length==1?'0':'') + chr;
},'');
Thereby secret is your credential provided by Coinbase - no need to decode it.
I try to use google apps script to create ticket with attachments via freshdesk API.
Freshdesk have google app script sample code here: https://github.com/freshdesk/fresh-samples/tree/master/google_script , but without attachment demo.
I tried the following code, but it seems always return error by /helpdesk/tickets.json api.
how to post a attachment in google app script with UrlFetchApp right?
function createFreshdeskTicketWithAttachments() {
var API_KEY = PropertiesService.getScriptProperties().getProperty('FreshDeskApiKey')
if (!API_KEY) throw new Error('FreshDeskApiKey not found in script properties.')
var ENDPOINT = Utilities.formatString('https://%s.freshdesk.com', 'zixia')
var headers = {
'Authorization': 'Basic ' + Utilities.base64Encode(API_KEY + ':X')
, 'Content-type': 'application/json'
//'Content-type': 'multipart/form-data'
};
var response = UrlFetchApp.fetch("https://circleci.com/gh/AKAMobi/ucapp/tree/master.svg?style=svg")
var fileBlob = response.getBlob()
Logger.log("%s:%s"
, response.getResponseCode()
, fileBlob.getContentType()
)
var payload = {
helpdesk_ticket: {
description: 'TEST 4'
, subject: "TEST 4"
, email: "test#test.com"
, priority: 1
, status: 2
, attachments: { '': [ { resource: fileBlob } ] }
}
}
//Adds the extensions that are needed to post a new ticket to the end of the url
var url = ENDPOINT + '/helpdesk/tickets.json';
var options = {
'method': 'post',
'headers': headers,
'payload': JSON.stringify(payload),
// 'payload': payload,
muteHttpExceptions: true
};
var response = UrlFetchApp.fetch(url, options);
Logger.log('resp: %s, %s'
, response.getResponseCode()
, response.getContentText()
)
}
after use debug with nc:
nc -l 211.99.222.55 3333
I found payload array should write like this:
var payload = {
'helpdesk_ticket[description]': 'test jjjj'
, 'helpdesk_ticket[subject]': 'test jj'
, 'helpdesk_ticket[email]': 'test#test.com'
, 'helpdesk_ticket[attachments][][resource]': fileBlob1
, 'helpdesk_ticket[attachments][][resource]': fileBlob2
}
but fileBlob2 will not post to server, because the key of array is duplicated. I tried to change 'helpdesk_ticket[attachments][][resource]' to 'helpdesk_ticket[attachments][1][resource]' but it did not work.
so here's a workable version, which only support single attachment:
function createTicket() {
var API_KEY = PropertiesService.getScriptProperties().getProperty('FreshDeskApiKey')
if (!API_KEY) throw new Error('FreshDeskApiKey not found in script properties.')
var ENDPOINT = Utilities.formatString('https://%s.freshdesk.com', 'zixia')
var headers = {
'Authorization': 'Basic ' + Utilities.base64Encode(API_KEY + ':X')
}
var response = UrlFetchApp.fetch("https://circleci.com/gh/AKAMobi/ucapp/tree/master.svg?style=svg")
var fileBlob1 = response.getBlob()
var fileBlob2 = UrlFetchApp
.fetch("http://imgcache.qq.com/open_proj/proj_qcloud_v2/qcloud_2015/css/img/global/internet-plus.png")
.getBlob()
var payload = {
'helpdesk_ticket[description]': 'test jjjj'
, 'helpdesk_ticket[subject]': 'test jj'
, 'helpdesk_ticket[email]': 'test#test.com'
, 'helpdesk_ticket[attachments][][resource]': fileBlob1
, 'helpdesk_ticket[attachments][][resource]': fileBlob2
}
//
// for (var i=0; i<attachments.length; i++) {
// payload['helpdesk_ticket[attachments][][resource]'] = attachments[i]
// }
//
// for (var k in payload) {
// Logger.log('%s = %s', k, payload[k])
// }
var options = {
'method': 'post'
, 'headers': headers
, 'payload': payload
, muteHttpExceptions: true
}
var url = ENDPOINT + '/helpdesk/tickets.json'
// url = 'http://211.99.222.55:3333'
var response = UrlFetchApp.fetch(url, options)
Logger.log('resp: %s, %s'
, response.getResponseCode()
, response.getContentText()
)
}
UPDATE Jan 20th, 2016
I wrote a library named GasFreshdesk for freshdesk v2 api in gas, which is very easy to use(with attachments support):
var MyFreshdesk = new GasFreshdesk('https://domain.freshdesk.com', 'TOKEN')
var ticket = new MyFreshdesk.Ticket({
description:'A description'
, subject: 'A subject'
, email: 'you#example.com'
, attachments: [
Utilities.newBlob('TEST DATA').setName('test-data.dat')
, Utilities.newBlob('TEST DATA2').setName('test-data2.dat')
]
})
ticket.assign(9000658396)
ticket.note({
body: 'Hi tom, Still Angry'
, private: true
, attachments: [
Utilities.newBlob('TEST DATA').setName('test-data.dat')
, Utilities.newBlob('TEST DATA2').setName('test-data2.dat')
]
})
ticket.reply({
body: 'Hi tom, Still Angry'
, cc_emails: ['you#example.com']
, attachments: [
Utilities.newBlob('TEST DATA').setName('test-data.dat')
, Utilities.newBlob('TEST DATA2').setName('test-data2.dat')
]
})
ticket.setPriority(2)
ticket.setStatus(2)
ticket.del()
ticket.restore()
Logger.log('ticket #' + ticket.getId() + ' was set!')
GasFreshdesk Github: https://github.com/zixia/gas-freshdesk
OLD POST:
finnaly, google apps script could attach multi attachments to new ticket on freshdesk by UrlFetchApp.fetch, with a hand made 'multipart' param generator helper function by myself.
put attachments in another array payload:
var payload = [
['helpdesk_ticket[description]', 'test jjjj']
, ['helpdesk_ticket[subject]', 'test jj']
, ['helpdesk_ticket[email]', 'test#test.com']
, ['helpdesk_ticket[attachments][][resource]', fileBlob2]
, ['helpdesk_ticket[attachments][][resource]', fileBlob1]
]
use makeMultipartBody function to generate a requestBody:
var multipartBody = makeMultipartBody(payload)
full code here:
function createTicket2() {
var API_KEY = PropertiesService.getScriptProperties().getProperty('FreshDeskApiKey')
if (!API_KEY) throw new Error('FreshDeskApiKey not found in script properties.')
var ENDPOINT = Utilities.formatString('https://%s.freshdesk.com', 'zixia')
var headers = {
'Authorization': 'Basic ' + Utilities.base64Encode(API_KEY + ':X')
}
var response = UrlFetchApp.fetch("https://circleci.com/gh/AKAMobi/ucapp/tree/master.svg?style=svg")
var fileBlob1 = response.getBlob()
var fileBlob2 = UrlFetchApp
.fetch("http://imgcache.qq.com/open_proj/proj_qcloud_v2/qcloud_2015/css/img/global/internet-plus.png")
.getBlob()
var payload = [
['helpdesk_ticket[description]', 'test jjjj']
, ['helpdesk_ticket[subject]', 'test jj']
, ['helpdesk_ticket[email]', 'test#test.com']
, ['helpdesk_ticket[attachments][][resource]', fileBlob2]
, ['helpdesk_ticket[attachments][][resource]', fileBlob1]
]
var boundary = '-----CUTHEREelH7faHNSXWNi72OTh08zH29D28Zhr3Rif3oupOaDrj'
payload = makeMultipartBody(payload, boundary)
//Logger.log('payload: %s', payload)
//return
var options = {
'method': 'post'
, contentType: "multipart/form-data; boundary=" + boundary
, 'headers': headers
, 'payload': payload
, muteHttpExceptions: true
}
var url = ENDPOINT + '/helpdesk/tickets.json'
// url = 'http://211.99.222.55:3333'
var response = UrlFetchApp.fetch(url, options)
Logger.log('resp: %s, %s'
, response.getResponseCode()
, response.getContentText()
)
}
function makeMultipartBody(payload, boundary) {
var body = Utilities.newBlob('').getBytes()
Logger.log(payload)
for (var i in payload) {
var [k, v] = payload[i]
Logger.log('############ %s = %s', k, v)
if (v.toString() == 'Blob') {
// attachment
body = body.concat(
Utilities.newBlob(
'--' + boundary + '\r\n'
+ 'Content-Disposition: form-data; name="' + k + '"; filename="' + v.getName() + '"\r\n'
+ 'Content-Type: ' + v.getContentType() + '\r\n\r\n'
).getBytes())
body = body
.concat(v.getBytes())
.concat(Utilities.newBlob('\r\n').getBytes())
} else {
// string
body = body.concat(
Utilities.newBlob(
'--'+boundary+'\r\n'
+ 'Content-Disposition: form-data; name="' + k + '"\r\n\r\n'
+ v + '\r\n'
).getBytes()
)
}
}
body = body.concat(Utilities.newBlob("\r\n--" + boundary + "--\r\n").getBytes())
return body
}