Code Monkey home page Code Monkey logo

svelte-stripe's Introduction

Everything you need to add Stripe Elements to your Svelte project. 100% SvelteKit compatible.

Stripe is now sponsoring this project

Documentation

Components

The following components are provided:

  • <Elements/>: A wrapper component to set context.
  • <CardNumber/>: Input field for the card's number.
  • <CardExpiry/>: Input field for the card's expiration date.
  • <CardCvc/>: Input field for Card Verification Value.
  • <Card/>: All-in-one component that has inputs for card number, expiry, cvc, and zip code.
  • <PaymentRequestButton/>: A GooglePay, ApplePay, or Link checkout button, depending on browser and user preferences.
  • <Iban/>: Input field for IBAN (International bank account number).
  • <Ideal/>: Input field for iDEAL (payment system used in the Netherlands).
  • <PaymentElement/>: All-in-one component that allows the user to choose the type of payment.
  • <ExpressCheckout/>: Pay with a wallet without leaving the page.
  • <LinkAuthenticationElement/>: Ability to use saved payment methods stored in Link.
  • <Address/>: Component for collecting billing and shipping addresses.

Examples

There is example code for:

Please open a PR or issue, if you'd like to add more.

Usage

See documentation for setup instructions and examples.

Sponsors

Stripe's logo

Code contributors

GitHub Contributors Image

Development mode

Run pnpm dev and visit https://localhost:5173:

pnpm dev

License

MIT

svelte-stripe's People

Contributors

chieft3ch avatar daniel-panhead avatar dependabot[bot] avatar hammadus avatar hmnd avatar joshnuss avatar mfix-stripe avatar scott-fischer avatar tnzk avatar unruha 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

svelte-stripe's Issues

Add Demo to README

Maybe it would be a good idea to add a demo to the README, in order for everyone to know what how it would look once they add this library to their application

client secret is not updated when creating new intent on the fly (on change)

Details:

  • Has 2 products, monthly and yearly subscriptions

Flow:

  1. On load, i would create a default subscription intent (monthly) then pass the clientSecret to the <Elements {stripe} clientSecret={userClientSecret} />
  2. I test pay it, and it is successful
  3. But, when I change the payment terms like to yearly, coz users has the right to change it either to monthly or yearly in the payment page, so if user decides to pay as yearly instead, I would delete previous subscription intent, then create new subscription intent, then the returned client secret I will update the variable "userClientSecret" which already mounted on load.
  4. I click Pay button, but it wouldn't pass, it will show 400 error

Why is that? Is the client secret not automatically updated? I mean, do I have to remount the component?

Add payment with Link

Saw this and thought it would be neat. Checked both the docs and some of the source code but didnt find any mentions of it being implemented (not so thoroughly though so excuse me if its already implemented). This library seems to have most payment methods so i think the very customer convinient Link method would be great to have

Embeddable Checkouts: Prefilled Emails.

Describe the problem

Most of the time, the user has already made an account by the time they go to checkout, so it would speed up things to...

Describe the proposed solution

...have the email be able to be prefilled in the embedded checkout component. It should be a variable that you can give to the svelte component. <EmbeddedCheckout prefilledEmail="[email protected]" />

Alternatives considered

No response

Importance

Nice to have

Additional Information

No response

How do I listen to element events?

Describe the bug

How do I listen to element events?

There appears to be no event handlers on element component

https://stripe.com/docs/js/element/events/on_loaderror

I get 'Unhandled payment Element loaderror' error

Reproduction

How do I listen to element events?

There appears to be no event handlers on element component

https://stripe.com/docs/js/element/events/on_loaderror

I get 'Unhandled payment Element loaderror' error

Severity

serious, but I can work around it

Additional Information

No response

Hidden Telemetry

Describe the bug

There is undisclosed telemetry in the utils.js file.

export function register(stripe) {
  if (!isServer) {
    return stripe.registerAppInfo({
      name: 'svelte-stripe-js',
      url: 'https://svelte-stripe-js.vercel.app'
    })
  }
}

For anyone considering using this package, it it not necessary. It's quite simple to integrate Stripe into SvelteKit without using these components.

Reproduction

It can be seen directly in the code.

Severity

serious, but I can work around it

Additional Information

No response

Changing locale of Elements

Describe the problem

I want my Stripe elements to be in a specific language all the time. It is not supported to change the language known in stripe docs as locale in the current state.

Describe the proposed solution

I would like an option to send a locale option when calling the Elements in svelte. This can be done when calling it in the source code with all the other options such as appearance and style (see stripe docs)

Alternatives considered

No response

Importance

Nice to have

Additional Information

No response

Elements custom fonts

I am working with the CardNumber, CardCvc, and CardExpiry elements, and unfortunately I wasn't able to get custom fonts working with the styling method shown in the examples.

However, in the stripe.js docs, when creating a new elements object there is the option to specify a fonts property which allows custom fonts to be used. However, currently the Elements component does not support this property. I believe adding this functionality shouldn't be too difficult since the @stripe/stripe-js package provides support for this already.

Elements.svelte just needs to accept a font variable:


/** @type {StripeElementsOptions["fonts"]} */
export let fonts = []
...
export let elements = isServer ? null : stripe.elements({ appearance: { theme, variables, rules, labels }, clientSecret, fonts, loader })

As well as the appropriate type being added to Elements.svelte.d.ts:

fonts?: import('@stripe/stripe-js').StripeElementsOptions["fonts"];

I tested these changes out on my local machine and I was able to get a custom Google font to work.

npm run build fails after adding css to svelte file

This error is produced
[rollup-plugin-dynamic-import-variables] Unexpected token (10:400)
file: /Users/user/project/stripe/src/routes/index.svelte:10:400

index.svelte -

<script>
	import { onMount } from 'svelte';
	import { loadStripe } from '@stripe/stripe-js';
	import { Container, CardNumber, CardExpiry, CardCvc } from 'svelte-stripe-js';

	let stripe = null;
	let cardElement;

	onMount(async () => {
		stripe = await loadStripe(import.meta.env.VITE_STRIPE_PUBLIC_KEY);
	});

	async function submit() {
		const result = await stripe.createToken(cardElement);

		// create payment intent
	}
</script>

{#if stripe}
	<Container {stripe}>
		<form on:submit|preventDefault={submit}>
			<CardNumber bind:element={cardElement} />
			<CardExpiry />
			<CardCvc />

			<button>Pay</button>
		</form>
	</Container>
{/if}

<style>
	* {
		background-color: blue;
	}
</style>

CORS issue with https://js.stripe.com

Hi,
I am trying to use this library on a sapper project. I have created a bare implementation of PaymentElemet component and trying to do a payment.
I am running into the issue where I am getting the following error

Access to XMLHttpRequest at 'https://r.stripe.com/0' from 
origin 'https://js.stripe.com' has been blocked by
CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
POST https://r.stripe.com/0 net::ERR_FAILED 400

My understanding for this is that js.stripe.com based library is trying to make a call to r.stripe.com which fails as they dont allow my origin.

For reference this is my CSP header

	<meta http-equiv="Content-Security-Policy" 
		content="
			img-src * 'self' data:;
			frame-src 'self' https://js.stripe.com https://hooks.stripe.com;
			connect-src * https://api.stripe.com;
			script-src 'self' 'unsafe-eval' https://js.stripe.com;
			script-src-elem * data: blob: 'unsafe-inline';
			script-src-attr 'self' data: 'unsafe-inline';
			object-src 'none'
		"
	/>

TIA

Failed to resolve entry for package (SvelteKit / Vite)

Hey, I just tried to start a fresh SvelteKit project with this package. Upon running, I encountered the following error using your example code:

yarn run v1.22.5
warning package.json: No license field
$ svelte-kit dev
 > node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:38757:14: error: [plugin: vite:dep-scan] Failed to resolve entry for package "svelte-stripe-js". The package may have incorrect main/module/exports specified in its package.json.
    38757 │         throw new Error(`Failed to resolve entry for package "${id}". ` +
          ╵               ^
    at resolvePackageEntry (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:38757:15)
    at tryNodeResolve (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:38576:11)
    at Context.resolveId (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:38459:28)
    at Object.resolveId (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:50882:55)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async resolve (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:51079:26)
    at async /Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:51181:34
    at async callback (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:812:28)
    at async handleRequest (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:644:30)

   node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:51171:18: note: This error came from the "onResolve" callback registered here
    51171 │             build.onResolve({
          ╵                   ~~~~~~~~~
    at setup (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:51171:19)
    at handlePlugins (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:736:23)
    at Object.buildOrServe (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1024:7)
    at /Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1754:17
    at new Promise (<anonymous>)
    at Object.build (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1753:14)
    at Object.build (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1629:51)
    at /Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:51039:54
    at Array.map (<anonymous>)

   html:/Users/didier/Projects/Experiments/stripe/src/routes/index.svelte:2:61: note: The plugin "vite:dep-scan" was triggered by this import
        2 │   import { Container, CardNumber, CardExpiry, CardCvc } from 'svelte-stripe-js'
          ╵                                                              ~~~~~~~~~~~~~~~~~~

> Build failed with 1 error:
node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:38757:14: error: [plugin: vite:dep-scan] Failed to resolve entry for package "svelte-stripe-js". The package may have incorrect main/module/exports specified in its package.json.
Error: Build failed with 1 error:
node_modules/.pnpm/[email protected]/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:38757:14: error: [plugin: vite:dep-scan] Failed to resolve entry for package "svelte-stripe-js". The package may have incorrect main/module/exports specified in its package.json.
    at failureErrorWithLog (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1449:15)
    at /Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1131:28
    at runOnEndCallbacks (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:921:63)
    at buildResponseToResult (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1129:7)
    at /Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:1236:14
    at /Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:609:9
    at handleIncomingPacket (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:706:9)
    at Socket.readFromStdout (/Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/[email protected]/node_modules/esbuild/lib/main.js:576:7)
    at Socket.emit (node:events:394:28)
    at Socket.emit (node:domain:470:12)
file:///Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/@[email protected][email protected]/node_modules/@sveltejs/kit/dist/chunks/index.js:3373
                        throw new Error('Cannot close server before it is initialized');
                              ^

Error: Cannot close server before it is initialized
    at Watcher.close (file:///Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/@[email protected][email protected]/node_modules/@sveltejs/kit/dist/chunks/index.js:3373:10)
    at process.<anonymous> (file:///Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/@[email protected][email protected]/node_modules/@sveltejs/kit/dist/chunks/index.js:3199:9)
    at process.emit (node:events:394:28)
    at process.emit (node:domain:470:12)
    at process.exit (node:internal/process/per_thread:184:15)
    at handle_error (file:///Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/@[email protected][email protected]/node_modules/@sveltejs/kit/dist/cli.js:851:10)
    at file:///Users/didier/Projects/Experiments/stripe/node_modules/.pnpm/@[email protected][email protected]/node_modules/@sveltejs/kit/dist/cli.js:903:4
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Need to add a style object...unclear how...

I need to style the elements, something along these lines...

  let style = {
    base: {
      padding: '8px',
      color: '#ffffff',
      fontFamily: 'Avenir Next',
      fontSmoothing: 'antialiased',
      fontSize: '16px',
      '::placeholder': {
        color: '#aaaaaa'
      },
    },
    invalid: {
      color: '#fa755a',
    }
  };

but I'm unclear as to how to do that in this library.

One does something like this usually:

let idealBank = elements.create('idealBank', {style: style});

...but unclear as to how to do this using the library :-)

dumb question??? How do i make the button 'submit'

Sorry if this is a dumb question but I'm not sure how to hook up the pay button to actually submit the form...I assume this is not stripe elements specific, but is there anything I would need to do here beyond adding type='submit' to the submit button to make it work with stripe elements?

svelte-stripe will not build on vite v2.8.6 / sveltekit 294

Hi,

I tried to run the following code:

<script > import { Container } from 'svelte-stripe'; let stripe = null; </script>

However, on pnpm build - svelte-kit build --verbose

I receive the following error:

[vite:resolve] Failed to resolve entry for package "svelte-stripe". The package may have incorrect main/module/exports specified in its package.json: Failed to resolve entry for package "svelte-stripe". The package may have incorrect main/module/exports specified in its package.json.

Failed to resolve entry for package "svelte-stripe". The package may have incorrect main/module/exports specified in its package.json: Failed to resolve entry for package "svelte-stripe". The package may have incorrect main/module/exports specified in its package.json.

I am running "svelte-stripe": "^0.0.13"

How to retrieve/input/use products and prices from stripe...

So,

Trying to read through the stripe docs but unclear about how I might go about retrieving/inputting/using stripe products and prices using SvelteKit. Just curious if you have thought about this at all and/or have any solutions to this kind of thing...it's one thing to manually add one price point, but another thing to integrate with products and prices from the stripe dashboard/account...

Thank you! XD

Can't create a new embedded checkout: 'target is null'

Describe the bug

Whenever you add a new EmbeddedCheckout component to a div, (and yes, i deleted the old one beforehand), it says the error "target is null" when that is definately not the case. Here's the code: https://codeberg.org/arth/observer/src/branch/next/src/routes/subscribe/+page.svelte

Reproduction

https://codeberg.org/arth/observer/src/branch/next/src/routes/subscribe/+page.svelte

Severity

blocking all usage

Additional Information

For context, i need to be able to do this because the whole reason I started using this in the first place is because stripe's payment links dont support choosing multiple plans. So, the left third of the page describes the different plans and the user selects a plan, and the right page has the embedded checkout of the selected plan.

Error when the payment modal is opened the second time

Describe the bug

<Elements /> is put into a modal that is opened on demand. However, if you close the modal and open it again, it will show the following error:

Uncaught (in promise) IntegrationError: Can only create one Element of type payment.

I believe there's something wrong with the bind:elements in <Elements />

Reproduction

<Modal bind:open={payModal} permanent={processing}>
    <div class="bg-white rounded-lg p-5">
        <div class="flex items-center my-5">
            <img src={BIcon} width="50" height="50" />
            <p class="text-2xl font-bold text-black mx-2">B</p>
        </div>
        {#if stripe && clientSecret}
            <div class="my-5">
                <Label for='email-input' class='block mb-2'>Email Address</Label>
                <Input id="email-input" type="email" size="lg" placeholder="[email protected]">
                    <svg slot="left" aria-hidden="true" class="w-5 h-5 text-gray-500 dark:text-gray-400" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"></path><path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"></path></svg>
                </Input>
            </div>
            <Elements {stripe} {clientSecret} bind:elements>
                <form on:submit|preventDefault={onSubmit} id="payment-form">
                    <PaymentElement />
                </form>
                <Button type="submit" form="payment-form" disabled={processing} class="my-5">
                    {#if processing}
                        <Spinner class="mr-3" size="4" color="white" />
                    {/if}
                    Pay
                </Button>
            </Elements>
        {/if}
        <p class="text-gray-700 italic font-light">Payment powered by Stripe</p>
    </div>
</Modal>

You can use any kind of modal, in this case I'm using Flowbite's <Modal />, you just have to close and reopen the modal and the error will appear.

Severity

annoyance

Additional Information

I know <Elements /> was probably not meant to be put in a popup/modal but it would be nice if this can be fixed

SvelteKit2 complains about missing export

Describe the bug

When building / running against a SvelteKit v2 project, I receive the following warning:

11:42:47 PM [vite-plugin-svelte] WARNING: The following packages have a svelte field in their package.json but no exports condition for svelte.

[email protected]

Please see https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition for details.

Reproduction

  1. Create an entirely new SvelteKit v2 project
  2. Add svelte-stripe
  3. run

Severity

annoyance

Additional Information

https://github.com/sveltejs/vite-plugin-svelte/blob/main/docs/faq.md#missing-exports-condition

Sveltekit support?

Apologies if you mentioned it and I missed it, but is sveltekit support included? And if not, does anything need to be altered in any way?

Thanks :-)

PaymentElement missing options

Describe the problem

It is not currently possible to specify options such as layout or defaultValues when creating a PaymentsElement.

Describe the proposed solution

The solution would be similar to the Address element, which offers this possibility.

Alternatives considered

No response

Importance

Would make my life easier

Additional Information

No response

Implement on:paymentmethod and on:shippingaddresschange

Describe the problem

I'm trying to figure out how to listen to shipping method changes to update the total, but can't figure this out yet.
There's a clear example on how to do this in Stripe's docs but no mention of it in svelte-stripe. It seems like the shpping method update event isn't propagated or added to the API.

Here's a reference to it
https://stripe.com/docs/stripe-js/elements/payment-request-button?client=html#html-js-collecting-shipping-info

Describe the proposed solution

  • Add shipping method update events to the API if not yet there, OR
  • If it's there, mention it in the documentation.

Alternatives considered

No response

Importance

I cannot use Svelte-Stripe without it

Additional Information

I need this since we have different shipping methods with different pricing, and "express" payment is important to us.

Failed to resolve entry

Describe the bug

Error: Failed to resolve entry for package "svelte-stripe". The package may have incorrect main/module/exports specified in its package.json.

Reproduction

my depencies

	"devDependencies": {
		"@stripe/stripe-js": "^2.1.11",
		"@sveltejs/adapter-auto": "^2.0.0",
		"@sveltejs/adapter-node": "^1.3.1",
		"@sveltejs/kit": "^1.20.4",
		"autoprefixer": "^10.4.16",
		"postcss": "^8.4.31",
		"stripe": "^14.5.0",
		"svelte": "^4.0.5",
		"svelte-check": "^3.4.3",
		"svelte-stripe": "^1.1.1",
		"tailwindcss": "^3.3.5",
		"tslib": "^2.4.1",
		"typescript": "^5.0.0",
		"vite": "^4.4.2"
	},

the command i used

pnpm install -D stripe svelte-stripe

Severity

blocking all usage

Additional Information

I ve tried to add noExternal: ['svelte-stripe-js'], to svelte.config.js without success

Invalid request body when running the first time the package.

Describe the bug

Hello,

After cloning the package, and running as described with the command line: pnpm dev,

The server starts on the URL : https://localhost:5173/

But when I open it, the message: "Invalid request body" along with the not secured flag next to the URL.
I cannot figure out how to run it properly.

Capture d’écran 2024-01-10 à 22 16 16

Please help,
Many thanks,

Benjamin

Reproduction

  1. Clone the project: git clone https://github.com/joshnuss/svelte-stripe.git
  2. And the .env file to the root with the PUBLIC_STRIPE_KEY and SECRET_STRIPE_KEY
  3. Run pnpm dev,
  4. Go to https://localhost:5173/

Severity

annoyance

Additional Information

No response

Seems legal policies are not shown?

I configured legal policies for my account on stripe as per https://stripe.com/docs/payments/checkout/customization#configure-support-and-legal-policies , and I turned on "Display agreement to legal terms" in https://dashboard.stripe.com/settings/checkout .

I expected to see a checkbox forcing a customer to agree to terms before clicking pay, but that didn't happen.

Might be me as this is my first time using stripe, but might also be a missing feature of the svelte adapter?

Dealing with stripe products...

Hi Josh!

Sooooo, coming back around to this...I have created products using the Stripe Dashboard and would like to access them in svelte-stripe. Dunno where to start or what to do to make that a thing...

Thinking about it a bit I suppose a couple options would be to grab them at runtime on a users device, or grab them at build time so that API call would not be necessary...I'm thinking the second choice is probably the better one, but not sure...

In either case...I just don't know where to start or how to go about it...

But before I go too deep into it, I was curious if you have thought about it much or have any thoughts and/or suggestions in this regard...

Thank you in advance :-)

ENV VAR's for stripe keys...

So, in the docs the examples show the test key in the .svelte file, but this does not seem to be the best idea, no?

I would assume they should be in ENV VAR's on the server and fed into the component...just don't quite know how to do that myself...and putting it into the component file itself means that it will be seen by github, which does not seem like a good idea, I think.

So this isn't an issue with the library directly, but rather a question as to how to go about using ENV Var's in the context of this library...I don't really know, but I believe that using VITe's built-in environment variables is not recommended for secret keys...

...curious if you have some suggestions as to what the best way to go about this would be...

id attribute on card elements

It would be great if one could add an id to the CardNumber, CardExpiry and CardCvc elements so labels work with them.

Is that possible or do stripe elements prevent that?

Passing metadata into stripe paymentIntent

Hello, I followed the docs until I ran into this issue with the paymentIntent flow. I need the ability to pass data from a svelte store into my paymentIntent post request, but this is not possible in a svelte module context. Is there any way to achieve this?

export async function load({ fetch }) {
  const response = await fetch('createPaymentIntent', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ metadata, session })
  })
  const { clientSecret } = await response.json()
  console.log(clientSecret)
  return {
    props: {
      clientSecret
    }
  }
}                     

Issue with PaymentElement default value for name

Describe the bug

When attempting to load default value for the name field of the PaymentElement. The value passed into the options is not pre-filling the input.
I am attempting to pass values to both the Email and the Name fields, and only the email's default value is showing.

Reproduction

Taking the PaymentElement example, you can attempt to pass the default values like below and see that the email works, but the name doesn't.

<Elements
...
<PaymentElement 
  options={{
    defaultValues: {
      billingDetails: {
        name: 'Bob',
        email: '[email protected]'
      }
    }
  }}
  />
</Elements>

Severity

annoyance

Additional Information

I'm not sure what's going on for it to partially work for one value and not the other. I've triple checked the stripe docs to make sure the object I'm passing in is in the right format and targeting the correct property names. I've also attempted to downgrade the stripe libs to as low as 13.11 to see if that's able to resolve it with no success.
Thanks for a great library, let me know what I can do to help test and sort this out.

EmbeddedCheckout IntegrationError: You cannot have multiple Embedded Checkout objects.

Describe the bug

First of all, thank you for the work put into this project, its providing a much cleaner checkout flow in SvelteKit for me as opposed to other methods.

When you load Embedded Checkout then navigate away client-side, and try to load the Embedded Checkout element again, you get this error on the client and the checkout doesn't load:
svelte-stripe-error

The checkout element then loads again when you refresh the page.

Reproduction

Create a checkout session on the server side (outlined here). Then mount the embedded checkout element and pass it your client secret provided by the checkout session creation response. It should show correctly on the first load.

If you navigate elsewhere on the client side then return to the checkout page and try to mount the embedded checkout element again, you see the error outlined above and the element doesn't show.

This behavior is seen both with the same checkout client secret and if you generate a new client secret before mounting the element.

Refreshing the page causes the element to load correctly again.

<script lang="ts">
    import { loadStripe } from "@stripe/stripe-js";
    import { onMount } from "svelte";
    import { EmbeddedCheckout } from "svelte-stripe";

    export let data: PageData;

    let stripe = null;

    onMount(async () => {
        stripe = await loadStripe(STRIPE_PUBLISHABLE_KEY);
    });
</script>

<div>
    <EmbeddedCheckout {stripe} clientSecret={data.clientSecret} >
    </EmbeddedCheckout>
</div>

Severity

serious, but I can work around it

Additional Information

No response

Elements theme and rules properties not working

image
I'm having trouble making the cardnumber input text white. Selecting a theme with the Elements component doesn't change anything, no errors or something alike. Using the rules and targeting .Input doesn't do anything either, it does throw an error when I type an invalid css value, but text color remains the same.
What am I doing wrong?
My checkout screen:

<script` lang="ts">
	import { PUBLIC_STRIPE_KEY } from '$env/static/public';
	import { onMount } from 'svelte';
	import { loadStripe, type Stripe, type StripeError } from '@stripe/stripe-js';
	import {
		Button,
		Column,
		FluidForm,
		Grid,
		Loading,
		Row,
		TextInput,
		Tile
	} from 'carbon-components-svelte';
	import { onDestroy } from 'svelte';
	import { CardCvc, CardExpiry, CardNumber, Elements } from 'svelte-stripe';
	import { goto } from '$app/navigation';
	import { cart, type CartProduct } from '$lib/stores';
	import Product from '../../components/Product.svelte';
	import { prevent_default } from 'svelte/internal';
	let elements: any;
	let clientSecret: string | null = null;
	let stripe: Stripe | null = null;
	let cartItems: CartProduct[];
	let cardElement: any;
	let email = '';
	let processing = false;
	let error: StripeError | null;
	let price: number | null;
	const fetchSecret = async () => {
		stripe = await loadStripe(PUBLIC_STRIPE_KEY);
		let response = await fetch('/api/stripe/create-payment-intent', {
			method: 'POST',
			headers: { 'Content-Type': 'application/json' },
			body: JSON.stringify({ items: cartItems })
		});
		let data = await response.json();
		clientSecret = data.client_secret;
		price = data.total_price;
	};

	const unsubscribe = cart.subscribe((value) => (cartItems = value));

	onMount(() => {
		fetchSecret();
	});

	async function submit() {
		// avoid processing duplicates
		if (!stripe) {
			return;
		}
		if (!clientSecret) {
			return;
		}
		if (processing) return;
		processing = true;
		// confirm payment with stripe
		const result = await stripe.confirmCardPayment(clientSecret, {
			payment_method: {
				card: cardElement,
				billing_details: {
					name: 'Oscar'
				}
			}
		});
		if (result.error) {
			// payment failed, notify user
			error = result.error;
			processing = false;
		} else {
			// payment succeeded, redirect to "thank you" page
			cart.clear();
			goto('/thanks');
		}
	}

	onDestroy(unsubscribe);
</script>

<svelte:head>Checkout</svelte:head>
{#if cartItems.length > 0}
	{#if error != null}
		{error}
	{:else if clientSecret != null && stripe != null && price != null}
		<Grid>
			<Row>
				<Column>
					{#each cartItems as item}
						<Product product={item.product} />
					{/each}
				</Column>
				<Column>
					<FluidForm
						on:submit={async (e) => {
							prevent_default(e);
							await submit();
						}}
					>
						<Elements
							theme="night"
							rules={{
								'.Input': {
									color: '#f4f4f4'
								}
							}}
							bind:elements
							{clientSecret}
							{stripe}
						>
							<h3>{(price / 100).toFixed(1)} kr</h3>
							<TextInput
								labelText="Email"
								bind:value={email}
								placeholder="[email protected]"
								required
							/>
							<div class="bx--form-item bx--text-input-wrapper">
								<label for="cardnumber" class="bx--label">Card number</label>
								<CardNumber
									classes={{ base: 'bx--text-input cardinput' }}
									bind:element={cardElement}
								/>
							</div>
							<div class="flex">
								<div class="bx--form-item bx--text-input-wrapper">
									<label for="cardnumber" class="bx--label">Card expiration</label>
									<CardExpiry classes={{ base: 'bx--text-input cardinput' }} />
								</div>
								<div class="bx--form-item bx--text-input-wrapper">
									<label for="cardnumber" class="bx--label">CVC</label>
									<CardCvc classes={{ base: 'bx--text-input cardinput' }} />
								</div>
							</div>
							<Button type="submit" id="submit" class="my-4">Submit</Button>
						</Elements>
					</FluidForm>
				</Column>
			</Row>
		</Grid>
	{:else}
		<Loading />
	{/if}
{:else}
	<div class="flex items-center justify-center">
		<h2>Your cart is empty</h2>
	</div>
{/if}

<style>
	:global(.cardinput) {
		color: #f4f4f4 !important;
	}
</style>

getting a few errors trying to implement the lib...

here is the code I'm running in the <script> tag:

<script>
  import { isServer, Container, CardNumber, CardExpiry, CardCvc } from 'svelte-stripe-js';

  const stripe = isServer ? null : Stripe('pk_test_1234');

  let cardElement;

  async function submit() {
    const result = await stripe.createToken(cardElement);

    const paymentIntent = await stripe.paymentIntents.create({
      amount: 999,
      currency: 'usd',
      payment_method_types: ['card'],
    });
  }
</script>

...and I'm getting the following errors in the console:

proxy.js:15 [HMR][Svelte] Unrecoverable error in <Stripe>: next update will trigger a full reload
stripe.svelte? [sm]:27 Uncaught (in promise) ReferenceError: Stripe is not defined
    at instance (stripe.svelte? [sm]:27)
    at init (index.mjs?v=6ff4de4f:1784)
    at new Stripe_1 (stripe.svelte? [sm]:118)
    at createProxiedComponent (svelte-hooks.js:245)
    at new ProxyComponent (proxy.js:239)
    at new Proxy<Stripe> (proxy.js:339)
    at create_if_block_2 (root.svelte? [sm]:38)
    at Array.create_default_slot (root.svelte? [sm]:37)
    at create_slot (index.mjs?v=6ff4de4f:69)
    at create_fragment (__layout.svelte? [sm]:21)

Unable to update payment element theme with a remount

I noticed that your recommended way to update the CSS of the Payment Element (discussed here)

I'm actually totally okay with destroying the user input state, however, I'm having an interesting issue when trying to unmount and remount with the key directive. Whenever my watched value changes, I'm seeing v3:1 Uncaught (in promise) IntegrationError: Can only create one Element of type payment.

To test if the issue is simply being caused by a failure to unmount the component, I added this to my click event handler:

const paymentElement = elements.getElement('payment');
paymentElement.destroy();

This time, I see: Uncaught (in promise) IntegrationError: This Element has already been destroyed. Please create a new one.

This leads me to wonder if the problem is being caused by a bit of a race condition, where it's attempting to add mount the new component before removing the old one.

I created a reproducible example on code sandbox (bring your own stripe key + intent)

getting an ESM error when trying to use the library...

getting the following error in the terminal when trying to use the library:

[vite] Error when evaluating SSR module /Users/rchrdnsh/Code/Svelte/RYKR-kit/src/routes/stripe.svelte:
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/svelte-stripe-js/index.js
require() of ES modules is not supported.
require() of /Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/svelte-stripe-js/index.js from /Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/vite/dist/node/chunks/dep-c1a9de64.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/svelte-stripe-js/package.json.

    at new NodeError (node:internal/errors:363:5)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1126:13)
    at Module.load (node:internal/modules/cjs/loader:989:32)
    at Function.Module._load (node:internal/modules/cjs/loader:829:14)
    at Module.require (node:internal/modules/cjs/loader:1013:19)
    at require (node:internal/modules/cjs/helpers:93:18)
    at nodeRequire (/Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:73479:17)
    at ssrImport (/Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:73431:20)
    at eval (/Users/rchrdnsh/Code/Svelte/RYKR-kit/src/routes/stripe.svelte:12:31)
    at instantiateModule (/Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/vite/dist/node/chunks/dep-c1a9de64.js:73464:166)
Must use import to load ES Module: /Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/svelte-stripe-js/index.js
require() of ES modules is not supported.
require() of /Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/svelte-stripe-js/index.js from /Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/vite/dist/node/chunks/dep-c1a9de64.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename index.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from /Users/rchrdnsh/Code/Svelte/RYKR-kit/node_modules/svelte-stripe-js/package.json.

...dunno if there is something that I need to do differently, as I have really only copied and pasted your code example so far...

I'm on the latest version of sveltekit, which at this moment is 144...

Does not work in Astro

Describe the bug

Get an error in Astro whhen using a component containing or any other component from this repo.

Tried both client:load and client:only. Would seem to me that client:only should work, because it is just svelte, but maybe my knowlegde in lacking here.

onMount function is not fired at all.

error:
[HMR][Svelte] Unrecoverable HMR error in <SvelteStripe>: next update will trigger a full reload

Reproduction

  1. Create an astro project
  2. create an astro page
  3. create a svelte component with the following code:
<script>
  import { loadStripe } from '@stripe/stripe-js'
  import { Elements, PaymentElement } from 'svelte-stripe'
  import { onMount } from 'svelte'
  import Stripe from 'stripe'

  async function createPaymentIntent() {
    return await stripeSecret.paymentIntents.create({
      amount: 2000,
      currency: 'eur',
      automatic_payment_methods: {
        enabled: true,
      },
    })
  }

  async function confirmPayment() {
    return await stripeSecret.confirmPayment({
      elements,
    })
  }

  let stripePublic = null
  let stripeSecret = null
  let clientSecret = null
  let elements

  onMount(async () => {
    console.log('onMount')
    stripePublic = await loadStripe(
      'yourpublickey'
    )
    stripeSecret = new Stripe(
      'yourtestkey'
    )
    clientSecret = await createPaymentIntent()

    console.log('stripePublic', stripePublic)
    console.log('stripeSecret', stripeSecret)
    console.log('clientSecret', clientSecret)
  })
</script>

<h1>Hello svelte stripe</h1>
<form on:submit|preventDefault={confirmPayment}>
  <Elements
    stripe={stripePublic}
    {clientSecret}
    bind:elements
  >
    <PaymentElement />
  </Elements>

  <button>Pay</button>
</form>
  1. import it with or

Severity

blocking all usage

Additional Information

Astro version 3.0.7

feat: upgrade to stripe-js 2.1

Describe the problem

StripeJS version is far outdated, and PNPM does not allow access to dependent packages. Asking users to depend on the package's version is also an antipattern.

Describe the proposed solution

Upgrade to Stripe Elements v2.1

Alternatives considered

For now I will lock to the previous version until new version is available. May make a pull request this weekend if it will be well-received.

Importance

Would make my life easier

Additional Information

No response

No way to set PaymentElement layout as Accordion

Describe the bug

as per the Stripe docs: https://stripe.com/docs/elements/appearance-api
there is a possibility of setting the Payment element as Accordion. from what i've seen this is not supported in svelte-stripe?

Reproduction

	<Elements
		{stripe}
		{clientSecret}
		theme="night"
		options={{
			layout: { type: 'accordion' },
		}} // doesn't work
	>
		<PaymentElement />
	</Elements>

Severity

blocking all usage

Additional Information

No response

EDIT:
My mistake. It works but I've put it in the wrong component.
Working example:

<Elements {stripe} {clientSecret} theme="night">
		<PaymentElement
			options={{
				layout: { type: 'accordion' },
			}}
		/>
</Elements>

I guess better docs could help. I found that options param in another framework's library actually and then found issue in this repo about somebody implementing support for those options

Address Component Type requires multiple props than just Mode (based off of example)

Describe the bug

Based on the example of the <Address> component used in the example here, the component only uses the prop of mode. Based on the type definition, the <Address> component requires: allowCountries, blockPoBox, defaultValues, fields, validation, contacts, and display.

Reproduction

Use the address component from the example and see the type errors.

Severity

annoyance

Additional Information

No response

Styling: Classes can't reach the font of the input.

I'm using tailwind and we have a bunch of custom utility classes set up for our design system. I'm trying to send those classes into the stripe elements, but it looks as though I can only reach the text inside the input using the style prop. Classes (even non-tailwind ones specified with global don't affect the text at all.

<script lang="ts">
const classes: StripeElementClasses = {
  base: 'stripe-input'
}
</script>

<CardNumber bind:value={cardElement} {classes} />

<style>
:global(.strip-input) {
  font-color: blue;
  font-size: x-large;
}
</style>

Expose loading option on payment element

Stripe exposes an option to change the appearance of the loading state while the payment element is initialized. This option is missing from the PaymentElement svelte component.

I opened a PR to address this #31

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.