Skip to content

[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

Closed
MartinMalinda opened this issue Apr 17, 2025 · 12 comments · Fixed by #16392
Closed

[BUG] Can't create DRAFT Stripe Invoice #16354

MartinMalinda opened this issue Apr 17, 2025 · 12 comments · Fixed by #16392
Labels
bug Something isn't working prioritized Prioritized issue triaged For maintainers: This issue has been triaged by a Pipedream employee

Comments

@MartinMalinda
Copy link

MartinMalinda commented Apr 17, 2025

With Stripe SDK, I'm able to create an invoice that has no line items:

const invoice = await stripeRequest('invoices', {
  customer: customerId,
  due_date: nowPlus30minutes,
  collection_method: 'send_invoice',
});

That's because I pass collection_method: 'send_invoice' and future due_date.

If I try to replicate the same via Pipedream action I get: Nothing to invoice for customer

Image

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.

@MartinMalinda MartinMalinda added the bug Something isn't working label Apr 17, 2025
@MartinMalinda
Copy link
Author

MartinMalinda commented Apr 17, 2025

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

@MartinMalinda
Copy link
Author

MartinMalinda commented Apr 17, 2025

This might be specific to days_until_due behaving differently than due_date maybe.

@vunguyenhung
Copy link
Collaborator

vunguyenhung commented Apr 18, 2025

Hey @MartinMalinda, even when I add custom code to use due_date (with Stripe SDK), the Stripe SDK still shows error Nothing to invoice for customer (image below). Could you share the result when you execute the Stripe SDK on your side for comparision?

Image

@vunguyenhung vunguyenhung added question Further information is requested triaged For maintainers: This issue has been triaged by a Pipedream employee labels Apr 18, 2025
@MartinMalinda
Copy link
Author

MartinMalinda commented Apr 18, 2025

@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

@MartinMalinda
Copy link
Author

@vunguyenhung

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);
  },
})

@MartinMalinda
Copy link
Author

MartinMalinda commented Apr 18, 2025

@vunguyenhung it seems to be connected to

this.stripe.sdk()

if stripe SDK is imported directly:

import stripeSDK from 'stripe';

it works

maybe this.stripe.sdk() has some pre-defined defaults that are causing the problem here?

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)
  }
})

@vunguyenhung vunguyenhung added prioritized Prioritized issue and removed question Further information is requested labels Apr 18, 2025
@vunguyenhung
Copy link
Collaborator

Got it @MartinMalinda. Thank you so much for providing us the context. I've added the ticket to Pipedream prioritized backlog

@SokolovskyiK
Copy link
Contributor

SokolovskyiK commented Apr 22, 2025

@MartinMalinda
@vunguyenhung

I found the root cause — it was only a one line problem, but very important line.
Thanks to Martin’s code examples, I was able to quickly narrow in on the issue. I tested it successfully and was able to create an invoice without line items via Pipedream:

Image

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 😅

@michelle0927 michelle0927 moved this from Prioritized to Ready for PR Review in Component (Source and Action) Backlog Apr 23, 2025
@michelle0927 michelle0927 moved this from Ready for PR Review to In Review in Component (Source and Action) Backlog Apr 23, 2025
@michelle0927 michelle0927 moved this from In Review to Ready for QA in Component (Source and Action) Backlog Apr 23, 2025
@vunguyenhung vunguyenhung moved this from Ready for QA to In QA in Component (Source and Action) Backlog Apr 24, 2025
@vunguyenhung
Copy link
Collaborator

vunguyenhung commented Apr 24, 2025

Hi @SokolovskyiK @michelle0927 @MartinMalinda,

I was reviewing the PR and noticed the updated API version is 2022-11-15. This is still considerably outdated compared to the latest version, 2025-03-31.basil.

I have two suggestions regarding this:

  • Targeted Version Update (for this ticket): Could we update only the API version 2022-11-15 used for that specific call? This might be simpler to implement for now, pending a full SDK upgrade.
  • Full Update to latest version: I can create a new ticket to plan and execute an update of the entire Stripe SDK to the latest version (2025-03-31.basil). This would ensure we benefit from all recent features and security updates.

On another note, thank you for your contribution @SokolovskyiK

@vunguyenhung vunguyenhung moved this from In QA to Changes Required in Component (Source and Action) Backlog Apr 24, 2025
@vunguyenhung
Copy link
Collaborator

See ticket for upgrading Stripe version here: #16415

@michelle0927 michelle0927 moved this from Changes Required to Ready for QA in Component (Source and Action) Backlog Apr 24, 2025
@vunguyenhung vunguyenhung moved this from Ready for QA to In QA in Component (Source and Action) Backlog Apr 25, 2025
@vunguyenhung
Copy link
Collaborator

Hi @MartinMalinda the new version works for your case as below. Please use it as an example
Image

@vunguyenhung vunguyenhung moved this from In QA to Ready for Release in Component (Source and Action) Backlog Apr 25, 2025
@vunguyenhung
Copy link
Collaborator

Hi everyone, all test cases are passed! Ready for release!

Test report
https://vunguyenhung.notion.site/BUG-Can-t-create-DRAFT-Stripe-Invoice-1debf548bb5e8194915ed799840b35af

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working prioritized Prioritized issue triaged For maintainers: This issue has been triaged by a Pipedream employee
Development

Successfully merging a pull request may close this issue.

3 participants