@vendure/payments-plugin 2.0.0-next.8 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +36 -0
  2. package/package/braintree/braintree-common.d.ts +4 -2
  3. package/package/braintree/braintree-common.js +11 -5
  4. package/package/braintree/braintree-common.js.map +1 -1
  5. package/package/braintree/braintree.handler.js +14 -7
  6. package/package/braintree/braintree.handler.js.map +1 -1
  7. package/package/braintree/braintree.plugin.d.ts +52 -4
  8. package/package/braintree/braintree.plugin.js +53 -5
  9. package/package/braintree/braintree.plugin.js.map +1 -1
  10. package/package/braintree/braintree.resolver.d.ts +2 -1
  11. package/package/braintree/braintree.resolver.js +27 -6
  12. package/package/braintree/braintree.resolver.js.map +1 -1
  13. package/package/braintree/index.js +5 -1
  14. package/package/braintree/index.js.map +1 -1
  15. package/package/braintree/types.d.ts +62 -4
  16. package/package/braintree/types.js.map +1 -1
  17. package/package/mollie/graphql/generated-shop-types.d.ts +489 -338
  18. package/package/mollie/graphql/generated-shop-types.js +25 -2
  19. package/package/mollie/graphql/generated-shop-types.js.map +1 -1
  20. package/package/mollie/index.js +5 -1
  21. package/package/mollie/index.js.map +1 -1
  22. package/package/mollie/mollie-shop-schema.js +25 -0
  23. package/package/mollie/mollie-shop-schema.js.map +1 -1
  24. package/package/mollie/mollie.controller.d.ts +2 -1
  25. package/package/mollie/mollie.controller.js +14 -8
  26. package/package/mollie/mollie.controller.js.map +1 -1
  27. package/package/mollie/mollie.handler.d.ts +14 -0
  28. package/package/mollie/mollie.handler.js +53 -15
  29. package/package/mollie/mollie.handler.js.map +1 -1
  30. package/package/mollie/mollie.helpers.d.ts +33 -0
  31. package/package/mollie/mollie.helpers.js +142 -0
  32. package/package/mollie/mollie.helpers.js.map +1 -0
  33. package/package/mollie/mollie.plugin.d.ts +75 -21
  34. package/package/mollie/mollie.plugin.js +61 -19
  35. package/package/mollie/mollie.plugin.js.map +1 -1
  36. package/package/mollie/mollie.resolver.d.ts +3 -4
  37. package/package/mollie/mollie.resolver.js +13 -1
  38. package/package/mollie/mollie.resolver.js.map +1 -1
  39. package/package/mollie/mollie.service.d.ts +21 -10
  40. package/package/mollie/mollie.service.js +188 -71
  41. package/package/mollie/mollie.service.js.map +1 -1
  42. package/package/stripe/index.js +5 -1
  43. package/package/stripe/index.js.map +1 -1
  44. package/package/stripe/metadata-sanitize.d.ts +13 -0
  45. package/package/stripe/metadata-sanitize.js +33 -0
  46. package/package/stripe/metadata-sanitize.js.map +1 -0
  47. package/package/stripe/raw-body.middleware.js.map +1 -1
  48. package/package/stripe/stripe-client.d.ts +9 -0
  49. package/package/stripe/stripe-client.js +21 -0
  50. package/package/stripe/stripe-client.js.map +1 -0
  51. package/package/stripe/stripe-utils.d.ts +19 -0
  52. package/package/stripe/stripe-utils.js +43 -0
  53. package/package/stripe/stripe-utils.js.map +1 -0
  54. package/package/stripe/stripe.controller.d.ts +5 -5
  55. package/package/stripe/stripe.controller.js +27 -26
  56. package/package/stripe/stripe.controller.js.map +1 -1
  57. package/package/stripe/stripe.handler.d.ts +27 -2
  58. package/package/stripe/stripe.handler.js +56 -25
  59. package/package/stripe/stripe.handler.js.map +1 -1
  60. package/package/stripe/stripe.plugin.d.ts +91 -14
  61. package/package/stripe/stripe.plugin.js +92 -15
  62. package/package/stripe/stripe.plugin.js.map +1 -1
  63. package/package/stripe/stripe.resolver.d.ts +1 -1
  64. package/package/stripe/stripe.resolver.js +7 -5
  65. package/package/stripe/stripe.resolver.js.map +1 -1
  66. package/package/stripe/stripe.service.d.ts +14 -6
  67. package/package/stripe/stripe.service.js +74 -41
  68. package/package/stripe/stripe.service.js.map +1 -1
  69. package/package/stripe/types.d.ts +12 -13
  70. package/package/stripe/types.js.map +1 -1
  71. package/package.json +28 -9
@@ -23,28 +23,20 @@ const missingHeaderErrorMessage = 'Missing stripe-signature header';
23
23
  const signatureErrorMessage = 'Error verifying Stripe webhook signature';
24
24
  const noPaymentIntentErrorMessage = 'No payment intent in the event payload';
25
25
  let StripeController = class StripeController {
26
- constructor(connection, channelService, orderService, stripeService) {
26
+ constructor(connection, orderService, stripeService, requestContextService) {
27
27
  this.connection = connection;
28
- this.channelService = channelService;
29
28
  this.orderService = orderService;
30
29
  this.stripeService = stripeService;
30
+ this.requestContextService = requestContextService;
31
31
  }
32
32
  async webhook(signature, request, response) {
33
- var _a;
33
+ var _a, _b;
34
34
  if (!signature) {
35
35
  core_1.Logger.error(missingHeaderErrorMessage, constants_1.loggerCtx);
36
36
  response.status(common_1.HttpStatus.BAD_REQUEST).send(missingHeaderErrorMessage);
37
37
  return;
38
38
  }
39
- let event = null;
40
- try {
41
- event = this.stripeService.constructEventFromPayload(request.rawBody, signature);
42
- }
43
- catch (e) {
44
- core_1.Logger.error(`${signatureErrorMessage} ${signature}: ${e.message}`, constants_1.loggerCtx);
45
- response.status(common_1.HttpStatus.BAD_REQUEST).send(signatureErrorMessage);
46
- return;
47
- }
39
+ const event = request.body;
48
40
  const paymentIntent = event.data.object;
49
41
  if (!paymentIntent) {
50
42
  core_1.Logger.error(noPaymentIntentErrorMessage, constants_1.loggerCtx);
@@ -52,9 +44,24 @@ let StripeController = class StripeController {
52
44
  return;
53
45
  }
54
46
  const { metadata: { channelToken, orderCode, orderId } = {} } = paymentIntent;
47
+ const ctx = await this.createContext(channelToken, request);
48
+ const order = await this.orderService.findOneByCode(ctx, orderCode);
49
+ if (!order) {
50
+ throw Error(`Unable to find order ${orderCode}, unable to settle payment ${paymentIntent.id}!`);
51
+ }
52
+ try {
53
+ // Throws an error if the signature is invalid
54
+ await this.stripeService.constructEventFromPayload(ctx, order, request.rawBody, signature);
55
+ }
56
+ catch (e) {
57
+ core_1.Logger.error(`${signatureErrorMessage} ${signature}: ${e === null || e === void 0 ? void 0 : e.message}`, constants_1.loggerCtx);
58
+ response.status(common_1.HttpStatus.BAD_REQUEST).send(signatureErrorMessage);
59
+ return;
60
+ }
55
61
  if (event.type === 'payment_intent.payment_failed') {
56
- const message = (_a = paymentIntent.last_payment_error) === null || _a === void 0 ? void 0 : _a.message;
62
+ const message = (_b = (_a = paymentIntent.last_payment_error) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : 'unknown error';
57
63
  core_1.Logger.warn(`Payment for order ${orderCode} failed: ${message}`, constants_1.loggerCtx);
64
+ response.status(common_1.HttpStatus.OK).send('Ok');
58
65
  return;
59
66
  }
60
67
  if (event.type !== 'payment_intent.succeeded') {
@@ -63,11 +70,6 @@ let StripeController = class StripeController {
63
70
  core_1.Logger.info(`Received ${event.type} status update for order ${orderCode}`, constants_1.loggerCtx);
64
71
  return;
65
72
  }
66
- const ctx = await this.createContext(channelToken);
67
- const order = await this.orderService.findOneByCode(ctx, orderCode);
68
- if (!order) {
69
- throw Error(`Unable to find order ${orderCode}, unable to settle payment ${paymentIntent.id}!`);
70
- }
71
73
  if (order.state !== 'ArrangingPayment') {
72
74
  const transitionToStateResult = await this.orderService.transitionToState(ctx, orderId, 'ArrangingPayment');
73
75
  if (transitionToStateResult instanceof generated_graphql_shop_errors_1.OrderStateTransitionError) {
@@ -79,6 +81,7 @@ let StripeController = class StripeController {
79
81
  const addPaymentToOrderResult = await this.orderService.addPaymentToOrder(ctx, orderId, {
80
82
  method: paymentMethod.code,
81
83
  metadata: {
84
+ paymentIntentAmountReceived: paymentIntent.amount_received,
82
85
  paymentIntentId: paymentIntent.id,
83
86
  },
84
87
  });
@@ -89,13 +92,11 @@ let StripeController = class StripeController {
89
92
  core_1.Logger.info(`Stripe payment intent id ${paymentIntent.id} added to order ${orderCode}`, constants_1.loggerCtx);
90
93
  response.status(common_1.HttpStatus.OK).send('Ok');
91
94
  }
92
- async createContext(channelToken) {
93
- const channel = await this.channelService.getChannelFromToken(channelToken);
94
- return new core_1.RequestContext({
95
+ async createContext(channelToken, req) {
96
+ return this.requestContextService.create({
95
97
  apiType: 'admin',
96
- isAuthorized: true,
97
- authorizedAsOwnerOnly: false,
98
- channel,
98
+ channelOrToken: channelToken,
99
+ req,
99
100
  languageCode: core_1.LanguageCode.en,
100
101
  });
101
102
  }
@@ -119,9 +120,9 @@ __decorate([
119
120
  StripeController = __decorate([
120
121
  (0, common_1.Controller)('payments'),
121
122
  __metadata("design:paramtypes", [core_1.TransactionalConnection,
122
- core_1.ChannelService,
123
123
  core_1.OrderService,
124
- stripe_service_1.StripeService])
124
+ stripe_service_1.StripeService,
125
+ core_1.RequestContextService])
125
126
  ], StripeController);
126
127
  exports.StripeController = StripeController;
127
128
  //# sourceMappingURL=stripe.controller.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stripe.controller.js","sourceRoot":"","sources":["../../src/stripe/stripe.controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stripe.controller.js","sourceRoot":"","sources":["../../src/stripe/stripe.controller.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,30 @@
1
- import { PaymentMethodHandler } from '@vendure/core';
1
+ import { LanguageCode, PaymentMethodHandler } from '@vendure/core';
2
2
  /**
3
3
  * The handler for Stripe payments.
4
4
  */
5
- export declare const stripePaymentMethodHandler: PaymentMethodHandler<{}>;
5
+ export declare const stripePaymentMethodHandler: PaymentMethodHandler<{
6
+ apiKey: {
7
+ type: "string";
8
+ label: {
9
+ languageCode: LanguageCode.en;
10
+ value: string;
11
+ }[];
12
+ ui: {
13
+ component: string;
14
+ };
15
+ };
16
+ webhookSecret: {
17
+ type: "string";
18
+ label: {
19
+ languageCode: LanguageCode.en;
20
+ value: string;
21
+ }[];
22
+ description: {
23
+ languageCode: LanguageCode.en;
24
+ value: string;
25
+ }[];
26
+ ui: {
27
+ component: string;
28
+ };
29
+ };
30
+ }>;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.stripePaymentMethodHandler = void 0;
7
7
  const core_1 = require("@vendure/core");
8
8
  const stripe_1 = __importDefault(require("stripe"));
9
+ const stripe_utils_1 = require("./stripe-utils");
9
10
  const stripe_service_1 = require("./stripe.service");
10
11
  const { StripeError } = stripe_1.default.errors;
11
12
  let stripeService;
@@ -15,18 +16,41 @@ let stripeService;
15
16
  exports.stripePaymentMethodHandler = new core_1.PaymentMethodHandler({
16
17
  code: 'stripe',
17
18
  description: [{ languageCode: core_1.LanguageCode.en, value: 'Stripe payments' }],
18
- args: {},
19
+ args: {
20
+ apiKey: {
21
+ type: 'string',
22
+ label: [{ languageCode: core_1.LanguageCode.en, value: 'API Key' }],
23
+ ui: { component: 'password-form-input' },
24
+ },
25
+ webhookSecret: {
26
+ type: 'string',
27
+ label: [
28
+ {
29
+ languageCode: core_1.LanguageCode.en,
30
+ value: 'Webhook secret',
31
+ },
32
+ ],
33
+ description: [
34
+ {
35
+ languageCode: core_1.LanguageCode.en,
36
+ value: 'Secret to validate incoming webhooks. Get this from your Stripe dashboard',
37
+ },
38
+ ],
39
+ ui: { component: 'password-form-input' },
40
+ },
41
+ },
19
42
  init(injector) {
20
43
  stripeService = injector.get(stripe_service_1.StripeService);
21
44
  },
22
- async createPayment(ctx, _, amount, ___, metadata) {
45
+ createPayment(ctx, order, amount, ___, metadata) {
23
46
  // Payment is already settled in Stripe by the time the webhook in stripe.controller.ts
24
47
  // adds the payment to the order
25
48
  if (ctx.apiType !== 'admin') {
26
49
  throw Error(`CreatePayment is not allowed for apiType '${ctx.apiType}'`);
27
50
  }
51
+ const amountInMinorUnits = (0, stripe_utils_1.getAmountFromStripeMinorUnits)(order, metadata.paymentIntentAmountReceived);
28
52
  return {
29
- amount,
53
+ amount: amountInMinorUnits,
30
54
  state: 'Settled',
31
55
  transactionId: metadata.paymentIntentId,
32
56
  };
@@ -37,36 +61,43 @@ exports.stripePaymentMethodHandler = new core_1.PaymentMethodHandler({
37
61
  };
38
62
  },
39
63
  async createRefund(ctx, input, amount, order, payment, args) {
40
- const result = await stripeService.createRefund(payment.transactionId, amount);
41
- if (result instanceof StripeError) {
64
+ // TODO: Consider passing the "reason" property once this feature request is addressed:
65
+ // https://github.com/vendure-ecommerce/vendure/issues/893
66
+ try {
67
+ const refund = await stripeService.createRefund(ctx, order, payment, amount);
68
+ if (refund.status === 'succeeded') {
69
+ return {
70
+ state: 'Settled',
71
+ transactionId: payment.transactionId,
72
+ };
73
+ }
74
+ if (refund.status === 'pending') {
75
+ return {
76
+ state: 'Pending',
77
+ transactionId: payment.transactionId,
78
+ };
79
+ }
42
80
  return {
43
81
  state: 'Failed',
44
82
  transactionId: payment.transactionId,
45
83
  metadata: {
46
- type: result.type,
47
- message: result.message,
84
+ message: refund.failure_reason,
48
85
  },
49
86
  };
50
87
  }
51
- if (result.status === 'succeeded') {
52
- return {
53
- state: 'Settled',
54
- transactionId: payment.transactionId,
55
- };
56
- }
57
- if (result.status === 'pending') {
58
- return {
59
- state: 'Pending',
60
- transactionId: payment.transactionId,
61
- };
88
+ catch (e) {
89
+ if (e instanceof StripeError) {
90
+ return {
91
+ state: 'Failed',
92
+ transactionId: payment.transactionId,
93
+ metadata: {
94
+ type: e.type,
95
+ message: e.message,
96
+ },
97
+ };
98
+ }
99
+ throw e;
62
100
  }
63
- return {
64
- state: 'Failed',
65
- transactionId: payment.transactionId,
66
- metadata: {
67
- message: result.failure_reason,
68
- },
69
- };
70
101
  },
71
102
  });
72
103
  //# sourceMappingURL=stripe.handler.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stripe.handler.js","sourceRoot":"","sources":["../../src/stripe/stripe.handler.ts"],"names":[],"mappings":";;;;;;AAAA,wCAOuB;AACvB,oDAA4B;AAE5B,qDAAiD;AAEjD,MAAM,EAAE,WAAW,EAAE,GAAG,gBAAM,CAAC,MAAM,CAAC;AAEtC,IAAI,aAA4B,CAAC;AAEjC;;GAEG;AACU,QAAA,0BAA0B,GAAG,IAAI,2BAAoB,CAAC;IAC/D,IAAI,EAAE,QAAQ;IAEd,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,mBAAY,CAAC,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAE1E,IAAI,EAAE,EAAE;IAER,IAAI,CAAC,QAAkB;QACnB,aAAa,GAAG,QAAQ,CAAC,GAAG,CAAC,8BAAa,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ;QAC7C,uFAAuF;QACvF,gCAAgC;QAChC,IAAI,GAAG,CAAC,OAAO,KAAK,OAAO,EAAE;YACzB,MAAM,KAAK,CAAC,6CAA6C,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC;SAC5E;QACD,OAAO;YACH,MAAM;YACN,KAAK,EAAE,SAAkB;YACzB,aAAa,EAAE,QAAQ,CAAC,eAAe;SAC1C,CAAC;IACN,CAAC;IAED,aAAa;QACT,OAAO;YACH,OAAO,EAAE,IAAI;SAChB,CAAC;IACN,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI;QACvD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAE/E,IAAI,MAAM,YAAY,WAAW,EAAE;YAC/B,OAAO;gBACH,KAAK,EAAE,QAAiB;gBACxB,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,QAAQ,EAAE;oBACN,IAAI,EAAE,MAAM,CAAC,IAAI;oBACjB,OAAO,EAAE,MAAM,CAAC,OAAO;iBAC1B;aACJ,CAAC;SACL;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE;YAC/B,OAAO;gBACH,KAAK,EAAE,SAAkB;gBACzB,aAAa,EAAE,OAAO,CAAC,aAAa;aACvC,CAAC;SACL;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE;YAC7B,OAAO;gBACH,KAAK,EAAE,SAAkB;gBACzB,aAAa,EAAE,OAAO,CAAC,aAAa;aACvC,CAAC;SACL;QAED,OAAO;YACH,KAAK,EAAE,QAAiB;YACxB,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,QAAQ,EAAE;gBACN,OAAO,EAAE,MAAM,CAAC,cAAc;aACjC;SACJ,CAAC;IACN,CAAC;CACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"stripe.handler.js","sourceRoot":"","sources":["../../src/stripe/stripe.handler.ts"],"names":[],"mappings":"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"}
@@ -7,9 +7,10 @@ import { StripePluginOptions } from './types';
7
7
  * ## Requirements
8
8
  *
9
9
  * 1. You will need to create a Stripe account and get your secret key in the dashboard.
10
- * 2. Create a webhook endpoint in the Stripe dashboard which listens to the `payment_intent.succeeded` and
11
- * `payment_intent.payment_failed` events. The URL should be `https://my-shop.com/payments/stripe`, where
12
- * `my-shop.com` is the host of your storefront application.
10
+ * 2. Create a webhook endpoint in the Stripe dashboard (Developers -> Webhooks, "Add an endpoint") which listens to the `payment_intent.succeeded`
11
+ * and `payment_intent.payment_failed` events. The URL should be `https://my-server.com/payments/stripe`, where
12
+ * `my-server.com` is the host of your Vendure server. *Note:* for local development, you'll need to use
13
+ * the Stripe CLI to test your webhook locally. See the _local development_ section below.
13
14
  * 3. Get the signing secret for the newly created webhook.
14
15
  * 4. Install the Payments plugin and the Stripe Node library:
15
16
  *
@@ -29,14 +30,13 @@ import { StripePluginOptions } from './types';
29
30
  *
30
31
  * plugins: [
31
32
  * StripePlugin.init({
32
- * apiKey: process.env.YOUR_STRIPE_SECRET_KEY,
33
- * webhookSigningSecret: process.env.YOUR_STRIPE_WEBHOOK_SIGNING_SECRET,
34
33
  * // This prevents different customers from using the same PaymentIntent
35
34
  * storeCustomersInStripe: true,
36
35
  * }),
37
36
  * ]
38
37
  * ````
39
38
  * 2. Create a new PaymentMethod in the Admin UI, and select "Stripe payments" as the handler.
39
+ * 3. Set the webhook secret and API key in the PaymentMethod form.
40
40
  *
41
41
  * ## Storefront usage
42
42
  *
@@ -54,20 +54,97 @@ import { StripePluginOptions } from './types';
54
54
  *
55
55
  * The high-level workflow is:
56
56
  * 1. Create a "payment intent" on the server by executing the `createStripePaymentIntent` mutation which is exposed by this plugin.
57
- * 2. Use the returned client secret to instantiate the Stripe Payment Element.
57
+ * 2. Use the returned client secret to instantiate the Stripe Payment Element:
58
+ * ```TypeScript
59
+ * import { Elements } from '\@stripe/react-stripe-js';
60
+ * import { loadStripe, Stripe } from '\@stripe/stripe-js';
61
+ * import { CheckoutForm } from './CheckoutForm';
62
+ *
63
+ * const stripePromise = getStripe('pk_test_....wr83u');
64
+ *
65
+ * type StripePaymentsProps = {
66
+ * clientSecret: string;
67
+ * orderCode: string;
68
+ * }
69
+ *
70
+ * export function StripePayments({ clientSecret, orderCode }: StripePaymentsProps) {
71
+ * const options = {
72
+ * // passing the client secret obtained from the server
73
+ * clientSecret,
74
+ * }
75
+ * return (
76
+ * <Elements stripe={stripePromise} options={options}>
77
+ * <CheckoutForm orderCode={orderCode} />
78
+ * </Elements>
79
+ * );
80
+ * }
81
+ * ```
82
+ * ```TypeScript
83
+ * // CheckoutForm.tsx
84
+ * import { useStripe, useElements, PaymentElement } from '@stripe/react-stripe-js';
85
+ * import { FormEvent } from 'react';
86
+ *
87
+ * export const CheckoutForm = ({ orderCode }: { orderCode: string }) => {
88
+ * const stripe = useStripe();
89
+ * const elements = useElements();
90
+ *
91
+ * const handleSubmit = async (event: FormEvent) => {
92
+ * // We don't want to let default form submission happen here,
93
+ * // which would refresh the page.
94
+ * event.preventDefault();
95
+ *
96
+ * if (!stripe || !elements) {
97
+ * // Stripe.js has not yet loaded.
98
+ * // Make sure to disable form submission until Stripe.js has loaded.
99
+ * return;
100
+ * }
101
+ *
102
+ * const result = await stripe.confirmPayment({
103
+ * //`Elements` instance that was used to create the Payment Element
104
+ * elements,
105
+ * confirmParams: {
106
+ * return_url: location.origin + `/checkout/confirmation/${orderCode}`,
107
+ * },
108
+ * });
109
+ *
110
+ * if (result.error) {
111
+ * // Show error to your customer (for example, payment details incomplete)
112
+ * console.log(result.error.message);
113
+ * } else {
114
+ * // Your customer will be redirected to your `return_url`. For some payment
115
+ * // methods like iDEAL, your customer will be redirected to an intermediate
116
+ * // site first to authorize the payment, then redirected to the `return_url`.
117
+ * }
118
+ * };
119
+ *
120
+ * return (
121
+ * <form onSubmit={handleSubmit}>
122
+ * <PaymentElement />
123
+ * <button disabled={!stripe}>Submit</button>
124
+ * </form>
125
+ * );
126
+ * };
127
+ * ```
58
128
  * 3. Once the form is submitted and Stripe processes the payment, the webhook takes care of updating the order without additional action
59
- * in the storefront.
129
+ * in the storefront. As in the code above, the customer will be redirected to `/checkout/confirmation/${orderCode}`.
60
130
  *
61
- * ## Local development
131
+ * {{% alert "primary" %}}
132
+ * A full working storefront example of the Stripe integration can be found in the
133
+ * [Remix Starter repo](https://github.com/vendure-ecommerce/storefront-remix-starter/tree/master/app/components/checkout/stripe)
134
+ * {{% /alert %}}
62
135
  *
63
- * Use something like [localtunnel](https://github.com/localtunnel/localtunnel) to test on localhost.
136
+ * ## Local development
64
137
  *
65
- * ```bash
66
- * npx localtunnel --port 3000 --subdomain my-shop-local-dev
67
- * > your url is: https://my-shop-local-dev.loca.lt
68
- * ```
138
+ * 1. Download & install the Stripe CLI: https://stripe.com/docs/stripe-cli
139
+ * 2. From your Stripe dashboard, go to Developers -> Webhooks and click "Add an endpoint" and follow the instructions
140
+ * under "Test in a local environment".
141
+ * 3. The Stripe CLI command will look like
142
+ * ```shell
143
+ * stripe listen --forward-to localhost:3000/payments/stripe
144
+ * ```
145
+ * 4. The Stripe CLI will create a webhook signing secret you can then use in your config of the StripePlugin.
69
146
  *
70
- * @docsCategory payments-plugin
147
+ * @docsCategory core plugins/PaymentsPlugin
71
148
  * @docsPage StripePlugin
72
149
  */
73
150
  export declare class StripePlugin {
@@ -23,9 +23,10 @@ const stripe_service_1 = require("./stripe.service");
23
23
  * ## Requirements
24
24
  *
25
25
  * 1. You will need to create a Stripe account and get your secret key in the dashboard.
26
- * 2. Create a webhook endpoint in the Stripe dashboard which listens to the `payment_intent.succeeded` and
27
- * `payment_intent.payment_failed` events. The URL should be `https://my-shop.com/payments/stripe`, where
28
- * `my-shop.com` is the host of your storefront application.
26
+ * 2. Create a webhook endpoint in the Stripe dashboard (Developers -> Webhooks, "Add an endpoint") which listens to the `payment_intent.succeeded`
27
+ * and `payment_intent.payment_failed` events. The URL should be `https://my-server.com/payments/stripe`, where
28
+ * `my-server.com` is the host of your Vendure server. *Note:* for local development, you'll need to use
29
+ * the Stripe CLI to test your webhook locally. See the _local development_ section below.
29
30
  * 3. Get the signing secret for the newly created webhook.
30
31
  * 4. Install the Payments plugin and the Stripe Node library:
31
32
  *
@@ -45,14 +46,13 @@ const stripe_service_1 = require("./stripe.service");
45
46
  *
46
47
  * plugins: [
47
48
  * StripePlugin.init({
48
- * apiKey: process.env.YOUR_STRIPE_SECRET_KEY,
49
- * webhookSigningSecret: process.env.YOUR_STRIPE_WEBHOOK_SIGNING_SECRET,
50
49
  * // This prevents different customers from using the same PaymentIntent
51
50
  * storeCustomersInStripe: true,
52
51
  * }),
53
52
  * ]
54
53
  * ````
55
54
  * 2. Create a new PaymentMethod in the Admin UI, and select "Stripe payments" as the handler.
55
+ * 3. Set the webhook secret and API key in the PaymentMethod form.
56
56
  *
57
57
  * ## Storefront usage
58
58
  *
@@ -70,20 +70,97 @@ const stripe_service_1 = require("./stripe.service");
70
70
  *
71
71
  * The high-level workflow is:
72
72
  * 1. Create a "payment intent" on the server by executing the `createStripePaymentIntent` mutation which is exposed by this plugin.
73
- * 2. Use the returned client secret to instantiate the Stripe Payment Element.
73
+ * 2. Use the returned client secret to instantiate the Stripe Payment Element:
74
+ * ```TypeScript
75
+ * import { Elements } from '\@stripe/react-stripe-js';
76
+ * import { loadStripe, Stripe } from '\@stripe/stripe-js';
77
+ * import { CheckoutForm } from './CheckoutForm';
78
+ *
79
+ * const stripePromise = getStripe('pk_test_....wr83u');
80
+ *
81
+ * type StripePaymentsProps = {
82
+ * clientSecret: string;
83
+ * orderCode: string;
84
+ * }
85
+ *
86
+ * export function StripePayments({ clientSecret, orderCode }: StripePaymentsProps) {
87
+ * const options = {
88
+ * // passing the client secret obtained from the server
89
+ * clientSecret,
90
+ * }
91
+ * return (
92
+ * <Elements stripe={stripePromise} options={options}>
93
+ * <CheckoutForm orderCode={orderCode} />
94
+ * </Elements>
95
+ * );
96
+ * }
97
+ * ```
98
+ * ```TypeScript
99
+ * // CheckoutForm.tsx
100
+ * import { useStripe, useElements, PaymentElement } from '@stripe/react-stripe-js';
101
+ * import { FormEvent } from 'react';
102
+ *
103
+ * export const CheckoutForm = ({ orderCode }: { orderCode: string }) => {
104
+ * const stripe = useStripe();
105
+ * const elements = useElements();
106
+ *
107
+ * const handleSubmit = async (event: FormEvent) => {
108
+ * // We don't want to let default form submission happen here,
109
+ * // which would refresh the page.
110
+ * event.preventDefault();
111
+ *
112
+ * if (!stripe || !elements) {
113
+ * // Stripe.js has not yet loaded.
114
+ * // Make sure to disable form submission until Stripe.js has loaded.
115
+ * return;
116
+ * }
117
+ *
118
+ * const result = await stripe.confirmPayment({
119
+ * //`Elements` instance that was used to create the Payment Element
120
+ * elements,
121
+ * confirmParams: {
122
+ * return_url: location.origin + `/checkout/confirmation/${orderCode}`,
123
+ * },
124
+ * });
125
+ *
126
+ * if (result.error) {
127
+ * // Show error to your customer (for example, payment details incomplete)
128
+ * console.log(result.error.message);
129
+ * } else {
130
+ * // Your customer will be redirected to your `return_url`. For some payment
131
+ * // methods like iDEAL, your customer will be redirected to an intermediate
132
+ * // site first to authorize the payment, then redirected to the `return_url`.
133
+ * }
134
+ * };
135
+ *
136
+ * return (
137
+ * <form onSubmit={handleSubmit}>
138
+ * <PaymentElement />
139
+ * <button disabled={!stripe}>Submit</button>
140
+ * </form>
141
+ * );
142
+ * };
143
+ * ```
74
144
  * 3. Once the form is submitted and Stripe processes the payment, the webhook takes care of updating the order without additional action
75
- * in the storefront.
145
+ * in the storefront. As in the code above, the customer will be redirected to `/checkout/confirmation/${orderCode}`.
76
146
  *
77
- * ## Local development
147
+ * {{% alert "primary" %}}
148
+ * A full working storefront example of the Stripe integration can be found in the
149
+ * [Remix Starter repo](https://github.com/vendure-ecommerce/storefront-remix-starter/tree/master/app/components/checkout/stripe)
150
+ * {{% /alert %}}
78
151
  *
79
- * Use something like [localtunnel](https://github.com/localtunnel/localtunnel) to test on localhost.
152
+ * ## Local development
80
153
  *
81
- * ```bash
82
- * npx localtunnel --port 3000 --subdomain my-shop-local-dev
83
- * > your url is: https://my-shop-local-dev.loca.lt
84
- * ```
154
+ * 1. Download & install the Stripe CLI: https://stripe.com/docs/stripe-cli
155
+ * 2. From your Stripe dashboard, go to Developers -> Webhooks and click "Add an endpoint" and follow the instructions
156
+ * under "Test in a local environment".
157
+ * 3. The Stripe CLI command will look like
158
+ * ```shell
159
+ * stripe listen --forward-to localhost:3000/payments/stripe
160
+ * ```
161
+ * 4. The Stripe CLI will create a webhook signing secret you can then use in your config of the StripePlugin.
85
162
  *
86
- * @docsCategory payments-plugin
163
+ * @docsCategory core plugins/PaymentsPlugin
87
164
  * @docsPage StripePlugin
88
165
  */
89
166
  let StripePlugin = StripePlugin_1 = class StripePlugin {
@@ -129,7 +206,7 @@ StripePlugin = StripePlugin_1 = __decorate([
129
206
  shopApiExtensions: {
130
207
  schema: (0, graphql_tag_1.gql) `
131
208
  extend type Mutation {
132
- createStripePaymentIntent: String
209
+ createStripePaymentIntent: String!
133
210
  }
134
211
  `,
135
212
  resolvers: [stripe_resolver_1.StripeResolver],
@@ -1 +1 @@
1
- {"version":3,"file":"stripe.plugin.js","sourceRoot":"","sources":["../../src/stripe/stripe.plugin.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,wCAAsF;AACtF,6CAAkC;AAElC,2CAAoD;AACpD,+DAA0D;AAC1D,2DAAuD;AACvD,qDAA8D;AAC9D,uDAAmD;AACnD,qDAAiD;AAGjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqEG;AA0CH,IAAa,YAAY,oBAAzB,MAAa,YAAY;IAGrB;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,OAA4B;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,OAAO,cAAY,CAAC;IACxB,CAAC;CACJ,CAAA;AAXY,YAAY;IAzCxB,IAAA,oBAAa,EAAC;QACX,OAAO,EAAE,CAAC,yBAAkB,CAAC;QAC7B,WAAW,EAAE,CAAC,oCAAgB,CAAC;QAC/B,SAAS,EAAE;YACP;gBACI,OAAO,EAAE,iCAAqB;gBAC9B,UAAU,EAAE,GAAwB,EAAE,CAAC,cAAY,CAAC,OAAO;aAC9D;YACD,8BAAa;SAChB;QACD,aAAa,EAAE,MAAM,CAAC,EAAE;YACpB,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,IAAI,CAAC,2CAA0B,CAAC,CAAC;YAE7E,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC;gBAC9B,KAAK,EAAE,kBAAkB;gBACzB,OAAO,EAAE,uCAAiB;gBAC1B,YAAY,EAAE,IAAI;aACrB,CAAC,CAAC;YAEH,IAAI,cAAY,CAAC,OAAO,CAAC,sBAAsB,EAAE;gBAC7C,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAC9B,IAAI,EAAE,kBAAkB;oBACxB,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,CAAC,EAAE,YAAY,EAAE,mBAAY,CAAC,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;oBACvE,QAAQ,EAAE,IAAI;oBACd,MAAM,EAAE,KAAK;oBACb,QAAQ,EAAE,IAAI;iBACjB,CAAC,CAAC;aACN;YAED,OAAO,MAAM,CAAC;QAClB,CAAC;QACD,iBAAiB,EAAE;YACf,MAAM,EAAE,IAAA,iBAAG,EAAA;;;;SAIV;YACD,SAAS,EAAE,CAAC,gCAAc,CAAC;SAC9B;KACJ,CAAC;GACW,YAAY,CAWxB;AAXY,oCAAY"}
1
+ {"version":3,"file":"stripe.plugin.js","sourceRoot":"","sources":["../../src/stripe/stripe.plugin.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,wCAAsF;AACtF,6CAAkC;AAElC,2CAAoD;AACpD,+DAA0D;AAC1D,2DAAuD;AACvD,qDAA8D;AAC9D,uDAAmD;AACnD,qDAAiD;AAGjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkJG;AA0CI,IAAM,YAAY,oBAAlB,MAAM,YAAY;IAGrB;;;OAGG;IACH,MAAM,CAAC,IAAI,CAAC,OAA4B;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,OAAO,cAAY,CAAC;IACxB,CAAC;CACJ,CAAA;AAXY,YAAY;IAzCxB,IAAA,oBAAa,EAAC;QACX,OAAO,EAAE,CAAC,yBAAkB,CAAC;QAC7B,WAAW,EAAE,CAAC,oCAAgB,CAAC;QAC/B,SAAS,EAAE;YACP;gBACI,OAAO,EAAE,iCAAqB;gBAC9B,UAAU,EAAE,GAAwB,EAAE,CAAC,cAAY,CAAC,OAAO;aAC9D;YACD,8BAAa;SAChB;QACD,aAAa,EAAE,MAAM,CAAC,EAAE;YACpB,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,IAAI,CAAC,2CAA0B,CAAC,CAAC;YAE7E,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC;gBAC9B,KAAK,EAAE,kBAAkB;gBACzB,OAAO,EAAE,uCAAiB;gBAC1B,YAAY,EAAE,IAAI;aACrB,CAAC,CAAC;YAEH,IAAI,cAAY,CAAC,OAAO,CAAC,sBAAsB,EAAE;gBAC7C,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAC9B,IAAI,EAAE,kBAAkB;oBACxB,IAAI,EAAE,QAAQ;oBACd,KAAK,EAAE,CAAC,EAAE,YAAY,EAAE,mBAAY,CAAC,EAAE,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;oBACvE,QAAQ,EAAE,IAAI;oBACd,MAAM,EAAE,KAAK;oBACb,QAAQ,EAAE,IAAI;iBACjB,CAAC,CAAC;aACN;YAED,OAAO,MAAM,CAAC;QAClB,CAAC;QACD,iBAAiB,EAAE;YACf,MAAM,EAAE,IAAA,iBAAG,EAAA;;;;SAIV;YACD,SAAS,EAAE,CAAC,gCAAc,CAAC;SAC9B;KACJ,CAAC;GACW,YAAY,CAWxB;AAXY,oCAAY"}
@@ -4,5 +4,5 @@ export declare class StripeResolver {
4
4
  private stripeService;
5
5
  private activeOrderService;
6
6
  constructor(stripeService: StripeService, activeOrderService: ActiveOrderService);
7
- createStripePaymentIntent(ctx: RequestContext): Promise<string | undefined>;
7
+ createStripePaymentIntent(ctx: RequestContext): Promise<string>;
8
8
  }
@@ -22,12 +22,14 @@ let StripeResolver = class StripeResolver {
22
22
  this.activeOrderService = activeOrderService;
23
23
  }
24
24
  async createStripePaymentIntent(ctx) {
25
- if (ctx.authorizedAsOwnerOnly) {
26
- const sessionOrder = await this.activeOrderService.getOrderFromContext(ctx);
27
- if (sessionOrder) {
28
- return this.stripeService.createPaymentIntent(ctx, sessionOrder);
29
- }
25
+ if (!ctx.authorizedAsOwnerOnly) {
26
+ throw new core_1.UnauthorizedError();
30
27
  }
28
+ const sessionOrder = await this.activeOrderService.getActiveOrder(ctx, undefined);
29
+ if (!sessionOrder) {
30
+ throw new core_1.UserInputError('No active order found for session');
31
+ }
32
+ return this.stripeService.createPaymentIntent(ctx, sessionOrder);
31
33
  }
32
34
  };
33
35
  __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"stripe.resolver.js","sourceRoot":"","sources":["../../src/stripe/stripe.resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,6CAAqD;AACrD,wCAA2F;AAE3F,qDAAiD;AAGjD,IAAa,cAAc,GAA3B,MAAa,cAAc;IACvB,YAAoB,aAA4B,EAAU,kBAAsC;QAA5E,kBAAa,GAAb,aAAa,CAAe;QAAU,uBAAkB,GAAlB,kBAAkB,CAAoB;IAAG,CAAC;IAIpG,KAAK,CAAC,yBAAyB,CAAQ,GAAmB;QACtD,IAAI,GAAG,CAAC,qBAAqB,EAAE;YAC3B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;YAC5E,IAAI,YAAY,EAAE;gBACd,OAAO,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;aACpE;SACJ;IACL,CAAC;CACJ,CAAA;AARG;IAFC,IAAA,kBAAQ,GAAE;IACV,IAAA,YAAK,EAAC,iBAAU,CAAC,KAAK,CAAC;IACS,WAAA,IAAA,UAAG,GAAE,CAAA;;qCAAM,qBAAc;;+DAOzD;AAZQ,cAAc;IAD1B,IAAA,kBAAQ,GAAE;qCAE4B,8BAAa,EAA8B,yBAAkB;GADvF,cAAc,CAa1B;AAbY,wCAAc"}
1
+ {"version":3,"file":"stripe.resolver.js","sourceRoot":"","sources":["../../src/stripe/stripe.resolver.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,6CAAqD;AACrD,wCAQuB;AAEvB,qDAAiD;AAG1C,IAAM,cAAc,GAApB,MAAM,cAAc;IACvB,YAAoB,aAA4B,EAAU,kBAAsC;QAA5E,kBAAa,GAAb,aAAa,CAAe;QAAU,uBAAkB,GAAlB,kBAAkB,CAAoB;IAAG,CAAC;IAI9F,AAAN,KAAK,CAAC,yBAAyB,CAAQ,GAAmB;QACtD,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE;YAC5B,MAAM,IAAI,wBAAiB,EAAE,CAAC;SACjC;QACD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAClF,IAAI,CAAC,YAAY,EAAE;YACf,MAAM,IAAI,qBAAc,CAAC,mCAAmC,CAAC,CAAC;SACjE;QACD,OAAO,IAAI,CAAC,aAAa,CAAC,mBAAmB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IACrE,CAAC;CACJ,CAAA;AAVS;IAFL,IAAA,kBAAQ,GAAE;IACV,IAAA,YAAK,EAAC,iBAAU,CAAC,KAAK,CAAC;IACS,WAAA,IAAA,UAAG,GAAE,CAAA;;qCAAM,qBAAc;;+DASzD;AAdQ,cAAc;IAD1B,IAAA,kBAAQ,GAAE;qCAE4B,8BAAa,EAA8B,yBAAkB;GADvF,cAAc,CAe1B;AAfY,wCAAc"}