Skip to content

feat: add MBWay and Wero APM integrations#198

Open
Bala1324 wants to merge 6 commits intopaypal-examples:mainfrom
Bala1324:feature/mbway-devdocs
Open

feat: add MBWay and Wero APM integrations#198
Bala1324 wants to merge 6 commits intopaypal-examples:mainfrom
Bala1324:feature/mbway-devdocs

Conversation

@Bala1324
Copy link
Copy Markdown

This PR adds sample integrations for two new Alternative Payment Methods (APMs) — MBWay and Wero

Changes

Client
MbWay

  1. client/components/mbwayPayments/html/src/app.js — MBWay payment flow: SDK initialization with testBuyerCountry: "PT", eligibility check, createMbWayOneTimePaymentSession, name + email SDK fields, custom phone number inputs (country code+ national number), validation, and popup flow
  2. client/components/mbwayPayments/html/src/index.html — HTML page for MBWay with and phone number inputs
  3. client/components/mbwayPayments/html/README.md — Full setup and integration documentation for MBWay

Wero

  1. client/components/weroPayments/html/src/app.js — Wero payment flow: SDK initialization with testBuyerCountry: "DE", eligibility check, createWeroOneTimePaymentSession, name SDK field, validation, and popup flow
  2. client/components/weroPayments/html/src/index.html — HTML page for Wero with
  3. client/components/weroPayments/html/README.md — Full setup and integration documentation for Wero
  4. client/index.html — Added navigation links for MBWay and Wero

Server

  1. server/node/src/paypalServerSdkClient.ts — Exported PAYPAL_BASE_URL constant for sandbox/production environment switching
  2. server/node/src/routes/ordersRouteHandler.ts — Added ClientOrderPayloadSchema and dual-path logic in createOrderForOneTimePaymentRouteHandler: detects raw purchase_units payload (used by APMs) and makes a direct REST API call to support processing_instruction: ORDER_COMPLETE_ON_PAYMENT_APPROVAL. Also added getOrderRouteHandler to fetch order details post-approval
  3. server/node/src/routes/index.ts — Registered GET /paypal-api/checkout/orders/:orderId route

@Bala1324 Bala1324 requested a review from a team as a code owner March 17, 2026 11:00
value: z.string(),
});

const ClientOrderPayloadSchema = z.object({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you able to implement these new APMs without any Order creation changes? We cannot accept purchase_units from the client code. We need to abstract this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, this is a blocker to merging, we cannot teach purchase_units to be passed in from the client side

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed ClientOrderPayloadSchema and the purchase_units path entirely. Client now sends only {currencyCode, processingInstruction } -- no purchase_units from client. Server builds the order payload using OneTimePaymentSchema.

Comment thread server/node/src/routes/index.ts Outdated
);

router.get(
"/paypal-api/checkout/orders/:orderId",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"/paypal-api/checkout/orders/:orderId",

Can we use the existing "/paypal-api/checkout/orders/create-order-for-one-time-payment" route for this behavior and add a new optional param to it for processingInstruction?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reused the existing /paypal-api/checkout/orders/create-order-for-one-time-payment route and added processingInstruction as an optional param

Copy link
Copy Markdown
Contributor

@dwilliams27 dwilliams27 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some comments that should be addressed

value: z.string(),
});

const ClientOrderPayloadSchema = z.object({
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, this is a blocker to merging, we cannot teach purchase_units to be passed in from the client side

Comment thread server/node/src/routes/index.ts Outdated
);

router.get(
"/paypal-api/checkout/orders/:orderId",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Comment thread server/node/src/routes/ordersRouteHandler.ts Outdated
for (const { sku, quantity } of cart) {
const { name, price } = getProduct(sku);
totalAmount += Number.parseFloat(price) * quantity;
totalAmount += parseFloat(price) * quantity;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be left as Number.parseFloat

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted back to Number.parseFloat. Fixed.

Comment on lines +155 to +158
// console.log(
// "[createOrderForOneTimePayment] Orders payload sent to v2/checkout/orders:",
// JSON.stringify(parsed, null, 2),
// );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These commented out debug log blocks should all be removed before merging

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed all commented out debug log blocks.


response.status(statusCode).json(result);
}
} No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was newline removed here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Added newline at end of file.

throw new Error("Missing API credentials");
}

export const PAYPAL_BASE_URL ="https://api-m.sandbox.paypal.com";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be needed once fetch is removed

Copy link
Copy Markdown
Author

@Bala1324 Bala1324 Apr 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Removed PAYPAL_BASE_URL and direct fetch. processingInstruction is now handled via ProcessingInstruction.OrderCompleteOnPaymentApproval enum from the SDK. The enum exists in the SDK source but not yet published to npm — raised a PR to the SDK repo. Once merged and released, this will work cleanly without any direct fetch.

@Bala1324 Bala1324 force-pushed the feature/mbway-devdocs branch from 7912441 to 650178e Compare April 1, 2026 05:54
```
The server will run on `http://localhost:8080`

### Client Setup
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these client steps are no longer needed. All a developer has to do is run the server for static examples like this. Ex:

 cd server/node
 npm install
 npm start

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the Client Setup section from both the MBWay and Wero README files. Developers only need to run the server for static examples.

) {
const { currencyCode, totalAmount, items } = OneTimePaymentSchema.parse(
request.body ?? {},
request.body,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add this back. There are use cases where the POST body is empty so we want it to default to an empty object.

Suggested change
request.body,
request.body ?? {},

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ?? {} back to default to an empty object when the POST body is empty.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants