-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[BUG] Can't create DRAFT Stripe Invoice #16354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
In my Connect code I'm trying to invoke the action as const invoiceResponse = await pd.runAction({
externalUserId,
actionId: "stripe-create-invoice",
configuredProps: {
app: {
authProvisionId: stripeAccount.account_id,
},
customer: customerId,
collection_method: "send_invoice",
auto_advance: false,
description: `Invoice for Airtable record ${recordId}`,
days_until_due: 30,
metadata: {
airtableRecordId: recordId,
},
},
}); With same error |
This might be specific to |
Hey @MartinMalinda, even when I add custom code to use due_date (with Stripe SDK), the Stripe SDK still shows error |
@vunguyenhung It passes for me with a custom request: import stripe from 'stripe'
export default defineComponent({
props: {
stripe: {
type: "app",
app: "stripe",
}
},
async run({steps, $}) {
const key = this.stripe.$auth.api_key;
async function stripeRequest(endpoint, params) {
const url = `https://api.stripe.com/v1/${endpoint}`;
// Stripe expects URL-encoded form data
const body = new URLSearchParams(params);
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${key}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: body.toString()
});
if (!response.ok) {
const errorData = await response.json();
console.error(`Stripe API error: ${errorData.error.message}`);
}
return response.json();
}
const nowPlus30minutes = Math.floor(Date.now() / 1000) + 1800;
const invoice = await stripeRequest('invoices', {
customer: 'cus_S7ycYnotKQzMFX',
due_date: nowPlus30minutes,
collection_method: 'send_invoice',
});
console.log('Invoice created:', invoice.id);
// return await client.accounts.list({ limit: 1 })
},
}) I'll try to do it via SDK now too |
This passes for me also: import stripe from 'stripe'
export default defineComponent({
props: {
stripe: {
type: "app",
app: "stripe",
}
},
async run({steps, $}) {
const key = this.stripe.$auth.api_key;
const nowPlus30minutes = Math.floor(Date.now() / 1000) + 1800;
const client = stripe(this.stripe.$auth.api_key);
const invoice = await client.invoices.create({
customer: 'cus_S7ycYnotKQzMFX',
due_date: nowPlus30minutes,
collection_method: 'send_invoice',
});
console.log(invoice);
},
}) |
@vunguyenhung it seems to be connected to
if stripe SDK is imported directly:
it works maybe here I tried both approaches side by side import stripe from "@pipedream/stripe"
import stripeSDK from 'stripe';
export default defineComponent({
props: {
stripe,
customer: {
type: "string",
label: "Customer ID",
description: "The ID of the customer to create an invoice for",
async options() {
const customers = await this.stripe.sdk().customers.list({
limit: 100,
})
return customers.data.map(customer => ({
label: `${customer.name || customer.email || customer.id}`,
value: customer.id
}))
}
},
collection_method: {
type: "string",
label: "Collection Method",
description: "How to collect payment for this invoice",
options: [
"charge_automatically",
"send_invoice"
],
default: "charge_automatically"
},
dueDate: {
type: "integer",
label: "Due Date",
optional: true
},
description: {
type: "string",
label: "Description",
description: "An arbitrary string to attach to the invoice. Often useful for displaying to users.",
optional: true
}
},
async run({ steps, $ }) {
const params = {
customer: this.customer,
collection_method: this.collection_method,
// description: this.description
}
if (this.collection_method === "send_invoice" && this.dueDate) {
params.due_date = this.dueDate
}
console.log(params);
const nowPlus30minutes = Math.floor(Date.now() / 1000) + 1800;
// this.stripe.sdk()
try {
console.log('this.stripe.sdk() SDK test');
const invoice = await this.stripe.sdk().invoices.create(params);
console.log(invoice);
} catch (e) {
console.error('Stripe SDK error', e);
}
// SDK imported directly
const client = stripeSDK(this.stripe.$auth.api_key);
const invoice = await client.invoices.create(params);
console.log(invoice);
return await this.stripe.sdk().invoices.create(params)
}
}) |
Got it @MartinMalinda. Thank you so much for providing us the context. I've added the ticket to Pipedream prioritized backlog |
I found the root cause — it was only a one line problem, but very important line. After tracing through the code and digging into the Stripe documentation, I discovered the problem was here: return stripe(this._apiKey(), {
apiVersion: "2020-03-02",
maxNetworkRetries: 2,
}); The API version "2020-03-02" doesn't support creating invoices without line items — that's why it worked in Martin's manual test but failed in the Pipedream component. I’ve updated the apiVersion to "2022-11-15" which does support that use case. The PR is up, but please note: this change could potentially impact other Stripe actions, since it upgrades the API version globally for the SDK. So it might need some careful testing before merging. So… I wouldn’t recommend merging my PR blindly 😅 |
Hi @SokolovskyiK @michelle0927 @MartinMalinda, I was reviewing the PR and noticed the updated API version is I have two suggestions regarding this:
On another note, thank you for your contribution @SokolovskyiK |
See ticket for upgrading Stripe version here: #16415 |
Hi @MartinMalinda the new version works for your case as below. Please use it as an example |
Hi everyone, all test cases are passed! Ready for release! Test report |
With Stripe SDK, I'm able to create an invoice that has no line items:
That's because I pass
collection_method: 'send_invoice'
and futuredue_date
.If I try to replicate the same via Pipedream action I get:
Nothing to invoice for customer
I suspect some prop might not get passed well? Or perhaps there's something about invoices and Stripe API I don't understand well enough yet.
The text was updated successfully, but these errors were encountered: