diff --git a/.changeset/orange-penguins-promise.md b/.changeset/orange-penguins-promise.md new file mode 100644 index 0000000000..66d4e5410f --- /dev/null +++ b/.changeset/orange-penguins-promise.md @@ -0,0 +1,6 @@ +--- +"medusa-payment-stripe": patch +"@medusajs/medusa": patch +--- + +fix(medusa-payment-stripe): missing transaction on create payment diff --git a/packages/medusa-payment-stripe/src/helpers/stripe-base.js b/packages/medusa-payment-stripe/src/helpers/stripe-base.js index 9919e763e8..c5e49b4333 100644 --- a/packages/medusa-payment-stripe/src/helpers/stripe-base.js +++ b/packages/medusa-payment-stripe/src/helpers/stripe-base.js @@ -12,8 +12,7 @@ class StripeBase extends AbstractPaymentService { regionService, manager, }, - options, - paymentMethodTypes + options ) { super( { @@ -25,8 +24,6 @@ class StripeBase extends AbstractPaymentService { }, options ) - /** @private @const {string[]} */ - this.paymentMethodTypes_ = paymentMethodTypes /** * Required Stripe options: @@ -123,18 +120,19 @@ class StripeBase extends AbstractPaymentService { * @return {Promise} Stripe payment intent */ async createPayment(cart) { - const intentRequest = this.getPaymentIntentOptions() + const intentRequestData = this.getPaymentIntentOptions() - return await this.stripeProviderService_.createPayment(cart, intentRequest) + return await this.stripeProviderService_ + .withTransaction(this.manager_) + .createPayment(cart, intentRequestData) } async createPaymentNew(paymentInput) { - const intentRequest = this.getPaymentIntentOptions() + const intentRequestData = this.getPaymentIntentOptions() - return await this.stripeProviderService_.createPaymentNew( - paymentInput, - intentRequest - ) + return await this.stripeProviderService_ + .withTransaction(this.manager_) + .createPaymentNew(paymentInput, intentRequestData) } /** @@ -183,17 +181,19 @@ class StripeBase extends AbstractPaymentService { * @return {Promise} Stripe payment intent */ async updatePayment(paymentSessionData, cart) { - return await this.stripeProviderService_.updatePayment( - paymentSessionData, - cart - ) + const intentRequestData = this.getPaymentIntentOptions() + + return await this.stripeProviderService_ + .withTransaction(this.manager_) + .updatePayment(paymentSessionData, cart, intentRequestData) } async updatePaymentNew(paymentSessionData, paymentInput) { - return await this.stripeProviderService_.updatePaymentNew( - paymentSessionData, - paymentInput - ) + const intentRequestData = this.getPaymentIntentOptions() + + return await this.stripeProviderService_ + .withTransaction(this.manager_) + .updatePaymentNew(paymentSessionData, paymentInput, intentRequestData) } async deletePayment(paymentSession) { diff --git a/packages/medusa-payment-stripe/src/services/stripe-provider.js b/packages/medusa-payment-stripe/src/services/stripe-provider.js index 7d26ec3915..37abdeaa87 100644 --- a/packages/medusa-payment-stripe/src/services/stripe-provider.js +++ b/packages/medusa-payment-stripe/src/services/stripe-provider.js @@ -127,6 +127,7 @@ class StripeProviderService extends AbstractPaymentService { * Creates a Stripe payment intent. * If customer is not registered in Stripe, we do so. * @param {Cart} cart - cart to create a payment for + * @param intentRequestData * @return {Promise} Stripe payment intent */ async createPayment(cart, intentRequestData = {}) { @@ -271,20 +272,24 @@ class StripeProviderService extends AbstractPaymentService { * Updates Stripe payment intent. * @param {PaymentSessionData} paymentSessionData - payment session data. * @param {Cart} cart + * @param intentRequestData * @return {Promise} Stripe payment intent */ - async updatePayment(sessionData, cart) { + async updatePayment(paymentSessionData, cart, intentRequestData) { try { const stripeId = cart.customer?.metadata?.stripe_id || undefined - if (stripeId !== sessionData.customer) { - return await this.createPayment(cart) + if (stripeId !== paymentSessionData.customer) { + return await this.createPayment(cart, intentRequestData) } else { - if (cart.total && sessionData.amount === Math.round(cart.total)) { - return sessionData + if ( + cart.total && + paymentSessionData.amount === Math.round(cart.total) + ) { + return paymentSessionData } - return await this.stripe_.paymentIntents.update(sessionData.id, { + return await this.stripe_.paymentIntents.update(paymentSessionData.id, { amount: Math.round(cart.total), }) } @@ -293,15 +298,15 @@ class StripeProviderService extends AbstractPaymentService { } } - async updatePaymentNew(paymentSessionData, paymentInput) { + async updatePaymentNew(paymentSessionData, paymentInput, intentRequestData) { try { const stripeId = paymentInput.customer?.metadata?.stripe_id if (stripeId !== paymentInput.customer_id) { - return await this.createPaymentNew(paymentInput) + return await this.createPaymentNew(paymentInput, intentRequestData) } else { if (paymentSessionData.amount === Math.round(paymentInput.amount)) { - return sessionData + return paymentSessionData } return await this.stripe_.paymentIntents.update(paymentSessionData.id, { diff --git a/packages/medusa/src/services/cart.ts b/packages/medusa/src/services/cart.ts index 3538da63ac..1ebd949bb1 100644 --- a/packages/medusa/src/services/cart.ts +++ b/packages/medusa/src/services/cart.ts @@ -27,7 +27,12 @@ import { isCart, LineItemUpdate, } from "../types/cart" -import { AddressPayload, FindConfig, TotalField } from "../types/common" +import { + AddressPayload, + FindConfig, + TotalField, + WithRequiredProperty, +} from "../types/common" import { buildQuery, isDefined, setMetadata } from "../utils" import { FlagRouter } from "../utils/flag-router" import { validateEmail } from "../utils/is-email" @@ -281,7 +286,7 @@ class CartService extends TransactionBaseService { cartId: string, options: FindConfig = {}, totalsConfig: TotalsConfig = {} - ): Promise { + ): Promise> { const relations = this.getTotalsRelations(options) const cart = await this.retrieve(cartId, { @@ -823,15 +828,14 @@ class CartService extends TransactionBaseService { relations, }) + const originalCartCustomer = { ...(cart.customer ?? {}) } if (data.customer_id) { await this.updateCustomerId_(cart, data.customer_id) - } else { - if (isDefined(data.email)) { - const customer = await this.createOrFetchUserFromEmail_(data.email) - cart.customer = customer - cart.customer_id = customer.id - cart.email = customer.email - } + } else if (isDefined(data.email)) { + const customer = await this.createOrFetchUserFromEmail_(data.email) + cart.customer = customer + cart.customer_id = customer.id + cart.email = customer.email } if (isDefined(data.customer_id) || isDefined(data.region_id)) { @@ -937,7 +941,10 @@ class CartService extends TransactionBaseService { const updatedCart = await cartRepo.save(cart) - if ("email" in data || "customer_id" in data) { + if ( + (data.email && data.email !== originalCartCustomer.email) || + (data.customer_id && data.customer_id !== originalCartCustomer.id) + ) { await this.eventBus_ .withTransaction(transactionManager) .emit(CartService.Events.CUSTOMER_UPDATED, updatedCart.id) @@ -1486,13 +1493,6 @@ class CartService extends TransactionBaseService { const { total, region } = cart - if (typeof total === "undefined") { - throw new MedusaError( - MedusaError.Types.UNEXPECTED_STATE, - "cart.total must be defined" - ) - } - // If there are existing payment sessions ensure that these are up to date const seen: string[] = [] if (cart.payment_sessions?.length) { @@ -2104,7 +2104,7 @@ class CartService extends TransactionBaseService { async decorateTotals( cart: Cart, totalsConfig: TotalsConfig = {} - ): Promise { + ): Promise> { const manager = this.transactionManager_ ?? this.manager_ const newTotalsServiceTx = this.newTotalsService_.withTransaction(manager) @@ -2192,7 +2192,7 @@ class CartService extends TransactionBaseService { cart.tax_total - (cart.gift_card_total + cart.discount_total + cart.gift_card_tax_total) - return cart + return cart as Cart & { total: number } } protected async refreshAdjustments_(cart: Cart): Promise {