Adding a Stripe subscription through API - javascript

I am trying to automate the creation of a customer and adding a subscription. I can create the customer through Zapier but I don't really know how to use Python or Javascript to add a subscription or invoice. I can pass in all the data I need into variables like the plan Id and invoice amount. Does anyone have experience with this?

You can create a subscription request if you have the customer_id and plan_id. If you want to do this with Zapier, you can make a POST request using the fetch library in the Code (Javascript) app.
Pass the customer_id and plan_id in the Input Data.
Encode your secret key from Stripe in Base64. You can use this site to encode your key. Replace the encodedAPiKey in the code below and paste it into Zapier.
When this code step runs, it will create a subscription for the customer.
const url = 'https://api.stripe.com/v1/subscriptions';
//Replace with Base64 encoded secret key from Stripe.
const encodedApiKey = "c2tLsfdGVzdF9aYlFNVjdBSzE3Tm1sTVdMVjkwVWdWTz";
const headers = {
'Authorization': `Basic ${encodedApiKey}`,
'Content-Type': 'application/x-www-form-urlencoded'
};
fetch(`${url}?customer=${inputData.customer_id}&items[0][plan]=${inputData.plan_id}`, {method:'POST',
headers: headers
})
.then(res => res.json())
.then(json => {
console.log(json);
callback(null, json);
})
.catch(callback);
You will find documentation for this on Stripe here.
Note: If this code gets called multiple times, it will create multiple subscriptions for the customer. You might want to add some code to handle that or setup your Zaps in a way that this step doesn't get called twice.
Hope that helps!

Related

Twitter API authorization issues when creating unique parameters

I am trying to create and post a tweet using the Twitter API. I have been using Postman to help create the API requests as per the instructions and walkthroughs on the Twitter API docs. When I am using Postman with hardcoded values everything works just fine and I can successfully post to twitter. The issue is when I try and create a unique signature to pass into the request, I get a 401(Unauthorized) from the twitter error response.
I follow the steps in the Twitter API docs at https://developer.twitter.com/en/docs/authentication/oauth-1-0a/creating-a-signature. And my outputs are identical in structure to the provided examples.
This is how I create the unique parameters:
To percentile encode the values I use encodeURIComponent()
oauth_nonce:
let OAUTH_NONCE = uuid.v1();
(uuid is one of many recommended way to create a random nonce, I have tried different ways but nothing works, also twitter says this can be any set of random alphanumerical strings)
oauth_timestamp:
let OAUTH_TIMESTAMP = Math.floor(Date.now() / 1000)
I create the parameter string like:
let parameterString = `include_entities=true&oauth_consumer_key=${CONSUMER_KEY}&oauth_nonce=${OAUTH_NONCE}&oauth_signature_method=${SIGNATURE_METHOD}&oauth_timestamp=${OAUTH_TIMESTAMP}&oauth_token=${ACCESS_TOKEN_KEY}&oauth_version=1.0&status=${encodedText}`
(The encoded text is percent encoded string that is being posted)
I then percent encode the parameter string and the base url which is ('https://api.twitter.com/2/tweets') to create a signature base string that looks like this
let signatureBaseString = `POST&${encodedURL}&${encodedParameterString}`
I create a signing key by encoding both the consumer secret token and access token secret
let signingKey = `${encodedConSecret}&${encodedOAuthSecret}`
I then use CryptoJS to create a hashed string:
let hash = CryptoJS.HmacSHA1(signatureBaseString, signingKey)
Then finally I create the signature like this:
let OAUTH_SIGNATURE = encodeURIComponent(Base64.stringify(hash))
I pass all that information into the config header for an axios post request.
Here is my config for the headers:
let config = {
method: 'post',
url: 'https://api.twitter.com/2/tweets',
headers: {
'Authorization': `OAuth oauth_consumer_key="${CONSUMER_KEY}",oauth_token="${ACCESS_TOKEN_KEY}",oauth_signature_method="HMAC-SHA1",oauth_timestamp="${OAUTH_TIMESTAMP}",oauth_nonce="${OAUTH_NONCE}",oauth_version="1.0",oauth_callback="https%3A%2F%2F127.0.0.1",oauth_signature="${OAUTH_SIGNATURE}"`,
'Content-Type': 'application/json',
},
data : data
};
Here are two exampled of the headers taken from the Network tab in the chrome dev tools. One is a success with hardcoded values from Postman and the fail is from the unique parameters that I created. The consumer key and oauth token are removed for security sake.
SUCCESS from hard coded Postman:
OAuth oauth_consumer_key="CONSUMER_KEY",oauth_token="OAUTH_TOKEN",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1637279149",oauth_nonce="Ry6ldroxEyM",oauth_version="1.0",oauth_callback="https%3A%2F%2F127.0.0.1",oauth_signature="G7AoS6gk1MyI3Eoc6o%2F%2Bp8dM4o8%3D"
FAIL from created parameters:
OAuth oauth_consumer_key="CONSUMER_KEY",oauth_token="OAUTH_TOKEN",oauth_signature_method="HMAC-SHA1",oauth_timestamp="1637279767",oauth_nonce="a8qgwtye6tw",oauth_version="1.0",oauth_callback="https%3A%2F%2F127.0.0.1",oauth_signature="an%2BpRdqwrqLsx9%2BS%2BrCqXY1omEw%3D"
Now I do not think its an issue with the signature, as I used the Twitter Doc example and got the same output as them, so the calculations for that seem to work just fine. My guess is that the problem is with the parameter string value, but I have tried a few different values but nothing seems to work. Again it works just fine with hardcoded values from Postman and I followed the examples and received similar outputs so I am a bit confused on why I receive the 401(Unauthorized) error. Any insight would be much appreciated, Thanks!

Vue JS how to accept the URLEncoded format

I am trying to accept the URL Encoded format in postman to post some data to the Vue JS app, I am using the below-encoded format, how can I achieve that which npm package should I use?
you can use axios
const axios = require('axios')
const params = new URLSearchParams()
params.append('name', 'Akexorcist')
params.append('age', '28')
params.append('position', 'Android Developer')
params.append('description', 'birthdate=25-12-1989&favourite=coding%20coding%20and%20coding&company=Nextzy%20Technologies&website=http://www.akexorcist.com/')
params.append('awesome', true)
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
axios.post(url, params, config)
.then((result) => {
// Do somthing
})
.catch((err) => {
// Do somthing
})
x-www-form-urlencoded data is sent via HTTP headers
Most HTTP headers are not visible to your front-end JavaScript application. They are only visible to the server responding to the request. You cannot read them directly from JavaScript running in a web browser.
However, there are options...
Change the source; have the POST request changed to a GET and encode the parameters in the URL
A reverse proxy for your application could convert from POST parameters to GET parameters with some additional coding or configuration
Receive the request on your server and feed them into your Vue.js application; use something like php/asp/etc to serve your html instead of static HTML files and embed the posted parameters in the generated HTML page
There may be other options if you are creative, but the simplest is the first - just change the source so it no longer posts data.
I resolved it by adding middleware(server-side code such as .net web API) and then redirected it using query string)

Making sense of podbean-api

I am trying to make a site where I fetch my favorite podcasts from Podbean API.
I have worked with fetch before, but those API's were much easier to setup and there was no auth part. So that's what I am struggling with.
So this is basically what I have used before :
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => console.log(json))
From what I understand looking through various other threads :
I need to send get request with my client_id and client_secret to the get the access_token
From there on with access_token I get access and therefore can fetch date from the podcasts object.
I would appreciate any kind of guidance how to handle the auth part and obviously let me know if some of my thought processes are completely wrong.
Thanks in advance!
Ok, so I know the question is over 2 years old but I will still share my solution as I have struggled A LOT to understand how to use this API. This solution is only applicable if you are the owner of the podcast (or at least have access to the dev account).
The thing with the API is if you do not want to use auth2 (which I am still not sure how it works exactly with podbean), you have to fecth the data with a POST method not a GET and provide parameters (body and headers) and use HTTP basic authentication scheme. Their documentation is only in php but with some research you get what they are doing, the section applicable to this solution can be found here.
Here is the code:
const fetch = require("node-fetch");
const btoa = require('btoa');
const client_id = 'Enter your client id';
const client_secret = 'Enter your client secret';
const uri = 'https://api.podbean.com/v1/oauth/token';
// Base 64 encode client_id and client_secret to use basic authentication scheme
const auth = "Basic " + btoa(client_id + ':' + client_secret);
// Set POST request params
const options = {
method: 'POST',
body: 'grant_type=client_credentials',
headers : {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": auth
}
}
// Fetch
fetch(uri, options)
.then(res => res.json())
.then(data => console.log(data))
I hope this helps anyone who would try to use this API with javascript in the future.

Unsupported grant type when getting OAuth token for Reddit API

I'm trying to get an OAuth token for the Reddit API following the Application Only OAuth instructions. My reddit app is an installed app, so for my grant_type I'm using https://oauth.reddit.com/grants/installed_client.
Currently I'm running a very short JS script to query the API and get a token:
const APP_ID = 'MY_APP_ID'
const DEVICE_ID = 'TRACKING_ID_20_TO_30_CHARS'
let form = new FormData()
form.append('grant_type', 'https://oauth.reddit.com/grants/installed_client')
form.append('device_id', DEVICE_ID)
fetch('https://www.reddit.com/api/v1/access_token', {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${btoa(`${APP_ID}:`)}`,
}),
body: form })
.then(handleResponse)
.then(function(data) {
console.log(data)
})
.catch(error => console.error(error))
function handleResponse(response) {
return response.json()
}
(Note: running the snippet as-is will give you a NetworkError because the APP_ID isn't a real one and I don't want to give mine out.)
The response I get is:
{
"error": "unsupported_grant_type"
}
When I try the same API request using a REST client I get back the expected response, so this makes me think that the problem is JavaScript-related. Since the grant_type matches what the instructions say I'm not really sure what to do with the error. I'm hoping someone else more experienced with OAuth will know what is going on here.
The problem was the use of the FormData object. In earlier stages of troubleshooting I found this answer on Reddit and decided to use it, but that didn't work for me.
It was submitting the data as multipart/form-data rather than application/x-www-form-urlencoded, which Reddit's OAuth server did not like. I wrote a helper function based on this answer which did the trick:
function urlEncode(data) {
let out = [];
for (let key in data) {
out.push(`${key}=${encodeURIComponent(data[key])}`);
}
return out.join('&')
}

Troubleshooting axios requests

I've come across this problem a few times now and I feel like there's someone out there who knows a better way to troubleshoot api calls than i - specifically request headers.
Often when i need to pass my api token via a request header, I am constantly groping at the exact format to pass my key's (it seems there's not a universal format for doing this).
For example, I am currently trying to access the vultr v1 api. The docs give a curl example where API-Key: SOMEKEY needs to be passed, yet, my first attempt rarely works then i'm just groping... Do they want my key in a key/value pair or a single string in an array? Do i use es6 objects (without quotes) or not.
here's what i mean:
// one method
const opts = {
headers: {
API-Key: 'SOMEKEY'
}
}
// another
const opts = {
'headers': {
'API-Key': 'SOMEKEY'
}
}
// another
const opts = {
headers: [
'API-Key: SOMEKEY'
]
}
axios.get(url, opts).then(res => console.log(res.data))
which is the proper way? In the curl example given by vultr it shows:
curl -H 'API-Key: EXAMPLE' https://api.vultr.com/v1/iso/list
I also see in my network inspector that the request headers show i am passing my API key yet i am still getting a 403 (bad key error)
I have double checked the validity of my key and that's not the problem.
My question is this:
How do i find the correct format for the headers? Is there a better troubleshooting method for this kind of problem? Any help would be greatly appreciated. Thanks ya'll
UPDATE:
Turns out they've got access control based on IP's. I hadn't noticed it till just now. They were blocking my request because of this. My question still stands however. Good methods for figuring out correct formats? Is there a correct format?
One way is setting Headers while creating axios object, as follows :
axios = axios.create({headers: {'API-Key': 'EXAMPLE'}});
axios.get(url, opts).then(res => console.log(res.data))
Or
axios.get(url, {headers: {'API-Key': 'EXAMPLE'}}).then(res => console.log(res.data))

Categories

Resources