Klarna clean up
This commit is contained in:
commit
419d5db340
26 files changed
+330
-138
No files matched your search
@@ -5,6 +5,7 @@ export default async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const cartService = req.scope.resolve("cartService")
|
const cartService = req.scope.resolve("cartService")
|
||||||
const klarnaProviderService = req.scope.resolve("pp_klarna")
|
const klarnaProviderService = req.scope.resolve("pp_klarna")
|
||||||
|
const shippingProfileService = req.scope.resolve("shippingProfileService")
|
||||||
|
|
||||||
const cart = await cartService.retrieve(merchant_data)
|
const cart = await cartService.retrieve(merchant_data)
|
||||||
|
|
||||||
@@ -23,6 +24,12 @@ export default async (req, res) => {
|
|||||||
await cartService.updateBillingAddress(cart._id, updatedAddress)
|
await cartService.updateBillingAddress(cart._id, updatedAddress)
|
||||||
await cartService.updateEmail(cart._id, shipping_address.email)
|
await cartService.updateEmail(cart._id, shipping_address.email)
|
||||||
|
|
||||||
|
const shippingOptions = await shippingProfileService.fetchCartOptions(cart)
|
||||||
|
if (shippingOptions.length === 1) {
|
||||||
|
const option = shippingOptions[0]
|
||||||
|
await cartService.addShippingMethod(cart._id, option._id, option.data)
|
||||||
|
}
|
||||||
|
|
||||||
// Fetch and return updated Klarna order
|
// Fetch and return updated Klarna order
|
||||||
const updatedCart = await cartService.retrieve(cart._id)
|
const updatedCart = await cartService.retrieve(cart._id)
|
||||||
const order = await klarnaProviderService.cartToKlarnaOrder(updatedCart)
|
const order = await klarnaProviderService.cartToKlarnaOrder(updatedCart)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const order = await orderService.retrieveByCartId(cartId)
|
const order = await orderService.retrieveByCartId(cartId)
|
||||||
await klarnaProviderService.acknowledgeOrder(klarnaOrder.id, order._id)
|
await klarnaProviderService.acknowledgeOrder(klarnaOrder.order_id, order._id)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.type === MeudsaError.Types.NOT_FOUND) {
|
if (err.type === MeudsaError.Types.NOT_FOUND) {
|
||||||
let cart = await cartService.retrieve(cartId)
|
let cart = await cartService.retrieve(cartId)
|
||||||
@@ -24,7 +24,7 @@ export default async (req, res) => {
|
|||||||
cart = await cartService.setPaymentMethod(cart._id, method)
|
cart = await cartService.setPaymentMethod(cart._id, method)
|
||||||
|
|
||||||
const order = await orderService.createFromCart(cart)
|
const order = await orderService.createFromCart(cart)
|
||||||
await klarnaProviderService.acknowledgeOrder(klarnaOrder.id, order._id)
|
await klarnaProviderService.acknowledgeOrder(klarnaOrder.order_id, order._id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,11 @@ export default async (req, res) => {
|
|||||||
const cart = await cartService.retrieve(merchant_data)
|
const cart = await cartService.retrieve(merchant_data)
|
||||||
const shippingOptions = await shippingProfileService.fetchCartOptions(cart)
|
const shippingOptions = await shippingProfileService.fetchCartOptions(cart)
|
||||||
|
|
||||||
const option = shippingOptions.find(({ _id }) => _id === selected_shipping_option.id)
|
const option = shippingOptions.find(({ _id }) => _id.equals(selected_shipping_option.id))
|
||||||
|
|
||||||
if (option) {
|
if (option) {
|
||||||
await cartService.addShippingMethod(cart._id, option._id, option.data)
|
const newCart = await cartService.addShippingMethod(cart._id, option._id, option.data)
|
||||||
|
const order = await klarnaProviderService.cartToKlarnaOrder(newCart)
|
||||||
// Fetch and return updated Klarna order
|
|
||||||
const updatedCart = await cartService.retrieve(cart._id)
|
|
||||||
const order = klarnaProviderService.cartToKlarnaOrder(updatedCart)
|
|
||||||
res.json(order)
|
res.json(order)
|
||||||
} else {
|
} else {
|
||||||
res.sendStatus(400)
|
res.sendStatus(400)
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ import { PaymentService } from "medusa-interfaces"
|
|||||||
class KlarnaProviderService extends PaymentService {
|
class KlarnaProviderService extends PaymentService {
|
||||||
static identifier = "klarna"
|
static identifier = "klarna"
|
||||||
|
|
||||||
constructor({ shippingProfileService, totalsService, regionService }, options) {
|
constructor(
|
||||||
|
{ shippingProfileService, totalsService, regionService },
|
||||||
|
options
|
||||||
|
) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
this.options_ = options
|
this.options_ = options
|
||||||
@@ -22,7 +25,8 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
|
|
||||||
this.klarnaOrderManagementUrl_ = "/ordermanagement/v1/orders"
|
this.klarnaOrderManagementUrl_ = "/ordermanagement/v1/orders"
|
||||||
|
|
||||||
this.backendUrl_ = process.env.BACKEND_URL || "https://58721b1f44d9.ngrok.io"
|
this.backendUrl_ =
|
||||||
|
process.env.BACKEND_URL || "https://2fe4e28015f5.ngrok.io"
|
||||||
|
|
||||||
this.totalsService_ = totalsService
|
this.totalsService_ = totalsService
|
||||||
|
|
||||||
@@ -77,7 +81,7 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
const quantity = item.content.quantity
|
const quantity = item.content.quantity
|
||||||
const unit_price = item.content.unit_price * 100 * (taxRate + 1)
|
const unit_price = item.content.unit_price * 100 * (taxRate + 1)
|
||||||
const total_discount_amount = itemDiscount * (taxRate + 1) * 100
|
const total_discount_amount = itemDiscount * (taxRate + 1) * 100
|
||||||
const total_amount = unit_price * quantity - total_discount_amount
|
const total_amount = unit_price * quantity - total_discount_amount
|
||||||
const total_tax_amount = total_amount * (taxRate / (1 + taxRate))
|
const total_tax_amount = total_amount * (taxRate / (1 + taxRate))
|
||||||
|
|
||||||
order_lines.push({
|
order_lines.push({
|
||||||
@@ -98,6 +102,7 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
order_lines.push({
|
order_lines.push({
|
||||||
name: `${shippingMethod.name}`,
|
name: `${shippingMethod.name}`,
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
|
type: "shipping_fee",
|
||||||
unit_price: price * (1 + taxRate) * 100,
|
unit_price: price * (1 + taxRate) * 100,
|
||||||
tax_rate: taxRate * 10000,
|
tax_rate: taxRate * 10000,
|
||||||
total_amount: price * (1 + taxRate) * 100,
|
total_amount: price * (1 + taxRate) * 100,
|
||||||
@@ -141,8 +146,8 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
order.purchase_country = "SE"
|
order.purchase_country = "SE"
|
||||||
}
|
}
|
||||||
|
|
||||||
order.order_amount = await this.totalsService_.getTotal(cart) * 100
|
order.order_amount = (await this.totalsService_.getTotal(cart)) * 100
|
||||||
order.order_tax_amount = await this.totalsService_.getTaxTotal(cart) * 100
|
order.order_tax_amount = (await this.totalsService_.getTaxTotal(cart)) * 100
|
||||||
// TODO: Check if currency matches ISO
|
// TODO: Check if currency matches ISO
|
||||||
order.purchase_currency = currency_code
|
order.purchase_currency = currency_code
|
||||||
|
|
||||||
@@ -155,45 +160,36 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
address_update: `${this.backendUrl_}/klarna/address`,
|
address_update: `${this.backendUrl_}/klarna/address`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cart.shipping_address && cart.shipping_address.first_name) {
|
||||||
|
const shippingOptions = await this.shippingProfileService_.fetchCartOptions(
|
||||||
|
cart
|
||||||
|
)
|
||||||
|
|
||||||
const shippingOptions = await this.shippingProfileService_.fetchCartOptions(cart)
|
// If the cart does not have shipping methods yet, preselect one from
|
||||||
|
// shipping_options and set the selected shipping method
|
||||||
|
if (cart.shipping_methods.length) {
|
||||||
|
const shipping_method = cart.shipping_methods[0]
|
||||||
|
order.selected_shipping_option = {
|
||||||
|
id: shipping_method._id,
|
||||||
|
name: shipping_method.name,
|
||||||
|
price: shipping_method.price * (1 + tax_rate) * 100,
|
||||||
|
tax_amount: shipping_method.price * tax_rate * 100,
|
||||||
|
tax_rate: tax_rate * 10000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the cart does not have shipping methods yet, preselect one from
|
// If the cart does have shipping methods, set the selected shipping method
|
||||||
// shipping_options and set the selected shipping method
|
|
||||||
if (!cart.shipping_methods.length) {
|
order.shipping_options = shippingOptions.map((so) => ({
|
||||||
const shipping_method = shippingOptions[0]
|
id: so._id,
|
||||||
order.selected_shipping_option = {
|
name: so.name,
|
||||||
id: shipping_method._id,
|
price: so.price * (1 + tax_rate) * 100,
|
||||||
name: shipping_method.name,
|
tax_amount: so.price * tax_rate * 100,
|
||||||
price: shipping_method.price * (1 + tax_rate) * 100,
|
|
||||||
tax_amount: shipping_method.price * tax_rate * 100,
|
|
||||||
// Medusa tax rate of e.g. 0.25 (25%) needs to be 2500 in Klarna
|
|
||||||
tax_rate: tax_rate * 10000,
|
tax_rate: tax_rate * 10000,
|
||||||
}
|
preselected: shippingOptions.length === 1
|
||||||
} else {
|
}))
|
||||||
const shipping_method = cart.shipping_methods[0]
|
|
||||||
order.selected_shipping_option = {
|
|
||||||
id: shipping_method._id,
|
|
||||||
name: shipping_method.name,
|
|
||||||
price: shipping_method.price * (1 + tax_rate) * 100,
|
|
||||||
tax_amount: shipping_method.price * tax_rate * 100,
|
|
||||||
tax_rate: tax_rate * 10000,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the cart does have shipping methods, set the selected shipping method
|
|
||||||
|
|
||||||
order.shipping_options = shippingOptions.map((so) => ({
|
|
||||||
id: so._id,
|
|
||||||
name: so.name,
|
|
||||||
price: so.price * (1 + tax_rate) * 100,
|
|
||||||
tax_amount: so.price * tax_rate * 100,
|
|
||||||
tax_rate: tax_rate * 10000,
|
|
||||||
preselected:
|
|
||||||
cart.shipping_methods[0] &&
|
|
||||||
`${cart.shipping_methods[0].provider_id}` === `${so.provider_id}`,
|
|
||||||
}))
|
|
||||||
|
|
||||||
return order
|
return order
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,11 +200,15 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
*/
|
*/
|
||||||
async getStatus(paymentData) {
|
async getStatus(paymentData) {
|
||||||
try {
|
try {
|
||||||
const { id } = paymentData
|
const { order_id } = paymentData
|
||||||
const order = await this.klarna_.get(`${this.klarnaOrderUrl_}/${id}`)
|
const { data: order } = await this.klarna_.get(
|
||||||
// TODO: Klarna docs does not provide a list of statues, so we need to
|
`${this.klarnaOrderUrl_}/${order_id}`
|
||||||
// play around our selves to figure it out
|
)
|
||||||
|
|
||||||
let status = "initial"
|
let status = "initial"
|
||||||
|
if (order.status === "checkout_complete") {
|
||||||
|
status = "authorized"
|
||||||
|
}
|
||||||
return status
|
return status
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
@@ -224,7 +224,8 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
async createPayment(cart) {
|
async createPayment(cart) {
|
||||||
try {
|
try {
|
||||||
const order = await this.cartToKlarnaOrder(cart)
|
const order = await this.cartToKlarnaOrder(cart)
|
||||||
return this.klarna_.post(this.klarnaOrderUrl_, order)
|
return this.klarna_
|
||||||
|
.post(this.klarnaOrderUrl_, order)
|
||||||
.then(({ data }) => data)
|
.then(({ data }) => data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
@@ -236,10 +237,10 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
* @param {string} cart - the cart to retrieve order for
|
* @param {string} cart - the cart to retrieve order for
|
||||||
* @returns {Object} Klarna order
|
* @returns {Object} Klarna order
|
||||||
*/
|
*/
|
||||||
async retrievePayment(cart) {
|
async retrievePayment(paymentData) {
|
||||||
try {
|
try {
|
||||||
const { data } = cart.payment_method
|
return this.klarna_.get(`${this.klarnaOrderUrl_}/${paymentData.order_id}`)
|
||||||
return this.klarna_.get(`${this.klarnaOrderUrl_}/${data.id}`)
|
.then(({ data }) => data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
@@ -306,8 +307,9 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
*/
|
*/
|
||||||
async updatePayment(paymentData, cart) {
|
async updatePayment(paymentData, cart) {
|
||||||
try {
|
try {
|
||||||
const order = await this.cartToKlarnaOrder(cart)
|
const order = await this.cartToKlarnaOrder(cart, true)
|
||||||
return this.klarna_.post(`${this.klarnaOrderUrl_}/${paymentData.order_id}`, order)
|
return this.klarna_
|
||||||
|
.post(`${this.klarnaOrderUrl_}/${paymentData.order_id}`, order)
|
||||||
.then(({ data }) => data)
|
.then(({ data }) => data)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
@@ -321,17 +323,19 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
*/
|
*/
|
||||||
async capturePayment(paymentData) {
|
async capturePayment(paymentData) {
|
||||||
try {
|
try {
|
||||||
const { id } = paymentData
|
const { order_id } = paymentData
|
||||||
const orderData = await this.klarna_.get(`${this.klarnaOrderUrl_}/${id}`)
|
const orderData = await this.klarna_.get(
|
||||||
|
`${this.klarnaOrderUrl_}/${order_id}`
|
||||||
|
)
|
||||||
const { order_amount } = orderData.order
|
const { order_amount } = orderData.order
|
||||||
|
|
||||||
await this.klarna_.post(
|
await this.klarna_.post(
|
||||||
`${this.klarnaOrderManagementUrl_}/${id}/captures`,
|
`${this.klarnaOrderManagementUrl_}/${order_id}/captures`,
|
||||||
{
|
{
|
||||||
captured_amount: order_amount,
|
captured_amount: order_amount,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return id
|
return order_id
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
@@ -344,14 +348,14 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
*/
|
*/
|
||||||
async refundPayment(paymentData, amount) {
|
async refundPayment(paymentData, amount) {
|
||||||
try {
|
try {
|
||||||
const { id } = paymentData
|
const { order_id } = paymentData
|
||||||
await this.klarna_.post(
|
await this.klarna_.post(
|
||||||
`${this.klarnaOrderManagementUrl_}/${id}/refunds`,
|
`${this.klarnaOrderManagementUrl_}/${order_id}/refunds`,
|
||||||
{
|
{
|
||||||
refunded_amount: amount,
|
refunded_amount: amount,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return id
|
return order_id
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
@@ -364,9 +368,9 @@ class KlarnaProviderService extends PaymentService {
|
|||||||
*/
|
*/
|
||||||
async cancelPayment(paymentData) {
|
async cancelPayment(paymentData) {
|
||||||
try {
|
try {
|
||||||
const { id } = paymentData
|
const { order_id } = paymentData
|
||||||
await this.klarna_.post(`${this.klarnaOrderUrl_}/${id}/cancel`)
|
await this.klarna_.post(`${this.klarnaOrderUrl_}/${order_id}/cancel`)
|
||||||
return id
|
return order_id
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ class StripeProviderService extends PaymentService {
|
|||||||
amount: amount * 100, // Stripe amount is in cents
|
amount: amount * 100, // Stripe amount is in cents
|
||||||
currency: currency_code,
|
currency: currency_code,
|
||||||
capture_method: "manual",
|
capture_method: "manual",
|
||||||
metadata: { cart_id: cart._id },
|
metadata: { cart_id: `${cart._id}` },
|
||||||
})
|
})
|
||||||
|
|
||||||
return paymentIntent
|
return paymentIntent
|
||||||
@@ -113,12 +113,11 @@ class StripeProviderService extends PaymentService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves Stripe PaymentIntent.
|
* Retrieves Stripe PaymentIntent.
|
||||||
* @param {string} cart - the cart to retrieve payment intent for
|
* @param {object} data - the data of the payment to retrieve
|
||||||
* @returns {Object} Stripe PaymentIntent
|
* @returns {Object} Stripe PaymentIntent
|
||||||
*/
|
*/
|
||||||
async retrievePayment(cart) {
|
async retrievePayment(data) {
|
||||||
try {
|
try {
|
||||||
const { data } = cart.payment_method
|
|
||||||
return this.stripe_.paymentIntents.retrieve(data.id)
|
return this.stripe_.paymentIntents.retrieve(data.id)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ class EconomicService extends BaseService {
|
|||||||
* customer_number_dk: 012
|
* customer_number_dk: 012
|
||||||
* customer_number_eu: 345
|
* customer_number_eu: 345
|
||||||
* customer_number_world: 678,
|
* customer_number_world: 678,
|
||||||
* vat_number: 42,
|
|
||||||
* unit_number: 42,
|
* unit_number: 42,
|
||||||
* payment_terms_number: 42,
|
* payment_terms_number: 42,
|
||||||
* shipping_product_number: 42,
|
* shipping_product_number: 42,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class SendGridService extends BaseService {
|
|||||||
* from: Medusa <hello@medusa.example>,
|
* from: Medusa <hello@medusa.example>,
|
||||||
* order_placed_template: 01234,
|
* order_placed_template: 01234,
|
||||||
* order_updated_template: 56789,
|
* order_updated_template: 56789,
|
||||||
* order_updated_cancelled_template: 4242,
|
* order_cancelled_template: 4242,
|
||||||
* user_password_reset_template: 0000,
|
* user_password_reset_template: 0000,
|
||||||
* customer_password_reset_template: 1111,
|
* customer_password_reset_template: 1111,
|
||||||
* }
|
* }
|
||||||
@@ -42,6 +42,9 @@ class SendGridService extends BaseService {
|
|||||||
case "order.cancelled":
|
case "order.cancelled":
|
||||||
templateId = this.options_.order_cancelled_template
|
templateId = this.options_.order_cancelled_template
|
||||||
break
|
break
|
||||||
|
case "order.completed":
|
||||||
|
templateId = this.options_.order_completed_template
|
||||||
|
break
|
||||||
case "user.password_reset":
|
case "user.password_reset":
|
||||||
templateId = this.options_.user_password_reset_template
|
templateId = this.options_.user_password_reset_template
|
||||||
break
|
break
|
||||||
@@ -55,7 +58,7 @@ class SendGridService extends BaseService {
|
|||||||
try {
|
try {
|
||||||
return SendGrid.send({
|
return SendGrid.send({
|
||||||
template_id: templateId,
|
template_id: templateId,
|
||||||
from: options.from,
|
from: this.options_.from,
|
||||||
to: order.email,
|
to: order.email,
|
||||||
dynamic_template_data: order,
|
dynamic_template_data: order,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ class OrderSubscriber {
|
|||||||
await this.sendgridService_.transactionalEmail("order.cancelled", order)
|
await this.sendgridService_.transactionalEmail("order.cancelled", order)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.eventBus_.subscribe("order.completed", async (order) => {
|
||||||
|
await this.sendgridService_.transactionalEmail("order.completed", order)
|
||||||
|
})
|
||||||
|
|
||||||
this.eventBus_.subscribe("order.updated", async (order) => {
|
this.eventBus_.subscribe("order.updated", async (order) => {
|
||||||
await this.sendgridService_.transactionalEmail("order.updated", order)
|
await this.sendgridService_.transactionalEmail("order.updated", order)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default () => {
|
|||||||
break
|
break
|
||||||
case MedusaError.Types.DB_ERROR:
|
case MedusaError.Types.DB_ERROR:
|
||||||
statusCode = 500
|
statusCode = 500
|
||||||
logger.error(err)
|
console.log(err)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
export default async (req, res) => {
|
||||||
|
const { id } = req.params
|
||||||
|
|
||||||
|
try {
|
||||||
|
const orderService = req.scope.resolve("orderService")
|
||||||
|
const order = await orderService.completeOrder(id)
|
||||||
|
res.json({ order })
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,9 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const orderService = req.scope.resolve("orderService")
|
const orderService = req.scope.resolve("orderService")
|
||||||
const order = await orderService.retrieve(id)
|
|
||||||
|
let order = await orderService.retrieve(id)
|
||||||
|
order = await orderService.decorate(order, [], ["region"])
|
||||||
|
|
||||||
res.json({ order })
|
res.json({ order })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ export default app => {
|
|||||||
|
|
||||||
route.post("/", middlewares.wrap(require("./create-order").default))
|
route.post("/", middlewares.wrap(require("./create-order").default))
|
||||||
route.post("/:id", middlewares.wrap(require("./update-order").default))
|
route.post("/:id", middlewares.wrap(require("./update-order").default))
|
||||||
|
route.post(
|
||||||
|
"/:id/complete",
|
||||||
|
middlewares.wrap(require("./complete-order").default)
|
||||||
|
)
|
||||||
|
|
||||||
route.post(
|
route.post(
|
||||||
"/:id/capture",
|
"/:id/capture",
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { Validator, MedusaError } from "medusa-core-utils"
|
||||||
|
|
||||||
|
export default async (req, res) => {
|
||||||
|
const { id, code } = req.params
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cartService = req.scope.resolve("cartService")
|
||||||
|
|
||||||
|
let cart = await cartService.removeDiscount(id, code)
|
||||||
|
cart = await cartService.decorate(cart, [], ["region"])
|
||||||
|
|
||||||
|
res.status(200).json({ cart })
|
||||||
|
} catch (err) {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,11 @@ export default app => {
|
|||||||
middlewares.wrap(require("./delete-line-item").default)
|
middlewares.wrap(require("./delete-line-item").default)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
route.delete(
|
||||||
|
"/:id/discounts/:code",
|
||||||
|
middlewares.wrap(require("./delete-discount").default)
|
||||||
|
)
|
||||||
|
|
||||||
// Payment sessions
|
// Payment sessions
|
||||||
route.post(
|
route.post(
|
||||||
"/:id/payment-sessions",
|
"/:id/payment-sessions",
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export default async (req, res) => {
|
|||||||
if (value.discounts && value.discounts.length) {
|
if (value.discounts && value.discounts.length) {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
value.discounts.map(async ({ code }) =>
|
value.discounts.map(async ({ code }) =>
|
||||||
cartService.applyPromoCode(id, code)
|
cartService.applyDiscount(id, code)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ export default async (req, res) => {
|
|||||||
const { id, line_id } = req.params
|
const { id, line_id } = req.params
|
||||||
|
|
||||||
const schema = Validator.object().keys({
|
const schema = Validator.object().keys({
|
||||||
variant_id: Validator.objectId().required(),
|
|
||||||
quantity: Validator.number().required(),
|
quantity: Validator.number().required(),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -16,15 +15,23 @@ export default async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const lineItemService = req.scope.resolve("lineItemService")
|
const lineItemService = req.scope.resolve("lineItemService")
|
||||||
const cartService = req.scope.resolve("cartService")
|
const cartService = req.scope.resolve("cartService")
|
||||||
let cart = await cartService.retrieve(id)
|
|
||||||
|
|
||||||
const lineItem = await lineItemService.generate(
|
let cart
|
||||||
value.variant_id,
|
if (value.quantity === 0) {
|
||||||
value.quantity,
|
cart = await cartService.removeLineItem(id, line_id)
|
||||||
cart.region_id
|
} else {
|
||||||
)
|
cart = await cartService.retrieve(id)
|
||||||
|
|
||||||
|
const existing = cart.items.find(i => i._id.equals(line_id))
|
||||||
|
const lineItem = await lineItemService.generate(
|
||||||
|
existing.content.variant._id,
|
||||||
|
cart.region_id,
|
||||||
|
value.quantity
|
||||||
|
)
|
||||||
|
|
||||||
|
cart = await cartService.updateLineItem(cart._id, line_id, lineItem)
|
||||||
|
}
|
||||||
|
|
||||||
cart = await cartService.updateLineItem(cart._id, line_id, lineItem)
|
|
||||||
cart = await cartService.decorate(cart, [], ["region"])
|
cart = await cartService.decorate(cart, [], ["region"])
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
res.status(200).json({ cart })
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
const schema = Validator.object().keys({
|
const schema = Validator.object().keys({
|
||||||
provider_id: Validator.string().required(),
|
provider_id: Validator.string().required(),
|
||||||
|
data: Validator.object().optional(),
|
||||||
})
|
})
|
||||||
|
|
||||||
const { value, error } = schema.validate(req.body)
|
const { value, error } = schema.validate(req.body)
|
||||||
@@ -15,13 +16,7 @@ export default async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const cartService = req.scope.resolve("cartService")
|
const cartService = req.scope.resolve("cartService")
|
||||||
|
|
||||||
const session = await cartService.retrievePaymentSession(
|
let cart = await cartService.setPaymentMethod(id, value)
|
||||||
id,
|
|
||||||
value.provider_id
|
|
||||||
)
|
|
||||||
await cartService.setPaymentMethod(id, session)
|
|
||||||
|
|
||||||
let cart = await cartService.retrieve(id)
|
|
||||||
cart = await cartService.decorate(cart, [], ["region"])
|
cart = await cartService.decorate(cart, [], ["region"])
|
||||||
|
|
||||||
res.status(200).json({ cart })
|
res.status(200).json({ cart })
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ export default async (req, res) => {
|
|||||||
|
|
||||||
const cart = await cartService.retrieve(value.cartId)
|
const cart = await cartService.retrieve(value.cartId)
|
||||||
let order = await orderService.createFromCart(cart)
|
let order = await orderService.createFromCart(cart)
|
||||||
|
|
||||||
|
order = await orderService.retrieveByCartId(value.cartId)
|
||||||
order = await orderService.decorate(order, [
|
order = await orderService.decorate(order, [
|
||||||
"status",
|
"status",
|
||||||
"fulfillment_status",
|
"fulfillment_status",
|
||||||
|
|||||||
@@ -4,21 +4,25 @@ export default async (req, res) => {
|
|||||||
try {
|
try {
|
||||||
const orderService = req.scope.resolve("orderService")
|
const orderService = req.scope.resolve("orderService")
|
||||||
let order = await orderService.retrieve(id)
|
let order = await orderService.retrieve(id)
|
||||||
order = await orderService.decorate(order, [
|
order = await orderService.decorate(
|
||||||
"status",
|
order,
|
||||||
"fulfillment_status",
|
[
|
||||||
"payment_status",
|
"status",
|
||||||
"email",
|
"fulfillment_status",
|
||||||
"billing_address",
|
"payment_status",
|
||||||
"shipping_address",
|
"email",
|
||||||
"items",
|
"billing_address",
|
||||||
"region",
|
"shipping_address",
|
||||||
"discounts",
|
"items",
|
||||||
"customer_id",
|
"region",
|
||||||
"payment_method",
|
"discounts",
|
||||||
"shipping_methods",
|
"customer_id",
|
||||||
"metadata",
|
"payment_method",
|
||||||
])
|
"shipping_methods",
|
||||||
|
"metadata",
|
||||||
|
],
|
||||||
|
["region"]
|
||||||
|
)
|
||||||
|
|
||||||
res.json({ order })
|
res.json({ order })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import mongooseLoader from "./mongoose"
|
|||||||
import apiLoader from "./api"
|
import apiLoader from "./api"
|
||||||
import modelsLoader from "./models"
|
import modelsLoader from "./models"
|
||||||
import servicesLoader from "./services"
|
import servicesLoader from "./services"
|
||||||
|
import subscribersLoader from "./subscribers"
|
||||||
import passportLoader from "./passport"
|
import passportLoader from "./passport"
|
||||||
import pluginsLoader from "./plugins"
|
import pluginsLoader from "./plugins"
|
||||||
import defaultsLoader from "./defaults"
|
import defaultsLoader from "./defaults"
|
||||||
@@ -37,6 +38,9 @@ export default async ({ directory: rootDirectory, expressApp }) => {
|
|||||||
await servicesLoader({ container })
|
await servicesLoader({ container })
|
||||||
Logger.info("Services initialized")
|
Logger.info("Services initialized")
|
||||||
|
|
||||||
|
await subscribersLoader({ container })
|
||||||
|
Logger.info("Subscribers initialized")
|
||||||
|
|
||||||
const dbConnection = await mongooseLoader({ container })
|
const dbConnection = await mongooseLoader({ container })
|
||||||
Logger.info("MongoDB Intialized")
|
Logger.info("MongoDB Intialized")
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
import glob from "glob"
|
||||||
|
import path from "path"
|
||||||
|
import { asFunction } from "awilix"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers all subscribers in the subscribers directory
|
||||||
|
*/
|
||||||
|
export default ({ container }) => {
|
||||||
|
const isTest = process.env.NODE_ENV === "test"
|
||||||
|
|
||||||
|
const corePath = isTest
|
||||||
|
? "../subscribers/__mocks__/*.js"
|
||||||
|
: "../subscribers/*.js"
|
||||||
|
const coreFull = path.join(__dirname, corePath)
|
||||||
|
|
||||||
|
const core = glob.sync(coreFull, { cwd: __dirname })
|
||||||
|
core.forEach(fn => {
|
||||||
|
const loaded = require(fn).default
|
||||||
|
|
||||||
|
container.build(asFunction(cradle => new loaded(cradle)).singleton())
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ class OrderModel extends BaseModel {
|
|||||||
billing_address: { type: AddressSchema, required: true },
|
billing_address: { type: AddressSchema, required: true },
|
||||||
shipping_address: { type: AddressSchema, required: true },
|
shipping_address: { type: AddressSchema, required: true },
|
||||||
items: { type: [LineItemSchema], required: true },
|
items: { type: [LineItemSchema], required: true },
|
||||||
|
currency_code: { type: String, required: true },
|
||||||
region_id: { type: String, required: true },
|
region_id: { type: String, required: true },
|
||||||
discounts: { type: [DiscountSchema], default: [] },
|
discounts: { type: [DiscountSchema], default: [] },
|
||||||
customer_id: { type: String },
|
customer_id: { type: String },
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ class CartService extends BaseService {
|
|||||||
const validatedLineItem = this.lineItemService_.validate(lineItem)
|
const validatedLineItem = this.lineItemService_.validate(lineItem)
|
||||||
const cart = await this.retrieve(cartId)
|
const cart = await this.retrieve(cartId)
|
||||||
const currentItem = cart.items.find(line =>
|
const currentItem = cart.items.find(line =>
|
||||||
_.isEqual(line.content, validatedLineItem.content)
|
this.lineItemService_.isEqual(line, validatedLineItem)
|
||||||
)
|
)
|
||||||
|
|
||||||
// If content matches one of the line items currently in the cart we can
|
// If content matches one of the line items currently in the cart we can
|
||||||
@@ -393,7 +393,7 @@ class CartService extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the line item exists in the cart
|
// Ensure that the line item exists in the cart
|
||||||
const lineItemExists = cart.items.find(i => i._id === lineItemId)
|
const lineItemExists = cart.items.find(i => i._id.equals(lineItemId))
|
||||||
if (!lineItemExists) {
|
if (!lineItemExists) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.Types.INVALID_DATA,
|
MedusaError.Types.INVALID_DATA,
|
||||||
@@ -519,6 +519,8 @@ class CartService extends BaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address.country_code = address.country_code.toUpperCase()
|
||||||
|
|
||||||
return this.cartModel_
|
return this.cartModel_
|
||||||
.updateOne(
|
.updateOne(
|
||||||
{
|
{
|
||||||
@@ -551,6 +553,8 @@ class CartService extends BaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address.country_code = address.country_code.toUpperCase()
|
||||||
|
|
||||||
const region = await this.regionService_.retrieve(cart.region_id)
|
const region = await this.regionService_.retrieve(cart.region_id)
|
||||||
if (!region.countries.includes(address.country_code.toUpperCase())) {
|
if (!region.countries.includes(address.country_code.toUpperCase())) {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
@@ -681,6 +685,16 @@ class CartService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async removeDiscount(cartId, discountCode) {
|
||||||
|
const cart = await this.retrieve(cartId)
|
||||||
|
return this.cartModel_.updateOne(
|
||||||
|
{ _id: cart._id },
|
||||||
|
{
|
||||||
|
$pull: { discounts: { code: discountCode } },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A payment method represents a way for the customer to pay. The payment
|
* A payment method represents a way for the customer to pay. The payment
|
||||||
* method will typically come from one of the payment sessions.
|
* method will typically come from one of the payment sessions.
|
||||||
@@ -736,20 +750,6 @@ class CartService extends BaseService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The provider service will be able to perform operations on the
|
|
||||||
// session we are trying to set as the payment method.
|
|
||||||
const provider = this.paymentProviderService_.retrieveProvider(
|
|
||||||
paymentMethod.provider_id
|
|
||||||
)
|
|
||||||
|
|
||||||
const status = await provider.getStatus(paymentMethod.data)
|
|
||||||
if (!(status === "authorized" || status === "succeeded")) {
|
|
||||||
throw new MedusaError(
|
|
||||||
MedusaError.Types.NOT_ALLOWED,
|
|
||||||
`The payment method was not authorized`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point we can register the payment method.
|
// At this point we can register the payment method.
|
||||||
return this.cartModel_
|
return this.cartModel_
|
||||||
.updateOne(
|
.updateOne(
|
||||||
@@ -883,7 +883,7 @@ class CartService extends BaseService {
|
|||||||
// that has the same profile as the selected shipping method.
|
// that has the same profile as the selected shipping method.
|
||||||
let exists = false
|
let exists = false
|
||||||
const newMethods = shipping_methods.map(sm => {
|
const newMethods = shipping_methods.map(sm => {
|
||||||
if (sm.profile_id === option.profile_id) {
|
if (option.profile_id.equals(sm.profile_id)) {
|
||||||
exists = true
|
exists = true
|
||||||
return option
|
return option
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,6 +117,28 @@ class LineItemService extends BaseService {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEqual(line, match) {
|
||||||
|
if (Array.isArray(line.content)) {
|
||||||
|
if (
|
||||||
|
Array.isArray(match.content) &&
|
||||||
|
match.content.length === line.content.length
|
||||||
|
) {
|
||||||
|
return line.content.every(
|
||||||
|
(c, index) =>
|
||||||
|
c.variant._id.equals(match[index].variant._id) &&
|
||||||
|
c.quantity === match[index].quantity
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (!Array.isArray(match.content)) {
|
||||||
|
return (
|
||||||
|
line.content.variant._id.equals(match.content.variant._id) &&
|
||||||
|
line.content.quantity === match.content.quantity
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LineItemService
|
export default LineItemService
|
||||||
@@ -7,6 +7,7 @@ class OrderService extends BaseService {
|
|||||||
PLACED: "order.placed",
|
PLACED: "order.placed",
|
||||||
UPDATED: "order.updated",
|
UPDATED: "order.updated",
|
||||||
CANCELLED: "order.cancelled",
|
CANCELLED: "order.cancelled",
|
||||||
|
COMPLETED: "order.completed",
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor({
|
constructor({
|
||||||
@@ -16,6 +17,7 @@ class OrderService extends BaseService {
|
|||||||
fulfillmentProviderService,
|
fulfillmentProviderService,
|
||||||
lineItemService,
|
lineItemService,
|
||||||
totalsService,
|
totalsService,
|
||||||
|
regionService,
|
||||||
eventBusService,
|
eventBusService,
|
||||||
}) {
|
}) {
|
||||||
super()
|
super()
|
||||||
@@ -38,6 +40,9 @@ class OrderService extends BaseService {
|
|||||||
/** @private @const {TotalsService} */
|
/** @private @const {TotalsService} */
|
||||||
this.totalsService_ = totalsService
|
this.totalsService_ = totalsService
|
||||||
|
|
||||||
|
/** @private @const {RegionService} */
|
||||||
|
this.regionService_ = regionService
|
||||||
|
|
||||||
/** @private @const {EventBus} */
|
/** @private @const {EventBus} */
|
||||||
this.eventBus_ = eventBusService
|
this.eventBus_ = eventBusService
|
||||||
}
|
}
|
||||||
@@ -160,7 +165,7 @@ class OrderService extends BaseService {
|
|||||||
*/
|
*/
|
||||||
async retrieveByCartId(cartId) {
|
async retrieveByCartId(cartId) {
|
||||||
const order = await this.orderModel_
|
const order = await this.orderModel_
|
||||||
.findOne({ metadata: { cart_id: cartId } })
|
.findOne({ cart_id: cartId })
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
|
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
|
||||||
})
|
})
|
||||||
@@ -200,6 +205,37 @@ class OrderService extends BaseService {
|
|||||||
return this.orderModel_.find(selector)
|
return this.orderModel_.find(selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} orderId - id of the order to complete
|
||||||
|
* @return {Promise} the result of the find operation
|
||||||
|
*/
|
||||||
|
async completeOrder(orderId) {
|
||||||
|
const order = await this.retrieve(orderId)
|
||||||
|
this.orderModel_
|
||||||
|
.updateOne(
|
||||||
|
{ _id: order._id },
|
||||||
|
{
|
||||||
|
$set: { status: "completed" },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(async result => {
|
||||||
|
const completeOrderJob = await this.eventBus_.emit(
|
||||||
|
OrderService.Events.COMPLETED,
|
||||||
|
result
|
||||||
|
)
|
||||||
|
|
||||||
|
return completeOrderJob
|
||||||
|
.finished()
|
||||||
|
.then(async () => {
|
||||||
|
return this.retrieve(order._id)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error)
|
||||||
|
throw error
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an order from a cart
|
* Creates an order from a cart
|
||||||
* @param {object} order - the order to create
|
* @param {object} order - the order to create
|
||||||
@@ -231,21 +267,41 @@ class OrderService extends BaseService {
|
|||||||
|
|
||||||
const { payment_method } = cart
|
const { payment_method } = cart
|
||||||
|
|
||||||
const paymentProvider = await this.paymentProviderService_.retrieveProvider(
|
let paymentSession = cart.payment_sessions.find(
|
||||||
payment_method.provider_id
|
ps => ps.provider_id === payment_method.provider_id
|
||||||
)
|
)
|
||||||
const paymentStatus = await paymentProvider.getStatus(payment_method.data)
|
|
||||||
|
// Throw if payment method does not exist
|
||||||
|
if (!paymentSession) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.INVALID_ARGUMENT,
|
||||||
|
"Cart does not have an authorized payment session"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const region = await this.regionService_.retrieve(cart.region_id)
|
||||||
|
const paymentProvider = this.paymentProviderService_.retrieveProvider(
|
||||||
|
paymentSession.provider_id
|
||||||
|
)
|
||||||
|
const paymentStatus = await paymentProvider.getStatus(paymentSession.data)
|
||||||
|
|
||||||
// If payment status is not authorized, we throw
|
// If payment status is not authorized, we throw
|
||||||
if (paymentStatus !== "authorized") {
|
if (paymentStatus !== "authorized" && paymentStatus !== "succeeded") {
|
||||||
throw new MedusaError(
|
throw new MedusaError(
|
||||||
MedusaError.types.INVALID_ARGUMENT,
|
MedusaError.Types.INVALID_ARGUMENT,
|
||||||
"Payment method is not authorized"
|
"Payment method is not authorized"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const paymentData = await paymentProvider.retrievePayment(
|
||||||
|
paymentSession.data
|
||||||
|
)
|
||||||
|
|
||||||
const o = {
|
const o = {
|
||||||
payment_method: cart.payment_method,
|
payment_method: {
|
||||||
|
provider_id: paymentSession.provider_id,
|
||||||
|
data: paymentData,
|
||||||
|
},
|
||||||
shipping_methods: cart.shipping_methods,
|
shipping_methods: cart.shipping_methods,
|
||||||
items: cart.items,
|
items: cart.items,
|
||||||
shipping_address: cart.shipping_address,
|
shipping_address: cart.shipping_address,
|
||||||
@@ -254,13 +310,15 @@ class OrderService extends BaseService {
|
|||||||
email: cart.email,
|
email: cart.email,
|
||||||
customer_id: cart.customer_id,
|
customer_id: cart.customer_id,
|
||||||
cart_id: cart._id,
|
cart_id: cart._id,
|
||||||
|
currency_code: region.currency_code,
|
||||||
}
|
}
|
||||||
|
|
||||||
const orderDocument = await this.orderModel_.create(o)
|
const orderDocument = await this.orderModel_.create([o], {
|
||||||
// Commit transaction
|
session: dbSession,
|
||||||
await dbSession.commitTransaction()
|
})
|
||||||
|
|
||||||
// Emit and return
|
// Emit and return
|
||||||
this.eventBus_emit(OrderService.Events.PLACED, orderDocument)
|
this.eventBus_.emit(OrderService.Events.PLACED, orderDocument)
|
||||||
return orderDocument
|
return orderDocument
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -594,9 +652,17 @@ class OrderService extends BaseService {
|
|||||||
* @return {Order} return the decorated order.
|
* @return {Order} return the decorated order.
|
||||||
*/
|
*/
|
||||||
async decorate(order, fields, expandFields = []) {
|
async decorate(order, fields, expandFields = []) {
|
||||||
const requiredFields = ["_id", "metadata"]
|
const o = order.toObject()
|
||||||
const decorated = _.pick(order, fields.concat(requiredFields))
|
o.shipping_total = await this.totalsService_.getShippingTotal(order)
|
||||||
return decorated
|
o.discount_total = await this.totalsService_.getDiscountTotal(order)
|
||||||
|
o.tax_total = await this.totalsService_.getTaxTotal(order)
|
||||||
|
o.subtotal = await this.totalsService_.getSubtotal(order)
|
||||||
|
o.total = await this.totalsService_.getTotal(order)
|
||||||
|
o.created = order._id.getTimestamp()
|
||||||
|
if (expandFields.includes("region")) {
|
||||||
|
o.region = await this.regionService_.retrieve(order.region_id)
|
||||||
|
}
|
||||||
|
return o
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class OrderSubscriber {
|
||||||
|
constructor({ paymentProviderService, eventBusService }) {
|
||||||
|
this.paymentProviderService_ = paymentProviderService
|
||||||
|
|
||||||
|
this.eventBus_ = eventBusService
|
||||||
|
|
||||||
|
this.eventBus_.subscribe("order.completed", async order => {
|
||||||
|
const paymentProvider = this.paymentProviderService_.retrieveProvider(
|
||||||
|
order.payment_method.provider_id
|
||||||
|
)
|
||||||
|
|
||||||
|
await paymentProvider.capturePayment(order._id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrderSubscriber
|
||||||
Reference in new issue
Block a user