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

如何将Midtrans Snap返回的JSON支付结果存储到MySQL数据库

Midtrans支付发票存储MySQL实现方案

原有JSON.parse报错原因

你的代码触发JSON.parse报错是逻辑错误导致的:

  1. Midtrans的snap.pay回调函数中传入的result参数本身就是标准JS对象,不需要额外做parse转换
  2. 你的代码通过+=把格式化后的JSON字符串追加到DOM元素的innerHTML中,此时赋值给stringjson的内容是DOM原有内容+新拼接字符串的混合文本,不是合法的JSON结构,直接parse必然报错
  3. 把parse后得到的JS对象直接赋值给innerHTML,会被强制转成[object Object],也不符合展示需求

修复后的前端回调逻辑

不需要做多余的字符串转对象操作,直接使用回调返回的result对象即可,同时把数据发给后端做存储:

<script src="https://app.sandbox.midtrans.com/snap/snap.js"></script>
<script type="text/javascript">
document.getElementById('pay-button').onclick = function() {
    snap.pay('<?php echo $snapToken ?>', {
        onSuccess: function(result) {
            // 页面展示结果
            document.getElementById('result-json').innerHTML = JSON.stringify(result, null, 2);
            // 发送结果到后端存储
            savePaymentResult(result);
        },
        onPending: function(result) {
            document.getElementById('result-json').innerHTML = JSON.stringify(result, null, 2);
            savePaymentResult(result);
        },
        onError: function(result) {
            document.getElementById('result-json').innerHTML = JSON.stringify(result, null, 2);
            savePaymentResult(result);
        }
    });
};

// 统一处理支付结果上传
function savePaymentResult(paymentData) {
    fetch('/save_payment.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(paymentData)
    }).then(res => res.json()).then(res => {
        console.log('支付结果存储状态:', res);
    }).catch(err => {
        console.error('存储请求失败:', err);
    });
}
</script>

MySQL存储完整实现流程

  • 第一步:创建支付发票数据表
    先在MySQL中建表,字段和Midtrans返回的支付字段对应,参考SQL:
    CREATE TABLE `payment_invoices` (
      `id` int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
      `transaction_id` varchar(100) NOT NULL UNIQUE COMMENT 'Midtrans交易ID',
      `order_id` varchar(100) NOT NULL COMMENT '商户订单号',
      `status_code` varchar(10) NOT NULL COMMENT '状态码',
      `status_message` varchar(255) NOT NULL COMMENT '状态描述',
      `gross_amount` decimal(10,2) NOT NULL COMMENT '交易金额',
      `payment_type` varchar(50) NOT NULL COMMENT '支付方式',
      `transaction_time` datetime NOT NULL COMMENT '交易时间',
      `transaction_status` varchar(20) NOT NULL COMMENT '交易状态',
      `fraud_status` varchar(20) DEFAULT NULL COMMENT '风控状态',
      `finish_redirect_url` varchar(255) DEFAULT NULL COMMENT '支付完成跳转地址',
      `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
  • 第二步:后端接口做合法性校验
    注意:绝对不能直接信任前端传来的支付结果,必须做服务端校验避免伪造支付请求
    后端收到前端传来的支付数据后,需要拿到transaction_id或order_id调用Midtrans服务端接口查询真实交易状态,确认返回结果和前端传参一致、交易状态合法后,再做存储操作。
  • 第三步:数据入库
    校验通过后,把支付字段和数据表字段做映射,通过预处理SQL语句插入到payment_invoices表中即可,避免SQL注入风险。
    以PHP后端简单示例为例:
    <?php
    // save_payment.php
    header('Content-Type: application/json');
    // 读取前端传的JSON数据
    $rawData = file_get_contents('php://input');
    $paymentData = json_decode($rawData, true);
    
    // 此处省略Midtrans服务端校验交易状态的逻辑,校验通过后再执行入库
    // ......
    
    // 连接数据库(替换为你自己的数据库配置)
    $pdo = new PDO('mysql:host=localhost;dbname=your_db;charset=utf8mb4', 'db_user', 'db_pass');
    // 预处理插入语句,重复交易ID则更新状态
    $stmt = $pdo->prepare("INSERT INTO payment_invoices 
      (transaction_id, order_id, status_code, status_message, gross_amount, payment_type, transaction_time, transaction_status, fraud_status, finish_redirect_url)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      ON DUPLICATE KEY UPDATE transaction_status = VALUES(transaction_status), updated_at = CURRENT_TIMESTAMP");
    // 绑定参数执行
    $stmt->execute([
        $paymentData['transaction_id'],
        $paymentData['order_id'],
        $paymentData['status_code'],
        $paymentData['status_message'],
        $paymentData['gross_amount'],
        $paymentData['payment_type'],
        date('Y-m-d H:i:s', strtotime($paymentData['transaction_time'])),
        $paymentData['transaction_status'],
        $paymentData['fraud_status'],
        $paymentData['finish_redirect_url']
    ]);
    
    echo json_encode(['code' => 0, 'msg' => '存储成功']);
    
  • 第四步:后续状态同步兜底
    对于pending状态的交易,建议配置Midtrans的Webhook回调,在支付状态变更时主动更新数据库中的交易状态,避免用户提前关闭页面导致前端请求漏发、交易状态不一致的问题。

内容的提问来源于stack exchange,提问作者Jessen Jie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 18:54:22