feat(medusa,medusa-payment-stripe): Move database mutation from plugin to core (#2743)
**what** The goal of that PR is to first refactor the payment provider and payment plugin to support the new API that removes the data mutation from within the plugin to be done by the core instead. In any case, this pr does not include the steps of the deeper refactoring. The last part will come in later pr. **How** - The payment plugin is now capable to handle both the deprecated and new API and the plugin works the same as it use to works. - The mutation made by the plugin have been moved into the core as well as the subscriber - The tests have been updated to reflect the changed - Remove all new methods introduced by the payment collections - Mutualise types - Update provider and payment collection services - cleanup around all those refactoring including cleanup of the payment collection - refactor stripe payment plugin FIXES CORE-887
This commit is contained in:
1 parent
8dcc805ccf
commit
c8724da503
87 files changed
+1138
-1429
No files matched your search
@@ -29,9 +29,9 @@
|
||||
"medusa-test-utils": "^1.1.37"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "babel src -d . --ignore **/__tests__",
|
||||
"build": "babel src -d . --ignore **/__tests__ --ignore **/__mocks__",
|
||||
"prepare": "cross-env NODE_ENV=production yarn run build",
|
||||
"watch": "babel -w src --out-dir . --ignore **/__tests__",
|
||||
"watch": "babel -w src --out-dir . --ignore **/__tests__ --ignore **/__mocks__",
|
||||
"test": "jest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -91,6 +91,8 @@ export const carts = {
|
||||
customer: IdMap.getId("not-lebron"),
|
||||
},
|
||||
},
|
||||
region: { currency_code: "usd" },
|
||||
total: 100,
|
||||
shipping_address: {},
|
||||
billing_address: {},
|
||||
discounts: [],
|
||||
|
||||
@@ -20,7 +20,7 @@ export const StripeMock = {
|
||||
if (data.customer === "cus_123456789_new") {
|
||||
return Promise.resolve({
|
||||
id: "pi_lebron",
|
||||
amount: 100,
|
||||
amount: data.amount,
|
||||
customer: "cus_123456789_new",
|
||||
description: data?.description,
|
||||
})
|
||||
@@ -28,7 +28,7 @@ export const StripeMock = {
|
||||
if (data.customer === "cus_lebron") {
|
||||
return Promise.resolve({
|
||||
id: "pi_lebron",
|
||||
amount: 100,
|
||||
amount: data.amount,
|
||||
customer: "cus_lebron",
|
||||
description: data?.description,
|
||||
})
|
||||
|
||||
+89
-103
@@ -1,58 +1,13 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import StripeProviderService from "../stripe-provider"
|
||||
import { CustomerServiceMock } from "../../__mocks__/customer"
|
||||
import { carts } from "../../__mocks__/cart"
|
||||
import { TotalsServiceMock } from "../../__mocks__/totals"
|
||||
import StripeBase from "../stripe-base";
|
||||
|
||||
const RegionServiceMock = {
|
||||
withTransaction: function () {
|
||||
return this
|
||||
},
|
||||
retrieve: jest.fn().mockReturnValue(Promise.resolve({})),
|
||||
}
|
||||
|
||||
describe("StripeProviderService", () => {
|
||||
describe("createCustomer", () => {
|
||||
let result
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
const stripeProviderService = new StripeProviderService(
|
||||
{
|
||||
customerService: CustomerServiceMock,
|
||||
regionService: RegionServiceMock,
|
||||
totalsService: TotalsServiceMock,
|
||||
},
|
||||
{
|
||||
api_key: "test",
|
||||
}
|
||||
)
|
||||
|
||||
result = await stripeProviderService.createCustomer({
|
||||
_id: IdMap.getId("vvd"),
|
||||
first_name: "Virgil",
|
||||
last_name: "Van Dijk",
|
||||
email: "virg@vvd.com",
|
||||
password_hash: "1234",
|
||||
metadata: {},
|
||||
})
|
||||
})
|
||||
|
||||
it("returns created stripe customer", () => {
|
||||
expect(result).toEqual({
|
||||
id: "cus_vvd",
|
||||
email: "virg@vvd.com",
|
||||
})
|
||||
})
|
||||
})
|
||||
const fakeContainer = {}
|
||||
|
||||
describe("StripeBase", () => {
|
||||
describe("createPayment", () => {
|
||||
let result
|
||||
const stripeProviderService = new StripeProviderService(
|
||||
{
|
||||
customerService: CustomerServiceMock,
|
||||
regionService: RegionServiceMock,
|
||||
totalsService: TotalsServiceMock,
|
||||
},
|
||||
const stripeBase = new StripeBase(
|
||||
fakeContainer,
|
||||
{
|
||||
api_key: "test"
|
||||
}
|
||||
@@ -63,45 +18,88 @@ describe("StripeProviderService", () => {
|
||||
})
|
||||
|
||||
it("returns created stripe payment intent for cart with existing customer", async () => {
|
||||
result = await stripeProviderService.createPayment(carts.frCart)
|
||||
const cart = carts.frCart
|
||||
const context = {
|
||||
cart,
|
||||
amount: cart.total,
|
||||
currency_code: cart.region?.currency_code,
|
||||
}
|
||||
Object.assign(context, cart)
|
||||
|
||||
result = await stripeBase.createPayment(context)
|
||||
expect(result).toEqual({
|
||||
id: "pi_lebron",
|
||||
customer: "cus_123456789_new",
|
||||
amount: 100,
|
||||
session_data: {
|
||||
id: "pi_lebron",
|
||||
customer: "cus_lebron",
|
||||
description: undefined,
|
||||
amount: 100,
|
||||
},
|
||||
update_requests: {
|
||||
customer_metadata: {
|
||||
stripe_id: "cus_lebron"
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it("returns created stripe payment intent for cart with no customer", async () => {
|
||||
carts.frCart.customer_id = ""
|
||||
carts.frCart.context.payment_description = 'some description'
|
||||
result = await stripeProviderService.createPayment(carts.frCart)
|
||||
const cart = carts.frCart
|
||||
const context = {
|
||||
cart,
|
||||
amount: cart.total,
|
||||
currency_code: cart.region?.currency_code,
|
||||
}
|
||||
Object.assign(context, cart)
|
||||
|
||||
context.cart.context.payment_description = 'some description'
|
||||
|
||||
result = await stripeBase.createPayment(context)
|
||||
expect(result).toEqual({
|
||||
id: "pi_lebron",
|
||||
customer: "cus_lebron",
|
||||
amount: 100,
|
||||
description: 'some description',
|
||||
session_data: {
|
||||
id: "pi_lebron",
|
||||
customer: "cus_lebron",
|
||||
description: 'some description',
|
||||
amount: 100,
|
||||
},
|
||||
update_requests: {
|
||||
customer_metadata: {
|
||||
stripe_id: "cus_lebron"
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it("returns created stripe payment intent for cart with no customer and the options default description", async () => {
|
||||
const localStripeProviderService = new StripeProviderService({
|
||||
customerService: CustomerServiceMock,
|
||||
regionService: RegionServiceMock,
|
||||
totalsService: TotalsServiceMock,
|
||||
},
|
||||
const localStripeProviderService = new StripeBase(
|
||||
fakeContainer,
|
||||
{
|
||||
api_key: "test",
|
||||
payment_description: "test options description"
|
||||
})
|
||||
|
||||
carts.frCart.customer_id = ""
|
||||
carts.frCart.context.payment_description = null
|
||||
result = await localStripeProviderService.createPayment(carts.frCart)
|
||||
const cart = carts.frCart
|
||||
const context = {
|
||||
cart,
|
||||
amount: cart.total,
|
||||
currency_code: cart.region?.currency_code,
|
||||
}
|
||||
Object.assign(context, cart)
|
||||
|
||||
context.cart.context.payment_description = null
|
||||
|
||||
result = await localStripeProviderService.createPayment(context)
|
||||
expect(result).toEqual({
|
||||
id: "pi_lebron",
|
||||
customer: "cus_lebron",
|
||||
amount: 100,
|
||||
description: "test options description",
|
||||
session_data: {
|
||||
id: "pi_lebron",
|
||||
customer: "cus_lebron",
|
||||
description: "test options description",
|
||||
amount: 100,
|
||||
},
|
||||
update_requests: {
|
||||
customer_metadata: {
|
||||
stripe_id: "cus_lebron"
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -110,18 +108,14 @@ describe("StripeProviderService", () => {
|
||||
let result
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
const stripeProviderService = new StripeProviderService(
|
||||
{
|
||||
customerService: CustomerServiceMock,
|
||||
regionService: RegionServiceMock,
|
||||
totalsService: TotalsServiceMock,
|
||||
},
|
||||
const stripeBase = new StripeBase(
|
||||
fakeContainer,
|
||||
{
|
||||
api_key: "test",
|
||||
}
|
||||
)
|
||||
|
||||
result = await stripeProviderService.retrievePayment({
|
||||
result = await stripeBase.retrievePayment({
|
||||
payment_method: {
|
||||
data: {
|
||||
id: "pi_lebron",
|
||||
@@ -142,18 +136,14 @@ describe("StripeProviderService", () => {
|
||||
let result
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
const stripeProviderService = new StripeProviderService(
|
||||
{
|
||||
customerService: CustomerServiceMock,
|
||||
regionService: RegionServiceMock,
|
||||
totalsService: TotalsServiceMock,
|
||||
},
|
||||
const stripeBase = new StripeBase(
|
||||
fakeContainer,
|
||||
{
|
||||
api_key: "test",
|
||||
}
|
||||
)
|
||||
|
||||
result = await stripeProviderService.updatePayment(
|
||||
result = await stripeBase.updatePayment(
|
||||
{
|
||||
id: "pi_lebron",
|
||||
amount: 800,
|
||||
@@ -177,18 +167,14 @@ describe("StripeProviderService", () => {
|
||||
let result
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
const stripeProviderService = new StripeProviderService(
|
||||
{
|
||||
customerService: CustomerServiceMock,
|
||||
regionService: RegionServiceMock,
|
||||
totalsService: TotalsServiceMock,
|
||||
},
|
||||
const stripeBase = new StripeBase(
|
||||
fakeContainer,
|
||||
{
|
||||
api_key: "test",
|
||||
}
|
||||
)
|
||||
|
||||
result = await stripeProviderService.updatePaymentIntentCustomer(
|
||||
result = await stripeBase.updatePaymentIntentCustomer(
|
||||
"pi_lebron",
|
||||
"cus_lebron_2"
|
||||
)
|
||||
@@ -207,14 +193,14 @@ describe("StripeProviderService", () => {
|
||||
let result
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
const stripeProviderService = new StripeProviderService(
|
||||
{},
|
||||
const stripeBase = new StripeBase(
|
||||
fakeContainer,
|
||||
{
|
||||
api_key: "test",
|
||||
}
|
||||
)
|
||||
|
||||
result = await stripeProviderService.capturePayment({
|
||||
result = await stripeBase.capturePayment({
|
||||
data: {
|
||||
id: "pi_lebron",
|
||||
customer: "cus_lebron",
|
||||
@@ -237,14 +223,14 @@ describe("StripeProviderService", () => {
|
||||
let result
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
const stripeProviderService = new StripeProviderService(
|
||||
{},
|
||||
const stripeBase = new StripeBase(
|
||||
fakeContainer,
|
||||
{
|
||||
api_key: "test",
|
||||
}
|
||||
)
|
||||
|
||||
result = await stripeProviderService.refundPayment(
|
||||
result = await stripeBase.refundPayment(
|
||||
{
|
||||
data: {
|
||||
id: "re_123",
|
||||
@@ -271,14 +257,14 @@ describe("StripeProviderService", () => {
|
||||
let result
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
const stripeProviderService = new StripeProviderService(
|
||||
{},
|
||||
const stripeBase = new StripeBase(
|
||||
fakeContainer,
|
||||
{
|
||||
api_key: "test",
|
||||
}
|
||||
)
|
||||
|
||||
result = await stripeProviderService.cancelPayment({
|
||||
result = await stripeBase.cancelPayment({
|
||||
data: {
|
||||
id: "pi_lebron",
|
||||
customer: "cus_lebron",
|
||||
@@ -1,29 +1,12 @@
|
||||
import { AbstractPaymentService, PaymentSessionData } from "@medusajs/medusa"
|
||||
import { AbstractPaymentService } from "@medusajs/medusa"
|
||||
import Stripe from "stripe"
|
||||
import { PaymentSessionStatus } from "@medusajs/medusa/dist";
|
||||
|
||||
class StripeBase extends AbstractPaymentService {
|
||||
static identifier = null
|
||||
|
||||
constructor(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
) {
|
||||
super(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
)
|
||||
constructor(_, options) {
|
||||
super(_, options)
|
||||
|
||||
/**
|
||||
* Required Stripe options:
|
||||
@@ -38,21 +21,6 @@ class StripeBase extends AbstractPaymentService {
|
||||
|
||||
/** @private @const {Stripe} */
|
||||
this.stripe_ = Stripe(options.api_key)
|
||||
|
||||
/** @private @const {CustomerService} */
|
||||
this.stripeProviderService_ = stripeProviderService
|
||||
|
||||
/** @private @const {CustomerService} */
|
||||
this.customerService_ = customerService
|
||||
|
||||
/** @private @const {RegionService} */
|
||||
this.regionService_ = regionService
|
||||
|
||||
/** @private @const {TotalsService} */
|
||||
this.totalsService_ = totalsService
|
||||
|
||||
/** @private @const {EntityManager} */
|
||||
this.manager_ = manager
|
||||
}
|
||||
|
||||
getPaymentIntentOptions() {
|
||||
@@ -74,22 +42,48 @@ class StripeBase extends AbstractPaymentService {
|
||||
return options
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches Stripe payment intent. Check its status and returns the
|
||||
* corresponding Medusa status.
|
||||
* @param {PaymentSessionData} paymentSessionData - payment method data from cart
|
||||
* @return {Promise<PaymentSessionStatus>} the status of the payment intent
|
||||
/**
|
||||
* Get payment session status
|
||||
* statuses.
|
||||
* @param {PaymentSessionData} paymentData - the data stored with the payment session
|
||||
* @return {Promise<PaymentSessionStatus>} the status of the order
|
||||
*/
|
||||
async getStatus(paymentSessionData) {
|
||||
return await this.stripeProviderService_.getStatus(paymentSessionData)
|
||||
async getStatus(paymentData) {
|
||||
const { id } = paymentData
|
||||
const paymentIntent = await this.stripe_.paymentIntents.retrieve(id)
|
||||
|
||||
switch (paymentIntent.status) {
|
||||
case "requires_payment_method":
|
||||
case "requires_confirmation":
|
||||
case "processing":
|
||||
return PaymentSessionStatus.PENDING
|
||||
case "requires_action":
|
||||
return PaymentSessionStatus.REQUIRES_MORE
|
||||
case "canceled":
|
||||
return PaymentSessionStatus.CANCELED
|
||||
case "requires_capture":
|
||||
case "succeeded":
|
||||
return PaymentSessionStatus.AUTHORIZED
|
||||
default:
|
||||
return PaymentSessionStatus.PENDING
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a customers saved payment methods if registered in Stripe.
|
||||
* @param {object} customer - customer to fetch saved cards for
|
||||
* @param {Customer} customer - customer to fetch saved cards for
|
||||
* @return {Promise<Data[]>} saved payments methods
|
||||
*/
|
||||
async retrieveSavedMethods(customer) {
|
||||
if (customer.metadata && customer.metadata.stripe_id) {
|
||||
const methods = await this.stripe_.paymentMethods.list({
|
||||
customer: customer.metadata.stripe_id,
|
||||
type: "card",
|
||||
})
|
||||
|
||||
return methods.data
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -99,49 +93,68 @@ class StripeBase extends AbstractPaymentService {
|
||||
* @return {Promise<object>} Stripe customer
|
||||
*/
|
||||
async retrieveCustomer(customerId) {
|
||||
return await this.stripeProviderService_.retrieveCustomer(customerId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Stripe customer using a Medusa customer.
|
||||
* @param {object} customer - Customer data from Medusa
|
||||
* @return {Promise<object>} Stripe customer
|
||||
*/
|
||||
async createCustomer(customer) {
|
||||
return await this.stripeProviderService_
|
||||
.withTransaction(this.manager_)
|
||||
.createCustomer(customer)
|
||||
if (!customerId) {
|
||||
return
|
||||
}
|
||||
return await this.stripe_.customers.retrieve(customerId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Stripe payment intent.
|
||||
* If customer is not registered in Stripe, we do so.
|
||||
* @param {Cart} cart - cart to create a payment for
|
||||
* @return {Promise<PaymentSessionData>} Stripe payment intent
|
||||
* @param {Cart & PaymentContext} context - context to use to create a payment for
|
||||
* @return {Promise<PaymentSessionResponse>} Stripe payment intent
|
||||
*/
|
||||
async createPayment(cart) {
|
||||
async createPayment(context) {
|
||||
const intentRequestData = this.getPaymentIntentOptions()
|
||||
const { id: cart_id, email, context: cart_context, currency_code, amount, resource_id, customer } = context
|
||||
|
||||
return await this.stripeProviderService_
|
||||
.withTransaction(this.manager_)
|
||||
.createPayment(cart, intentRequestData)
|
||||
}
|
||||
const intentRequest = {
|
||||
description:
|
||||
cart_context.payment_description ??
|
||||
this.options_?.payment_description,
|
||||
amount: Math.round(amount),
|
||||
currency: currency_code,
|
||||
metadata: { cart_id, resource_id },
|
||||
capture_method: this.options_.capture ? "automatic" : "manual",
|
||||
...intentRequestData,
|
||||
}
|
||||
|
||||
async createPaymentNew(paymentInput) {
|
||||
const intentRequestData = this.getPaymentIntentOptions()
|
||||
if (this.options_?.automatic_payment_methods) {
|
||||
intentRequest.automatic_payment_methods = { enabled: true }
|
||||
}
|
||||
|
||||
return await this.stripeProviderService_
|
||||
.withTransaction(this.manager_)
|
||||
.createPaymentNew(paymentInput, intentRequestData)
|
||||
if (customer?.metadata?.stripe_id) {
|
||||
intentRequest.customer = customer?.metadata?.stripe_id
|
||||
} else {
|
||||
const stripeCustomer = await this.stripe_.customers.create({
|
||||
email,
|
||||
})
|
||||
|
||||
intentRequest.customer = stripeCustomer.id
|
||||
}
|
||||
|
||||
const session_data = await this.stripe_.paymentIntents.create(
|
||||
intentRequest
|
||||
)
|
||||
|
||||
return {
|
||||
session_data,
|
||||
update_requests: {
|
||||
customer_metadata: {
|
||||
stripe_id: intentRequest.customer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves Stripe payment intent.
|
||||
* @param {PaymentData} paymentData - the data of the payment to retrieve
|
||||
* @param {PaymentData} data - the data of the payment to retrieve
|
||||
* @return {Promise<Data>} Stripe payment intent
|
||||
*/
|
||||
async retrievePayment(paymentData) {
|
||||
return await this.stripeProviderService_.retrievePayment(paymentData)
|
||||
async retrievePayment(data) {
|
||||
return await this.stripe_.paymentIntents.retrieve(data.id)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,67 +163,73 @@ class StripeBase extends AbstractPaymentService {
|
||||
* @return {Promise<PaymentData>} Stripe payment intent
|
||||
*/
|
||||
async getPaymentData(paymentSession) {
|
||||
return await this.stripeProviderService_.getPaymentData(paymentSession)
|
||||
return await this.stripe_.paymentIntents.retrieve(paymentSession.data.id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorizes Stripe payment intent by simply returning
|
||||
* the status for the payment intent in use.
|
||||
* @param {PaymentSession} paymentSession - payment session data
|
||||
* @param {object} context - properties relevant to current context
|
||||
* @return {Promise<{data: PaymentSessionData; status: PaymentSessionStatus}>} result with data and status
|
||||
* @param {Data} context - properties relevant to current context
|
||||
* @return {Promise<{ data: PaymentSessionData; status: PaymentSessionStatus }>} result with data and status
|
||||
*/
|
||||
async authorizePayment(paymentSession, context = {}) {
|
||||
return await this.stripeProviderService_.authorizePayment(
|
||||
paymentSession,
|
||||
context
|
||||
)
|
||||
const stat = await this.getStatus(paymentSession.data)
|
||||
return { data: paymentSession.data, status: stat }
|
||||
}
|
||||
|
||||
async updatePaymentData(paymentSessionData, data) {
|
||||
return await this.stripeProviderService_.updatePaymentData(
|
||||
paymentSessionData,
|
||||
data
|
||||
)
|
||||
async updatePaymentData(sessionData, update) {
|
||||
return await this.stripe_.paymentIntents.update(sessionData.id, {
|
||||
...update.data,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates Stripe payment intent.
|
||||
* @param {PaymentSessionData} paymentSessionData - payment session data.
|
||||
* @param {Cart} cart
|
||||
* @param {Cart & PaymentContext} context
|
||||
* @return {Promise<PaymentSessionData>} Stripe payment intent
|
||||
*/
|
||||
async updatePayment(paymentSessionData, cart) {
|
||||
const intentRequestData = this.getPaymentIntentOptions()
|
||||
async updatePayment(paymentSessionData, context) {
|
||||
const { amount, customer } = context
|
||||
const stripeId = customer?.metadata?.stripe_id || undefined
|
||||
|
||||
return await this.stripeProviderService_
|
||||
.withTransaction(this.manager_)
|
||||
.updatePayment(paymentSessionData, cart, intentRequestData)
|
||||
if (stripeId !== paymentSessionData.customer) {
|
||||
return await this.createPayment(context)
|
||||
} else {
|
||||
if (
|
||||
amount &&
|
||||
paymentSessionData.amount === Math.round(amount)
|
||||
) {
|
||||
return paymentSessionData
|
||||
}
|
||||
|
||||
return await this.stripe_.paymentIntents.update(paymentSessionData.id, {
|
||||
amount: Math.round(amount),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async updatePaymentNew(paymentSessionData, paymentInput) {
|
||||
const intentRequestData = this.getPaymentIntentOptions()
|
||||
|
||||
return await this.stripeProviderService_
|
||||
.withTransaction(this.manager_)
|
||||
.updatePaymentNew(paymentSessionData, paymentInput, intentRequestData)
|
||||
}
|
||||
|
||||
async deletePayment(paymentSession) {
|
||||
return await this.stripeProviderService_.deletePayment(paymentSession)
|
||||
async deletePayment(payment) {
|
||||
const { id } = payment.data
|
||||
return this.stripe_.paymentIntents.cancel(id).catch((err) => {
|
||||
if (err.statusCode === 400) {
|
||||
return
|
||||
}
|
||||
throw err
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates customer of Stripe payment intent.
|
||||
* @param {string} paymentIntentId - id of payment intent to update
|
||||
* @param {string} customerId - id of new Stripe customer
|
||||
* @param {string} customerId - id of \ Stripe customer
|
||||
* @return {object} Stripe payment intent
|
||||
*/
|
||||
async updatePaymentIntentCustomer(paymentIntentId, customerId) {
|
||||
return await this.stripeProviderService_.updatePaymentIntentCustomer(
|
||||
paymentIntentId,
|
||||
customerId
|
||||
)
|
||||
return await this.stripe_.paymentIntents.update(paymentIntentId, {
|
||||
customer: customerId,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,7 +238,18 @@ class StripeBase extends AbstractPaymentService {
|
||||
* @return {Promise<PaymentData>} Stripe payment intent
|
||||
*/
|
||||
async capturePayment(payment) {
|
||||
return await this.stripeProviderService_.capturePayment(payment)
|
||||
const { id } = payment.data
|
||||
try {
|
||||
const intent = await this.stripe_.paymentIntents.capture(id)
|
||||
return intent
|
||||
} catch (error) {
|
||||
if (error.code === "payment_intent_unexpected_state") {
|
||||
if (error.payment_intent.status === "succeeded") {
|
||||
return error.payment_intent
|
||||
}
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,11 +258,14 @@ class StripeBase extends AbstractPaymentService {
|
||||
* @param {number} refundAmount - amount to refund
|
||||
* @return {Promise<PaymentData>} refunded payment intent
|
||||
*/
|
||||
async refundPayment(payment, refundAmount) {
|
||||
return await this.stripeProviderService_.refundPayment(
|
||||
payment,
|
||||
refundAmount
|
||||
)
|
||||
async refundPayment(payment, amountToRefund) {
|
||||
const { id } = payment.data
|
||||
await this.stripe_.refunds.create({
|
||||
amount: Math.round(amountToRefund),
|
||||
payment_intent: id,
|
||||
})
|
||||
|
||||
return payment.data
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,7 +274,31 @@ class StripeBase extends AbstractPaymentService {
|
||||
* @return {Promise<PaymentData>} canceled payment intent
|
||||
*/
|
||||
async cancelPayment(payment) {
|
||||
return await this.stripeProviderService_.cancelPayment(payment)
|
||||
const { id } = payment.data
|
||||
try {
|
||||
return await this.stripe_.paymentIntents.cancel(id)
|
||||
} catch (error) {
|
||||
if (error.payment_intent.status === "canceled") {
|
||||
return error.payment_intent
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs Stripe Webhook event
|
||||
* @param {object} data - the data of the webhook request: req.body
|
||||
* @param {object} signature - the Stripe signature on the event, that
|
||||
* ensures integrity of the webhook event
|
||||
* @return {object} Stripe Webhook event
|
||||
*/
|
||||
constructWebhookEvent(data, signature) {
|
||||
return this.stripe_.webhooks.constructEvent(
|
||||
data,
|
||||
signature,
|
||||
this.options_.webhook_secret
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
|
||||
export const StripeProviderServiceMock = {
|
||||
withTransaction: function () {
|
||||
return this
|
||||
},
|
||||
retrievePayment: jest.fn().mockImplementation((payData) => {
|
||||
if (payData.id === "pi_123456789") {
|
||||
return Promise.resolve({
|
||||
id: "pi",
|
||||
customer: "cus_123456789",
|
||||
})
|
||||
}
|
||||
if (payData.id === "pi_no") {
|
||||
return Promise.resolve({
|
||||
id: "pi_no",
|
||||
})
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
}),
|
||||
cancelPayment: jest.fn().mockImplementation((cart) => {
|
||||
return Promise.resolve()
|
||||
}),
|
||||
updatePaymentIntentCustomer: jest.fn().mockImplementation((cart) => {
|
||||
return Promise.resolve()
|
||||
}),
|
||||
retrieveCustomer: jest.fn().mockImplementation((customerId) => {
|
||||
if (customerId === "cus_123456789_new") {
|
||||
return Promise.resolve({
|
||||
id: "cus_123456789_new",
|
||||
})
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
}),
|
||||
createCustomer: jest.fn().mockImplementation((customer) => {
|
||||
if (customer._id === IdMap.getId("vvd")) {
|
||||
return Promise.resolve({
|
||||
id: "cus_123456789_new_vvd",
|
||||
})
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
}),
|
||||
createPayment: jest.fn().mockImplementation((cart) => {
|
||||
return Promise.resolve({
|
||||
id: "pi_new",
|
||||
customer: "cus_123456789_new",
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
const mock = jest.fn().mockImplementation(() => {
|
||||
return StripeProviderServiceMock
|
||||
})
|
||||
|
||||
export default mock
|
||||
@@ -3,26 +3,8 @@ import StripeBase from "../helpers/stripe-base"
|
||||
class BancontactProviderService extends StripeBase {
|
||||
static identifier = "stripe-bancontact"
|
||||
|
||||
constructor(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
) {
|
||||
super(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
)
|
||||
constructor(_, options) {
|
||||
super(_, options)
|
||||
}
|
||||
|
||||
get paymentIntentOptions() {
|
||||
|
||||
@@ -3,26 +3,8 @@ import StripeBase from "../helpers/stripe-base"
|
||||
class BlikProviderService extends StripeBase {
|
||||
static identifier = "stripe-blik"
|
||||
|
||||
constructor(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
) {
|
||||
super(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
)
|
||||
constructor(_, options) {
|
||||
super(_, options)
|
||||
}
|
||||
|
||||
get paymentIntentOptions() {
|
||||
|
||||
@@ -3,26 +3,8 @@ import StripeBase from "../helpers/stripe-base"
|
||||
class GiropayProviderService extends StripeBase {
|
||||
static identifier = "stripe-giropay"
|
||||
|
||||
constructor(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
) {
|
||||
super(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
)
|
||||
constructor(_, options) {
|
||||
super(_, options)
|
||||
}
|
||||
|
||||
get paymentIntentOptions() {
|
||||
|
||||
@@ -3,26 +3,8 @@ import StripeBase from "../helpers/stripe-base"
|
||||
class IdealProviderService extends StripeBase {
|
||||
static identifier = "stripe-ideal"
|
||||
|
||||
constructor(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
) {
|
||||
super(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
)
|
||||
constructor(_, options) {
|
||||
super(_, options)
|
||||
}
|
||||
|
||||
get paymentIntentOptions() {
|
||||
|
||||
@@ -1,424 +1,14 @@
|
||||
import {
|
||||
AbstractPaymentService,
|
||||
PaymentSessionData,
|
||||
PaymentSessionStatus,
|
||||
} from "@medusajs/medusa"
|
||||
import Stripe from "stripe"
|
||||
import StripeBase from "../helpers/stripe-base";
|
||||
|
||||
class StripeProviderService extends AbstractPaymentService {
|
||||
class StripeProviderService extends StripeBase {
|
||||
static identifier = "stripe"
|
||||
|
||||
constructor(
|
||||
{ customerService, totalsService, regionService, manager },
|
||||
options
|
||||
) {
|
||||
super({ customerService, totalsService, regionService, manager }, options)
|
||||
|
||||
/**
|
||||
* Required Stripe options:
|
||||
* {
|
||||
* api_key: "stripe_secret_key", REQUIRED
|
||||
* webhook_secret: "stripe_webhook_secret", REQUIRED
|
||||
* // Use this flag to capture payment immediately (default is false)
|
||||
* capture: true
|
||||
* }
|
||||
*/
|
||||
this.options_ = options
|
||||
|
||||
/** @private @const {Stripe} */
|
||||
this.stripe_ = Stripe(options.api_key)
|
||||
|
||||
/** @private @const {CustomerService} */
|
||||
this.customerService_ = customerService
|
||||
|
||||
/** @private @const {RegionService} */
|
||||
this.regionService_ = regionService
|
||||
|
||||
/** @private @const {TotalsService} */
|
||||
this.totalsService_ = totalsService
|
||||
|
||||
/** @private @const {EntityManager} */
|
||||
this.manager_ = manager
|
||||
constructor(_, options) {
|
||||
super(_, options)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get payment session status
|
||||
* statuses.
|
||||
* @param {PaymentSessionData} paymentData - the data stored with the payment session
|
||||
* @return {Promise<PaymentSessionStatus>} the status of the order
|
||||
*/
|
||||
async getStatus(paymentData) {
|
||||
const { id } = paymentData
|
||||
const paymentIntent = await this.stripe_.paymentIntents.retrieve(id)
|
||||
|
||||
switch (paymentIntent.status) {
|
||||
case "requires_payment_method":
|
||||
case "requires_confirmation":
|
||||
case "processing":
|
||||
return PaymentSessionStatus.PENDING
|
||||
case "requires_action":
|
||||
return PaymentSessionStatus.REQUIRES_MORE
|
||||
case "canceled":
|
||||
return PaymentSessionStatus.CANCELED
|
||||
case "requires_capture":
|
||||
case "succeeded":
|
||||
return PaymentSessionStatus.AUTHORIZED
|
||||
default:
|
||||
return PaymentSessionStatus.PENDING
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a customers saved payment methods if registered in Stripe.
|
||||
* @param {Customer} customer - customer to fetch saved cards for
|
||||
* @return {Promise<Data[]>} saved payments methods
|
||||
*/
|
||||
async retrieveSavedMethods(customer) {
|
||||
if (customer.metadata && customer.metadata.stripe_id) {
|
||||
const methods = await this.stripe_.paymentMethods.list({
|
||||
customer: customer.metadata.stripe_id,
|
||||
type: "card",
|
||||
})
|
||||
|
||||
return methods.data
|
||||
}
|
||||
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a Stripe customer
|
||||
* @param {string} customerId - Stripe customer id
|
||||
* @return {Promise<object>} Stripe customer
|
||||
*/
|
||||
async retrieveCustomer(customerId) {
|
||||
if (!customerId) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return this.stripe_.customers.retrieve(customerId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Stripe customer using a Medusa customer.
|
||||
* @param {object} customer - Customer data from Medusa
|
||||
* @return {Promise<object>} Stripe customer
|
||||
*/
|
||||
async createCustomer(customer) {
|
||||
try {
|
||||
const stripeCustomer = await this.stripe_.customers.create({
|
||||
email: customer.email,
|
||||
})
|
||||
|
||||
if (customer.id) {
|
||||
await this.customerService_
|
||||
.withTransaction(this.manager_)
|
||||
.update(customer.id, {
|
||||
metadata: { stripe_id: stripeCustomer.id },
|
||||
})
|
||||
}
|
||||
|
||||
return stripeCustomer
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<PaymentSessionData>} Stripe payment intent
|
||||
*/
|
||||
async createPayment(cart, intentRequestData = {}) {
|
||||
const { customer_id, region_id, email } = cart
|
||||
const { currency_code } = await this.regionService_
|
||||
.withTransaction(this.manager_)
|
||||
.retrieve(region_id)
|
||||
|
||||
const amount = cart.total
|
||||
|
||||
const intentRequest = {
|
||||
description:
|
||||
cart?.context?.payment_description ??
|
||||
this.options_?.payment_description,
|
||||
amount: Math.round(amount),
|
||||
currency: currency_code,
|
||||
metadata: { cart_id: `${cart.id}` },
|
||||
capture_method: this.options_.capture ? "automatic" : "manual",
|
||||
...intentRequestData,
|
||||
}
|
||||
|
||||
if (this.options_?.automatic_payment_methods) {
|
||||
intentRequest.automatic_payment_methods = { enabled: true }
|
||||
}
|
||||
|
||||
if (customer_id) {
|
||||
const customer = await this.customerService_
|
||||
.withTransaction(this.manager_)
|
||||
.retrieve(customer_id)
|
||||
|
||||
if (customer.metadata?.stripe_id) {
|
||||
intentRequest.customer = customer.metadata.stripe_id
|
||||
} else {
|
||||
const stripeCustomer = await this.createCustomer({
|
||||
email,
|
||||
id: customer_id,
|
||||
})
|
||||
|
||||
intentRequest.customer = stripeCustomer.id
|
||||
}
|
||||
} else {
|
||||
const stripeCustomer = await this.createCustomer({
|
||||
email,
|
||||
})
|
||||
|
||||
intentRequest.customer = stripeCustomer.id
|
||||
}
|
||||
|
||||
return await this.stripe_.paymentIntents.create(intentRequest)
|
||||
}
|
||||
|
||||
async createPaymentNew(paymentInput, intentRequestData = {}) {
|
||||
const { customer, currency_code, amount, resource_id, cart } = paymentInput
|
||||
const { id: customer_id, email } = customer ?? {}
|
||||
|
||||
const intentRequest = {
|
||||
description:
|
||||
cart?.context?.payment_description ??
|
||||
this.options_?.payment_description,
|
||||
amount: Math.round(amount),
|
||||
currency: currency_code,
|
||||
metadata: { resource_id },
|
||||
capture_method: this.options_.capture ? "automatic" : "manual",
|
||||
...intentRequestData,
|
||||
}
|
||||
|
||||
if (customer_id) {
|
||||
if (customer.metadata?.stripe_id) {
|
||||
intentRequest.customer = customer.metadata.stripe_id
|
||||
} else {
|
||||
const stripeCustomer = await this.createCustomer({
|
||||
email,
|
||||
id: customer_id,
|
||||
})
|
||||
|
||||
intentRequest.customer = stripeCustomer.id
|
||||
}
|
||||
} else if (email) {
|
||||
const stripeCustomer = await this.createCustomer({
|
||||
email,
|
||||
})
|
||||
|
||||
intentRequest.customer = stripeCustomer.id
|
||||
}
|
||||
|
||||
return await this.stripe_.paymentIntents.create(intentRequest)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves Stripe payment intent.
|
||||
* @param {PaymentData} paymentData - the data of the payment to retrieve
|
||||
* @return {Promise<Data>} Stripe payment intent
|
||||
*/
|
||||
async retrievePayment(data) {
|
||||
try {
|
||||
return await this.stripe_.paymentIntents.retrieve(data.id)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Stripe payment intent and returns it.
|
||||
* @param {PaymentSession} paymentSession - the data of the payment to retrieve
|
||||
* @return {Promise<PaymentData>} Stripe payment intent
|
||||
*/
|
||||
async getPaymentData(paymentSession) {
|
||||
try {
|
||||
return await this.stripe_.paymentIntents.retrieve(paymentSession.data.id)
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authorizes Stripe payment intent by simply returning
|
||||
* the status for the payment intent in use.
|
||||
* @param {PaymentSession} paymentSession - payment session data
|
||||
* @param {Data} context - properties relevant to current context
|
||||
* @return {Promise<{ data: PaymentSessionData; status: PaymentSessionStatus }>} result with data and status
|
||||
*/
|
||||
async authorizePayment(paymentSession, context = {}) {
|
||||
const stat = await this.getStatus(paymentSession.data)
|
||||
try {
|
||||
return { data: paymentSession.data, status: stat }
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async updatePaymentData(sessionData, update) {
|
||||
try {
|
||||
return await this.stripe_.paymentIntents.update(sessionData.id, {
|
||||
...update.data,
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates Stripe payment intent.
|
||||
* @param {PaymentSessionData} paymentSessionData - payment session data.
|
||||
* @param {Cart} cart
|
||||
* @param intentRequestData
|
||||
* @return {Promise<PaymentSessionData>} Stripe payment intent
|
||||
*/
|
||||
async updatePayment(paymentSessionData, cart, intentRequestData) {
|
||||
try {
|
||||
const stripeId = cart.customer?.metadata?.stripe_id || undefined
|
||||
|
||||
if (stripeId !== paymentSessionData.customer) {
|
||||
return await this.createPayment(cart, intentRequestData)
|
||||
} else {
|
||||
if (
|
||||
cart.total &&
|
||||
paymentSessionData.amount === Math.round(cart.total)
|
||||
) {
|
||||
return paymentSessionData
|
||||
}
|
||||
|
||||
return await this.stripe_.paymentIntents.update(paymentSessionData.id, {
|
||||
amount: Math.round(cart.total),
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async updatePaymentNew(paymentSessionData, paymentInput, intentRequestData) {
|
||||
try {
|
||||
const stripeId = paymentInput.customer?.metadata?.stripe_id
|
||||
|
||||
if (stripeId !== paymentSessionData.customer) {
|
||||
return await this.createPaymentNew(paymentInput, intentRequestData)
|
||||
} else {
|
||||
if (paymentSessionData.amount === Math.round(paymentInput.amount)) {
|
||||
return paymentSessionData
|
||||
}
|
||||
|
||||
return await this.stripe_.paymentIntents.update(paymentSessionData.id, {
|
||||
amount: Math.round(paymentInput.amount),
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
async deletePayment(payment) {
|
||||
try {
|
||||
const { id } = payment.data
|
||||
return this.stripe_.paymentIntents.cancel(id).catch((err) => {
|
||||
if (err.statusCode === 400) {
|
||||
return
|
||||
}
|
||||
throw err
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates customer of Stripe payment intent.
|
||||
* @param {string} paymentIntentId - id of payment intent to update
|
||||
* @param {string} customerId - id of new Stripe customer
|
||||
* @return {object} Stripe payment intent
|
||||
*/
|
||||
async updatePaymentIntentCustomer(paymentIntentId, customerId) {
|
||||
try {
|
||||
return await this.stripe_.paymentIntents.update(paymentIntentId, {
|
||||
customer: customerId,
|
||||
})
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures payment for Stripe payment intent.
|
||||
* @param {Payment} payment - payment method data from cart
|
||||
* @return {Promise<PaymentData>} Stripe payment intent
|
||||
*/
|
||||
async capturePayment(payment) {
|
||||
const { id } = payment.data
|
||||
try {
|
||||
const intent = await this.stripe_.paymentIntents.capture(id)
|
||||
return intent
|
||||
} catch (error) {
|
||||
if (error.code === "payment_intent_unexpected_state") {
|
||||
if (error.payment_intent.status === "succeeded") {
|
||||
return error.payment_intent
|
||||
}
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refunds payment for Stripe payment intent.
|
||||
* @param {Payment} payment - payment method data from cart
|
||||
* @param {number} refundAmount - amount to refund
|
||||
* @return {Promise<PaymentData>} refunded payment intent
|
||||
*/
|
||||
async refundPayment(payment, amountToRefund) {
|
||||
const { id } = payment.data
|
||||
try {
|
||||
await this.stripe_.refunds.create({
|
||||
amount: Math.round(amountToRefund),
|
||||
payment_intent: id,
|
||||
})
|
||||
|
||||
return payment.data
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels payment for Stripe payment intent.
|
||||
* @param {Payment} payment - payment method data from cart
|
||||
* @return {Promise<PaymentData>} canceled payment intent
|
||||
*/
|
||||
async cancelPayment(payment) {
|
||||
const { id } = payment.data
|
||||
try {
|
||||
return await this.stripe_.paymentIntents.cancel(id)
|
||||
} catch (error) {
|
||||
if (error.payment_intent.status === "canceled") {
|
||||
return error.payment_intent
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs Stripe Webhook event
|
||||
* @param {object} data - the data of the webhook request: req.body
|
||||
* @param {object} signature - the Stripe signature on the event, that
|
||||
* ensures integrity of the webhook event
|
||||
* @return {object} Stripe Webhook event
|
||||
*/
|
||||
constructWebhookEvent(data, signature) {
|
||||
return this.stripe_.webhooks.constructEvent(
|
||||
data,
|
||||
signature,
|
||||
this.options_.webhook_secret
|
||||
)
|
||||
get paymentIntentOptions() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,26 +3,8 @@ import StripeBase from "../helpers/stripe-base"
|
||||
class Przelewy24ProviderService extends StripeBase {
|
||||
static identifier = "stripe-przelewy24"
|
||||
|
||||
constructor(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
) {
|
||||
super(
|
||||
{
|
||||
stripeProviderService,
|
||||
customerService,
|
||||
totalsService,
|
||||
regionService,
|
||||
manager,
|
||||
},
|
||||
options
|
||||
)
|
||||
constructor(_, options) {
|
||||
super(_, options)
|
||||
}
|
||||
|
||||
get paymentIntentOptions() {
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
class CartSubscriber {
|
||||
constructor({
|
||||
manager,
|
||||
cartService,
|
||||
paymentProviderService,
|
||||
eventBusService,
|
||||
}) {
|
||||
this.cartService_ = cartService
|
||||
this.paymentProviderService_ = paymentProviderService
|
||||
this.eventBus_ = eventBusService
|
||||
this.manager_ = manager
|
||||
|
||||
this.eventBus_.subscribe("cart.customer_updated", async (cart) => {
|
||||
await this.onCustomerUpdated(cart)
|
||||
})
|
||||
}
|
||||
|
||||
async onCustomerUpdated(cartId) {
|
||||
await this.manager_.transaction(async (transactionManager) => {
|
||||
const cart = await this.cartService_
|
||||
.withTransaction(transactionManager)
|
||||
.retrieve(cartId, {
|
||||
select: [
|
||||
"subtotal",
|
||||
"tax_total",
|
||||
"shipping_total",
|
||||
"discount_total",
|
||||
"gift_card_total",
|
||||
"total",
|
||||
],
|
||||
relations: [
|
||||
"billing_address",
|
||||
"shipping_address",
|
||||
"region",
|
||||
"region.payment_providers",
|
||||
"items",
|
||||
"items.adjustments",
|
||||
"payment_sessions",
|
||||
"customer",
|
||||
],
|
||||
})
|
||||
|
||||
if (!cart.payment_sessions?.length) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const session = cart.payment_sessions.find(
|
||||
(ps) => ps.provider_id === "stripe"
|
||||
)
|
||||
|
||||
if (session) {
|
||||
return await this.paymentProviderService_
|
||||
.withTransaction(transactionManager)
|
||||
.updateSession(session, cart)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default CartSubscriber
|
||||
Reference in new issue
Block a user