@prood/payment-easypay
Easypay payment provider for Portugal — Multibanco, MB WAY, and credit card.
@prood/payment-easypay implements the PaymentProvider interface for Easypay — a Portuguese payment provider supporting Multibanco references, MB WAY, and credit card.
Installation
Workspace package. Available from the source repo for now.
Usage
import { EasypayPaymentProvider } from '@prood/payment-easypay'
const provider = new EasypayPaymentProvider({
accountId: config.accountId,
apiKey: config.apiKey,
baseUrl: config.baseUrl,
})Configuration
| Field | Description |
|---|---|
accountId | Easypay account ID |
apiKey | API key |
baseUrl | API base URL. Optional, defaults to live |
Each store enters these under Integrations in the dashboard. There is no environment fallback.
Environments
| Environment | Base URL |
|---|---|
| Production | https://api.prod.easypay.pt |
| Sandbox | https://api.test.easypay.pt |
Payment methods
| Method | Flow | UI |
|---|---|---|
| Multibanco | Reference-based | Entity + reference displayed; customer pays at ATM/homebanking |
| MB WAY | Push notification | Phone number input; customer confirms on phone |
| Credit card | Redirect | Redirect to Easypay hosted payment page |
Selecting a method
Pass method on createSession() (defaults to multibanco):
method | Flow |
|---|---|
multibanco | Multibanco reference (entity + reference, 3-day deadline) |
mbway | MB WAY push notification; needs a Portuguese mobile number |
card | Redirect to Easypay hosted card page |
const session = await provider.createSession({
amount: 29.99,
currency: 'EUR',
orderId: 'ord_456',
method: 'multibanco',
})Easypay confirms payments asynchronously via notifications. Use confirmSession() after redirect, but treat webhooks as the authoritative completion signal for reference payments.
Refunds
refund() posts to /2.0/refund/{captureId}, using the capture of the payment, with a 20 second deadline. MB WAY and card payments can be refunded this way. Multibanco can't: Easypay needs the shopper's IBAN, so those orders use the manual refund path.
Two guards keep a retry from paying twice:
- The
Idempotency-Keyheader. Easypay documents it for every POST, not on the refund operation itself, and forgets keys after 24 hours. - The capture's status. A capture already marked
refundedsends nothing.
transaction_key is only Easypay's internal reference for the refund. It doesn't deduplicate anything.
Easypay's refund notification carries the refund's id, not the payment's, so verifyWebhook reads /2.0/refund/{id} to find the payment and its order. Only a refund with status success changes the order: a value below the capture is payment.partially_refunded, anything else payment.refunded.
Factory usage
import { getTenantPaymentProvider } from '@prood/commerce'
const { provider } = await getTenantPaymentProvider(orgId, 'easypay')Payment flow
Drag to pan · Scroll to zoom
Webhook setup
Configure in Easypay merchant panel:
URL: https://checkout.example.com/api/webhooks/easypay/{orgId}