You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mpesa Webhook开发:如何从Name/Value对象数组提取值赋值变量

M-Pesa支付Webhook回调元数据字段提取实现方案

你拿到的CallbackMetadata.Item是键值对数组结构:每个数组元素的Name字段存字段名,Value字段存对应值,部分字段(如示例中的Balance)可能不返回Value属性,提取时做好空值兼容即可。

实现方式1:遍历匹配字段(兼容性最优)

直接循环数组匹配Name值赋值给预定义变量,不需要额外ES语法支持,直接替换你代码中// populate vars with their values注释位置即可:

if (ResultCode === 0) {
  // 遍历元数据匹配字段
  for (const item of CallbackMetadata) {
    switch(item.Name) {
      case 'Amount':
        Amount = item.Value;
        break;
      case 'MpesaReceiptNumber':
        ReceiptNumber = item.Value;
        break;
      case 'TransactionDate':
        TransactionDate = item.Value;
        break;
      case 'PhoneNumber':
        PhoneNumber = item.Value;
        break;
    }
  }

  // 必要字段非空校验
  if (!Amount || !ReceiptNumber || !TransactionDate || !PhoneNumber) {
    console.log("回调元数据缺失必要字段", {Amount, ReceiptNumber, TransactionDate, PhoneNumber});
    return res.status(400).json({message: "invalid callback metadata"});
  }

  // 组装响应对象
  const mpesaResponseObject = {
    Amount,
    ReceiptNo: ReceiptNumber,
    PhoneNumber,
    TransactionDate
  };
}

实现方式2:数组转普通对象后取值

代码更简洁,先把键值对数组转成常规对象,再直接按属性名取值:

if (ResultCode === 0) {
  // 将元数据数组转换为 {字段名: 字段值} 格式的普通对象
  const metadataMap = Object.fromEntries(
    CallbackMetadata.map(item => [item.Name, item.Value])
  );

  // 直接取值赋值
  Amount = metadataMap.Amount;
  ReceiptNumber = metadataMap.MpesaReceiptNumber;
  TransactionDate = metadataMap.TransactionDate;
  PhoneNumber = metadataMap.PhoneNumber;

  const mpesaResponseObject = {
    Amount,
    ReceiptNo: ReceiptNumber,
    PhoneNumber,
    TransactionDate
  };
}

注意事项:

  • 回调返回的TransactionDate是YYYYMMDDHHmmss格式的数字,不是标准时间戳,后续做日期处理时需要先转字符串再做格式化
  • PhoneNumber字段已经携带国家码前缀,不需要额外拼接
  • 接口处理完成后要及时返回200响应,否则M-Pesa回调服务会重复推送请求

修正后完整业务代码

const express = require("express");
const prettyjson = require("prettyjson");
const Router = express.Router();

Router.post("/stk-webhook", async (req, res) => {
  let CallbackMetadata;
  let ResultCode;
  let Amount;
  let ReceiptNumber;
  let TransactionDate;
  let PhoneNumber;
  let mpesaResponseObject;

  console.log("_____________RECEIVED_MPESA_WEBHOOK________");
  console.log(prettyjson.render(req.body));
  try {
    ResultCode = req.body.Body.stkCallback.ResultCode;
    CallbackMetadata = req.body.Body.stkCallback.CallbackMetadata.Item;
    if (ResultCode === 0) {
      const metadataMap = Object.fromEntries(
        CallbackMetadata.map(item => [item.Name, item.Value])
      );
      Amount = metadataMap.Amount;
      ReceiptNumber = metadataMap.MpesaReceiptNumber;
      TransactionDate = metadataMap.TransactionDate;
      PhoneNumber = metadataMap.PhoneNumber;

      mpesaResponseObject = {
        Amount,
        ReceiptNo: ReceiptNumber,
        PhoneNumber,
        TransactionDate
      };

      // 支付成功后续业务逻辑写在此处
      res.status(200).json({message: "callback received success"});
    } else {
      console.log("You cancelled transaction");
      return res.status(400).json({ message: "you cancelled transaction" });
    }
    console.log(mpesaResponseObject);
  } catch (error) {
    console.log(error);
    res.status(500).json({message: "server process error"});
  }
});
module.exports = Router;

内容的提问来源于stack exchange,提问作者MAXWEL OCHIENG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 04:27:18