diff --git a/packages/medusa-payment-klarna/.gitignore b/packages/medusa-payment-klarna/.gitignore index 134ab70b93..89114faaff 100644 --- a/packages/medusa-payment-klarna/.gitignore +++ b/packages/medusa-payment-klarna/.gitignore @@ -6,5 +6,11 @@ node_modules !index.js !jest.config.js -dist +/dist +/api +/services +/models +/subscribers +/__mocks__ + diff --git a/packages/medusa-payment-klarna/src/services/klarna-provider.js b/packages/medusa-payment-klarna/src/services/klarna-provider.js index 24ac70eb99..b4b73b94cd 100644 --- a/packages/medusa-payment-klarna/src/services/klarna-provider.js +++ b/packages/medusa-payment-klarna/src/services/klarna-provider.js @@ -5,7 +5,7 @@ import { PaymentService } from "medusa-interfaces" class KlarnaProviderService extends PaymentService { static identifier = "klarna" - constructor({ totalsService, regionService }, options) { + constructor({ shippingProfileService, totalsService, regionService }, options) { super() this.options_ = options @@ -22,11 +22,13 @@ class KlarnaProviderService extends PaymentService { this.klarnaOrderManagementUrl_ = "/ordermanagement/v1/orders" - this.backendUrl_ = process.env.BACKEND_URL || "" + this.backendUrl_ = process.env.BACKEND_URL || "https://58721b1f44d9.ngrok.io" this.totalsService_ = totalsService this.regionService_ = regionService + + this.shippingProfileService_ = shippingProfileService } async lineItemsToOrderLines_(cart, taxRate) { @@ -35,12 +37,16 @@ class KlarnaProviderService extends PaymentService { const discount = cart.discounts.find( ({ discount_rule }) => discount_rule.type !== "free_shipping" ) - // If the discount has an item specific allocation method, - // we need to fetch the discount for each item - const itemDiscounts = await this.totalsService_.getAllocationItemDiscounts( - discount, - cart - ) + + let itemDiscounts = [] + if (discount) { + // If the discount has an item specific allocation method, + // we need to fetch the discount for each item + itemDiscounts = await this.totalsService_.getAllocationItemDiscounts( + discount, + cart + ) + } cart.items.forEach((item) => { // For bundles, we create an order line for each item in the bundle @@ -50,20 +56,17 @@ class KlarnaProviderService extends PaymentService { const total_tax_amount = total_amount * taxRate order_lines.push({ + name: item.title, unit_price: c.unit_price, // Medusa does not allow discount on bundles total_discount_amount: 0, quantity: c.quantity, - tax_rate: taxRate, + tax_rate: taxRate * 10000, total_amount, total_tax_amount, }) }) } else { - const total_amount = - item.content.unit_price * item.content.quantity * (taxRate + 1) - const total_tax_amount = total_amount * taxRate - // Find the discount for current item and default to 0 const itemDiscount = (itemDiscounts && @@ -71,19 +74,25 @@ class KlarnaProviderService extends PaymentService { 0 // Withdraw discount from the total item amount - const total_discount_amount = - total_amount - itemDiscount * (taxRate + 1) + const quantity = item.content.quantity + const unit_price = item.content.unit_price * 100 * (taxRate + 1) + const total_discount_amount = itemDiscount * (taxRate + 1) * 100 + const total_amount = unit_price * quantity - total_discount_amount + const total_tax_amount = total_amount * (taxRate / (1 + taxRate)) order_lines.push({ - unit_price: item.content.unit_price, - quantity: item.content.quantity, + name: item.title, + tax_rate: taxRate * 10000, + quantity, + unit_price, total_discount_amount, - tax_rate: taxRate, total_amount, total_tax_amount, }) } }) + + return order_lines } async cartToKlarnaOrder(cart) { @@ -98,9 +107,9 @@ class KlarnaProviderService extends PaymentService { cart.region_id ) - order.order_lines = this.lineItemsToOrderLines_(cart, tax_rate) + order.order_lines = await this.lineItemsToOrderLines_(cart, tax_rate) - if (cart.billing_address) { + if (!_.isEmpty(cart.billing_address)) { order.billing_address = { email: cart.email, street_address: cart.billing_address.address_1, @@ -112,15 +121,15 @@ class KlarnaProviderService extends PaymentService { } // TODO: Check if country matches ISO - if (cart.billing_address.country) { + if (!_.isEmpty(cart.billing_address) && cart.billing_address.country) { order.purchase_country = cart.billing_address.country } else { // Defaults to Sweden order.purchase_country = "SE" } - order.order_amount = this.totalsService_.getTotal(cart) - order.order_tax_amount = this.totalsService_.getTaxTotal(cart) + order.order_amount = await this.totalsService_.getTotal(cart) * 100 + order.order_tax_amount = await this.totalsService_.getTaxTotal(cart) * 100 // TODO: Check if currency matches ISO order.purchase_currency = currency_code @@ -133,10 +142,13 @@ class KlarnaProviderService extends PaymentService { address_update: `${this.backendUrl_}/klarna/hooks/address`, } + + 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) { - const shipping_method = cart.shipping_options[0] + if (!cart.shipping_methods.length) { + const shipping_method = shippingOptions[0] order.selected_shipping_option = { id: shipping_method._id, // TODO: Add shipping method name @@ -146,10 +158,7 @@ class KlarnaProviderService extends PaymentService { // Medusa tax rate of e.g. 0.25 (25%) needs to be 2500 in Klarna tax_rate: tax_rate * 10000, } - } - - // If the cart does have shipping methods, set the selected shipping method - if (cart.shipping_methods) { + } else { const shipping_method = cart.shipping_methods[0] order.selected_shipping_option = { id: shipping_method._id, @@ -160,7 +169,9 @@ class KlarnaProviderService extends PaymentService { } } - order.shipping_options = cart.shipping_options.map((so) => ({ + // If the cart does have shipping methods, set the selected shipping method + + order.shipping_options = shippingOptions.map((so) => ({ id: so._id, name: so.provider_id, price: so.price * (1 + tax_rate) * 100, @@ -201,7 +212,8 @@ class KlarnaProviderService extends PaymentService { async createPayment(cart) { try { const order = await this.cartToKlarnaOrder(cart) - return this.klarna_.post(this.klarnaOrderUrl__, order) + return this.klarna_.post(this.klarnaOrderUrl_, order) + .then(({ data }) => data) } catch (error) { throw error } @@ -280,10 +292,11 @@ class KlarnaProviderService extends PaymentService { * @param {Object} data - the update object * @returns {Object} updated order */ - async updatePayment(order, update) { + async updatePayment(paymentData, cart) { try { - const { data } = order.payment_method - return this.klarna_.post(`${this.klarnaOrderUrl_}/${data.id}`, update) + const order = await this.cartToKlarnaOrder(cart) + return this.klarna_.post(`${this.klarnaOrderUrl_}/${paymentData.order_id}`, order) + .then(({ data }) => data) } catch (error) { throw error } diff --git a/packages/medusa/src/services/cart.js b/packages/medusa/src/services/cart.js index 5ecb368a34..d33c0ec021 100644 --- a/packages/medusa/src/services/cart.js +++ b/packages/medusa/src/services/cart.js @@ -968,6 +968,21 @@ class CartService extends BaseService { update.shipping_methods = [] } + //if (cart.items.length && cart.payment_sessions.length) { + // update.payment_sessions = await Promise.all( + // region.payment_providers.map(async pId => { + // const data = await this.paymentProviderService_.createSession(pId, { + // ...cart, + // ...update, + // }) + // return { + // provider_id: pId, + // data, + // } + // }) + // ) + //} + // Payment methods are region specific so the user needs to find a // new payment method if (!_.isEmpty(cart.payment_method)) {