求助:修改PHP代理文件解决Expensify API调用的CORS问题
解决Expensify Authenticate API的CORS问题及PHP代理修复方案
我想调用Expensify的Authenticate API,但受CORS限制无法直接调用,编写了PHP代理却无法正常工作,求修改方案及参考建议。
原前端调用脚本
$(document).ready(function () { $("#login").click(function () { var partnerName = ""; var partnerPassword = ""; var partnerUserID = $("#email").val(); var partnerUserSecret = $("#password").val(); var apiResponse; var token; $.ajax({ crossDomain: true, type: "POST", url: "https://www.expensify.com/api?command=Authenticate", data: { partnerName: partnerName, partnerPassword: partnerPassword, partnerUserID: partnerUserID, partnerUserSecret: partnerUserSecret }, cache: false, success: function (data) { apiResponse = data; console.log(apiResponse); token = apiResponse.authToken; jCode = apiResponse.jsonCode; if (jCode == 200) { window.sessionStorage sessionStorage.setItem('authToken', token) window.location.href = "dashboard.html"; } else if (jCode == 401) { alert('Wrong Password! Please enter password again') } else if (jCode == 404) { alert('Email not found, enter a valid email') } else if (jCode == 407) { alert('Auth Token expired, please log in again') } else if (jCode == 402) { alert('Missing Information. Please fill all fields') } } }); }); });
原PHP代理文件
<?php header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST'); header("Access-Control-Allow-Headers: X-Requested-With"); $baseURL = $_REQUEST['url']; function getRequestMethod() { return $_SERVER["REQUEST_METHOD"]; } function getPostData() { return http_build_query($_POST); } function makeGetRequest($baseURL) { $ch = curl_init(); $fullURL = $baseURL; curl_setopt($ch, CURLOPT_URL, $fullURL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $response = curl_exec($ch); curl_close($ch); if($e = curl_error($ch)) { echo $e; } else { $json = json_decode($response, true); return print_r($json); } } function makePostRequest($baseURL) { $ch = curl_init(); $data = http_build_query($_POST); curl_setopt($ch, CURLOPT_URL, $baseURL); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); if($e = curl_error($ch)) { echo $e; } else { $json = json_decode($response, true); return print_r($json); } } $response = ""; switch (getRequestMethod()) { case 'GET': $response = makeGetRequest($baseURL); break; case 'POST': $response = makePostRequest($baseURL); break; default: echo "There has been an error"; return; } echo $response;
修复步骤
1. 前端代码修改
- 将AJAX请求地址改为你的PHP代理文件路径(如
proxy.php) - 添加
url参数,值为Expensify的API地址 - 指定
dataType: 'json'确保前端正确解析响应 - 增加错误处理逻辑排查问题
修改后的前端代码:
$(document).ready(function () { $("#login").click(function () { var partnerName = ""; var partnerPassword = ""; var partnerUserID = $("#email").val(); var partnerUserSecret = $("#password").val(); var apiResponse; var token; $.ajax({ crossDomain: true, type: "POST", url: "proxy.php", // 替换为你的代理文件路径 data: { url: "https://www.expensify.com/api?command=Authenticate", partnerName: partnerName, partnerPassword: partnerPassword, partnerUserID: partnerUserID, partnerUserSecret: partnerUserSecret }, dataType: 'json', cache: false, success: function (data) { apiResponse = data; console.log(apiResponse); token = apiResponse.authToken; jCode = apiResponse.jsonCode; if (jCode == 200) { sessionStorage.setItem('authToken', token) window.location.href = "dashboard.html"; } else if (jCode == 401) { alert('Wrong Password! Please enter password again') } else if (jCode == 404) { alert('Email not found, enter a valid email') } else if (jCode == 407) { alert('Auth Token expired, please log in again') } else if (jCode == 402) { alert('Missing Information. Please fill all fields') } }, error: function(xhr, status, error) { console.error('请求错误:', error); alert('请求失败,请检查代理配置'); } }); }); });
2. PHP代理文件修改
- 移除
print_r,直接返回原始JSON响应,避免前端解析失败 - 调整curl错误检查时机(需在
curl_close前调用) - 添加JSON响应头,明确返回格式
- 过滤
url参数,避免干扰API请求数据 - 建议生产环境开启SSL验证,提升安全性
修改后的PHP代理代码:
<?php header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST'); header("Access-Control-Allow-Headers: X-Requested-With"); header('Content-Type: application/json'); // 检查必填的url参数 if (!isset($_REQUEST['url'])) { echo json_encode(['error' => 'Missing url parameter']); exit; } $baseURL = $_REQUEST['url']; // 移除url参数,防止传递给目标API unset($_REQUEST['url']); unset($_POST['url']); function getRequestMethod() { return $_SERVER["REQUEST_METHOD"]; } function makeGetRequest($baseURL, $params) { $ch = curl_init(); // 拼接GET参数 if (!empty($params)) { $baseURL .= '?' . http_build_query($params); } curl_setopt($ch, CURLOPT_URL, $baseURL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 生产环境请开启SSL验证 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); $response = curl_exec($ch); // 在关闭curl前检查错误 if ($e = curl_error($ch)) { curl_close($ch); echo json_encode(['error' => $e]); exit; } curl_close($ch); return $response; } function makePostRequest($baseURL, $postData) { $ch = curl_init(); $data = http_build_query($postData); curl_setopt($ch, CURLOPT_URL, $baseURL); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // 生产环境请开启SSL验证 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); // 在关闭curl前检查错误 if ($e = curl_error($ch)) { curl_close($ch); echo json_encode(['error' => $e]); exit; } curl_close($ch); return $response; } $response = ""; switch (getRequestMethod()) { case 'GET': $response = makeGetRequest($baseURL, $_GET); break; case 'POST': $response = makePostRequest($baseURL, $_POST); break; default: echo json_encode(['error' => 'Unsupported request method']); exit; } echo $response;
关键注意事项
- 生产环境必须开启SSL验证,避免中间人攻击
- 可给代理添加IP白名单或密钥验证,防止被滥用
- 确保PHP环境已启用curl扩展(可通过
phpinfo()检查)
内容的提问来源于stack exchange,提问作者Aayush
相关产品推荐
相关产品推荐

