Merge pull request #271 from medusajs/fix/mp

Fix/mp
This commit is contained in:
Sebastian Rindom authored and GitHub committed 2021-06-22 10:38:44 +02:00
commit db9d6c0cf5
16 files changed
+82 -501

No files matched your search

@@ -1,30 +0,0 @@
import { Router } from "express"
import cors from "cors"
import bodyParser from "body-parser"
import middlewares from "../../middlewares"
import { getConfigFile } from "medusa-core-utils"
const route = Router()
export default (app, rootDirectory) => {
const { configModule } = getConfigFile(rootDirectory, `medusa-config`)
const config = (configModule && configModule.projectConfig) || {}
const storeCors = config.store_cors || ""
route.use(
cors({
origin: storeCors.split(","),
credentials: true,
})
)
app.use("/adyen", route)
route.post(
"/payment-methods",
bodyParser.json(),
middlewares.wrap(require("./retrieve-payment-methods").default)
)
return app
}
@@ -1,57 +0,0 @@
import { Validator, MedusaError } from "medusa-core-utils"
export default async (req, res) => {
const schema = Validator.object().keys({
cart_id: Validator.string().required(),
})
const { value, error } = schema.validate(req.body)
if (error) {
throw new MedusaError(MedusaError.Types.INVALID_DATA, error.details)
}
try {
const adyenService = req.scope.resolve("adyenService")
const cartService = req.scope.resolve("cartService")
const cart = await cartService.retrieve(value.cart_id, {
select: ["total"],
relations: ["region", "region.payment_providers", "payment_sessions"],
})
const allowedMethods = cart.payment_sessions.map((ps) => {
if (ps.provider_id.includes("adyen")) {
return ps.provider_id.split("-adyen")[0]
}
})
if (allowedMethods.length === 0) {
res.status(200).json({ paymentMethods: {} })
return
}
const pmMethods = await adyenService.retrievePaymentMethods(
allowedMethods,
cart.total,
cart.currency_code,
cart.customer_id || ""
)
// Adyen does not behave 100% correctly in regards to allowed methods
// Therefore, we sanity filter before sending them to the storefront
const { paymentMethods, groups, storedPaymentMethods } = pmMethods
const methods = paymentMethods.filter((pm) =>
allowedMethods.includes(pm.type)
)
const response = {
paymentMethods: methods,
groups,
storedPaymentMethods,
}
res.status(200).json({ payment_methods: response })
} catch (err) {
throw err
}
}
@@ -28,7 +28,7 @@ class AdyenService extends BaseService {
/** @private @constant {AxiosClient} */
this.adyenClient_ = this.initAdyenClient()
/** @private @constant {AdyenClient} */
/** @private @constant {AxiosClient} */
this.adyenPaymentApi = this.initPaymentClient()
}
@@ -51,16 +51,6 @@ class AdyenService extends BaseService {
return this.options_
}
initPaymentClient() {
return axios.create({
baseURL: this.options_.payment_endpoint,
headers: {
"Content-Type": "application/json",
"x-API-key": this.options_.api_key,
},
})
}
initAdyenClient() {
const config = new Config()
config.apiKey = this.options_.api_key
@@ -70,14 +60,22 @@ class AdyenService extends BaseService {
config,
})
client.setEnvironment(
this.options_.environment,
this.options_.live_endpoint_prefix
)
client.setEnvironment(this.options_.environment)
return client
}
initPaymentClient() {
return axios.create({
baseURL:
this.options_.payment_endpoint || "https://checkout-test.adyen.com/v67",
headers: {
"Content-Type": "application/json",
"x-API-key": this.options_.api_key,
},
})
}
/**
* Validates an Adyen webhook notification
* @param {object} notification - notification to validate
@@ -90,6 +88,7 @@ class AdyenService extends BaseService {
notification,
this.options_.notification_hmac
)
return validated
}
@@ -228,6 +227,10 @@ class AdyenService extends BaseService {
const status = this.getStatus(sessionData)
if (sessionData.resultCode === "RedirectShopper") {
return { data: sessionData, status: "requires_more" }
}
// If session data is present, we already called authorize once.
// Therefore, this is most likely a call for getting additional details
if (status === "requires_more") {
@@ -253,38 +256,28 @@ class AdyenService extends BaseService {
value: cart.total,
}
let paymentData = sessionData.paymentData
if (!paymentData) {
paymentData = {
paymentMethod: {
type: sessionData.type,
},
}
}
let request = {
amount,
merchantAccount: this.options_.merchant_account,
shopperIP: context.ip_address || "",
shopperReference: cart.customer_id,
paymentMethod: sessionData.paymentData.paymentMethod,
reference: cart.id,
merchantAccount: this.options_.merchant_account,
returnUrl: this.options_.return_url,
origin: this.options_.origin,
channel: "Web",
redirectFromIssuerMethod: "GET",
browserInfo: sessionData.browserInfo || {},
billingAddress: {
city: cart.shipping_address.city,
country: cart.shipping_address.country_code,
houseNumberOrName: cart.shipping_address.address_2 || "",
postalCode: cart.shipping_address.postal_code,
stateOrProvice: cart.shipping_address.province || "",
street: cart.shipping_address.address_1,
},
paymentMethod: paymentData.paymentMethod,
reference: cart.id,
metadata: {
cart_id: cart.id,
},
}
// If customer chose to save the payment method
if (sessionData.storePaymentMethod) {
request.storePaymentMethod = "true"
request.shopperInteraction = "Ecommerce"
request.recurringProcessingModel = "CardOnFile"
}
const checkout = new CheckoutAPI(this.adyenClient_)
try {
@@ -344,31 +337,34 @@ class AdyenService extends BaseService {
* @returns {string} status = processing_captures
*/
async capturePayment(payment) {
if (payment.captured_at !== null) {
return
}
const { pspReference, merchantReference } = payment.data
const { amount, currency_code } = payment
try {
const captured = await this.adyenPaymentApi.post("/capture", {
originalReference: pspReference,
modificationAmount: {
value: amount,
currency: currency_code.toUpperCase(),
},
merchantAccount: this.options_.merchant_account,
reference: merchantReference,
})
const captured = await this.adyenPaymentApi.post(
`/payments/${pspReference}/captures`,
{
merchantAccount: this.options_.merchant_account,
amount: {
value: amount,
currency: currency_code.toUpperCase(),
},
reference: merchantReference,
}
)
if (
captured.data.pspReference &&
captured.data.response !== "[capture-received]"
) {
if (captured.data.pspReference && captured.data.status !== "received") {
throw new MedusaError(
MedusaError.Types.INVALID_ARGUMENT,
"Could not process capture"
)
}
return { originalReference: pspReference, ...captured.data }
return { pspReference }
} catch (error) {
throw error
}
@@ -381,7 +377,7 @@ class AdyenService extends BaseService {
* @returns {object} payment data result of refund
*/
async refundPayment(payment, amountToRefund) {
const { originalReference, merchantReference } = payment.data
const { pspReference } = payment.data
const { currency_code } = payment
const refundAmount = {
@@ -390,14 +386,12 @@ class AdyenService extends BaseService {
}
try {
const refunded = await this.adyenPaymentApi.post("/refund", {
originalReference,
await this.adyenPaymentApi.post(`/payments/${pspReference}/refunds`, {
merchantAccount: this.options_.merchant_account,
modificationAmount: refundAmount,
reference: merchantReference,
amount: refundAmount,
})
return { originalReference, ...refunded.data }
return { pspReference }
} catch (error) {
throw error
}
@@ -1,104 +0,0 @@
import _ from "lodash"
import https from "https"
import fs from "fs"
import axios from "axios"
import { PaymentService } from "medusa-interfaces"
class ApplePayAdyenService extends PaymentService {
static identifier = "applepay-adyen"
constructor({ adyenService }, options) {
super()
this.adyenService_ = adyenService
this.options_ = options
}
/**
* Status for Adyen payment.
* @param {Object} paymentData - payment method data from cart
* @returns {string} the status of the payment
*/
async getStatus(paymentData) {
const { resultCode } = paymentData
let status = "initial"
if (resultCode === "Authorised") {
status = "authorized"
}
return status
}
async createPayment(_) {
return {}
}
async getApplePaySession(validationUrl) {
let certificate
try {
// Place certificate in root folder
certificate = fs.readFileSync("./apple-pay-cert.pem")
} catch (error) {
throw new Error(
"Could not find ApplePay certificate. Make sure to place it in root folder of your server"
)
}
const httpsAgent = new https.Agent({
cert: certificate,
key: certificate,
rejectUnauthorized: false,
})
const request = {
merchantIdentifier: this.options_.applepay_merchant_id,
displayName: this.options_.applepay_display_name,
initiative: "web",
initiativeContext: this.options_.applepay_initiative_context,
}
return axios.post(validationUrl, request, {
httpsAgent,
})
}
async authorizePayment(sessionData, context) {
return this.adyenService_.authorizePayment(sessionData, context)
}
async getPaymentData(data) {
return this.adyenService_.getPaymentData(data)
}
async retrievePayment(data) {
return this.adyenService_.retrievePayment(data)
}
async updatePaymentData(sessionData, update) {
return this.adyenService_.updatePaymentData(sessionData, update)
}
async updatePayment(data, _) {
return this.adyenService_.updatePayment(data)
}
async deletePayment(data) {
return this.adyenService_.deletePayment(data)
}
async capturePayment(data) {
return this.adyenService_.capturePayment(data)
}
async refundPayment(data, amountToRefund) {
return this.adyenService_.refundPayment(data, amountToRefund)
}
async cancelPayment(data) {
return this.adyenService_.cancelPayment(data)
}
}
export default ApplePayAdyenService
@@ -1,62 +0,0 @@
import _ from "lodash"
import { PaymentService } from "medusa-interfaces"
class CardAdyenService extends PaymentService {
static identifier = "scheme-adyen"
constructor({ adyenService }) {
super()
this.adyenService_ = adyenService
}
async retrieveSavedMethods(customer) {
return this.adyenService_.retrieveSavedMethods(customer)
}
async getStatus(paymentData) {
return this.adyenService_.getStatus(paymentData)
}
async createPayment(data) {
return this.adyenService_.createPayment(data)
}
async authorizePayment(sessionData, context) {
return this.adyenService_.authorizePayment(sessionData, context)
}
async retrievePayment(data) {
return this.adyenService_.retrievePayment(data)
}
async getPaymentData(data) {
return this.adyenService_.getPaymentData(data)
}
async updatePayment(data, _) {
return this.adyenService_.updatePayment(data)
}
async updatePaymentData(sessionData, update) {
return this.adyenService_.updatePaymentData(sessionData, update)
}
async deletePayment(data) {
return this.adyenService_.deletePayment(data)
}
async capturePayment(data) {
return this.adyenService_.capturePayment(data)
}
async refundPayment(data, amountToRefund) {
return this.adyenService_.refundPayment(data, amountToRefund)
}
async cancelPayment(data) {
return this.adyenService_.cancelPayment(data)
}
}
export default CardAdyenService
@@ -1,58 +0,0 @@
import _ from "lodash"
import { PaymentService } from "medusa-interfaces"
class GooglePayAdyenService extends PaymentService {
static identifier = "paywithgoogle-adyen"
constructor({ adyenService }) {
super()
this.adyenService_ = adyenService
}
async getStatus(paymentData) {
return this.adyenService_.getStatus(paymentData)
}
async createPayment(data) {
return this.adyenService_.createPayment(data)
}
async authorizePayment(sessionData, context) {
return this.adyenService_.authorizePayment(sessionData, context)
}
async retrievePayment(data) {
return this.adyenService_.retrievePayment(data)
}
async updatePayment(data, _) {
return this.adyenService_.updatePayment(data)
}
async updatePaymentData(sessionData, update) {
return this.adyenService_.updatePaymentData(sessionData, update)
}
async getPaymentData(data) {
return this.adyenService_.getPaymentData(data)
}
async deletePayment(data) {
return this.adyenService_.deletePayment(data)
}
async capturePayment(data) {
return this.adyenService_.capturePayment(data)
}
async refundPayment(data, amountToRefund) {
return this.adyenService_.refundPayment(data, amountToRefund)
}
async cancelPayment(data) {
return this.adyenService_.cancelPayment(data)
}
}
export default GooglePayAdyenService
@@ -1,62 +0,0 @@
import _ from "lodash"
import { PaymentService } from "medusa-interfaces"
class IdealAdyenService extends PaymentService {
static identifier = "ideal-adyen"
constructor({ adyenService }) {
super()
this.adyenService_ = adyenService
}
async getStatus(paymentData) {
return this.adyenService_.getStatus(paymentData)
}
async createPayment(data) {
return this.adyenService_.createPayment(data)
}
async authorizePayment(sessionData, context) {
return this.adyenService_.authorizePayment(sessionData, context)
}
async retrievePayment(data) {
return this.adyenService_.retrievePayment(data)
}
async getPaymentData(data) {
return this.adyenService_.getPaymentData(data)
}
async updatePayment(data, _) {
return this.adyenService_.updatePayment(data)
}
async updatePaymentData(sessionData, update) {
return this.adyenService_.updatePaymentData(sessionData, update)
}
async getPaymentData(data) {
return this.adyenService_.getPaymentData(data)
}
async deletePayment(data) {
return this.adyenService_.deletePayment(data)
}
async capturePayment(data) {
return this.adyenService_.capturePayment(data)
}
async refundPayment(data, amountToRefund) {
return this.adyenService_.refundPayment(data, amountToRefund)
}
async cancelPayment(data) {
return this.adyenService_.cancelPayment(data)
}
}
export default IdealAdyenService
@@ -15,7 +15,9 @@ class MobilePayAdyenService extends PaymentService {
}
async createPayment(data) {
return this.adyenService_.createPayment(data)
const raw = await this.adyenService_.createPayment(data)
raw.type = "mobilepay"
return raw
}
async authorizePayment(sessionData, context) {
@@ -1,58 +0,0 @@
import _ from "lodash"
import { PaymentService } from "medusa-interfaces"
class PayPalAdyenService extends PaymentService {
static identifier = "paypal-adyen"
constructor({ adyenService }) {
super()
this.adyenService_ = adyenService
}
async getStatus(paymentData) {
return this.adyenService_.getStatus(paymentData)
}
async createPayment(data) {
return this.adyenService_.createPayment(data)
}
async authorizePayment(sessionData, context) {
return this.adyenService_.authorizePayment(sessionData, context)
}
async retrievePayment(data) {
return this.adyenService_.retrievePayment(data)
}
async getPaymentData(data) {
return this.adyenService_.getPaymentData(data)
}
async updatePayment(data, _) {
return this.adyenService_.updatePayment(data)
}
async updatePaymentData(sessionData, update) {
return this.adyenService_.updatePaymentData(sessionData, update)
}
async deletePayment(data) {
return this.adyenService_.deletePayment(data)
}
async capturePayment(data) {
return this.adyenService_.capturePayment(data)
}
async refundPayment(data, amountToRefund) {
return this.adyenService_.refundPayment(data, amountToRefund)
}
async cancelPayment(data) {
return this.adyenService_.cancelPayment(data)
}
}
export default PayPalAdyenService
@@ -105,7 +105,6 @@ class AdyenSubscriber {
await this.paymentRepository_.save(updatedPayment)
} catch (error) {
console.log(error)
await this.manager_.transaction(async (manager) => {
const session = {
pspReference: notification.pspReference,