Stripe API error - "Received unknown parameter: source" - api

Creating subscription site in wix code. I keep getting a 400 unknown parameter: source error. (/subscripton)
if you can spot where i am going wrong it would be appreciated. thanks!
import { fetch } from 'wix-fetch';
export async function subscription(token, item) {
const cart = item;
const apiKey = "PRIVATEAPI";
const response = await
fetch("https://api.stripe.com/v1/subscriptions", {
method: 'post',
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Bearer " + apiKey
},
body: encodeBody(token, cart)
});
if (response.status >= 200 && response.status < 300) {
const ret = await response.json();
return { "chargeId": ret.id };
}
let res = await response.json();
let err = res.error.message;
let code = res.error.code;
let type = res.error.type;
return { "error": err, "code": code, "type": type };
}
function encodeBody(token, cart) {
let encoded = "";
for (let [k, v] of Object.entries(cart)) {
encoded = encoded.concat(k, "=", encodeURI(v), "&");
}
encoded = encoded.concat("source=", encodeURI(token));
return encoded;
}

welcome to StackOverflow!
It looks like you're creating a Subscription. According to the API docs: https://stripe.com/docs/api/subscriptions/create?lang=ruby
customer is a required parameter when creating subscriptions on Stripe. You would need to create a Customer first, attaching a tokenized card to the Customer as a source. Then, you can create a subscription, by passing customer: customer.id
Also, is this request being made client-side? Requests made with your secret API key should be made from your server-side code and preferably using Stripe's API libraries: https://stripe.com/docs/libraries
Since you're using Subscriptions, you should also look into the new version of Stripe Checkout (https://stripe.com/docs/payments/checkout), it allows creating subscriptions with client-side code with just a few lines of code!

You're likely passing additional keys that you're not expecting to when you call encodeBody(token, cart).
You should verify that the keys you're passing in token and cart are all valid according to the documentation at https://stripe.com/docs/api/subscriptions/create.

Related

How to use Nuxt 3 server as a passthrough API with FormData to hide external endpoints

I'm trying to get my head around the Nuxt /server API and can't seem to figure out how to send a POST request with form-data (ie files) to Nuxt server to forward on to an external service:
In my pages.vue file I have this method:
async function onSubmit() {
const formData = new FormData();
for (let file of form.files) {
await formData.append("image", file);
}
await $fetch("/api/send", {
method: "POST",
body: formData
});
}
and then in /server/api/send.js I have:
export default defineEventHandler(async (event) => {
const { method } = event.node.req;
// I THINK THE ISSUE IS HERE
const body =
method !== "GET" && method !== "HEAD"
? await readMultipartFormData(event)
: undefined;
const response = await $fetch.raw(https://*******, {
method,
baseURL: *********,
headers: {
},
body: body
});
return response._data;
}
I'm effectively creating a passthrough API using Nuxt so that the external endpoint isn't exposed to the end user. Just can't figure out how to access the formData in the correct format to pass through on the server side. I don't think I am supposed to use readMultipartFormData() because that seems to be parsing the data somehow whereas I just want to pass the formData straight through to the external API. Any tips?
I've tried using both readMultipartFormData() and readBody() and neither seem to work. I don't actually need to read the body but rather get it and pass it through without any formatting...
If you want to pass the data with formdata to the endpoint try this library:
https://www.npmjs.com/package/object-to-formdata
code:
import { serialize } from 'object-to-formdata';
const formData = serialize(body);
const response = await $fetch.raw(https://*******, {
method,
baseURL: *********,
headers: {
},
body: formData
});
I managed to make it work with ugly solution, first you have to update nuxt to version 3.2.0 min then here my front side
let jobApplicationDTO = {
firstName: values.firstName,
lastName: values.lastName,
email: values.email,
phoneNumber: values.phoneNumber,
company: values.company,
shortDescription: values.shortDescription
};
const formData = new FormData();
formData.append("application", new Blob([JSON.stringify(jobApplicationDTO)], {type: "application/json"}));
formData.append("file", values.file) ;
//formData.append("file", values.file );
await useFetch("/api/application", {
method: "POST",
body: formData,
onResponse({request, response, options}) {
// Process the response data
if (response.status === 200) {
errorMessage.value = "";
successMessage.value = "Your application wa sent successfully, you will be contacted soon !";
}
},
onResponseError({request, response, options}) {
console.debug(response);
if (response.status === 400) {
successMessage.value = "";
errorMessage.value = "There may be an issue with our server. Please try again later, or send an email to support#mantiq.com";
} else {
successMessage.value = "";
errorMessage.value = "Sorry we couldn’t send the message, there may be an issue with our server. Please try again later, or send an email to support#mantiq.com";
}
},
});
}
and server side
import {FormData} from "node-fetch-native";
export default defineEventHandler(async (event) => {
const {BACKEND_REST_API, ENQUIRY_TOKEN} = useRuntimeConfig();
//retrieve frontend post formData
const form = await readMultipartFormData(event);
const applicationUrl = BACKEND_REST_API + '/job/apply'
console.log("url used for enquiry rest call :" + applicationUrl);
console.log("Job application token :" + ENQUIRY_TOKEN);
const formData = new FormData();
console.log(form);
if (form) {
formData.append(form[0].name, new Blob([JSON.stringify(JSON.parse(form[0].data))], {type: form[0].type}));
formData.append(form[1].name, new Blob([form[1].data], {type: form[1].type}), form[1].filename);
}
console.log(formData.values);
return await $fetch(applicationUrl, {
method: "POST",
body: formData,
headers: {
Authorization: ENQUIRY_TOKEN,
},
});
})
What is funny is on frontend you have to create a formData , then to get content and to recreate a formData from your previous formData converted in MultiFormPart[], i created a ticket on nuxt to see how to do it properly

Shopify API returns 400 bad request when creating new custom collection

I'm trying to create a custom collection following the document. I'm getting a 400 about the request being malformed.
My code:
require('dotenv').config()
const { Shopify } = require('#shopify/shopify-api')
const client = new Shopify.Clients.Rest(
process.env.SHOPIFY_STORE,
process.env.SHOPIFY_API_SECRET_KEY
);
(async () => {
try {
const data = await client.post({
path: 'custom_collections',
body: { 'custom_collection': { 'title': 'Nike' } },
type: 'application/json',
})
} catch(err) {
console.error(JSON.stringify(err))
}
})()
And the error response from Shopify is:
{"code":400,"statusText":"Bad Request"}
Any ideas what I'm doing wrong here? My tokens are correct because I can use the same token to view collections using the https URL https://API_KEY:SECRET#SHOPIFY_STORE/admin/api/2021-07/collections.json

Unauthorized error in Back4App in fetch api on React Native android

I am trying to access public database of back4app. I'm using react-native and trying to access below API code:
const where = encodeURIComponent(JSON.stringify({
"postalCode": postalCode
}));
const response = await fetch(
`https://parseapi.back4app.com/classes/IN?limit=10&where=${where}`,
{
headers: {
'X-Parse-Application-Id': Constants.BACK4APP_API_KEY, // This is actual Application Id
'X-Parse-Master-Key': Constants.BACK4APP_REST_API_KEY, // This is actual App Master Key
}
}
);
const data = await response.json();
I have tried to use Javascript Key, Client Key, .NET Key, REST API Key but it is always giving unauthorized error to me. When i used Master Key for test(not recommended by Back4App), there was no error but it returned empty results, for the same query with Sample API KEY it returned data.
Can anybody help?
I received help from Back4App support team. Rether then master key header, rest api key worked well.
const where = encodeURIComponent(JSON.stringify({
"postalCode": postalCode
}));
const response = await fetch(
`https://parseapi.back4app.com/classes/IN?limit=10&where=${where}`,
{
headers: {
'dataType': 'json',
'X-Parse-Application-Id': Constants.BACK4APP_API_KEY,
'X-Parse-REST-API-Key': Constants.BACK4APP_REST_API_KEY,
'Content-Type': 'application/json'
}
}
);
const data = await response.json();

How to add private members to external api

Good afternoon all,
I am attempting to create a function that will automatically create a membership through my external loyalty program (through Whisqr) for the current user on my Wix.com website. I am receiving an error message stating the public key is not found.
Here is my backend code:
import {fetch} from 'wix-fetch';
import {wixData} from 'wix-data';
export function postLoyalty() {
let options ={
"headers": {
"X-Public": "pk_live_ba43e74df464cbf521dd07ee20443ff754c3afc11adc16df2594facb2147cd76"
}
}
const url = 'https://whisqr.com/api/v1.2/user/customer/';
const key = '<pk_live_ba43e74df464cbf521dd07ee20443ff754c3afc11adc16df2594facb2147cd76>';
console.log("Url: ");
return fetch(url, {method: 'post'})
.then(response => {
return response.json();
})
.then((data) => {
console.log(data);
return data;
});
}
Here is my page code:
import {postLoyalty} from 'backend/Loyalty.jsw';
import {wixData} from 'wix-data';
import wixLocation from "wix-location";
import {myFunction} from 'public/core.js';
import wixUsers from 'wix-users';
$w.onReady(function () {
let publickey = 'pk_live_ba43e74df464cbf521dd07ee20443ff754c3afc11adc16df2594facb2147cd76';
myFunction(publickey)
.then( (response) => {
console.log(response); //your base64 encoded string
})});
export function page1_viewportEnter(event) {
//Add your code for this event here:
let email = wixUsers.currentUser.getEmail();
postLoyalty(email)
.then(LoyaltyInfo => {
console.log(LoyaltyInfo)
$w("#text1").text = LoyaltyInfo.Results.Value;
})
}
Any and all feedback is greatly appreciated!
You are making a call to the URL using the POST method but you are not utilizing any of the keys, headers which you have defined.
A proper POST call which utilizes the header and body in its request will look like the below:
export function myFunction(data) {
const url = "https://whisqr.com/api/v1.2/user/customer/";
const headers = {
"Authorization": "Bearer " + key, //if api key is required like this
"Content-Type": "application/json" //the content type
};
return fetch(url, {
"method": "POST",
"headers": headers,
"body": JSON.stringify(data) //if there is a body
});
}
You said that you need to create a member on the external platform so you must be needing to send a body with the customer's data. Read the API Documentation.

API Request in Dialogflow Fulfillment (Javascript)

So I'm trying to make a google action using Dialogflow that requires an external API. I've always used jQuery .getJSON() to make API calls, so I had no idea how to do this. After searching this up online, I found a way to do this using vanilla javascript (I also tested the way on my website and it worked fine). The code for that is below:
function loadXMLDoc() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
console.log(xmlhttp.responseText);
}
};
xmlhttp.open("GET", "https://translate.yandex.net/api/v1.5/tr.json/translate?lang=en-es&key=trnsl.1.1.20190105T052356Z.7f8f950adbfaa46e.9bb53211cb35a84da9ce6ef4b30649c6119514a4&text=eat", true);
xmlhttp.send();
}
The code worked fine on my website, but as soon as I added it to the Dialogflow, it would give me the error
XMLHttpRequest is not defined
Obviously that happened because I never defined it (using var), except it worked without me doing anything. So then, I tried adding this line
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
to the code, and it stopped giving me the error (because I defined XMLHttpRequest). But then, my code wouldn't work.
TL;DR: How can I make an external API call using Dialogflow fulfillment?
You can use https. But make sure that you upgrade to Blaze Pay(or any other plans) to make external API calls, else you will receive an error such as
Error:
Billing account not configured. External network is not accessible and quotas are severely limited. Configure billing account to remove these restrictions.
Code to make external api call,
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
"use strict";
const functions = require("firebase-functions");
const { WebhookClient } = require("dialogflow-fulfillment");
const { Card, Suggestion } = require("dialogflow-fulfillment");
const https = require("https");
process.env.DEBUG = "dialogflow:debug"; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(
(request, response) => {
const agent = new WebhookClient({ request, response });
console.log(
"Dialogflow Request headers: " + JSON.stringify(request.headers)
);
console.log("Dialogflow Request body: " + JSON.stringify(request.body));
function getWeather() {
return weatherAPI()
.then(chat => {
agent.add(chat);
})
.catch(() => {
agent.add(`I'm sorry.`);
});
}
function weatherAPI() {
const url =
"https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22";
return new Promise((resolve, reject) => {
https.get(url, function(resp) {
var json = "";
resp.on("data", function(chunk) {
console.log("received JSON response: " + chunk);
json += chunk;
});
resp.on("end", function() {
let jsonData = JSON.parse(json);
let chat = "The weather is " + jsonData.weather[0].description;
resolve(chat);
});
});
});
}
function welcome(agent) {
agent.add(`Welcome to my agent!`);
}
function fallback(agent) {
agent.add(`I didn't understand`);
agent.add(`I'm sorry, can you try again?`);
}
let intentMap = new Map();
intentMap.set("Default Welcome Intent", welcome);
intentMap.set("Default Fallback Intent", fallback);
intentMap.set("Weather Intent", getWeather);
agent.handleRequest(intentMap);
}
);
This article is a diamond! It really helped to clarify what's going on and what's required in Dialogflow fullfilments.
A small suggestion is to gracefully catch the error in the connection to the webservice:
function weatherAPI() {
const url = "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22";
return new Promise((resolve, reject) => {
https.get(url, function(resp) {
var json = "";
resp.on("data", function(chunk) {
console.log("received JSON response: " + chunk);
json += chunk;
});
resp.on("end", function() {
let jsonData = JSON.parse(json);
let chat = "The weather is " + jsonData.weather[0].description;
resolve(chat);
});
}).on("error", (err) => {
reject("Error: " + err.message);
});
});
}