feat(medusa): manage payment sessions from payment collection (#2402)
* feat: manage payment sessions from payment collection
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
|
||||
export default async (req, res) => {
|
||||
const { klarna_order_id } = req.query
|
||||
|
||||
function isPaymentCollection(id) {
|
||||
return id && id.startsWith("paycol")
|
||||
}
|
||||
|
||||
try {
|
||||
const orderService = req.scope.resolve("orderService")
|
||||
const klarnaProviderService = req.scope.resolve("pp_klarna")
|
||||
@@ -11,10 +13,18 @@ export default async (req, res) => {
|
||||
klarna_order_id
|
||||
)
|
||||
|
||||
const cartId = klarnaOrder.merchant_data
|
||||
const order = await orderService.retrieveByCartId(cartId)
|
||||
const resourceId = klarnaOrder.merchant_data
|
||||
|
||||
await klarnaProviderService.acknowledgeOrder(klarnaOrder.order_id, order.id)
|
||||
if (isPaymentCollection(resourceId)) {
|
||||
await klarnaProviderService.acknowledgeOrder(klarnaOrder.order_id)
|
||||
} else {
|
||||
const order = await orderService.retrieveByCartId(resourceId)
|
||||
|
||||
await klarnaProviderService.acknowledgeOrder(
|
||||
klarnaOrder.order_id,
|
||||
order.id
|
||||
)
|
||||
}
|
||||
|
||||
res.sendStatus(200)
|
||||
} catch (error) {
|
||||
|
||||
@@ -230,6 +230,84 @@ class KlarnaProviderService extends PaymentService {
|
||||
return order
|
||||
}
|
||||
|
||||
validateKlarnaOrderUrls(property) {
|
||||
const required = ["terms", "checkout", "confirmation"]
|
||||
|
||||
const isMissing = required.some((prop) => !this.options_[property]?.[prop])
|
||||
|
||||
if (isMissing) {
|
||||
throw new Error(
|
||||
`options.${property} is required to create a Klarna Order.\n` +
|
||||
`medusa-config.js file has to contain ${property} { ${required.join(
|
||||
", "
|
||||
)}}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
replaceStringWithPropertyValue(string, obj) {
|
||||
const keys = Object.keys(obj)
|
||||
for (const key of keys) {
|
||||
if (string.includes(`{${key}}`)) {
|
||||
string = string.replace(`{${key}}`, obj[key])
|
||||
}
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
async paymentInputToKlarnaOrder(paymentInput) {
|
||||
if (paymentInput.cart) {
|
||||
this.validateKlarnaOrderUrls("merchant_urls")
|
||||
return this.cartToKlarnaOrder(paymentInput.cart)
|
||||
}
|
||||
|
||||
this.validateKlarnaOrderUrls("payment_collection_urls")
|
||||
|
||||
let order = {
|
||||
// Custom id is stored, such that we can use it for hooks
|
||||
merchant_data: paymentInput.resource_id,
|
||||
locale: "en-US",
|
||||
}
|
||||
|
||||
const { currency_code, amount } = paymentInput
|
||||
|
||||
order.order_lines = [
|
||||
{
|
||||
name: "Payment Collection",
|
||||
quantity: 1,
|
||||
unit_price: amount,
|
||||
tax_rate: 0,
|
||||
total_amount: amount,
|
||||
total_tax_amount: 0,
|
||||
},
|
||||
]
|
||||
|
||||
// Defaults to Sweden
|
||||
order.purchase_country = "SE"
|
||||
|
||||
order.order_amount = amount
|
||||
order.order_tax_amount = 0
|
||||
order.purchase_currency = currency_code.toUpperCase()
|
||||
|
||||
order.merchant_urls = {
|
||||
terms: this.replaceStringWithPropertyValue(
|
||||
this.options_.payment_collection_urls.terms,
|
||||
paymentInput
|
||||
),
|
||||
checkout: this.replaceStringWithPropertyValue(
|
||||
this.options_.payment_collection_urls.checkout,
|
||||
paymentInput
|
||||
),
|
||||
confirmation: this.replaceStringWithPropertyValue(
|
||||
this.options_.payment_collection_urls.confirmation,
|
||||
paymentInput
|
||||
),
|
||||
push: `${this.backendUrl_}/klarna/push?klarna_order_id={checkout.order.id}`,
|
||||
}
|
||||
|
||||
return order
|
||||
}
|
||||
|
||||
/**
|
||||
* Status for Klarna order.
|
||||
* @param {Object} paymentData - payment method data from cart
|
||||
@@ -251,7 +329,7 @@ class KlarnaProviderService extends PaymentService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Stripe PaymentIntent.
|
||||
* Creates Klarna PaymentIntent.
|
||||
* @param {string} cart - the cart to create a payment for
|
||||
* @param {number} amount - the amount to create a payment for
|
||||
* @returns {string} id of payment intent
|
||||
@@ -271,6 +349,21 @@ class KlarnaProviderService extends PaymentService {
|
||||
}
|
||||
}
|
||||
|
||||
async createPaymentNew(paymentInput) {
|
||||
try {
|
||||
const order = await this.paymentInputToKlarnaOrder(paymentInput)
|
||||
|
||||
const klarnaPayment = await this.klarna_
|
||||
.post(this.klarnaOrderUrl_, order)
|
||||
.then(({ data }) => data)
|
||||
|
||||
return klarnaPayment
|
||||
} catch (error) {
|
||||
this.logger_.error(error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves Klarna Order.
|
||||
* @param {string} cart - the cart to retrieve order for
|
||||
@@ -338,18 +431,20 @@ class KlarnaProviderService extends PaymentService {
|
||||
* @param {string} klarnaOrderId - id of the order to acknowledge
|
||||
* @returns {string} id of acknowledged order
|
||||
*/
|
||||
async acknowledgeOrder(klarnaOrderId, orderId) {
|
||||
async acknowledgeOrder(klarnaOrderId, orderId = null) {
|
||||
try {
|
||||
await this.klarna_.post(
|
||||
`${this.klarnaOrderManagementUrl_}/${klarnaOrderId}/acknowledge`
|
||||
)
|
||||
|
||||
await this.klarna_.patch(
|
||||
`${this.klarnaOrderManagementUrl_}/${klarnaOrderId}/merchant-references`,
|
||||
{
|
||||
merchant_reference1: orderId,
|
||||
}
|
||||
)
|
||||
if (orderId !== null) {
|
||||
await this.klarna_.patch(
|
||||
`${this.klarnaOrderManagementUrl_}/${klarnaOrderId}/merchant-references`,
|
||||
{
|
||||
merchant_reference1: orderId,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return klarnaOrderId
|
||||
} catch (error) {
|
||||
@@ -408,6 +503,22 @@ class KlarnaProviderService extends PaymentService {
|
||||
return paymentData
|
||||
}
|
||||
|
||||
async updatePaymentNew(paymentData, paymentInput) {
|
||||
if (paymentInput.amount !== paymentData.order_amount) {
|
||||
const order = await this.paymentInputToKlarnaOrder(paymentInput)
|
||||
return this.klarna_
|
||||
.post(`${this.klarnaOrderUrl_}/${paymentData.order_id}`, order)
|
||||
.then(({ data }) => data)
|
||||
.catch(async (_) => {
|
||||
return this.klarna_
|
||||
.post(this.klarnaOrderUrl_, order)
|
||||
.then(({ data }) => data)
|
||||
})
|
||||
}
|
||||
|
||||
return paymentData
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures Klarna order.
|
||||
* @param {Object} paymentData - payment method data from cart
|
||||
|
||||
Reference in New Issue
Block a user