Avistadocs
集成指南

MED 集成

概览

本指南展示如何将 MED 流程集成到您的应用中。您将了解如何:

  1. 配置 webhook 以接收 MED 通知
  2. 查询账户中的 MED 列表
  3. 处理各类事件(创建、批准、拒绝)

开始之前,请先阅读 MED 概览 以了解涉及的生命周期和概念。

1. 配置 MED webhook

为您希望接收的每种 MED 事件类型配置一个端点。使用 POST /api/webhooks:

针对您账户接收到新 MED 的通知。

curl -X POST https://api.avista.global/api/webhooks \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.yourcompany.com/webhooks/med-created",
    "eventType": "med_created",
    "headers": [
      { "key": "Authorization", "value": "Bearer your-secret-token" }
    ]
  }'

MED 已批准的通知(退款被接受 — 金额将退还给付款人)。

curl -X POST https://api.avista.global/api/webhooks \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.yourcompany.com/webhooks/med-accepted",
    "eventType": "med_accepted"
  }'

MED 被拒绝的通知(退款被驳回 — 余额保留在受益人处)。

curl -X POST https://api.avista.global/api/webhooks \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.yourcompany.com/webhooks/med-rejected",
    "eventType": "med_rejected"
  }'

我们建议配置全部三种 webhook 类型(med_createdmed_acceptedmed_rejected),以便全面掌握 MED 生命周期。

2. 查询 MED

使用 GET /api/med 列出账户中的 MED,并支持筛选和分页。

列出所有 MED

curl -X GET "https://api.avista.global/api/med" \
  -H "Authorization: Bearer $TOKEN"

按状态筛选

curl -X GET "https://api.avista.global/api/med?status=RECEIVED" \
  -H "Authorization: Bearer $TOKEN"

按时间段筛选

curl -X GET "https://api.avista.global/api/med?startDate=2026-01-01T00:00:00.000Z&endDate=2026-01-31T23:59:59.999Z&page=1&pageSize=50" \
  -H "Authorization: Bearer $TOKEN"

响应示例

{
  "data": [
    {
      "id": 42,
      "endToEnd": "E12345678202604101030abcdef123456",
      "status": "RECEIVED",
      "reason": "REFUND_REQUEST",
      "cause": "UNAUTHORIZED_TRANSACTION",
      "description": "Customer claims not to have performed the transaction",
      "analysisResult": null,
      "analysisDetails": null,
      "requestingBank": {
        "ispb": "00000000",
        "name": "BCO DO BRASIL S.A."
      },
      "contestedBank": {
        "ispb": "13140088",
        "name": "ACESSO SOLUÇÕES DE PAGAMENTO"
      },
      "originalTransaction": {
        "amount": 1500.00,
        "type": "PIX",
        "transactionType": "CASH_IN",
        "name": "João da Silva",
        "document": "***456789**",
        "dateTime": "2026-04-05T14:30:00.000Z"
      },
      "isReconciled": true,
      "originalTransactionId": 78432,
      "createdAt": "2026-04-10T10:00:00.000Z",
      "updatedAt": "2026-04-10T10:00:00.000Z"
    }
  ],
  "metadata": {
    "total": 1,
    "page": 1,
    "pageSize": 20,
    "totalPages": 1
  }
}

isReconciled 字段表示该 MED 是否已自动关联到您账户中的本地交易。当其为 true 时,originalTransactionId 中包含原始 PIX 交易的 ID。

3. 处理 MED webhook

Node.js 处理示例

import express from 'express';
const app = express();
app.use(express.json());

app.post('/webhooks/med', async (req, res) => {
  const { event, medId, status, cause, originalTransaction } = req.body;

  console.log(`MED ${medId}: ${event} (status: ${status})`);

  switch (event) {
    case 'MedCreated':
      // New MED received — notify team and/or block beneficiary operations
      await notifyTeam({
        message: `MED #${medId} received — cause: ${cause}`,
        amount: originalTransaction?.amount,
        endToEndId: originalTransaction?.endToEndId,
      });
      break;

    case 'MedAccepted':
      // Refund approved — amount will be returned to payer
      await updateTransaction({
        medId,
        status: 'REFUNDED',
        note: 'MED approved — amount returned to original payer',
      });
      break;

    case 'MedRejected':
      // Refund rejected — balance remains with beneficiary
      await updateTransaction({
        medId,
        status: 'KEPT',
        note: 'MED rejected — balance unblocked',
      });
      break;
  }

  // Always return 200 to confirm receipt
  res.status(200).json({ received: true });
});

Python 处理示例

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhooks/med', methods=['POST'])
def handle_med_webhook():
    data = request.json
    event = data.get('event')
    med_id = data.get('medId')
    cause = data.get('cause')

    print(f"MED {med_id}: {event} (cause: {cause})")

    if event == 'MedCreated':
        # New MED — alert team
        notify_team(med_id, cause, data.get('originalTransaction'))

    elif event == 'MedAccepted':
        # Refund approved
        update_transaction(med_id, 'REFUNDED')

    elif event == 'MedRejected':
        # Refund rejected
        update_transaction(med_id, 'KEPT')

    return jsonify({'received': True}), 200

4. 推荐流程

┌─────────────────────────────────────────────────────────────┐
│                   YOUR APPLICATION                           │
│                                                              │
│  MedCreated webhook ──────▶ Alert risk team                 │
│       │                     Mark transaction as "under MED" │
│       │                     (Optional) Block beneficiary    │
│       │                                                      │
│       ▼                                                      │
│  Query GET /api/med ──────▶ Check details and cause         │
│       │                     Track status                     │
│       │                                                      │
│       ▼                                                      │
│  MedAccepted webhook ─────▶ Record refund                   │
│       OR                    Update customer balance          │
│  MedRejected webhook ─────▶ Unblock beneficiary             │
│                              Keep balance                    │
└─────────────────────────────────────────────────────────────┘

最佳实践

配置全部 3 个 webhook

始终配置 med_createdmed_acceptedmed_rejected,以便全面跟踪生命周期。

快速返回 200

以异步方式处理 webhook。如果处理程序超过 5 秒,系统将重新投递。

使用幂等性

使用 medId 作为幂等键。同一个 webhook 在失败时可能被重新投递。

监控未处理的 MED

定期查询 GET /api/med?status=RECEIVED,确保没有遗漏任何 MED。

后续步骤

本页目录