Browse Source

fix(payments-plugin): Use idempotency key for Stripe API calls

Michael Bromley 3 years ago
parent
commit
9b77d5c79a
1 changed files with 16 additions and 25 deletions
  1. 16 25
      packages/payments-plugin/src/stripe/stripe.service.ts

+ 16 - 25
packages/payments-plugin/src/stripe/stripe.service.ts

@@ -31,32 +31,23 @@ export class StripeService {
         if (this.options.storeCustomersInStripe && ctx.activeUserId) {
             customerId = await this.getStripeCustomerId(ctx, order);
         }
-
-        // From the [Stripe docs](https://stripe.com/docs/currencies#zero-decimal):
-        // > All API requests expect amounts to be provided in a currency’s smallest unit.
-        // > For example, to charge 10 USD, provide an amount value of 1000 (that is, 1000 cents).
-        // > For zero-decimal currencies, still provide amounts as an integer but without multiplying by 100.
-        // > For example, to charge ¥500, provide an amount value of 500.
-        //
-        // Therefore, for a fractionless currency like JPY, we need to divide the amount by 100 (since Vendure always
-        // stores money amounts multiplied by 100). See https://github.com/vendure-ecommerce/vendure/issues/1630
-        const amountInMinorUnits = this.currencyHasFractionPart(order.currencyCode)
-            ? order.totalWithTax
-            : Math.round(order.totalWithTax / 100);
-
-        const { client_secret } = await this.stripe.paymentIntents.create({
-            amount: amountInMinorUnits,
-            currency: order.currencyCode.toLowerCase(),
-            customer: customerId,
-            automatic_payment_methods: {
-                enabled: true,
-            },
-            metadata: {
-                channelToken: ctx.channel.token,
-                orderId: order.id,
-                orderCode: order.code,
+        const amountInMinorUnits = getAmountInStripeMinorUnits(order);
+        const { client_secret } = await this.stripe.paymentIntents.create(
+            {
+                amount: amountInMinorUnits,
+                currency: order.currencyCode.toLowerCase(),
+                customer: customerId,
+                automatic_payment_methods: {
+                    enabled: true,
+                },
+                metadata: {
+                    channelToken: ctx.channel.token,
+                    orderId: order.id,
+                    orderCode: order.code,
+                },
             },
-        });
+            { idempotencyKey: `${order.code}_${amountInMinorUnits}` },
+        );
 
         if (!client_secret) {
             // This should never happen