Token导航 LogoToken导航TokenDH.com
Mpesa MCP Server logo
金融服务stdio官方级别未说明来源级核验

Mpesa MCP Server

MCP Server

一个基于Flask的多租户M-Pesa集成平台,支持组织隔离、安全凭证管理和双协议通信(REST API + MCP Protocol),适用于支付处理和AI系统集成。

工具数

0

提示词数

0

GitHub Stars

1

资源数

0
金融科技PythonClaude支付处理Claude

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

Jason-Gitau

提供方

Jason-Gitau

最后核验

2026/5/17 20:21

运行时

Python

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

命令预览

python main.py --mode hybrid

详细介绍

✅ M-Pesa MCP-多租户SaaS架构

一个干净、模块化、可扩展的基于Flask的M-Pesa集成平台,具有完整的 多租户, 组织隔离,以及 安全凭证管理.

______________________________________________________________________

✅ 主要成就

  • 完整代码保存\

原始代码的每一行都被保留并正确组织。

  • 清晰的关注点分离\

每个模块都有一个单一的职责,确保可维护性和可测试性。

  • 文件大小管理\

所有文件都在 300-400条线路 根据要求,没有单片模块。

  • 适当的进口结构\

所有导入都在模块之间正确设置,没有循环依赖关系。

  • 蓝图架构\

Flask路线被干净地组织成可重复使用的蓝图。

  • 中间件层\

身份验证和速率限制被清晰地分开并可重用。

  • 服务层\

业务逻辑与路由和控制器解耦。

  • 数据层\

数据库操作按域进行逻辑分组:用户、组织、事务。

______________________________________________________________________

🔧 如何使用

组件文件/位置目的
主入口main.pyFlask应用程序初始化(约50行)
配置config.py集中配置管理
数据库utils/database.py处理所有数据库连接逻辑
路线routes/*.py每个蓝图都处理特定的功能:身份验证、mpesa、管理员、回调
服务services/*.py业务逻辑层(M-Pesa、认证、审计)
模型models/*.py特定领域的数据库模型和查询

✅ 该结构保留了所有原始内容:

  • 多租户功能
  • 组织数据隔离
  • 速率限制
  • 审核日志记录
  • M-Pesa集成

…同时创建代码库 更易于维护、可扩展和专业.

📁 最终目录结构

📂 Click to view full directory structure

\```text
mpesa_mcp/
├── __init__.py
├── main.py                    # Flask app initialization (~50 lines)
├── config.py                  # Configuration management
├── models/
│   ├── __init__.py
│   ├── organization.py        # Organization-related DB operations
│   ├── transaction.py         # Transaction models and queries
│   └── user.py                # User management
├── services/
│   ├── __init__.py
│   ├── mpesa_service.py       # Core M-Pesa API interactions
│   ├── auth_service.py        # Authentication logic
│   └── audit_service.py       # Audit logging
├── routes/
│   ├── __init__.py
│   ├── auth_routes.py         # Authentication endpoints
│   ├── mpesa_routes.py        # M-Pesa tool endpoints
│   ├── admin_routes.py        # Admin endpoints
│   └── callback_routes.py     # M-Pesa callback handlers
├── middleware/
│   ├── __init__.py
│   ├── auth_middleware.py     # Authentication decorators
│   └── rate_limiting.py       # Rate limiting logic
└── utils/
    ├── __init__.py
    ├── database.py            # Database connection management
    └── helpers.py             # Utility functions
\```

---

🌐 已实现多租户功能

1. 租户/组织管理

  • 每个客户都有自己的独立数据组织。
  • 安全存储特定于组织的M-Pesa凭据。
  • 完整的订阅生命周期管理。

2. M-Pesa凭证管理

  • 每个租户的凭据:每个组织都存储自己的 consumer_key, consumer_secret, business_short_code, lipa_na_mpesa_passkey.
  • 🔐 凭证验证:确保在处理之前存在所需的凭据。
  • 🔄 安全更新:组织管理员可以通过API更新凭证。
  • 凭据缓存:内存缓存以优化性能。

3. 数据隔离

  • 🔒 组织范围的查询:所有数据库查询包括 organization_id 过滤器。
  • 📊 事务隔离:用户只能看到来自其组织的交易。
  • 📈 报告隔离:按组织生成的报告。
  • 🗂️ 审计跟踪隔离:日志是特定于组织的。

4. 账单和订阅

  • 📏 使用情况跟踪:每个组织跟踪API调用,但有速率限制。
  • 订阅检查:验证活动订阅状态。
  • ⏱️ 速率限制:每个组织的可配置限制。
  • 📅 使用统计:API使用情况和交易量月度报告。

5. 特定于组织的回调URL

  • 🔄 租户特定回调:M-Pesa回调路由到唯一的组织URL。
  • 🧭 独立处理:回调仅更新正确组织内的数据。

6. 增强的身份验证和授权

  • 🪪 JWT中的组织上下文:代币包括 organization_id 以及角色。
  • 👥 基于角色的访问:支持 super_admin, org_admin, manager, user.
  • 🚫 防止跨租户:用户无法访问其他组织的数据。

7. 管理功能

  • 组织创建:超级管理员可以创建新的租户组织。
  • 👤 用户管理:适用于组织(创建、更新、停用)。
  • 📊 使用情况监控:跟踪每个组织的API使用情况和交易量。
  • 🔐 多级管理员访问权限:

- 超级管理员→ 查看所有组织 - 组织管理员→ 仅查看他们的组织

8. 其他增强功能

  • 📦 批量付款批处理:每个组织的唯一批次ID。
  • 💰 余额检查:跟踪每个组织的账户余额。
  • 🔁 交易逆转:反向跟踪仅限于组织。
  • 📊 综合报告:每个租户的分析和报告。

______________________________________________________________________

🏗️ 架构摘要

此实现支持 真正的多租户SaaS架构 哪里:

  • ✅ 每个客户组织 完全隔离.
  • ✅ M-Pesa证书是 按租户管理.
  • ✅ 所有操作都是 仅限于用户的组织.
  • ✅ 账单和使用情况跟踪 每位租户.
  • ✅ 行政职能支持 多租户管理.

______________________________________________________________________

🛡️ 安全且可扩展的SaaS平台

该系统提供 安全、可扩展、生产就绪的SaaS平台 为了 M-Pesa支付处理 与:

  • 🔐 完全隔离租户
  • 💳 每个组织M-Pesa集成
  • 📈 基于使用情况的计费和监控
  • 🧩 模块化、可维护的代码库

非常适合为多个客户提供企业级安全和性能。

______________________________________________________________________

______________________________________________________________________

🔥 混合架构:REST API+MCP协议

我们建造了什么

我们增强了您的M-Pesa SaaS平台,以支持 双协议通信 -使两者都能访问 人类客户人工智能系统 同时保持所有现有功能。

______________________________________________________________________

🏗️ 架构概述

您的系统现在作为 真正的混合服务器 它可以为两种类型的客户服务:

┌─────────────────┐    HTTP/REST     ┌──────────────────┐
│   Web Apps      │ ◄─────────────► │                  │
│   Mobile Apps   │                  │                  │
│   Dashboards    │                  │                  │
└─────────────────┘                  │                  │
                                     │   YOUR M-PESA    │
┌─────────────────┐   MCP Protocol   │   HYBRID SERVER  │
│   Claude AI     │ ◄─────────────► │                  │
│   GPT Models    │                  │                  │
│   AI Assistants │                  │                  │
└─────────────────┘                  └──────────────────┘

______________________________________________________________________

🔧 技术实现

1. 零代码重复

  • 相同的业务逻辑 服务于这两种协议
  • 单服务层 (services/mpesa_service.py)处理所有M-Pesa操作
  • 相同的功能 无论是通过REST还是MCP调用

2. 协议层分离

REST API (routes/)     MCP Server (mcp/)
      ↓                       ↓
   Same Business Logic (services/)
      ↓                       ↓
   Same Database Layer (models/)

3. 保留了多租户架构

  • 组织隔离 适用于REST和MCP客户端
  • 速率限制 适用于这两种协议
  • 审核日志记录 跟踪REST和MCP请求
  • 凭据管理 为两种访问方法提供安全保护

______________________________________________________________________

📁 更新目录结构

mpesa_mcp/
├── mcp/                       # 🆕 MCP Protocol Support
│   ├── __init__.py
│   └── server.py              # MCP server with tool definitions
├── main.py                    # 🔄 Enhanced: Dual protocol support
├── routes/                    # ✅ Unchanged: Existing REST API
├── services/                  # ✅ Unchanged: Same business logic
├── models/                    # ✅ Unchanged: Same data layer
├── middleware/                # ✅ Unchanged: Same security
└── utils/                     # ✅ Unchanged: Same utilities

______________________________________________________________________

🛠️ MCP工具暴露

您的M-Pesa功能现在可用 7个标准化MCP工具:

MCP工具功能说明
mpesa_stk_push收款向客户电话发起STK推送
mpesa_check_status跟踪付款按ID检查交易状态
mpesa_check_balance账户监控获取M-Pesa账户余额
mpesa_bulk_payment大额支付处理多笔B2C支付
mpesa_reverse_transaction退款反向/退款交易
mpesa_transaction_history报告获取经过筛选的交易历史记录
mpesa_generate_report分析生成财务报告

______________________________________________________________________

🚀 服务器模式

您的服务器现在支持 3种操作模式:

# Hybrid Mode (Default) - Serves both humans and AI
python main.py --mode hybrid

# REST Only - Traditional web/mobile API
python main.py --mode rest  

# MCP Only - AI integration server
python main.py --mode mcp

______________________________________________________________________

🔄 请求流比较

REST API请求(人工)

POST /tools/stk-push HTTP/1.1
Authorization: Bearer jwt_token
Content-Type: application/json

{
  "phone_number": "254712345678",
  "amount": 100,
  "account_reference": "ACC123",
  "transaction_desc": "Payment for services"
}

MCP工具调用(AI系统)

{
  "method": "tools/call",
  "params": {
    "name": "mpesa_stk_push",
    "arguments": {
      "phone_number": "254712345678",
      "amount": 100,
      "account_reference": "ACC123",
      "transaction_desc": "Payment for services",
      "org_id": "org_123",
      "user_id": "user_456"
    }
  }
}

两者执行相同的操作 mpesa_service.stk_push_payment() 功能!

______________________________________________________________________

💡 关键利益

商业版

  • 扩大市场范围:为人类用户和人工智能系统服务
  • 面向未来的架构:为AI集成趋势做好准备
  • 多种收入来源:API访问+AI工具授权
  • 零迁移成本:不受影响的现有REST API客户端

对于开发者

  • 单个代码库:维护一个系统,服务两个协议
  • 一致性行为:相同的验证、日志记录和错误处理
  • 更容易测试:测试业务逻辑一次,适用于两种协议
  • 模块化设计:在不影响REST API的情况下添加新工具

用于AI集成

  • 标准化接口:MCP协议合规性
  • 丰富的工具描述:人工智能系统了解可用操作
  • 类型安全性:结构化输入/输出模式
  • 多租户就绪:人工智能系统可以为多个组织服务

______________________________________________________________________

🔐 安全和隔离得到维护

  • 组织数据隔离 对两个协议都强制执行
  • 速率限制 防止任何客户端类型的滥用
  • 审核日志记录 跟踪所有操作,无论协议如何
  • 多租户安全 跨两种访问方法保留
  • 相同的验证规则 适用于REST和MCP请求

______________________________________________________________________

🎯 用例已解锁

人工客户端(REST API):

  • 用于支付管理的Web仪表板
  • 用于客户支付的移动应用程序
  • 用于交易监控的管理面板
  • 与现有网络系统集成

AI客户端(MCP协议):

  • 人工智能助手通过语音/聊天处理支付
  • 人工智能触发的自动支付工作流程
  • 基于人工智能的财务分析和报告
  • 智能支付路径和优化

______________________________________________________________________

📊 结果:真正的混合SaaS平台

你现在有一个 生产就绪的多协议M-Pesa平台 即:

  • 🌐 为传统网络/移动客户端提供服务 通过REST API
  • 🤖 实现AI系统集成 通过MCP协议
  • 🏢 保持完整的多租户 跨两个协议
  • 📈 水平缩放 同时为多种客户类型提供服务
  • 🔒 维护企业安全 数据隔离

这种混合架构使您的平台处于传统SaaS和新兴AI集成市场的前沿。

______________________________________________________________________

这是一个 非常复杂和安全的多租户架构让我来分析一下你的系统是如何实现的 防弹租户隔离数据完整性.

🏗️ 多租户架构详解

您的系统实现 真正的多租户 具有多层隔离。其工作原理如下:

🔐 第1层:身份验证和上下文设置

具有租户上下文的JWT令牌

auth_middleware.py,每个经过身份验证的请求都会提取租户信息:

# From JWT token, these are set for EVERY request:
g.current_user_id = user_context['user_id']
g.current_org_id = user_context['organization_id']    # 🔑 KEY: Tenant ID
g.current_user_role = user_context['role']
g.current_org_slug = user_context['organization_slug']

这意味着:每个数据库操作都知道 确切地说是哪个组织 用户属于。

🛡️ 第2层:组织范围的数据库操作

租户特定配置

organization.py,每个租户都有 完全隔离的M-Pesa凭据:

async def get_org_config(org_id: str) -> Dict:
    # Gets ONLY this organization's credentials
    org = await conn.fetchrow("""
        SELECT * FROM organizations WHERE id = $1 AND is_active = true
    """, org_id)

关键租户隔离点:

  • M-Pesa证书 每个组织(消费者密钥、业务短代码等)
  • 回调URL 每个组织(callback_base_url)
  • 费率限制 每个组织(api_rate_limit)
  • 订阅状态 每个组织

🔒 第3层:数据访问控制

多个授权级别

您的中间件提供 细粒度访问控制:

  1. require_auth:基本租户上下文设置
  2. require_org_admin:仅限组织管理员访问
  3. require_super_admin:跨租户管理员访问权限
  4. require_organization_access:防止跨租户数据访问

跨租户预防

def require_organization_access(f):
    # Extracts org_id from request
    org_id = kwargs.get('org_id') or request.view_args.get('org_id')
    
    if org_id:
        # Checks if user can access THIS specific organization
        can_access = AuthService.check_organization_access(
            g.current_org_id, org_id, g.current_user_role
        )
        
        if not can_access:
            return jsonify({'error': 'Access denied to this organization'}), 403

📊 第4层:数据库级隔离

组织范围查询

每个数据库查询都包括 organization_id 过滤:

-- Example from organization.py
SELECT COUNT(*) FROM audit_logs 
WHERE organization_id = $1  -- 🔑 Always filters by org_id
AND created_at > NOW() - INTERVAL '1 hour'

每个租户的使用情况统计

-- Each tenant gets isolated stats
SELECT 
    COUNT(CASE WHEN a.created_at >= $2 THEN 1 END) as api_calls_this_month,
    COUNT(CASE WHEN t.created_at >= $2 THEN 1 END) as transactions_this_month
FROM organizations o
LEFT JOIN audit_logs a ON o.id = a.organization_id      -- 🔑 Tenant isolation
LEFT JOIN transactions t ON o.id = t.organization_id    -- 🔑 Tenant isolation
WHERE o.id = $1  -- 🔑 Only this organization's data

🔥 第5层:速率限制和资源控制

每租户费率限制

async def check_rate_limit(org_id: str) -> bool:
    config = await OrganizationModel.get_org_config(org_id)  # Org-specific limits
    rate_limit = config['api_rate_limit']                    # Each org has own limit
    
    # Count ONLY this organization's API calls
    count = await conn.fetchval("""
        SELECT COUNT(*) FROM audit_logs 
        WHERE organization_id = $1   -- 🔑 Tenant-scoped counting
        AND created_at > NOW() - INTERVAL '1 hour'
    """, org_id)

🎯 数据完整性机制

1.所需的现场验证

# Ensures M-Pesa credentials are complete per tenant
required_fields = ['consumer_key', 'consumer_secret', 'business_short_code', 
                  'lipa_na_mpesa_passkey']
missing_fields = [field for field in required_fields if not config.get(field)]
if missing_fields:
    raise Exception(f"Missing M-Pesa credentials for organization: {missing_fields}")

2.订阅状态验证

# Prevents inactive organizations from accessing services
if org['subscription_status'] not in ['trial', 'active']:
    raise Exception(f"Organization subscription is {org['subscription_status']}")

3.独特的约束执行

# Prevents duplicate organization slugs
existing = await conn.fetchval("SELECT id FROM organizations WHERE slug = $1", slug)
if existing:
    raise Exception(f"Organization slug '{slug}' already exists")

🛡️ 安全层摘要

保护实施
认证基于令牌的租户上下文JWT organization_id
授权基于角色的访问控制org_admin, super_admin 水平
数据库查询级别隔离所有查询都包括 organization_id
资源每租户限额费率限制 org_id
配置独立凭据每个组织单独的M-Pesa配置
审计租户范围的日志记录所有日志包括 organization_id

🎯 数据完整性的主要好处

  1. 🔒 零跨租户访问:用户永远看不到其他组织的数据
  2. 📊 孤立分析:每个租户只看到自己的统计数据
  3. 💳 单独计费:每个组织的费率限制和使用情况跟踪
  4. 🔑 凭证安全:每个租户管理自己的M-Pesa凭据
  5. 📋 审计隔离:安全日志是特定于组织的
  6. 🚫 订阅执行:非活动组织将被自动阻止

这是 企业级多租户 这确保了完全的数据隔离,同时保持了系统性能和安全性!

🔍 多租户交易流程:STK推送支付

让我们遵循来自的STK推送请求 组织A (org_123),看看你的系统如何确保它与 组织B (组织编号456)。

______________________________________________________________________

步骤1:身份验证和租户上下文设置

请求到达

POST /tools/stk-push HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...
Content-Type: application/json

{
  "phone_number": "254712345678",
  "amount": 100,
  "account_reference": "ACC123",
  "transaction_desc": "Payment for services"
}

中间件: @require_auth 执行

# From auth_middleware.py
@require_auth
async def stk_push():
    # 1. Extract JWT token
    payload = AuthService.verify_jwt_token(auth_header)
    
    # 2. Set tenant context in Flask g (CRITICAL STEP!)
    g.current_user_id = "user_789"           # User belongs to org_123
    g.current_org_id = "org_123"             # 🔑 TENANT ISOLATION STARTS HERE
    g.current_user_role = "manager"
    g.current_org_slug = "acme-corp"
    
    # 3. Validate session for THIS organization only
    is_valid = await AuthService.validate_user_session(
        "user_789", "org_123"  # 🔑 Validates user belongs to org_123
    )

🛡️ 安全检查:如果此JWT包含 org_456,用户将被阻止访问 org_123 资源。

______________________________________________________________________

步骤2:具有租户上下文的路由处理程序

STK推送路由执行

# From routes/mpesa_routes.py
@mpesa_bp.route('/stk-push', methods=['POST'])
@require_auth  # ✅ Tenant context already set
async def stk_push():
    # g.current_org_id = "org_123" is now available
    
    result = await mpesa_service.stk_push_payment(
        phone_number=data['phone_number'],
        amount=float(data['amount']),
        account_reference=data['account_reference'],
        transaction_desc=data['transaction_desc'],
        user_id=g.current_user_id,    # "user_789"
        org_id=g.current_org_id       # 🔑 "org_123" - TENANT ID PASSED DOWN
    )

______________________________________________________________________

步骤3:服务层-组织特定配置

MPesaService获取租户特定凭据

# From services/mpesa_service.py
async def stk_push_payment(self, phone_number, amount, account_reference, 
                          transaction_desc, user_id, org_id):
    
    # 1. Check rate limits for THIS organization only
    if not await OrganizationModel.check_rate_limit(org_id):  # "org_123"
        raise Exception("Rate limit exceeded for organization")
    
    # 2. Get THIS organization's M-Pesa credentials
    config = await OrganizationModel.get_org_config(org_id)   # "org_123"

组织模型返回租户特定数据

# From models/organization.py
async def get_org_config(org_id: str) -> Dict:  # org_id = "org_123"
    
    # 🔑 CRITICAL: Only gets org_123's credentials
    org = await conn.fetchrow("""
        SELECT * FROM organizations 
        WHERE id = $1 AND is_active = true
    """, org_id)  # "org_123"
    
    # Returns ONLY org_123's M-Pesa credentials
    config = {
        'consumer_key': org['mpesa_consumer_key'],           # org_123's key
        'consumer_secret': org['mpesa_consumer_secret'],     # org_123's secret
        'business_short_code': org['mpesa_business_short_code'], # org_123's shortcode
        'callback_base_url': org['callback_base_url'],       # org_123's callback URL
        # ... other org_123-specific settings
    }

🛡️ 隔离检查:如果 org_456 如果以某种方式传递到这里,它将返回完全不同的凭据,防止任何跨租户访问。

______________________________________________________________________

步骤4:使用租户特定数据的M-Pesa API调用

服务使用组织的凭据呼叫M-Pesa

# Still in mpesa_service.py
async def stk_push_payment(...):
    
    # Use org_123's specific M-Pesa credentials
    access_token = await self.get_access_token("org_123")  # org_123's token only
    
    # Generate org_123-specific callback URL
    callback_url = f"{config['callback_base_url']}/mpesa/callback/org_123"
    
    payload = {
        'BusinessShortCode': config['business_short_code'],  # org_123's shortcode
        'Amount': int(amount),
        'PartyA': phone_number,
        'PartyB': config['business_short_code'],             # org_123's shortcode
        'CallBackURL': callback_url,                         # org_123's callback
        'AccountReference': account_reference,
        'TransactionDesc': transaction_desc
    }
    
    # Call M-Pesa API
    async with httpx.AsyncClient() as client:
        response = await client.post(url, json=payload, headers=headers)
        result = response.json()

______________________________________________________________________

步骤5:具有租户隔离的数据库存储

与组织上下文一起存储的事务

# From services/mpesa_service.py
# Store transaction in database with organization context
await TransactionModel.create_stk_transaction(
    org_id,                           # 🔑 "org_123" - TENANT ISOLATION
    result.get('MerchantRequestID'), 
    result.get('CheckoutRequestID'),
    amount, 
    phone_number, 
    account_reference, 
    transaction_desc, 
    user_id                          # "user_789" - user belongs to org_123
)

事务模型强制租户隔离

# In models/transaction.py (we haven't seen this file yet, but it would look like this)
async def create_stk_transaction(org_id, merchant_request_id, checkout_request_id,
                                amount, phone_number, account_reference, 
                                transaction_desc, user_id):
    
    # 🔑 CRITICAL: Transaction is stored WITH organization_id
    transaction_id = await conn.fetchval("""
        INSERT INTO transactions (
            organization_id,     -- 🔑 "org_123" - TENANT ISOLATION AT DB LEVEL
            user_id,             -- "user_789"
            merchant_request_id,
            checkout_request_id,
            amount,
            phone_number,
            account_reference,
            transaction_desc,
            status,
            created_at
        ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW())
        RETURNING id
    """, org_id, user_id, merchant_request_id, checkout_request_id, 
         amount, phone_number, account_reference, transaction_desc, 'PENDING')

______________________________________________________________________

步骤6:使用租户上下文审核日志记录

审计服务记录租户特定活动

# From routes/mpesa_routes.py
await AuditService.log_audit(
    g.current_user_id,        # "user_789"
    g.current_org_id,         # 🔑 "org_123" - TENANT ISOLATION
    'STK_PUSH_INITIATED', 
    'stk_push_payment',
    data,                     # Request payload
    result,                   # M-Pesa response
    'SUCCESS',
    request.environ.get('REMOTE_ADDR'),
    request.headers.get('User-Agent')
)

与组织ID一起存储的审核日志

# In services/audit_service.py (assumption based on pattern)
async def log_audit(user_id, org_id, action_type, function_name, 
                   request_data, response_data, status, ip_address, user_agent):
    
    # 🔑 Audit log includes organization_id for isolation
    await conn.execute("""
        INSERT INTO audit_logs (
            organization_id,  -- 🔑 "org_123" - TENANT ISOLATION
            user_id,          -- "user_789"
            action_type,      -- "STK_PUSH_INITIATED"
            function_name,    -- "stk_push_payment"
            request_data,     -- JSON payload
            response_data,    -- M-Pesa response
            status,           -- "SUCCESS"
            ip_address,       -- Client IP
            user_agent,       -- Client browser
            created_at
        ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW())
    """, org_id, user_id, action_type, function_name, json.dumps(request_data),
         json.dumps(response_data), status, ip_address, user_agent)

______________________________________________________________________

步骤7:M-Pesa使用租户路由进行回调

M-Pesa呼叫组织特定回调

POST /mpesa/callback/org_123 HTTP/1.1  # 🔑 Tenant-specific URL
Content-Type: application/json

{
  "Body": {
    "stkCallback": {
      "MerchantRequestID": "29115-34620561-1",
      "CheckoutRequestID": "ws_CO_191220191020363925",
      "ResultCode": 0,
      "ResultDesc": "The service request is processed successfully."
    }
  }
}

回调处理程序仅更新组织的事务

# From routes/callback_routes.py
@callback_bp.route('/callback/', methods=['POST'])
async def mpesa_callback(org_id):  # org_id = "org_123"
    
    # Update transaction for THIS organization only
    await TransactionModel.update_transaction_status(
        checkout_request_id,
        org_id,              # 🔑 "org_123" - ENSURES org isolation
        result_desc,
        result_code
    )

使用租户筛选器更新数据库

# In models/transaction.py
async def update_transaction_status(checkout_request_id, org_id, result_desc, result_code):
    
    # 🔑 CRITICAL: Update ONLY transactions belonging to this organization
    await conn.execute("""
        UPDATE transactions 
        SET status = $1, result_desc = $2, result_code = $3, updated_at = NOW()
        WHERE checkout_request_id = $4 
        AND organization_id = $5     -- 🔑 TENANT ISOLATION - Only org_123 transactions
    """, 'SUCCESS' if result_code == 0 else 'FAILED', 
         result_desc, result_code, checkout_request_id, org_id)

______________________________________________________________________

🔒 多租户隔离摘要

刚刚发生的事情:

  1. 认证:用户已通过身份验证,属于 org_123
  2. 配置:已使用 org_123仅限M-Pesa凭据
  3. API调用:M-Pesa与 org_123的商业简码
  4. 数据库:交易存储在 organization_id = org_123
  5. 回调:M-Pesa电话 org_123-特定回调URL
  6. 更新:只有 org_123的交易已更新
  7. 审计:所有标记为的日志 org_123

🛡️ 隔离保证:

  • 组织机构456 看不到此交易
  • 组织机构456 无法访问 组织123的M-Pesa证书
  • 组织机构456 无法更新 组织123的交易
  • 组织123 不能超过 组织机构456的费率限制
  • ❌ 任何级别都没有跨租户数据访问

🔑 关键隔离点:

  1. JWT代币 包含 organization_id
  2. 数据库查询 始终按以下方式过滤 organization_id
  3. M-Pesa证书 是特定于组织的
  4. 回调URL 是特定于组织的
  5. 费率限制 是特定于组织的
  6. 审计日志 是特定于组织的

目录标签

目录标签

金融科技PythonClaude支付处理多租户架构本地部署SaaS平台AI集成M-Pesa集成

支持客户端

Claude

接入字段

传输方式(transport,传输协议)

stdio

鉴权方式(authType,认证方式)

token

运行时(runtime,运行环境)

Python

工具数量(toolCount,工具数)

0

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

stdiotoken部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

来源信息

继续浏览同类 MCP