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

本地Odoo环境下Ajax调用Midtrans POST API跨域权限错误排查

问题分析与解决方案

为什么会出现OPTIONS预请求?

当你发起跨域POST请求,且满足以下任一条件时,浏览器会自动发送OPTIONS预请求(预检请求)来验证服务器是否允许该实际请求:

  • 请求包含自定义HTTP头(比如你这里的Authorization)
  • 请求的Content-Type是application/json(非application/x-www-form-urlencoded、multipart/form-data或text/plain)

所以即使你设置了POST方法,浏览器依然会先发OPTIONS请求确认权限,这是跨域请求的标准机制。

核心错误原因

你设置了xhrFields: { withCredentials: true },这个属性会告诉浏览器在跨域请求中携带当前域名的Cookie等凭证。但此时CORS响应头Access-Control-Allow-Origin不能是通配符*,必须是具体的请求源(比如你的http://10.0.75.1:8069)。而cors-anywhere默认返回的Access-Control-Allow-Origin是*,这就导致了冲突,触发了报错。

更关键的是:调用Midtrans Snap API完全不需要携带你本地Odoo的凭证,这个withCredentials设置是多余的!


修复步骤与修改后的代码

  1. 移除不必要的withCredentials配置:这是解决CORS错误的核心。
  2. 清理冗余代码:你同时初始化了原生XMLHttpRequest和jQuery的$.ajax,保留后者即可。
  3. 用JSON对象代替字符串格式的data:避免手动转义的错误,让jQuery自动处理JSON序列化。
  4. 统一请求配置:type和method重复了,保留一个即可。

修改后的代码如下:

function make_base_auth(user, password) {
    var tok = user;
    var hash = btoa(tok);
    return "Basic " + hash;
}

$.ajax({
    url: "https://cors-anywhere.herokuapp.com/https://app.sandbox.midtrans.com/snap/v1/transactions",
    method: 'POST',
    dataType: "json",
    crossDomain: true,
    async: true, // 建议设为true,同步请求会阻塞浏览器
    contentType: "application/json; charset=utf-8",
    beforeSend: function(xhr){
        xhr.setRequestHeader('Authorization', make_base_auth("SB-Mid-server-aaaa:",""));
    },
    // 用JSON对象代替字符串,更易维护
    data: JSON.stringify({
        "transaction_details": {
            "order_id": "ORDER-109",
            "gross_amount": 75000
        },
        "credit_card": {
            "secure": true
        },
        "item_details": [
            {
                "id": "ITEM1",
                "price": 10000,
                "quantity": 5,
                "name": "Midtrans wwwwww"
            },
            {
                "id": "ITEM2",
                "price": 5000,
                "quantity": 5,
                "name": "Midtrans wwdwdwdwd"
            }
        ],
        "customer_details": {
            "first_name": "TEST",
            "last_name": "MIDTRANSER",
            "email": "noreply@example.com",
            "phone": "+628123456",
            "billing_address": {
                "first_name": "TEST",
                "last_name": "MIDTRANSER",
                "email": "noreply@example.com",
                "phone": "081 2233 44-55",
                "address": "Sudirman",
                "city": "Jakarta",
                "postal_code": "12190",
                "country_code": "IDN"
            },
            "shipping_address": {
                "first_name": "TEST",
                "last_name": "MIDTRANSER",
                "email": "noreply@example.com",
                "phone": "0812345678910",
                "address": "Sudirman",
                "city": "Jakarta",
                "postal_code": "12190",
                "country_code": "IDN"
            }
        }
    }),
    success: function (data) {
        console.log(data);
        snap.pay(data.token);
        alert("请求成功");
    },
    error: function (xhr, status, error) {
        console.error("请求失败:", xhr.responseText);
        alert("请求失败,请查看控制台日志");
    }
});

额外建议

  • 避免使用同步请求:把async: false改成true,同步请求会阻塞浏览器主线程,影响用户体验。
  • 自行部署CORS代理:免费的cors-anywhere.herokuapp.com有请求限制,长期使用建议自己部署一个CORS代理服务(比如基于Node.js的cors-anywhere包)。
  • 后端中转请求(更优方案):在生产环境中,不建议在前端直接调用Midtrans API(会暴露你的Server Key)。正确的做法是在Odoo后端编写一个控制器,由后端中转请求到Midtrans API,前端调用Odoo的控制器接口,这样完全避免跨域问题,也更安全。

内容的提问来源于stack exchange,提问作者Albert Chang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:42:05