Converting Stripe API syntax to Google Apps Script - google-apps-script

This SO answer correctly explains that since the require Node/JS library is not supported by Google Apps Script, the following code changes must be made to get Stripe to work properly in a GAS project:
from
const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
(async () => {
const product = await stripe.products.create({
name: 'My SaaS Platform',
type: 'service',
});
})();
to
function myFunction() {
var url = "https://api.stripe.com/v1/products";
var params = {
method: "post",
headers: {Authorization: "Basic " + Utilities.base64Encode("sk_test_4eC39HqLyjWDarjtT1zdp7dc:")},
payload: {name: "My SaaS Platform", type: "service"}
};
var res = UrlFetchApp.fetch(url, params);
Logger.log(res.getContentText())
}
Now, I want to convert the following code into the Google Apps Script friendly version.
from https://stripe.com/docs/payments/checkout/accept-a-payment#create-checkout-session
const stripe = require('stripe')('sk_test_4eC39HqLyjWDarjtT1zdp7dc');
const session = await stripe.checkout.sessions.create({
payment_method_types: ['card', 'ideal'],
line_items: [{
price_data: {
currency: 'eur',
product_data: {
name: 'T-shirt',
},
unit_amount: 2000,
},
quantity: 1,
}],
mode: 'payment',
success_url: 'https://example.com/success?session_id={CHECKOUT_SESSION_ID}',
cancel_url: 'https://example.com/cancel',
});
So, I'm trying the following.
to
function myFunction() {
var url = "https://api.stripe.com/v1/checkout/sessions";
var params = {
method: "post",
headers: {
Authorization:
"Basic " + Utilities.base64Encode("sk_test_4eC39HqLyjWDarjtT1zdp7dc:"),
},
payload: {
payment_method_types: ["card", "ideal"],
line_items: [
{
price_data: {
currency: "eur",
product_data: {
name: "T-shirt",
},
unit_amount: 2000,
},
quantity: 1,
},
],
mode: "payment",
success_url:
"https://example.com/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url: "https://example.com/cancel",
},
};
var res = UrlFetchApp.fetch(url, params);
Logger.log(res.getContentText());
}
However, instead of getting the expected response object returned, I get the following error:
Exception: Request failed for https://api.stripe.com returned code 400. Truncated server response:
Log.error
{
error: {
message: "Invalid array",
param: "line_items",
type: "invalid_request_error",
},
}
What am I doing wrong? And how can I generalize the first example? What is the specific documentation I need that I'm not seeing?
Edit:
After stringifying the payload per the suggestion from the comments, now I get the following error:
Exception: Request failed for https://api.stripe.com returned code 400. Truncated server response:
Log.error
{
"error": {
"code": "parameter_unknown",
"doc_url": "https://stripe.com/docs/error-codes/parameter-unknown",
"message": "Received unknown parameter: {\"payment_method_types\":. Did you mean payment_method_types?",
"param": "{\"payment_method_types\":",
"type": "invalid_request_error"
}
}

I modified the script mentioned in the comments and now have a one that works for this purpose.
// [ BEGIN ] utilities library
/**
* Returns encoded form suitable for HTTP POST: x-www-urlformencoded
* #see code: https://gist.github.com/lastguest/1fd181a9c9db0550a847
* #see context: https://stackoverflow.com/a/63024022
* #param { Object } element a data object needing to be encoded
* #param { String } key not necessary for initial call, but used for recursive call
* #param { Object } result recursively populated return object
* #returns { Object } a stringified object
* #example
* `{
"cancel_url": "https://example.com/cancel",
"line_items[0][price_data][currency]": "eur",
"line_items[0][price_data][product_data][name]": "T-shirt",
"line_items[0][price_data][unit_amount]": "2000",
"line_items[0][quantity]": "1",
"mode": "payment",
"payment_method_types[0]": "card",
"payment_method_types[1]": "ideal",
"success_url": "https://example.com/success?session_id={CHECKOUT_SESSION_ID}"
}`
*/
const json2urlEncoded = ( element, key, result={}, ) => {
const OBJECT = 'object';
const typeOfElement = typeof( element );
if( typeOfElement === OBJECT ){
for ( const index in element ) {
const elementParam = element[ index ];
const keyParam = key ? `${ key }[${ index }]` : index;
json2urlEncoded( elementParam, keyParam, result, );
}
} else {
result[ key ] = element.toString();
}
return result;
}
// // test
// const json2urlEncoded_test = () => {
// const data = {
// time : +new Date,
// users : [
// { id: 100 , name: 'Alice' , } ,
// { id: 200 , name: 'Bob' , } ,
// { id: 300 , name: 'Charlie' , } ,
// ],
// };
// const test = json2urlEncoded( data, );
// // Logger.log( 'test\n%s', test, );
// return test;
// // Output:
// // users[0][id]=100&users[0][name]=Stefano&users[1][id]=200&users[1][name]=Lucia&users[2][id]=300&users[2][name]=Franco&time=1405014230183
// }
// // quokka
// const test = json2urlEncoded_test();
// const typeOfTest = typeof test;
// typeOfTest
// test
// [ END ] utilities library

From this question and this sample script, I thought that in this case, the values are required to be sent as the form data. So how about the following modification?
Modified script:
function myFunction() {
var url = "https://httpbin.org/anything";
var params = {
method: "post",
headers: {Authorization: "Basic " + Utilities.base64Encode("sk_test_4eC39HqLyjWDarjtT1zdp7dc:")},
payload: {
"cancel_url": "https://example.com/cancel",
"line_items[0][price_data][currency]": "eur",
"line_items[0][price_data][product_data][name]": "T-shirt",
"line_items[0][price_data][unit_amount]": "2000",
"line_items[0][quantity]": "1",
"mode": "payment",
"payment_method_types[0]": "card",
"payment_method_types[1]": "ideal",
"success_url": "https://example.com/success?session_id={CHECKOUT_SESSION_ID}"
}
};
var res = UrlFetchApp.fetch(url, params);
Logger.log(res.getContentText()); // or console.log(res.getContentText())
}
I think that point might be payment_method_types: ["card", "ideal"] is required to be sent as "payment_method_types[0]": "card" and "payment_method_types[1]": "ideal".
References:
Create a Session of official document
How to integrate Stripe payments with Google Apps Script

Related

No Data in Google Data Studio

I'm trying to show JSON data got from API in Google Data Studio.
so I created community connector and in script verified JSON data from api.
here is script code.
function getFields(request) {
var cc = DataStudioApp.createCommunityConnector();
var fields = cc.getFields();
var types = cc.FieldType;
// var aggregations = cc.AggregationType;
fields.newDimension()
.setId('username')
.setType(types.TEXT);
fields.newMetric()
.setId('version')
.setType(types.NUMBER);
fields.newDimension()
.setId('address')
.setType(types.TEXT);
return fields;
}
function getSchema(request) {
var fields = getFields(request).build();
return { schema: fields };
}
function responseToRows(requestedFields, response) {
// Transform parsed data and filter for requested fields
var row = [];
requestedFields.asArray().forEach(function (field) {
switch (field.getId()) {
case 'username':
return row.push(response.result.user.createdByName);
case 'version':
return row.push(response.result.user.version);
case 'address':
return row.push(response.result.user.address);
default:
return row.push('');
}
});
return { values: row };
}
function getData(request) {
var requestedFieldIds = request.fields.map(function(field) {
return field.name;
});
var requestedFields = getFields().forIds(requestedFieldIds);
// Fetch and parse data from API
var options = {
'method' : 'post',
'contentType': 'application/json',
"headers":{ "api-key": request.configParams.api_key },
"payload": "{username:\""+username+"\", password: \""+password+"\"}",
'muteHttpExceptions': true
};
var response = UrlFetchApp.fetch(url, options);
var parsedResponse = JSON.parse(response);
var rows = responseToRows(requestedFields, parsedResponse);
console.log('getData request', parsedResponse);
return {
schema: requestedFields.build(),
rows: rows
};
}
this is JSON file
{
"result": {
"user": {
"type": "User",
"id": 1073787385,
"address": null,
"version": 1675247127459332096,
"createdBy": 310055,
"createdByName": "Jeirick Hiponia",
}
}
}
Result in data studio.
why don't address show?
And why no data? I think row.push in responseToRows() function is issue.
I'd like to show data like this.

How to fix Community Connector Error in look studio?

I created api connector myself.
This is Code.gs file.
var cc = DataStudioApp.createCommunityConnector();
function getAuthType() {
var AuthTypes = cc.AuthType;
return cc
.newAuthTypeResponse()
.setAuthType(AuthTypes.NONE)
.build();
}
function getConfig(request) {
var config = cc.getConfig();
config.newInfo()
.setId('instructions')
.setText('Enter api url to get data , api token , username and password');
config.newTextInput()
.setId('api_url')
.setName('Enter a api url')
.setPlaceholder('https://');
config.newTextInput()
.setId('api_key')
.setName('Enter a Api Key')
.setHelpText('e.g. xxxxxxxxxxxxxxxxx');
config.newTextInput()
.setId('username')
.setName('Enter a username');
config.newTextInput()
.setId('password')
.setName('Enter a username')
.setType('password');
return config.build();
}
function getFields(request) {
var cc = DataStudioApp.createCommunityConnector();
var fields = cc.getFields();
var types = cc.FieldType;
var aggregations = cc.AggregationType;
fields.newDimension()
.setId('username')
.setType(types.TEXT);
fields.newMetric()
.setId('version')
.setType(types.NUMBER);
fields.newDimension()
.setId('address')
.setType(types.TEXT);
return fields;
}
function getSchema(request) {
var fields = getFields(request).build();
return { schema: fields };
}
function responseToRows(requestedFields, response) {
// Transform parsed data and filter for requested fields
return response.map(function(data) {
var row = [];
requestedFields.asArray().forEach(function (field) {
switch (field.getId()) {
case 'username':
return row.push(data.result.user.createdByName);
case 'version':
return row.push(data.result.user.version);
case 'address':
return row.push(data.result.user.address);
default:
return row.push('');
}
});
return { values: row };
});
}
function getData(request) {
var requestedFieldIds = request.fields.map(function(field) {
return field.name;
});
var requestedFields = getFields().forIds(requestedFieldIds);
// Fetch and parse data from API
const API_KEY = request.configParams.api_key;
var url = request.configParams.api_url;
var options = {
'method' : 'post',
'contentType': 'application/json',
"headers":{ "api-key": API_KEY },
"payload": "{username:\""+request.configParams.username+"\", password: \""+request.configParams.password+"\"}",
'muteHttpExceptions': true
};
var response = UrlFetchApp.fetch(url, options);
var parsedResponse = JSON.parse(response);
var rows = responseToRows(requestedFields, parsedResponse);
return {
schema: requestedFields.build(),
rows: rows
};
}
data from api in postman.
{
"result": {
"user": {
"type": "User",
"id": 1073787385,
"address": null,
"version": 1675221634311192576,
"createdBy": 310055,
"createdByName": "Jeirick Hiponia",
}
}
}
In the Apps Script development environment, Clicked on Deploy > Test deployments to open the Test deployments dialog.
To load your connector in Looker Studio, replace the <HEAD_DEPLOYMENT_ID> placeholder in the following link with your connector's Head Deployment ID and follow the link in your browser:
what is the issue?

Sending a Direct Message using Twitter API using Twitter Lib from Google App Script

I am trying to send direct message through twitter api using Twitter-Lib through App-Script. Below is the definition of sendMsg fucntion
function sendMsg(user, tweet) {
var twitterKeys = {
TWITTER_CONSUMER_KEY: "<<>>",
TWITTER_CONSUMER_SECRET: "<<>>",
TWITTER_ACCESS_TOKEN: "<<>>",
TWITTER_ACCESS_SECRET: "<<>>",
}
var props = PropertiesService.getScriptProperties();
// props.deleteAllProperties()
props.setProperties(twitterKeys);
var service = new Twitterlib.OAuth(props);
if ( service.hasAccess() ) {
var user_id = '77773855';
var dm_link = 'https://api.twitter.com/1.1/direct_messages/events/new.json'
var response = service.fetch(dm_link, {
method: "POST",
muteHttpExceptions: true,
data: {"event":
{"type": "message_create",
"message_create": {
"target": {"recipient_id": user_id},
"message_data": {"text": "Hello"}
}
}
}
});
console.log(response.getResponseCode())
}
}
But when I execute this code, the response is always empty and response.getResponseCode() returns 422. Any leads on what I am doing wrong?

Calling yahoofinanceapi API

How to convert the below JAVA code to apps script?
I want the quote to be pulled into my sheet
Ticker symbol is in A2
I want the price in B2
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://rest.yahoofinanceapi.com/v6/finance/quote/AAPL"))
.header("x-api-key", "YOUR-PERSONAL-API-KEY")
.method("GET", HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
try the following script
const YOUR_PERSONAL_API_KEY = '... Your API KEY ...';
function fetch_yfapi(ticker_symbol){
let urlToFetch = `https://yfapi.net/v6/finance/quote?region=US&lang=en&symbols=${ticker_symbol}`,
options = {
method: 'get',
headers: {
'accept' : 'application/json',
'X-API-KEY' : YOUR_PERSONAL_API_KEY, },
muteHttpExceptions: true
},
fetched = {
code: null,
body: null,
}
try{
const response = UrlFetchApp.fetch(urlToFetch, options);
fetched.code = response.getResponseCode();
fetched.body = response.getContentText();
if (fetched.code !== 200) {
console.log(Utilities.formatString("Request failed. Expected 200, got %d: %s", fetched.code, fetched.body))
}
} catch(e) {
console.log('Method call error UrlFetchApp.fetch : %s',e)
}
return fetched.body
}
function getTickerData(){
let sheet = SpreadsheetApp.getActive().getSheetByName('... sheet name ...'),
ticker_symbol = sheet.getRange('A2').getValue();
if (ticker_symbol.length) {
let ticker_data = fetch_yfapi(ticker_symbol);
if (ticker_data) {
console.log(ticker_data);
sheet.getRange('B2').setValue(JSON.parse(ticker_data).quoteResponse.result[0].ask)
}
}
}
I didn't know exactly what price you wanted to get in the end - so I put 'ask'. In the console you can see the whole body of the returned response

Convert Json into Xlsx File

I am trying to covert json data into Xlsx file and save it in a folder.
I have been trying to use icg-json-to-xlsx module but till now I have been unable to use it.
My code looks like this:
jsonXlsx = require('icg-json-to-xlsx');
filename = path.join('./files', "output.xlsx");
outputFile = jsonXlsx(filename, result) //result contains json data
console.log(outputFile);
but I got this error
outputFile = jsonXlsx(filename, result)
^
TypeError: Property 'jsonXlsx' of object # is not a function
Getting data from mongodb:
in routes:
router.get('/', function(req, res, next) {
fileController.getAll(function(err, result){
if(err){
res.send(500,err);
}
// res.json(result);
var data = result;
in controller:
FileController.prototype.getAll = function(callback){
File.find( {}, {_id: false, id: true, name: true, status: true}, function(err, file){
if(err) {
return callback(err);
} else {
if (!file) {
return callback('file not found');
}
}
callback(null, file);
}
)};
Try this
outputFile = jsonXlsx.writeFile(filename, result);
jsonXlsx is object, which contains methods like writeFile, writeBuffer, so you can't call jsonXlsx as function... or you need add reference to function like this
jsonXlsxWriteFile = require('icg-json-to-xlsx').writeFile;
outputFile = jsonXlsxWriteFile(filename, result)
Example
var jsonXlsx = require('icg-json-to-xlsx');
var path = require('path');
var filename = path.join('./files', "output.xlsx");
var result = [
{ id: '1', name: 'test', status: '123' },
{ id: '2', name: 'david', status: '323'},
{ id: '3', name: 'ram', status: '2323' }
];
var outputFile = jsonXlsx.writeFile(filename, JSON.stringify(result));
console.log(outputFile);
Update:
File
.find({ })
.select({
_id: false, id: true, name: true, status: true
})
.lean()
.exec(function(err, file) {
//
});
In your case, query returns MongooseDocuments, but jsonXlsx needs plain JavaScript objects, so that's why you should use lean()
You can try Alasql JavaScript SQL library. It includes a module to work with JSON and XLSX files (with support of js-xlsx.js library).
Install these two libraries into your project.
npm install alasql
npm install xlsx
Then call alasql function:
var alasql = require(alasql);
alasql('SELECT * INTO XLSX("mydata.xlsx",{headers:true}) \
FROM JSON("mydata.json")');
var cities = [{City:'London',Population:2500000},{City:"Paris",Population:2000000}];
alasql("SELECT * INTO XLSX("mydata.xlsx",{headers:true}) FROM ?",[cities]);
See more examples in this demo file.
There are a lot of modules that can do it. But if you want to control the formatting of xlsx file, then I suggest you use this below code. Rows contain data in the form of JSON array.
var excel = require('node-excel-export');
var styles = {
headerDark: {
fill: {
fgColor: {
rgb: 'FF000000'
}
},
font: {
color: {
rgb: 'FFFFFFFF'
},
sz: 14,
bold: true,
underline: true
}
},
cellPink: {
fill: {
fgColor: {
rgb: 'FFFFCCFF'
}
}
},
cellGreen: {
fill: {
fgColor: {
rgb: 'FF00FF00'
}
}
}
};
var specification = {
"Col1": {
"displayName": 'Col1Name',
"headerStyle": styles.headerDark,
"width": 250
},
"Col2": {
"displayName": 'Col2Name',
"headerStyle": styles.headerDark,
"width": 215
},
"Col3": {
displayName: 'Col3Name',
headerStyle: styles.headerDark,
width: 150
}
}
var report = excel.buildExport(
[{
name: 'Report.xlsx',
specification: specification,
data: rows
}]
);