1 parent
c62dd66911
commit
427ae25016
16 files changed
+612
-6
No files matched your search
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"@babel/plugin-proposal-optional-chaining",
|
||||||
|
"@babel/plugin-proposal-class-properties",
|
||||||
|
"@babel/plugin-transform-instanceof",
|
||||||
|
"@babel/plugin-transform-classes"
|
||||||
|
],
|
||||||
|
"presets": ["@babel/preset-env"],
|
||||||
|
"env": {
|
||||||
|
"test": {
|
||||||
|
"plugins": ["@babel/plugin-transform-runtime"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["prettier"],
|
||||||
|
"extends": ["prettier"],
|
||||||
|
"rules": {
|
||||||
|
"prettier/prettier": "error",
|
||||||
|
"semi": "error",
|
||||||
|
"no-unused-expressions": "true"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/lib
|
||||||
|
node_modules
|
||||||
|
.DS_store
|
||||||
|
.env*
|
||||||
|
/*.js
|
||||||
|
!index.js
|
||||||
|
yarn.lock
|
||||||
|
|
||||||
|
/dist
|
||||||
|
|
||||||
|
/api
|
||||||
|
/services
|
||||||
|
/models
|
||||||
|
/subscribers
|
||||||
|
/loaders
|
||||||
|
/__mocks__
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
/lib
|
||||||
|
node_modules
|
||||||
|
.DS_store
|
||||||
|
.env*
|
||||||
|
/*.js
|
||||||
|
!index.js
|
||||||
|
yarn.lock
|
||||||
|
src
|
||||||
|
.gitignore
|
||||||
|
.eslintrc
|
||||||
|
.babelrc
|
||||||
|
.prettierrc
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": false,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5"
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# medusa-payment-paypal
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
```
|
||||||
|
sandbox: [default: false],
|
||||||
|
client_id: "CLIENT_ID", REQUIRED
|
||||||
|
client_secret: "CLIENT_SECRET", REQUIRED
|
||||||
|
auth_webhook_id: REQUIRED for webhook to work
|
||||||
|
```
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
// noop
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"name": "medusa-payment-paypal",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Paypal Payment provider for Meduas Commerce",
|
||||||
|
"main": "index.js",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/medusajs/medusa",
|
||||||
|
"directory": "packages/medusa-payment-paypal"
|
||||||
|
},
|
||||||
|
"author": "Sebastian Rindom",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.7.5",
|
||||||
|
"@babel/core": "^7.7.5",
|
||||||
|
"@babel/node": "^7.7.4",
|
||||||
|
"@babel/plugin-proposal-class-properties": "^7.7.4",
|
||||||
|
"@babel/plugin-proposal-optional-chaining": "^7.12.7",
|
||||||
|
"@babel/plugin-transform-classes": "^7.9.5",
|
||||||
|
"@babel/plugin-transform-instanceof": "^7.8.3",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||||
|
"@babel/preset-env": "^7.7.5",
|
||||||
|
"@babel/register": "^7.7.4",
|
||||||
|
"@babel/runtime": "^7.9.6",
|
||||||
|
"client-sessions": "^0.8.0",
|
||||||
|
"cross-env": "^5.2.1",
|
||||||
|
"eslint": "^6.8.0",
|
||||||
|
"jest": "^25.5.2",
|
||||||
|
"medusa-test-utils": "^1.1.2"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "babel src -d . --ignore **/__tests__",
|
||||||
|
"prepare": "cross-env NODE_ENV=production npm run build",
|
||||||
|
"watch": "babel -w src --out-dir . --ignore **/__tests__",
|
||||||
|
"test": "jest"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"medusa-interfaces": "1.x"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@paypal/checkout-server-sdk": "^1.0.2",
|
||||||
|
"body-parser": "^1.19.0",
|
||||||
|
"express": "^4.17.1",
|
||||||
|
"medusa-core-utils": "^1.1.0"
|
||||||
|
},
|
||||||
|
"gitHead": "0646bd395a6056657cb0aa93c13699c4a9dbbcdd"
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import { Router } from "express"
|
||||||
|
import hooks from "./routes/hooks"
|
||||||
|
|
||||||
|
export default (container) => {
|
||||||
|
const app = Router()
|
||||||
|
|
||||||
|
hooks(app)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export default (fn) => (...args) => fn(...args).catch(args[2])
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { default as wrap } from "./await-middleware"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
wrap,
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { Router } from "express"
|
||||||
|
import bodyParser from "body-parser"
|
||||||
|
import middlewares from "../../middlewares"
|
||||||
|
|
||||||
|
const route = Router()
|
||||||
|
|
||||||
|
export default (app) => {
|
||||||
|
app.use("/paypal", route)
|
||||||
|
|
||||||
|
route.use(bodyParser.json())
|
||||||
|
route.post("/hooks", middlewares.wrap(require("./paypal").default))
|
||||||
|
return app
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
export default async (req, res) => {
|
||||||
|
const auth_algo = req.headers["paypal-auth-algo"]
|
||||||
|
const cert_url = req.headers["paypal-cert-url"]
|
||||||
|
const transmission_id = req.headers["paypal-transmission-id"]
|
||||||
|
const transmission_sig = req.headers["paypal-transmission-sig"]
|
||||||
|
const transmission_time = req.headers["paypal-transmission-time"]
|
||||||
|
|
||||||
|
const paypalService = req.scope.resolve("paypalProviderService")
|
||||||
|
|
||||||
|
try {
|
||||||
|
await paypalService.verifyWebhook({
|
||||||
|
auth_algo,
|
||||||
|
cert_url,
|
||||||
|
transmission_id,
|
||||||
|
transmission_sig,
|
||||||
|
transmission_time,
|
||||||
|
webhook_event: req.body,
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
res.sendStatus(401)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const authId = req.body.resource.id
|
||||||
|
const auth = await paypalService.retrieveAuthorization(authId)
|
||||||
|
|
||||||
|
const order = await paypalService.retrieveOrderFromAuth(auth)
|
||||||
|
|
||||||
|
const purchaseUnit = order.purchase_units[0]
|
||||||
|
const cartId = purchaseUnit.custom_id
|
||||||
|
|
||||||
|
const manager = req.scope.resolve("manager")
|
||||||
|
const cartService = req.scope.resolve("cartService")
|
||||||
|
const orderService = req.scope.resolve("orderService")
|
||||||
|
|
||||||
|
await manager.transaction(async (m) => {
|
||||||
|
const order = await orderService
|
||||||
|
.withTransaction(m)
|
||||||
|
.retrieveByCartId(cartId)
|
||||||
|
.catch((_) => undefined)
|
||||||
|
|
||||||
|
if (!order) {
|
||||||
|
await cartService.withTransaction(m).setPaymentSession(cartId, "paypal")
|
||||||
|
await cartService.withTransaction(m).authorizePayment(cartId)
|
||||||
|
await orderService.withTransaction(m).createFromCart(cartId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
res.sendStatus(200)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
res.sendStatus(409)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,402 @@
|
|||||||
|
import _ from "lodash"
|
||||||
|
import PayPal from "@paypal/checkout-server-sdk"
|
||||||
|
import { PaymentService } from "medusa-interfaces"
|
||||||
|
|
||||||
|
class PayPalProviderService extends PaymentService {
|
||||||
|
static identifier = "paypal"
|
||||||
|
|
||||||
|
constructor({ customerService, totalsService, regionService }, options) {
|
||||||
|
super()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required PayPal options:
|
||||||
|
* {
|
||||||
|
* sandbox: [default: false],
|
||||||
|
* client_id: "CLIENT_ID", REQUIRED
|
||||||
|
* client_secret: "CLIENT_SECRET", REQUIRED
|
||||||
|
* auth_webhook_id: REQUIRED for webhook to work
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
this.options_ = options
|
||||||
|
|
||||||
|
let environment
|
||||||
|
if (this.options_.sandbox) {
|
||||||
|
environment = new PayPal.core.SandboxEnvironment(
|
||||||
|
options.client_id,
|
||||||
|
options.client_secret
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
environment = new PayPal.core.LiveEnvironment(
|
||||||
|
options.client_id,
|
||||||
|
options.client_secret
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private @const {PayPalHttpClient} */
|
||||||
|
this.paypal_ = new PayPal.core.PayPalHttpClient(environment)
|
||||||
|
|
||||||
|
/** @private @const {CustomerService} */
|
||||||
|
this.customerService_ = customerService
|
||||||
|
|
||||||
|
/** @private @const {RegionService} */
|
||||||
|
this.regionService_ = regionService
|
||||||
|
|
||||||
|
/** @private @const {TotalsService} */
|
||||||
|
this.totalsService_ = totalsService
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches an open PayPal order and maps its status to Medusa payment
|
||||||
|
* statuses.
|
||||||
|
* @param {object} paymentData - the data stored with the payment
|
||||||
|
* @returns {string} the status of the order
|
||||||
|
*/
|
||||||
|
async getStatus(paymentData) {
|
||||||
|
const order = await this.retrievePayment(paymentData)
|
||||||
|
|
||||||
|
let status = "pending"
|
||||||
|
|
||||||
|
switch (order.status) {
|
||||||
|
case "CREATED":
|
||||||
|
return "pending"
|
||||||
|
case "COMPLETED":
|
||||||
|
return "authorized"
|
||||||
|
case "SAVED":
|
||||||
|
case "APPROVED":
|
||||||
|
case "PAYER_ACTION_REQUIRED":
|
||||||
|
return "requires_more"
|
||||||
|
case "VOIDED":
|
||||||
|
return "canceled"
|
||||||
|
// return "captured"
|
||||||
|
default:
|
||||||
|
return status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not supported
|
||||||
|
*/
|
||||||
|
async retrieveSavedMethods(customer) {
|
||||||
|
return Promise.resolve([])
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PayPal order, with an Authorize intent. The plugin doesn't
|
||||||
|
* support shipping details at the moment.
|
||||||
|
* Reference docs: https://developer.paypal.com/docs/api/orders/v2/
|
||||||
|
* @param {object} cart - cart to create a payment for
|
||||||
|
* @returns {object} the data to be stored with the payment session.
|
||||||
|
*/
|
||||||
|
async createPayment(cart) {
|
||||||
|
const { customer_id, region_id, email } = cart
|
||||||
|
const { currency_code } = await this.regionService_.retrieve(region_id)
|
||||||
|
|
||||||
|
const amount = await this.totalsService_.getTotal(cart)
|
||||||
|
|
||||||
|
const request = new PayPal.orders.OrdersCreateRequest()
|
||||||
|
request.requestBody({
|
||||||
|
intent: "AUTHORIZE",
|
||||||
|
application_context: {
|
||||||
|
shipping_preference: "NO_SHIPPING",
|
||||||
|
},
|
||||||
|
purchase_units: [
|
||||||
|
{
|
||||||
|
custom_id: cart.id,
|
||||||
|
amount: {
|
||||||
|
currency_code: currency_code.toUpperCase(),
|
||||||
|
value: (amount / 100).toFixed(2),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
const res = await this.paypal_.execute(request)
|
||||||
|
|
||||||
|
return { id: res.result.id }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a PayPal order.
|
||||||
|
* @param {object} data - the data stored with the payment
|
||||||
|
* @returns {Promise<object>} PayPal order
|
||||||
|
*/
|
||||||
|
async retrievePayment(data) {
|
||||||
|
try {
|
||||||
|
const request = new PayPal.orders.OrdersGetRequest(data.id)
|
||||||
|
const res = await this.paypal_.execute(request)
|
||||||
|
return res.result
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the payment data from a payment session
|
||||||
|
* @param {object} session - the session to fetch payment data for.
|
||||||
|
* @returns {Promise<object>} the PayPal order object
|
||||||
|
*/
|
||||||
|
async getPaymentData(session) {
|
||||||
|
try {
|
||||||
|
return this.retrievePayment(paymentSession.data)
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method does not call the PayPal authorize function, but fetches the
|
||||||
|
* status of the payment as it is expected to have been authorized client side.
|
||||||
|
* @param {object} session - payment session
|
||||||
|
* @param {object} context - properties relevant to current context
|
||||||
|
* @returns {Promise<{ status: string, data: object }>} result with data and status
|
||||||
|
*/
|
||||||
|
async authorizePayment(session, context = {}) {
|
||||||
|
const stat = await this.getStatus(session.data)
|
||||||
|
|
||||||
|
try {
|
||||||
|
return { data: session.data, status: stat }
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the data stored with the payment session.
|
||||||
|
* @param {object} data - the currently stored data.
|
||||||
|
* @param {object} update - the update data to store.
|
||||||
|
* @returns {object} the merged data of the two arguments.
|
||||||
|
*/
|
||||||
|
async updatePaymentData(data, update) {
|
||||||
|
try {
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
...update.data,
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the PayPal order.
|
||||||
|
* @param {object} sessionData - payment session data.
|
||||||
|
* @param {object} cart - the cart to update by.
|
||||||
|
* @returns {object} the resulting order object.
|
||||||
|
*/
|
||||||
|
async updatePayment(sessionData, cart) {
|
||||||
|
try {
|
||||||
|
const { region_id } = cart
|
||||||
|
const { currency_code } = await this.regionService_.retrieve(region_id)
|
||||||
|
|
||||||
|
const request = new PayPal.orders.OrdersPatchRequest(sessionData.id)
|
||||||
|
request.requestBody([
|
||||||
|
{
|
||||||
|
op: "replace",
|
||||||
|
path: "/purchase_units/@reference_id=='default'",
|
||||||
|
value: {
|
||||||
|
amount: {
|
||||||
|
currency_code: currency_code.toUpperCase(),
|
||||||
|
value: (cart.total / 100).toFixed(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
await this.paypal_.execute(request)
|
||||||
|
|
||||||
|
return sessionData
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not suported
|
||||||
|
*/
|
||||||
|
async deletePayment(payment) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Captures a previously authorized order.
|
||||||
|
* @param {object} payment - the payment to capture
|
||||||
|
* @returns {object} the PayPal order
|
||||||
|
*/
|
||||||
|
async capturePayment(payment) {
|
||||||
|
const { purchase_units } = payment.data
|
||||||
|
|
||||||
|
const id = purchase_units[0].payments.authorizations[0].id
|
||||||
|
|
||||||
|
try {
|
||||||
|
const request = new PayPal.payments.AuthorizationsCaptureRequest(id)
|
||||||
|
await this.paypal_.execute(request)
|
||||||
|
return this.retrievePayment(payment.data)
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refunds a given amount.
|
||||||
|
* @param {object} payment - payment to refund
|
||||||
|
* @param {number} amountToRefund - amount to refund
|
||||||
|
* @returns {string} the resulting PayPal order
|
||||||
|
*/
|
||||||
|
async refundPayment(payment, amountToRefund) {
|
||||||
|
const { purchase_units } = payment.data
|
||||||
|
|
||||||
|
try {
|
||||||
|
const payments = purchase_units[0].payments
|
||||||
|
if (!(payments && payments.captures.length)) {
|
||||||
|
throw new Error("Order not yet captured")
|
||||||
|
}
|
||||||
|
|
||||||
|
const payId = payments.captures[0].id
|
||||||
|
const request = new PayPal.payments.CapturesRefundRequest(payId)
|
||||||
|
|
||||||
|
request.requestBody({
|
||||||
|
amount: {
|
||||||
|
currency_code: payment.currency_code.toUpperCase(),
|
||||||
|
value: (amountToRefund / 100).toFixed(),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
await this.paypal_.execute(request)
|
||||||
|
|
||||||
|
return this.retrievePayment(payment.id)
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancels payment for Stripe payment intent.
|
||||||
|
* @param {object} paymentData - payment method data from cart
|
||||||
|
* @returns {object} canceled payment intent
|
||||||
|
*/
|
||||||
|
async cancelPayment(payment) {
|
||||||
|
try {
|
||||||
|
const { purchase_units } = payment.data
|
||||||
|
if (payment.captured_at) {
|
||||||
|
const payments = purchase_units[0].payments
|
||||||
|
|
||||||
|
const payId = payments.captures[0].id
|
||||||
|
const request = new PayPal.payments.CapturesRefundRequest(payId)
|
||||||
|
await this.paypal_.execute(request)
|
||||||
|
} else {
|
||||||
|
const id = purchase_units[0].payments.authorizations[0].id
|
||||||
|
const request = new PayPal.payments.AuthorizationsVoidRequest(id)
|
||||||
|
await this.paypal_.execute(request)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.retrievePayment(payment.data)
|
||||||
|
} catch (error) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a PayPal authorization object the method will find the order that
|
||||||
|
* created the authorization, by following the HATEOAS link to the order.
|
||||||
|
* @param {object} auth - the authorization object.
|
||||||
|
* @returns {Promise<object>} the PayPal order object
|
||||||
|
*/
|
||||||
|
async retrieveOrderFromAuth(auth) {
|
||||||
|
const link = auth.links.find((l) => l.rel === "up")
|
||||||
|
const parts = link.href.split("/")
|
||||||
|
const orderId = parts[parts.length - 1]
|
||||||
|
const orderReq = new PayPal.orders.OrdersGetRequest(orderId)
|
||||||
|
const res = await this.paypal_.execute(orderReq)
|
||||||
|
if (res.result) {
|
||||||
|
return res.result
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a PayPal authorization.
|
||||||
|
* @param {string} id - the id of the authorization.
|
||||||
|
* @returns {Promise<object>} the authorization.
|
||||||
|
*/
|
||||||
|
async retrieveAuthorization(id) {
|
||||||
|
const authReq = new PayPal.payments.AuthorizationsGetRequest(id)
|
||||||
|
const res = await this.paypal_.execute(authReq)
|
||||||
|
if (res.result) {
|
||||||
|
return res.result
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a webhook is verified.
|
||||||
|
* @param {object} data - the verficiation data.
|
||||||
|
* @returns {Promise<object>} the response of the verification request.
|
||||||
|
*/
|
||||||
|
async verifyWebhook(data) {
|
||||||
|
const verifyReq = {
|
||||||
|
verb: "POST",
|
||||||
|
path: "/v1/notifications/verify-webhook-signature",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
webhook_id: this.options_.auth_webhook_id,
|
||||||
|
...data,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.paypal_.execute(verifyReq)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upserts a webhook that listens for order authorizations.
|
||||||
|
*/
|
||||||
|
async ensureWebhooks() {
|
||||||
|
if (!this.options_.backend_url) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const webhookReq = {
|
||||||
|
verb: "GET",
|
||||||
|
path: "/v1/notifications/webhooks",
|
||||||
|
}
|
||||||
|
const webhookRes = await this.paypal_.execute(webhookReq)
|
||||||
|
|
||||||
|
console.log(webhookRes.result.webhooks)
|
||||||
|
let found
|
||||||
|
if (webhookRes.result && webhookRes.result.webhooks) {
|
||||||
|
found = webhookRes.result.webhooks.find((w) => {
|
||||||
|
const notificationType = w.event_types.find(
|
||||||
|
(e) => e.name === "PAYMENT.AUTHORIZATION.CREATED"
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
!!notificationType &&
|
||||||
|
w.url === `${this.options_.backend_url}/paypal/hooks`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
const whCreateReq = {
|
||||||
|
verb: "POST",
|
||||||
|
path: "/v1/notifications/webhooks",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
id: "medusa-auth-notification",
|
||||||
|
url: `${this.options_.backend_url}/paypal/hooks`,
|
||||||
|
event_types: [
|
||||||
|
{
|
||||||
|
name: "PAYMENT.AUTHORIZATION.CREATED",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.paypal_.execute(whCreateReq)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PayPalProviderService
|
||||||
@@ -21,7 +21,7 @@ const defaultRelations = [
|
|||||||
"claims.fulfillments",
|
"claims.fulfillments",
|
||||||
"claims.claim_items",
|
"claims.claim_items",
|
||||||
"claims.claim_items.images",
|
"claims.claim_items.images",
|
||||||
"claims.claim_items.tags",
|
// "claims.claim_items.tags",
|
||||||
"swaps",
|
"swaps",
|
||||||
"swaps.return_order",
|
"swaps.return_order",
|
||||||
"swaps.payment",
|
"swaps.payment",
|
||||||
|
|||||||
@@ -905,11 +905,13 @@ class OrderService extends BaseService {
|
|||||||
|
|
||||||
const result = await orderRepo.save(order)
|
const result = await orderRepo.save(order)
|
||||||
|
|
||||||
this.eventBus_
|
if (order.payment_status === "captured") {
|
||||||
.withTransaction(manager)
|
this.eventBus_
|
||||||
.emit(OrderService.Events.PAYMENT_CAPTURED, {
|
.withTransaction(manager)
|
||||||
id: result.id,
|
.emit(OrderService.Events.PAYMENT_CAPTURED, {
|
||||||
})
|
id: result.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in new issue
Block a user