Giter VIP home page Giter VIP logo

subscription-use-cases's Introduction

Set up subscriptions with Stripe Billing

This sample shows how to create a customer and subscribe them to a plan with Stripe Billing. For the official documentation for Stripe billing checkout the overview.

Checkout Fixed-price-subscriptions with Elements Usage-based-subscriptions with Elements
Demo checkout.stripe.dev
Define prices in: CLI, Dashboard, or API Create a price with the Stripe: CLI, Dashboard, or API.
Charge users a fixed price on a recurring basis Create a subscription with a fixed price recurring monthly/yearly/etc.
Charge customers based on their usage. Create a metered subscriptions so you can charge customers based on their usage.
Apple Pay & Google Pay support ✅ Built in, no extra code needed
Coupon support for subscriptions

The hosted demos linked above are running in test mode -- use 4242424242424242 as a test card number with any CVC + future expiration date.

Use the 4000002500003155 test card number to trigger a 3D Secure challenge flow.

Read more about test cards on Stripe at https://stripe.com/docs/testing.

Run the sample locally

This sample can be installed two ways -- Stripe CLI or git clone. The .env configuration will vary depending on which way you install.

Requirements

Installing the sample

The Stripe CLI is the fastest way to clone and configure a sample to run locally and is the recommended approach as it will only download the code required for the server language you select. Alternatively, you can download and run directly with this repository.

Option 1: Installing with Stripe CLI

  1. If you haven't already installed the CLI, follow the installation steps. The CLI is useful for cloning samples and locally testing webhooks and Stripe integrations.

  2. Ensure the CLI is linked to your Stripe account by running:

stripe login
  1. Start the sample installer and follow the prompts with:
stripe samples create subscription-use-cases

The CLI will walk you through picking your integration type, server and client languages, and partially configuring your .env file with your Stripe API keys.

  1. Move into the server directory:
cd subscription-use-cases/server
  1. Open server/.env. The STATIC_DIR value should be ../client when installed using the Stripe CLI.
# Stripe keys
STRIPE_PUBLISHABLE_KEY=pk_12345
STRIPE_SECRET_KEY=sk_12345
STRIPE_WEBHOOK_SECRET=whsec_1234

# Stripe key for React front end
REACT_APP_STRIPE_PUBLISHABLE_KEY=pk_12345

# Environment variables
STATIC_DIR=../client
  1. Follow the instructions in server/README.md for how to build and/or run the server.

  2. View in the browser: localhost:4242 and test with 4242424242424242.

  3. [Optional] Forward webhook events

You can use the Stripe CLI to forward webhook events to your server running locally.

stripe listen --forward-to localhost:4242/webhook

You should see events logged in the console where the CLI is running.

When you are ready to create a live webhook endpoint, follow our guide in the docs on configuring a webhook endpoint in the dashboard.

Option 2: Installing manually

If you do not want to use the Stripe CLI, you can manually clone and configure the sample:

  1. Clone the repository
git clone [email protected]:stripe-samples/subscription-use-cases.git
cd subscription-use-cases
  1. Configure .env

The .env file contains the API keys and some settings to enable the sample to run with data for your Stripe account.

Copy the .env.example file from the root of the project into a file named .env in the folder of the server language you want to use. For example with node:

cp .env.example fixed-price-subscriptions/server/node/.env
cd fixed-price-subscriptions/server/node

For example with ruby:

cp .env.example fixed-price-subscriptions/server/ruby/.env
cd fixed-price-subscriptions/server/ruby
  1. Edit the copied .env and populate all of the variables. For more information see: .env config
# Stripe keys
STRIPE_PUBLISHABLE_KEY=pk_12345
STRIPE_SECRET_KEY=sk_12345
STRIPE_WEBHOOK_SECRET=whsec_1234

# Stripe key for React front end
REACT_APP_STRIPE_PUBLISHABLE_KEY=pk_12345

# Billing variables
BASIC=price_12345...
PREMIUM=price_7890...

# Environment variables
STATIC_DIR=../../client/vanillajs
  1. Follow the server instructions on how to run:

Pick the server language you want and follow the instructions in the server folder README on how to run.

cd fixed-price-subscriptions/server/node # there's a README in this folder with instructions
npm install
npm start
  1. [Optional] Forward webhook events

You can use the Stripe CLI to forward webhook events to your server running locally.

If you haven't already, install the CLI and link your Stripe account.

stripe listen --forward-to localhost:4242/webhook

You should see events logged in the console where the CLI is running.

When you are ready to create a live webhook endpoint, follow our guide in the docs on configuring a webhook endpoint in the dashboard.

How to create Prices

With Stripe CLI Fixtures

Use the seed.json fixture file:

stripe fixtures seed.json

With Stripe CLI API calls

Or run the following commands and copy the resulting IDs.

stripe prices create --unit-amount 500 --currency usd -d "recurring[interval]=month" -d "product_data[name]=basic" --lookup-key sample_basic
stripe prices create --unit-amount 900 --currency usd -d "recurring[interval]=month" -d "product_data[name]=premium" --lookup-key sample_premium

With cURL

Replace sk_test_xxx with your secret API key:

curl https://api.stripe.com/v1/prices \
  -u sk_test_xxx: \
  -d "unit_amount"=500 \
  -d "currency"=usd \
  -d "recurring[interval]"=month \
  -d "product_data[name]"=basic \
  -d "lookup_key"=sample_basic \
curl https://api.stripe.com/v1/prices \
  -u sk_test_xxx: \
  -d "unit_amount"=900 \
  -d "currency"=usd \
  -d "recurring[interval]"=month \
  -d "product_data[name]"=premium \
  -d "lookup_key"=sample_premium \

.env config

Example configuration file .env.example

FAQ

Q: Why did you pick these frameworks?

A: We chose the most minimal framework to convey the key Stripe calls and concepts you need to understand. These demos are meant as an educational tool that helps you roadmap how to integrate Stripe within your own system independent of the framework.

Get support

If you found a bug or want to suggest a new [feature/use case/sample], please file an issue.

If you have questions, comments, or need help with code, we're here to help:

Sign up to stay updated with developer news.

Author(s)

Contributors

Made with contrib.rocks.

subscription-use-cases's People

Contributors

anatolzak avatar bbrodsky avatar ch-stripe avatar charliegerard-stripe avatar cjavilla-stripe avatar code-hex avatar ctrudeau-stripe avatar dawn-stripe avatar dependabot[bot] avatar dmontero-stripe avatar froydnj-stripe avatar github-actions[bot] avatar hibariya avatar hideokamoto-stripe avatar huumn avatar jlomas-stripe avatar jmarkowski avatar klapko-stripe avatar marwie avatar matthewling-stripe avatar pantera-stripe avatar paulasjes-stripe avatar pazams avatar stephen-lane avatar suz-stripe avatar tmarek-stripe avatar trag-stripe avatar vcheung-stripe avatar viktorfx avatar wroscoe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

subscription-use-cases's Issues

README is not correct

README about Node js say to use npm allover but you bundle yarn in the package.json (nowadays going donw in popularity). Can we just stay with npm?

see Option 2, step 4. here: https://github.com/stripe-samples/subscription-use-cases/blob/master/README.md#option-2-installing-manually

4. Follow the server instructions on how to run:
Pick the server language you want and follow the instructions in the server folder README on how to run.

cd fixed-price-subscriptions/server/node # there's a README in this folder with instructions
npm install
npm start

Cancel - Subscription

How can we cancel a subscription at a particular time?
Platform - NodeJS
Code I have used is -
const cancelSubscription = await stripe.subscriptions.del(StripeSubscriptionId);

It cancels the subscription immediately. What is the way to cancel it at the end of period?
Do we have to pass that thing at the time of Creating Subscription or at the time of Cancellation?

Inconsistent SDK usage.

Bug report

Describe the bug

subscription-cancel is inconsistent with the rest of the sdk usage.

To Reproduce

View this repo

    $subscription = $stripe->subscriptions->retrieve($body->subscriptionId);
    $subscription->delete();

Expected behavior

    $subscription = $stripe->subscriptions->cancel($body->subscriptionId);

Additional context

It looks like these are equivalent calls and the second is consistent with other examples in the repo. If these calls are not equivalent please let me know.

live-mode API keys not work in kubernetes cluster

I have followd fixed-price-subscription, and deployed docker containerized nodejs server on Kubernetes cluster, and tried to access stripe API.

When I used test-mode API keys, It worked and paymant was successful in test-mode. But it did not work when I used live-mode API keys.
When I tried live-mode API Keys locally without using container, It worked.

Nginx reverse proxy in kubernetes cluster shows 502 bad gateway error, when I access stripe API. How can I solve this issue? Is there any live-mode specific issue?

per-seat-subscriptions not working

Bug report

Describe the bug

Whenever either the hosted example or the fork is opened for per-seat-subscriptions example, there appears to be an error while opening the sandbox. It works fine for all other use cases.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

Go to https://codesandbox.io/s/github/stripe-samples/subscription-use-cases/tree/master/per-seat-subscriptions or https://fqizg.sse.codesandbox.io/

Expected behavior

The given example shows up

Screenshots

https://i.imgur.com/a5mpfV0.png

System information

  • OS: Windows
  • Browser (if applies) Firefox
  • Server environment Node

Php solution doesn't work

When I do your step-by-step tutorial to set up a subscription with PHP as a server. I only have error messages that appear. I used the method with the CLI, it doesn't work. Same thing by doing it manually. I put a screenshot so that you can see the error messages.

Can you help me because my project needs this solution?

Regards,
Capture d’écran 2021-12-05 à 12 04 29

Ambiguity with regards to proration

Bug report

Describe the bug

The docs have some ambiguity as far as how to prorate per-seat licensing.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Go to https://stripe.com/docs/billing/subscriptions/per-seat#change-price
  2. Note the example has you manually create an invoice then pay it immediately.
  3. And yet, there's also an entire set of proration_behavior options.

Ambiguities

  • Why does this example manually create an invoice and bill it?
  • What's the difference between doing that and instead just passing proration_behavior into the Subscription.modify command?
  • If the example can be simplified by using proration_behavior, then what's the right value to use to mirror the documented example?
  • When you go on the Stripe dashboard itself and manually increase/decrease per-seat quantities, what's the behavior being applied behind the scenes? Basically, what value is used for proration_behavior there?

Thanks guys. Great docs, just some ambiguity.

"Error fetching sandbox." at demo

Bug report

Describe the bug

"Error fetching sandbox" at demo

A clear and concise description of what the bug is.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Go to 'https://v211e.sse.codesandbox.io/'
  2. See error "Error fetching sandbox"
  3. Forking does not resolve.

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

image

If applicable, add screenshots to help explain your problem.

System information

  • OS: [e.g. macOS, Windows] Windows 10
  • Browser (if applies) [e.g. chrome, safari] Version 88.0.4324.190 (Official Build) (64-bit)
  • Server environment [e.g. Go, Java, Node, PHP, Python, Ruby, TypeScript]

Additional context

Add any other context about the problem here.

Random arguments in promise flow

In file: https://github.com/stripe-samples/subscription-use-cases/blob/master/fixed-price-subscriptions/client/react/src/PaymentForm.js

        .then((result) => {
          return {
            // Use the Stripe 'object' property on the
            // returned result to understand what object is returned.
            subscription: result,
            paymentMethodId: paymentMethodId,
            priceId: productSelected.name,
          };
        })
        // Some payment methods require a customer to do additional
        // authentication with their financial institution.
        // Eg: 2FA for cards.
        .then(handleCustomerActionRequired)
  function handleCustomerActionRequired({
    subscription,
    invoice,
    priceId,
    paymentMethodId,
    isRetry,
  }) {

Where does 'invoice', 'isRetry' come from??

Subscriptions incomplete despite payments successful

I've been following the paymentintent SCA docs, but can't get the subscriptions to become active.

They keep showing Incomplete "This subscription will expire tomorrow unless the first payment is completed."

Even though the payment has been taken!

My flow is as follows:
Fetch stripeUrl from front-end => create paymentIntent, customer, plan, subscription on the server
=> send intent.client_secret to the client => Verify SCA => Payment made, but subscription is still showing "incomplete"

const subscription = await stripe.subscriptions.create({
          customer: customer.id,
          items: [
            {
              plan: plan.id,
            },
          ],
          // trial_from_plan: true,
          expand: ["latest_invoice.payment_intent"],
        });

For some reason subscription is not tracking the payment status. Any ideas how to make it do so?

Sample not currently supported by the CLI

As per the instructions - when you run "stripe samples create subscriptions-with-fixed-price"

You get:

"The sample provided is not currently supported by the CLI: subscriptions-with-fixed-price
To see supported samples, run 'stripe samples list'"

If I do run: stripe samples list - I get:

"A list of available Stripe Samples:

accept-a-card-payment
Learn how to accept a basic card payment
Repo: https://github.com/stripe-samples/accept-a-card-payment

adding-sales-tax
Learn how to use PaymentIntents to build a simple checkout flow
Repo: https://github.com/stripe-samples/adding-sales-tax

au-becs-debit-payment
Collecting AU BECS Direct Debit mandates and payments
Repo: https://github.com/stripe-samples/au-becs-debit-payment

card-brand-choice
Supporting Card Brand Choice with Stripe.
Repo: https://github.com/stripe-samples/card-brand-choice
.........
"

I am running this on:
4.9.0-12-amd64 #1 SMP Debian 4.9.210-1 (2020-01-20) x86_64 GNU/Linux
Standard LAMP installation

Subscription process hangs forever

Bug report

Subscription process hangs forever. In the browser I see:

Subscribing... please wait.
Payment method created pm_0IZc3I5gXfqf

Describe the bug

The npm run start return the following

Node server listening on port http://localhost:4242!
(node:143960) UnhandledPromiseRejectionWarning: Error: Payment for this subscription requires additional user action before it can be completed successfully. Payment can be completed using the PaymentIntent associated with `subscription.latest_invoice`. Additional information is available here: https://stripe.com/docs/billing/subscriptions/overview#requires-action
    at Function.generate (/home/lsoave/STRIPE/subscription-use-cases/fixed-price-subscriptions/server/node/node_modules/stripe/lib/Error.js:50:16)
    at IncomingMessage.<anonymous> (/home/lsoave/STRIPE/subscription-use-cases/fixed-price-subscriptions/server/node/node_modules/stripe/lib/StripeResource.js:168:39)
    at Object.onceWrapper (events.js:420:28)
    at IncomingMessage.emit (events.js:326:22)
    at endReadableNT (_stream_readable.js:1223:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21)
(node:143960) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:143960) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

To Reproduce

Just follow the official README

Expected behavior

Working REAME

Screenshots

If applicable, add screenshots to help explain your problem.

System information

  • OS: Linux basenode 5.4.0-67-generic # 75-Ubuntu SMP Fri Feb 19 18:03:38 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
  • Browser: Chrome Version 89.0.4389.82 (Official Build) (64-bit)
  • Server environment: Node v12.19.0

Bug: wrong ConfirmCardPayment error handling

// start code flow to handle updating the payment details

If the confirm card payment operation fails a subscription already exists, no we need to update our client state to reflect the failed payment intent status.

That can be achieve by adding this code on error handler:

if (result.error) {
    // start code flow to handle updating the payment details
    // The card was declined (i.e. insufficient funds, card has expired, etc)
    if (result.error.payment_intent.status === 'requires_payment_method') {
        sessionStorage.setItem('latestInvoiceId', subscription.latest_invoice.id);
        sessionStorage.setItem('latestInvoicePaymentIntentStatus', result.error.payment_intent.status);
    }
    throw result.error;
}

Also, session storage seems a much better approach to persist the user session state than the local storage.

Incorrect env var for premium example

In subscription-use-cases/fixed-price-subscriptions/server/node/server.js this should be process.env.PREMIUM:

process.env.STRIPE_SECRET_KEY
    ? ''
    : console.log(
        'Add PREMIUM priceID to your .env file. See repo readme for setup instructions.'
      )

Clients don't work

Bug report

Describe the bug

I used VS plug-in to create project - i tried both clients using Java server
Client doesn't work
React - 2nd page not correctly render, no option to select
other client is stuck on register page

A clear and concise description of what the bug is.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. start app
  2. click register - not correctly render on React. Other client is stuck on register page

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

If applicable, add screenshots to help explain your problem.

System information

  • OS: macOS
  • Browser (if applies) chrome
  • Server environmentJava

Additional context

Add any other context about the problem here.

invoice.retrieveUpcoming cannot set property `subscription_prorate`

Bug report

Describe the bug

When trying to implementing the /retrieve-upcoming-invoice endpoint and calling the method stripe.invoices.retrieveUpcoming(...) in typescript the property subscription_prorate: true cannot be set as the example describes.

The error is: Argument of type '{ subscription_prorate: boolean; customer: any; subscription: any; subscription_items: ({ id: string; deleted: true; } | { price: string; deleted: false; })[]; }' is not assignable to parameter of type 'InvoiceRetrieveUpcomingParams'

To Reproduce

// Retrieve invoice
  const invoice = await stripe.invoices.retrieveUpcoming({
    subscription_prorate: true, // This gives an error
    customer: req.body.customerId,
    subscription: req.body.subscriptionId,
    subscription_items: [
      {
        id: subscription.items.data[0].id,
        deleted: true,
      },
      {
        price: process.env[req.body.newPriceId],
        deleted: false,
      },
    ],
  });

Fixed-price-subscriptions sample site fails

Fixed-price-subscriptions sample site fails with the following error:
Error: ENOENT: no such file or directory, stat '/sandbox/client/index.html'

To Reproduce

  1. Navigate to https://github.com/stripe-samples/subscription-use-cases
  2. Scroll down to the Demo area.
  3. In the fixed-price-subscriptions column, click Sample.

Instead of the sample site, the following error appears:
https://xt7b9.sse.codesandbox.io/
Error: ENOENT: no such file or directory, stat '/sandbox/client/index.html'

Inconsistent live API examples documentation on `createSubscription`

in API documentation "short" example, createSubscription is called passing object with three attributes, but in an example function definition - it's defined with 3 parameters

https://stripe.com/docs/billing/subscriptions/fixed-price#create-subscription

Defined with 3 parameters:

function createSubscription(customerId, paymentMethodId, priceId) { ...

Passing object:

...
 createSubscription({
          customerId: customerId,
          paymentMethodId: result.paymentMethod.id,
          priceId: priceId,
        });

I a full example script, it's used with 3 attributes, so that would be preferred method.

https://github.com/stripe-samples/subscription-with-fixed-price/blob/master/client/script.js

Successful retried payments not returning success status

Bug report

Possible issue in fixed-price-subscriptions example.

Describe the bug

When a card is declined, and the customer retries with a new card, the payment status on the invoice (returned from retry-invoice) is open, and payment status never changes to success.

To Reproduce

In React.js mode:

  1. On the checkout, enter the payment fail test card 4000000000000341
  2. Press submit, and the error response is as declined, as expected.
  3. Enter the test card that should succeed 4242424242424242
  4. After onSubscriptionComplete, in setAccountInformation, result.subscription.status = open

Expected behavior

  1. On the checkout, enter the payment fail test card 4000000000000341
  2. Press submit, and the error response is as declined, as expected.
  3. Enter the test card that should succeed 4242424242424242
  4. After onSubscriptionComplete, in setAccountInformation, result.subscription.status = success

Solution

To solve it, I have modified onSubscriptionComplete with an extra check with retrievePaymentIntent for payments that have previously failed (see below).

    async function onSubscriptionComplete(result) {

        if (result && !result.subscription) {
            //this is hit when a payment failed and is retried, so there's no subscriptionon the result
            const subscription = { id: result.invoice.subscription };
            result.subscription = subscription;
            localStorage.removeItem('latestInvoiceId');
            localStorage.removeItem('latestInvoicePaymentIntentStatus');

            let paymentIntent = result.invoice.payment_intent

           //double check if the payment has been successful
            await stripe
                .retrievePaymentIntent(paymentIntent.client_secret)
                .then((confirmationResult) => {
                    console.log(confirmationResult)
                    if (confirmationResult.error) {
                        // start code flow to handle updating the payment details
                        // Display error message in your UI.
                        // The card was declined (i.e. insufficient funds, card has expired, etc)
                        throw confirmationResult.error;
                    } else {
                        if (confirmationResult.paymentIntent.status === 'succeeded') {
                            console.log('succeeded')
                          //do something like this to update payment status, not working properly though
                           result.invoice.subscription.status = confirmationResult.paymentIntent.status
                        }
                    }
                });
        }
     
        setAccountInformation(result);

        // Change your UI to show a success message to your customer.
        // successful if (accountInformation.subscription.status == 'active' || accountInformation.subscription.status =='succeeded')
    }

System information

  • OS: [e.g. macOS]
  • Browser (if applies) [chrome]
  • Server environment [ Node]

Additional context

Overall, I'm not sure this is even an issue, and doing this extra check is necessary..it depends if open status on an invoice means the subscription has succeeded.

[REQUEST] log-in integration

Subscription use case is useful,
but could be even more if you could integrate it with a full flagged sign-up/sign-in method.

clientSecret should not be passed as a queryPararm?

Bug report

Describe the bug

Hi there. Working on an integration when I came across the code in the frontend vanillajs example that passes the client secret between pages: https://github.com/stripe-samples/subscription-use-cases/blob/master/fixed-price-subscriptions/client/vanillajs/prices.js#L53-L55.

I know this repo is just for example and not expected to be a highly secure configuration. But in the tutorials online the handling of client secret was fairly opaque to me. For example in https://stripe.com/docs/billing/subscriptions/build-subscription, I inferred I should be accept the POST response from the Subscription.create call as JSON and then do some in-page DOM modifications to show the new payment element created w/the client secret, but I wasn't sure. Then when I found this github repo I was like "Voila! They just make a GET request and pass the clientSecret as a query param! Then the new subscribe.html page has its own js script lifecycle, and sets up the payment element - so easy! Client secret must not be that secret after all!"

Until I came across the API docs for payment element, https://stripe.com/docs/payments/payment-intents#passing-to-client, which explicitly state

Don’t log it, embed it in URLs, or expose it to anyone other than the customer.

Like I said, I understand the example repo says its not supposed to be secure, but shouldn't it follow the major expectations set by the API docs? This seems like a fairly substantial code flow difference. Passing the client secret as a query param is embedding it in the URL, to get logged, cached, etc. Or am I confused here (admittedly very likely)?

Anyway, I figured out how I'm going to proceed personally, but thought some attention might be given to this issue. Thanks!

Fixed Price Subscription Sample creating new payment methods instead of updating previous payment method.

Bug report

Describe the bug

Fixed Price Subscription Sample creating new payment methods instead of updating previous payment method.

To Reproduce

  1. Use card 4000000000000341 to test it and fails to charge customer.
  2. Using it again or add a new card, it creates a new payment method.

Expected behavior

The payment method should be updated if a customer already has a payment method attached to his account.

Expected header does not match header sent from Stripe test harness

Bug report

Describe the bug

When using the Stripe test harness to send events to the webhook endpoint, the "stripe-signature" header is sent with capitalised words, i.e. "Stripe-Signature".

This file is incorrect:
https://github.com/stripe-samples/subscription-use-cases/blob/master/fixed-price-subscriptions/server/node/server.js

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Provision a webhook
  2. Setup a webhook here: https://dashboard.stripe.com/test/webhooks/
  3. Send a test webhook event

Expected behavior

The demo code should properly reflect the actual header
https://github.com/stripe-samples/subscription-use-cases/blob/master/fixed-price-subscriptions/server/node/server.js

System information

  • AWS lambda function

Additional context

This was when using "Viewing test data", I'm yet to try in live.

Incorrect upcoming invoice calculations

Bug report

Describe the bug

The documentation here shows how to compute the immediate_total and next_invoice_sum amounts.

However, the logic is incorrect when using discounts.

See here: https://stripe.com/docs/billing/subscriptions/per-seat#change-price

To Reproduce

  1. Create a subscription with per-seat licensing and tiers.
  2. Create a customer and subscribe them to said subscription with a quantity of X.
  3. Attach a discount/coupon to this subscription. Make it 100% for simplicity.
  4. Recreate the code sample from the documentation, making sure to increase the quantity from X to X+1 for the upcoming invoice preview.

Expected behavior

Per the code sample and the 100% discount, I would expect both immediate_total and next_invoice_sum to both be zero. However, code sample will produce the right immediate_total of 0 but will not produce the right next_invoice_sum as the discount will be ignored.

Why? Because the logic loops over the line items of each invoice, and those don't reflect any discount.

Possible solution that works for me: next_invoice_sum = invoice.total - immediate_total. But I don't know how reliable this is.

Additional context

I checked the sample for all languages.

Changing subscription does not work

Bug report

Describe the bug

This is using Node.js and VanillaJS.

It is not possible to upgrade an existing subscription due to an IntegrationError.

To Reproduce

  1. I have signed up for the basic subscription and can see it is active in my account.
  2. I go to change-plan.html. Immediately the following error appears in the console:

[Error] Unhandled Promise Rejection: TypeError: null is not an object (evaluating 'subscriptionsDiv')
(anonymous function) (account.js:9)
asyncFunctionResume
(anonymous function)
promiseReactionJobWithoutPromise
promiseReactionJob

  1. I select the Premium plan, enter credit card details and click Subscribe. The following error appears in the console:

[Error] Unhandled Promise Rejection: IntegrationError: Invalid value for stripe.confirmCardPayment intent secret: value should be a client_secret string. You specified: null.
k (v3:1:54498)
(anonymous function) (subscribe.js:46)
asyncFunctionResume
(anonymous function) (subscribe.js:41)

  1. Nothing happens (no new subscription is created) and I am stuck on the credit card screen.

Expected behavior

The plan should upgrade and there should be proration.

System information

  • OS: macOS
  • Browser: happens in all browsers
  • Server environment: Node

3D secure challenge flow is not working.

Hi,

I'm running fixed-price-subscriptions in my local environment (ruby/server.rb and vanillajs).

This works fine for 424242424242424242, however, when using the 3D Secure challenge flow card number 4000000000003220, I get an error on the way and don't get the dialog.

When executing the createSubscription function in script.js, The server returns an error response. Then, in the Promiss, return response.json();, the Json A Parse error occurs.

What is the best way to fix this?

can't get to prices.html

Bug report

Simply can't get to prices.html, upon running the app I click on the 'Register' button & get 'The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.'

Steps to reproduce the behavior, please provide code snippets or a repository:

As per line 26 of register.js file found here

window.location.href = '/prices.html';

flask redirects to the url but that route isn't even defined anywhere in the server.py file found here...

Now I could simply create the route on my own

@app.route('/prices', methods=['GET'])
def get_prices():
    return render_template('prices.html')

which would remove the error but to be honest I don't know how to integrate that route with the rest of the server.py code... can someone assist???

flask

System information

  • OS: Ubuntu 18.04
  • Browser (if applies) [e.g. chrome, safari]
  • Server environment Python 3.6.9

Additional context

FYI I commented out lines 24 & 25 of the server.py & just replaced them with app = Flask(__name__) but I don't think that's an issue here. I'm just running a standard flask app where all the html,js & css are in the templates folder :) I made several attempts to configure the .env file like so STATIC_DIR=../../stripemonthly/templates but kept getting template not found errors

Trial period not showing up in the demo

I am currently testing the code and it all worked well until I got to the check out part. Instead of displaying the trial period, it says "Your subscription will start now". I see that in the official documentation that is in fact the case, but in the sandbox demo, the trial is shown.

Migrate to default_incomplete

  1. Update to fetch prices from server
  2. Create the subscription when the price is selected
  3. Pass the sub id and client_secret in query string when redirecting to subscribe.html
  4. Update and set the payment method as default on subscription

Payment method is left attached to customer if subscription.status incomplete

If stripe.subscriptions.create is successful but has a status of incomplete then it returns to the client to call stripe.confirmCardPayment. But at this point if the user abandons the purchase they're left with a unused payment method attached to their customer.

If stripe.confirmCardPayment also fails the user can submit the form again which creates a new payment method on the client (stripe.createPaymentMethod). On the server the new payment method is attached to the customer (payment_method.attach). Now the user has two new payment methods attached to their customer but one of them unused.

Is there a way to prevent the unused payment methods remaining attached to the customer?

Inconsistent response nesting

In some cases we return the JSON for the stripe object raw like:

subscription.to_json

In other cases we're nesting the response like:

{ customer: customer }.to_json

We should always nest so that if we need to return multiple things back to the client, we can add those without changing the API expected by the clients.

Huge Security Issue with Examples

I have contacted stripe support regarding a huge security issue I have found in the examples.

Support completely misunderstood me and were no help unfortunately. Should I describe the security issue here or should I write it to someone privately?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.