我遇到以下问题:
我在 Oracle APEX 中有一个应用程序,当我单击按钮时,我需要调用外部 API。
我想到的解决方案是在按钮上创建一个动态操作,单击时执行 JavaScript 代码(代码如下)。
但是当代码执行时,我在控制台中收到以下错误:
从源“http://minha-url.com.br”获取“https://api.rd.services/platform/events?event_type=sale”的访问已被 CORS 策略阻止:对预检的响应请求未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明响应满足您的需求,请将请求模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。
我的代码:
let options = {
method: 'POST',
headers: {
accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
},
body: JSON.stringify({
event_type: 'SALE',
event_family: 'CDP',
payload: {
email: '[email protected]',
funnel_name: 'default',
value: 999
}
})
};
fetch('https://api.rd.services/platform/events?event_type=sale', options)
.then(response => response.json())
.then(response => console.log(response))
.catch(err => console.error(err));
我查阅了API文档,其中包含以下信息:
使用 access_token 授权请求的 RD Station 营销 API 仅允许来自应用程序后端的请求。这是因为此 API 中使用的令牌无法在浏览器中公开,因为它允许访问有关您帐户中联系人的私人信息。
如何使用 CORS 解决此错误?
单击按钮时我需要向外部 API 发出 POST 请求。
他们的 API 文档很好地解释了 CORS 问题:你无法从客户端浏览器使用 javascript 调用他们的 API;你必须从你的服务器调用他们的 API。
您没有一种简单的方法来解决 CORS - API 告诉浏览器不允许它来自您的站点,并且浏览器同意。这些都不是你能控制的。
您可以做的是从 PL/SQL 调用他们的 API。 API 请求将来自您的数据库服务器,而不是来自客户端的浏览器,因此 CORS 不适用。正如他们的文档指出的那样,敏感的访问令牌只会从您的服务器传递到 API,因此您的客户端无法窃取它。
您最简单的选择可能是APEX_WEB_SERVICE.make_rest_request。
首先需要创建ACL以允许数据库访问远程Web服务器。作为系统或管理员帐户运行:
declare
l_principal VARCHAR2(20) := 'APEX_190200'; -- this should match your APEX schema name
l_host varchar2(100) := 'api.rd.services'; -- remote server name
begin
dbms_network_acl_admin.create_acl (
acl => 'my_acl.xml',
description => 'my acl',
principal => l_principal,
is_grant => TRUE,
privilege => 'connect',
start_date => systimestamp,
end_date => null);
dbms_network_acl_admin.assign_acl (
acl => 'my_acl.xml',
host => l_host,
lower_port => 443,
upper_port => 443);
commit;
end;
/
然后你可以在 APEX 中使用这样的块:
declare
l_clob clob;
l_access_token varchar2(100) := 'io7u34907iafh394897';
begin
apex_web_service.set_request_headers(
p_name_01 => 'Content-Type',
p_value_01 => 'application/json',
p_name_02 => 'Authorization',
p_value_02 => 'Bearer ' || l_access_token,
p_reset => false,
p_skip_if_exists => true );
l_clob := apex_web_service.make_rest_request(
p_url => 'https://api.rd.services/platform/events?event_type=sale',
p_http_method => 'POST',
p_body => '{
event_type: ''SALE'',
event_family: ''CDP'',
payload: {
email: ''[email protected]'',
funnel_name: ''default'',
value: 999
}
}'
) ;
:P101_RESULT := l_clob;
end;
在此示例中,访问令牌被硬编码在 PL/SQL 块中,但您也可以将其存储在应用程序项变量中。您可能不希望将其存储在最终用户可以在 HTML 中看到的页面项中。
本例中的 API 结果存储在页面项 P101_RESULT 中。您可能想将其存储在其他地方。
Oracle-Base 站点上也有 这样的示例