PAYATHON 2026

如何使用 jQuery submit 发送 FormData?

支付老李

结论

jQuery.submit() 不能接收或发送 FormData 对象,它只用于绑定或触发表单的提交事件。

如果要通过 AJAX 发送已经创建的 formData,需要在 submit 事件中调用 $.ajax(),同时设置:

processData: false,
contentType: false

如果支付网关要求浏览器跳转,并通过普通表单发起 POST 请求,就不应使用 FormData 和 AJAX。此时可以创建隐藏字段,再调用原生的 form.submit()。

使用 AJAX 发送 FormData

假设需要提交的表单是 #frmPayment,可以这样写:

<form id="frmPayment">
    <button type="submit">支付</button>
</form>
var formData;

$.ajax({
    url: "/MyController/MyAction/",
    type: "POST",
    data: {
        MyVariable: objData
    },
    success: function (data) {
        if (data === "Error") {
            return;
        }

        var payment = data;

        formData = new FormData();
        formData.append("key", gtKFFx);
        formData.append("tsnId", payment.TransantionId);
        formData.append("amount", billAmount);
        formData.append("productinfo", "Test");
        formData.append("firstname", custName);
        formData.append("email", "chetan.gupta21@gmail.com");
        formData.append("surl", "http://google.com");
        formData.append("furl", "http://facebook.com");
        formData.append("hash", payment.TransactionHash);

        $("#frmPayment").trigger("submit");
    },
    error: function (xhr) {
        console.log(xhr);
    }
});

$("#frmPayment").on("submit", function (e) {
    e.preventDefault();

    if (!formData) {
        return;
    }

    $.ajax({
        url: "https://payment-gateway.example.com/pay",
        type: "POST",
        data: formData,
        processData: false,
        contentType: false,
        success: function (response) {
            console.log(response);
        },
        error: function (xhr) {
            console.log(xhr);
        }
    });
});

processData: false 会阻止 jQuery 把 FormData 转换成查询字符串。contentType: false 会让浏览器自动生成带有正确 boundary 的 multipart/form-data 请求头。

不要手动设置:

contentType: "multipart/form-data"

手动设置后,请求头中会缺少浏览器生成的 boundary,服务器可能因此无法解析请求体。

submit 事件最好在页面初始化时绑定一次。不要在第一个 AJAX 请求每次成功后重复绑定,否则再次执行这段流程时,可能会同时触发多个提交处理器。

支付网关需要页面跳转时

不少支付网关不适合通过 AJAX 调用。它们通常要求浏览器提交普通 HTML 表单,再跳转到网关页面。遇到这种情况,可以把参数添加为隐藏字段:

<form
    id="frmPayment"
    method="post"
    action="https://payment-gateway.example.com/pay">
</form>
function addHiddenField(form, name, value) {
    $("<input>", {
        type: "hidden",
        name: name,
        value: value
    }).appendTo(form);
}

$.ajax({
    url: "/MyController/MyAction/",
    type: "POST",
    data: {
        MyVariable: objData
    },
    success: function (data) {
        if (data === "Error") {
            return;
        }

        var payment = data;
        var $form = $("#frmPayment");

        addHiddenField($form, "key", gtKFFx);
        addHiddenField($form, "tsnId", payment.TransantionId);
        addHiddenField($form, "amount", billAmount);
        addHiddenField($form, "productinfo", "Test");
        addHiddenField($form, "firstname", custName);
        addHiddenField($form, "email", "chetan.gupta21@gmail.com");
        addHiddenField($form, "surl", "http://google.com");
        addHiddenField($form, "furl", "http://facebook.com");
        addHiddenField($form, "hash", payment.TransactionHash);

        $form[0].submit();
    },
    error: function (xhr) {
        console.log(xhr);
    }
});

这里调用:

$form[0].submit();

是为了使用浏览器原生的表单提交方式。浏览器会直接向表单的 action 地址发送请求,并跳转到支付页面。

如何选择

目标接口明确支持 AJAX,且 CORS 已正确配置时,可以使用 FormData + $.ajax()。

如果支付网关要求用户跳转、显示支付页面或完成第三方认证,应使用隐藏字段和普通表单 POST。具体采用哪种方式,以支付网关的接口文档为准。

交易金额、订单号、签名和回调地址等重要参数,不能只在前端生成或校验。支付签名应由服务端生成,支付结果也要通过服务端回调再次验证,不能只根据浏览器的跳转结果更新订单状态。

备注:内容仅供参考。