• Интеграции и плагины
  • Сообщество
  • Связаться с нами
Документация

Нужна помощь в разработке плагина интеграции для Medusa?

Написать намНайти плагины

Gorgo снижает затраты на адаптацию Medusa к локальным рынкам.

Мы разрабатываем плагины интеграции, осуществляем поддержку и развиваем сообщество разработчиков на Medusa в Telegram.

  • Ресурсы
  • Интеграции и плагины
  • Сообщество
  • Medusa Чат в Telegram
  • Medusa Новости в Telegram
  • Документация
  • Контакты
  • head@gorgojs.com
  • TelegramGitHub
MedusaПлагиныCybersource
C

Cybersource

CyberSource payment provider for Medusa.js v2 with Flex Microform (PCI DSS SAQ-A)

Нужна доработка этого плагина?

Связаться с нами
npm install medusa-payment-cybersource
Категория
Платежи
Создано
Geovannygil
Версия
1.1.1
Последнее обновление
1 неделю назад
Ежемесячные загрузки
528
Звезды на Github
4
npmNPMGitHubGithub
MedusaПлагиныCybersource

Medusa Payment Cybersource for Medusa

CyberSource payment plugin for Medusa.js v2, built on Flex Microform v2 (PCI DSS SAQ-A compliant).

Features

  • Flex Microform v2 — card data is tokenized directly at CyberSource; it never touches your server
  • Device Fingerprint (ThreatMetrix) — fraud scoring via device profiling before payment
  • Authorization + manual capture from the Medusa admin dashboard
  • Auto-capture (sale mode) for instant settlement
  • Partial and full refunds
  • Zero-amount orders — 100% discounts and free orders are handled automatically (no gateway call)
  • Admin widget — CyberSource transaction details panel injected into order detail view

Requirements

Medusa.jsv2 ()
Node.js18+
CyberSourceBusiness Center account

Installation

npm install medusa-payment-cybersource

Environment Variables

Add these to your :

CYBERSOURCE_MERCHANT_ID=your_merchant_id
CYBERSOURCE_KEY_ID=your_shared_key_id
CYBERSOURCE_SECRET_KEY=your_shared_secret_key
CYBERSOURCE_ENV=sandbox # or "production"
CYBERSOURCE_AUTO_CAPTURE=false # set to "true" for sale/auto-capture mode

Where to find these values: CyberSource Business Center → Account Management → Transaction Security Keys → Security Keys for the HTTP Signature Security Policy

Configuration

In , add the plugin to both (for the API route) and (for the payment provider):

import { loadEnv, defineConfig } from "@medusajs/framework/utils"
loadEnv(process.env.NODE_ENV || "development", process.cwd())
module.exports = defineConfig({
plugins: [
// Required: registers the built-in /store/cybersource/authorize route
{ resolve: "medusa-payment-cybersource" },
],
projectConfig: {
// ... your existing config
},
modules: [
{
resolve: "@medusajs/medusa/payment",
options: {
providers: [
{
resolve: "medusa-payment-cybersource",
id: "cybersource",
options: {
merchantID: process.env.CYBERSOURCE_MERCHANT_ID,
merchantKeyId: process.env.CYBERSOURCE_KEY_ID,
merchantsecretKey: process.env.CYBERSOURCE_SECRET_KEY,
environment:
process.env.CYBERSOURCE_ENV === "production"
? "production"
: "sandbox",
capture: process.env.CYBERSOURCE_AUTO_CAPTURE === "true",
},
},
],
},
},
],
})

Plugin Options

OptionTypeDescription
Required. Your CyberSource Merchant ID
Required. Shared key ID (HTTP Signature)
Required. Shared secret key (HTTP Signature)
or . Default:
Auto-capture on authorization (sale mode). Default:
Card networks for Flex. Default:

Payment Flow

Frontend Integration

1. Load Flex Microform

<script src="https://flex.cybersource.com/microform/bundle/v2/flex-microform.min.js"></script>

2. Load Device Fingerprint Script

When the user selects CyberSource as payment method, generate a unique session ID and load the ThreatMetrix script. The same ID must be sent in the authorize request.

const fingerprintSessionId = crypto.randomUUID()
const script = document.createElement("script")
script.src = `https://h.online-metrix.net/fp/tags.js?org_id=${ORG_ID}&session_id=${fingerprintSessionId}`
script.async = true
document.head.appendChild(script)
// org_id values:
// Sandbox: 1snn5n9w
// Production: k8vif92e (confirm in Business Center → Decision Manager)

3. Initialize Flex

// captureContext comes from payment_session.data.captureContext
const flex = new Flex(captureContext)
const microform = flex.microform()
const cardNumber = microform.createField("number", { placeholder: "Card number" })
const cvn = microform.createField("securityCode", { placeholder: "CVV" })
cardNumber.load("#card-number-container")
cvn.load("#cvn-container")

4. Tokenize and Pre-authorize

Call this before :

async function authorizePayment(paymentSessionId, fingerprintSessionId) {
// 1. Get transient token from Flex Microform
const transientToken = await new Promise((resolve, reject) => {
microform.createToken({ expirationMonth: "12", expirationYear: "2030" }, (err, token) => {
if (err) reject(err)
else resolve(token)
})
})
// 2. Pre-authorize at CyberSource via the built-in plugin route
const response = await fetch("/store/cybersource/authorize", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-publishable-api-key": YOUR_PUBLISHABLE_API_KEY,
},
body: JSON.stringify({
payment_session_id: paymentSessionId,
transient_token: transientToken,
fingerprint_session_id: fingerprintSessionId, // same UUID used in the script URL
bill_to: { // optional but recommended
firstName: "John",
lastName: "Doe",
email: "john@example.com",
address1: "123 Main St",
locality: "Guatemala City",
administrativeArea: "Guatemala",
postalCode: "01001",
country: "GT",
},
}),
})
const result = await response.json()
if (!response.ok) {
throw new Error(result.message || "Payment declined")
}
return result // { success: true, cs_payment_id, cs_status }
}
// Usage
await authorizePayment(
cart.payment_collection.payment_sessions[0].id,
fingerprintSessionId,
)
await placeOrder() // Medusa completes the order using the stored cs_payment_id

— Request / Response

Request body:

FieldRequiredDescription
YesMedusa payment session ID
YesJWT from
NoSession ID used in the ThreatMetrix script URL
NoBilling address object for AVS/fraud checks

Success response (200):

{ "success": true, "cs_payment_id": "7278957202756800104005", "cs_status": "AUTHORIZED" }

Declined response (402):

{ "error": "Payment declined", "reason": "INSUFFICIENT_FUND", "cs_status": "DECLINED" }

Device Fingerprint

The plugin sends and to the CyberSource Payments API. The flag is required so that CyberSource looks up ThreatMetrix using the raw session ID (your UUID) instead of the default composite key — which would cause a mismatch with what the frontend script registered.

You can verify fingerprint collection is working by checking a transaction in CyberSource Business Center. A successful integration shows a hash under Device Fingerprint ID instead of "Not Submitted".

Capture Modes

Manual Capture (default)

CyberSource authorizes the card on order placement. You capture the funds from the Medusa Admin → Orders → Payment panel. Authorization expires in 5–7 days if not captured.

Auto-Capture (sale mode)

Set . CyberSource processes authorization and capture together; the payment is marked as captured immediately on order placement.

Admin Widget

The plugin injects a CyberSource panel into the order detail page of the Medusa admin (). It shows:

FieldDescription
Status badgeDerived display status (see table below)
Transaction IDCyberSource authorization ID
Capture IDOnly shown if different from Transaction ID (manual capture)
Reconciliation IDCyberSource reconciliation ID
CardCard brand + last 4 digits
Last Refund IDID of the last refund issued
Last Refund AmountAmount of the last refund

Status badge logic:

ConditionBadge
is set🔵 REFUNDED
+ set (auto-capture)🟢 CAPTURED
(no capture ID)🟠 AUTHORIZED
🟢 CAPTURED
⚫ VOIDED
🔴 DECLINED

Admin Refund Route

Medusa's default refund UI has a validation that can block refunds in some edge cases. Add this route to your Medusa store for a direct refund bypass:

Create in your Medusa project:

import { MedusaRequest, MedusaResponse } from "@medusajs/framework"
import { Modules } from "@medusajs/framework/utils"
type RefundRequestBody = {
payment_id: string
amount?: number
note?: string
}
export const POST = async (
req: MedusaRequest<RefundRequestBody>,
res: MedusaResponse
) => {
const { payment_id, amount, note } = req.body
if (!payment_id) {
return res.status(400).json({ error: "payment_id is required" })
}
const paymentModule = req.scope.resolve(Modules.PAYMENT)
const payments = await paymentModule.listPayments(
{ id: [payment_id] },
{ relations: ["captures", "refunds"] }
)
const payment = payments[0]
if (!payment) {
return res.status(404).json({ error: "Payment not found" })
}
const captured = (payment.captures ?? []).reduce(
(sum: number, c: any) => sum + Number(c.amount ?? 0),
0
)
const alreadyRefunded = (payment.refunds ?? []).reduce(
(sum: number, r: any) => sum + Number(r.amount ?? 0),
0
)
const refundable = captured - alreadyRefunded
if (refundable <= 0) {
return res.status(400).json({ error: "No capturable amount available to refund" })
}
const refundAmount = amount ?? refundable
if (refundAmount > refundable) {
return res.status(400).json({
error: `Cannot refund ${refundAmount}. Maximum refundable: ${refundable}`,
})
}
const updatedPayment = await paymentModule.refundPayment({
payment_id,
amount: refundAmount,
created_by: (req as any).auth_context?.actor_id,
note,
})
return res.json({ payment: updatedPayment })
}

Call it from your admin UI or custom dashboard:

curl -X POST http://localhost:9000/admin/cybersource/refund \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{ "payment_id": "pay_01...", "amount": 50.00 }'

Development

# Clone
git clone https://github.com/Eleven-Estudio/medusa-payment-cybersource.git
cd medusa-payment-cybersource
# Install dependencies
npm install
# Build
npm run build
# Watch mode (backend only)
npm run dev

Linking to a local Medusa store with yalc

# In the plugin directory
npm run build
npx yalc push
# In your Medusa store directory
npx yalc add medusa-payment-cybersource
npx medusa develop

After any plugin change, re-run in the plugin directory, then fully restart the Medusa server (yalc updates , hot-reload won't pick it up).

CyberSource Resources

  • Business Center — sandbox + production portal
  • Flex Microform v2 docs
  • Payments API reference
  • Sandbox test cards

License

MIT

Еще в этой категории

Посмотреть все
Платежи
Braintree logo

Braintree

От Lambda Curry

Поддержка платежей и 3D Secure через Braintree

GitHubnpm
Платежи
Pay. logo

Pay.

От Webbers

Принимайте кредитные карты, цифровые платежи и купи сейчас — плати потом

GitHubnpm
Платежи
Mollie logo

Mollie

От Variable Vic

Легко принимайте мультивалютные платежи через Mollie

GitHubnpm