Skip to main content

Integrate MEID Payment Provider

This document describes how to add MEID as a new payment provider, similar to linkmepay, btcpay, and zeroxprocessing.

FieldValue
Providermeid
OperationDeposit
Initial scopePlayer deposit only
CurrencyUSD unless MEID requires another currency
Flow typeProvider-hosted payment URL / payment details
SettlementMEID webhook / callback settles the existing PaymentTransaction
note

CDN credit purchase for Shop, Agent, and Super Agent is intentionally out of scope for the first MEID integration.


Current Payment Architecture​

Deposit creation uses a provider adapter registry:

POST /api/payment/deposit
β”‚
β–Ό
payment route validation
β”‚
β–Ό
depositService.processDeposit()
β”‚
β–Ό
getDepositAdapter(provider)
β”‚
β”œβ”€β”€ linkmepay
β”œβ”€β”€ btcpay
└── zeroxprocessing
β”‚
β–Ό
adapter.createPayment()
β”‚
β–Ό
PaymentTransaction updated with paymentUrl / provider response
β”‚
β–Ό
Gateway callback settles the transaction

MEID should be added as a fourth deposit provider:

getDepositAdapter(provider)
β”‚
β”œβ”€β”€ linkmepay
β”œβ”€β”€ btcpay
β”œβ”€β”€ zeroxprocessing
└── meid

Relevant files:

AreaFile
Deposit validationkioskgaming_backend/src/routes/payment/validations.js
Deposit servicekioskgaming_backend/src/services/payment/depositService.js
Multi-game deposit servicekioskgaming_backend/src/services/payment/multiGameDepositService.js
Deposit adapter registrykioskgaming_backend/src/services/payment/depositAdapters/index.js
Existing LinkMePay adapter examplekioskgaming_backend/src/services/payment/depositAdapters/linkMePayDepositAdapter.js
Existing BTCPay adapter examplekioskgaming_backend/src/services/payment/depositAdapters/btcPayDepositAdapter.js
Existing 0x adapter examplekioskgaming_backend/src/services/payment/depositAdapters/zeroxProcessingDepositAdapter.js
Public payment routeskioskgaming_backend/src/routes/payment.js
User payment controller callbackskioskgaming_backend/src/controllers/user/paymentUserController.js
Provider fee configkioskgaming_backend/src/services/core/paymentProviderFeeCoreService.js
Payment method catalogkioskgaming_backend/src/services/biz/paymentMethodCatalogBizService.js

Required Backend Changes​

1. Add meid To Provider Validation​

Update:

kioskgaming_backend/src/routes/payment/validations.js

Add meid anywhere provider validation currently allows:

['linkmepay', 'btcpay', 'zeroxprocessing', 'meid']

This applies to:

ValidationNeeded for
depositValidationPlayer wallet-only and direct-to-game deposits
multiGameDepositValidationPlayer multi-game deposits
withdrawalValidationOnly if MEID supports withdrawals

If MEID is deposit-only, do not add it to withdrawal validation yet.

2. Add meid To Deposit Service Provider Guard​

Update:

kioskgaming_backend/src/services/payment/depositService.js

Current guard:

if (provider !== 'linkmepay' && provider !== 'zeroxprocessing' && provider !== 'btcpay') {
throw new Error('Invalid provider');
}

Expected:

if (
provider !== 'linkmepay' &&
provider !== 'zeroxprocessing' &&
provider !== 'btcpay' &&
provider !== 'meid'
) {
throw new Error('Invalid provider');
}

3. Create MEID Deposit Adapter​

Add:

kioskgaming_backend/src/services/payment/depositAdapters/meidDepositAdapter.js

The adapter must expose:

async function createPayment(params) {
// params: { transaction, user, amount, currency, paymentMethod, description }
}

module.exports = {
createPayment
};

The normalized adapter response must match the existing adapter contract:

{
success: true,
transactionId: 'MEID_PROVIDER_TRANSACTION_ID',
paymentUrl: 'https://meid.example/checkout/...',
invoiceId: 'MEID_INVOICE_ID',
paymentAddress: null,
endTime: null,
expiryTime: null,
requestData: {},
data: {}
}

Required contract:

FieldRequirement
successtrue only when MEID order creation succeeds
transactionIdProvider-facing transaction ID or current internal transaction ID
paymentUrlRequired when success = true, unless MEID returns non-URL payment details and frontend supports that
invoiceIdMEID order / invoice ID if available
requestDataExact outbound provider request, for admin/debug
dataRaw provider response

4. Register MEID Adapter​

Update:

kioskgaming_backend/src/services/payment/depositAdapters/index.js

Add:

const meidDepositAdapter = require('./meidDepositAdapter');

Add it to ADAPTERS:

const ADAPTERS = {
btcpay: btcPayDepositAdapter,
linkmepay: linkMePayDepositAdapter,
zeroxprocessing: zeroxProcessingDepositAdapter,
meid: meidDepositAdapter
};

Also export it if needed for tests:

meidDepositAdapter

5. Add MEID Provider Service​

Recommended structure:

kioskgaming_backend/src/services/payment/meid/
β”œβ”€β”€ config.js
β”œβ”€β”€ helpers.js
└── meidService.js

Expected responsibilities:

FileResponsibility
config.jsBase URL, endpoint paths, timeout, credentials from env
helpers.jsSignature generation / verification, payload normalization
meidService.jsCreate payment, verify callback, query transaction if supported

Environment variables should be explicit:

MEID_BASE_URL=
MEID_MERCHANT_ID=
MEID_PUBLIC_KEY=
MEID_PRIVATE_KEY=
MEID_CALLBACK_SECRET=
MEID_SANDBOX=true

Adjust names to match MEID's real API contract.


Callback / Webhook Flow​

Add MEID public callback routes in:

kioskgaming_backend/src/routes/payment.js

Example:

router.post('/meid/webhook', paymentUserController.handleMEIDWebhook.bind(paymentUserController));
router.post('/meid/ipn/:transaction_id', paymentUserController.handleMEIDCallback.bind(paymentUserController));

Choose the route shape based on MEID's actual webhook contract:

MEID callback styleRecommended route
Provider sends transaction ID in path/api/payment/meid/ipn/:transaction_id
Provider sends transaction ID in body/api/payment/meid/webhook

In paymentUserController, add a handler that:

  1. Verifies MEID signature.
  2. Normalizes provider payload.
  3. Finds PaymentTransaction by internal transaction ID, provider transaction ID, or invoice ID.
  4. Saves callback log / raw provider response.
  5. Delegates settlement to the existing deposit callback / settlement service.
  6. Returns the response format MEID expects.

Player Deposit Flow​

Player selects MEID on deposit screen
β”‚
β–Ό
Frontend submits:
POST /api/payment/deposit
{
"amount": 50,
"provider": "meid"
}
β”‚
β–Ό
Backend creates PaymentTransaction
provider = 'meid'
paymentMethod = null or MEID sub-method
status = 'pending'
β”‚
β–Ό
MEID adapter creates provider payment order
β”‚
β–Ό
MEID returns payment URL / payment details
β”‚
β–Ό
User completes payment
β”‚
β–Ό
MEID callback hits backend
β”‚
β–Ό
Existing settlement flow credits player wallet or game wallet

Example request:

POST /api/payment/deposit
Authorization: Bearer USER_TOKEN
Content-Type: application/json

{
"amount": 50,
"provider": "meid",
"description": "Player deposit via MEID"
}

Expected response:

{
"success": true,
"data": {
"transactionId": "MEID_OR_INTERNAL_TRANSACTION_ID",
"paymentUrl": "https://...",
"amount": 50,
"currency": "USD",
"status": "pending",
"syncStatus": "none"
}
}

Supported Methods Endpoint​

Update:

kioskgaming_backend/src/services/biz/paymentMethodCatalogBizService.js

For provider meid, return supported methods or a single default method.

Example:

GET /api/payment/supported-methods?provider=meid&operation=deposit

Expected shape:

{
"methods": [
{
"id": "meid",
"methodId": "meid",
"name": "MEID",
"currency": "USD",
"min": 10,
"max": 1000,
"comingSoon": false,
"sortOrder": 0
}
]
}

If MEID has multiple rails or channels, expose them as sub-methods:

{
"methods": [
{
"id": "meid_default",
"methodId": "meid_default",
"name": "MEID",
"currency": "USD"
}
]
}

Fee Configuration​

The code resolves deposit fee snapshots through:

resolveProviderFeeRate({
provider,
operation: 'deposit',
methodId: paymentMethod || 'all'
})

Add fee config rows for MEID:

provideroperationmethod_idfee_rate
meiddepositallProduct-defined
meiddepositmeidOptional method-specific override

If MEID supports withdrawal later:

provideroperationmethod_idfee_rate
meidwithdrawalallProduct-defined

Transaction Data Requirements​

For every MEID deposit transaction:

FieldExpected value
typedeposit
providermeid
paymentMethodmeid, MEID sub-method, or null
currencyUSD unless MEID requires another currency
status at creationpending
paymentUrlPresent after MEID order creation if MEID uses hosted checkout
externalTransactionIdMEID order / invoice ID if available
providerRequestRaw outbound MEID create-payment request
paymentResultNormalized adapter result plus raw MEID response

Error Cases​

CaseExpected behavior
provider = 'meid' not added to validationAPI returns 422 before reaching service
provider = 'meid' not added to adapter registryService throws unsupported provider
MEID create-payment API failsTransaction is marked failed; request and response are saved
MEID returns success without checkout detailsAdapter should return failure unless frontend supports the returned payment details
MEID callback signature invalidReject callback and do not settle transaction
MEID callback references unknown transactionLog callback; return provider-safe error response
Duplicate MEID callbackExisting idempotency guards should prevent double credit

Test Cases​

#CaseStepsExpected result
1Player MEID deposit passes validationPOST /api/payment/deposit with provider='meid'Request reaches service; no provider validation error
2MEID adapter is selectedMock meidDepositAdapter.createPayment()Adapter called once with transaction, user, amount, currency
3MEID creates payment successfullyMock MEID success responseHTTP 200; transaction has provider='meid', status='pending', paymentUrl saved
4MEID create-payment failure is persistedMock MEID API errorTransaction status becomes failed; providerRequest / paymentResult saved
5MEID callback settles wallet-only depositSimulate successful MEID webhookTransaction moves to completed; player wallet credited once
6Duplicate MEID callback is idempotentSend same successful webhook twiceNo double wallet credit
7Invalid MEID callback signature is rejectedSend webhook with bad signatureTransaction remains unchanged
8Supported methods includes MEIDGET /api/payment/supported-methods?provider=meid&operation=depositResponse includes method meid
9Fee snapshot resolves for MEIDCreate MEID deposit with fee configplatformFeeRate and platformFeeAmount saved on transaction

Implementation Checklist​

  • Confirm MEID API documentation: create payment endpoint, callback format, signature rules, status values, and required response body.
  • Add MEID env vars and config.
  • Implement meidService.
  • Implement meidDepositAdapter.
  • Register meid in deposit adapter registry.
  • Add meid to deposit provider validation.
  • Add meid to depositService provider guard.
  • Add MEID callback route and controller handler.
  • Normalize MEID callback statuses to existing transaction statuses.
  • Add MEID to supported-methods response.
  • Add MEID provider fee config rows.
  • Add integration tests for player deposit, callback settlement, and duplicate callback.
  • Confirm frontend sends provider = 'meid'.

Open Questions​

QuestionOwner
What are MEID's create-payment endpoint, request fields, and success response shape?Payment / MEID
Does MEID return a hosted paymentUrl, QR/payment address, or both?Payment / MEID
What signature algorithm does MEID use for requests and callbacks?Payment / MEID
What callback statuses map to pending, processing, completed, failed, cancelled, and expired?Payment / MEID
Does MEID support only deposits, or deposits and withdrawals?Product / Payment
What are MEID min/max amount limits and fee rates?Product / Payment