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

Salesforce Apex调用REST API(OAuth1.0)报400错误求助

Salesforce Apex调用REST API返回400 Bad Request的排查与修复

核心问题分析

你的代码存在几处关键错误,导致请求格式非法或签名验证失败,这是Postman正常但Apex报错的根本原因:

1. Authorization头格式破坏

拼接OAuth授权头时,oauth_signature_method字段末尾遗漏了逗号,导致后续的oauth_consumer_key字段直接粘连在它后面,完全不符合OAuth头的语法规范:

header+= 'oauth_signature_method="HMAC-SHA1"'; // 此处末尾无逗号,破坏格式
header+= 'oauth_consumer_key="<KEY>", ';

这种错误会让服务器无法解析授权头,直接返回400。

2. OAuth签名密钥计算错误

OAuth 1.0 HMAC-SHA1的签名密钥必须遵循消费者密钥(consumerSecret) + "&" + 令牌密钥(oauth_token_secret)的规则,但你的generateSignature方法仅使用了consumerSecret,完全忽略了token secret:

Blob sig = Crypto.generateMac( 'HmacSHA1', Blob.valueOf(s), Blob.valueOf(consumerSecret) );

这会导致生成的签名与Postman的签名完全不匹配,服务器验证签名失败。

3. Token Secret值前后不一致

在Authorization头中你填写的是oauth_token_secret="<TOKEN>",但在签名计算用的参数Map里却填了parameters.put('oauth_token_secret','<SECRET>'),两者值不统一,进一步导致签名错误。

4. JSON Body未参与签名(若API要求)

你的请求Content-Type为application/json,但当前代码仅在Content-Type是application/x-www-form-urlencoded时,才会将Body参数加入签名基串。如果目标API要求JSON Body也参与签名,这部分逻辑需要调整。


修正后的关键代码片段

针对上述问题,调整后的核心代码如下:

修正Authorization头拼接

String header = 'OAuth ';
header+= 'realm="8305111_SB1", ';
header+= 'oauth_signature_method="HMAC-SHA1", '; // 补充末尾逗号
header+= 'oauth_consumer_key="<KEY>", ';
header+= 'oauth_token="<TOKEN>", ';
header+= 'oauth_token_secret="<TOKEN_SECRET>", '; // 统一使用正确的token secret值
header+= 'oauth_version="1.0", ';
header+= 'oauth_timestamp="'+timestamp+'", ';
header+= 'oauth_nonce="'+nonce+'", ';

修正签名密钥计算

修改generateSignature方法,传入并使用token secret:

// 调用时传入正确的token secret
header += 'oauth_signature=&quot;'+generateSignature(request, consumerSecret, '<TOKEN_SECRET>', parameters)+'&quot;';

// 修正后的签名生成方法
private static String generateSignature(HttpRequest req, String consumerSecret, String tokenSecret, Map<String,String> parameters) {
    String s = createBaseString(parameters,req);
    // 按OAuth规范构建签名密钥
    String signingKey = consumerSecret + '&' + tokenSecret;
    Blob sig = Crypto.generateMac( 'HmacSHA1', Blob.valueOf(s), Blob.valueOf(signingKey) );
    return EncodingUtil.urlEncode(EncodingUtil.base64encode(sig), 'UTF-8');
}

统一参数Map中的Token Secret

parameters.put('oauth_token_secret','<TOKEN_SECRET>'); // 与头信息中的值保持一致

额外排查建议

  • 开启Postman的请求日志,对比Apex输出的Authorization头、timestamp、nonce、签名值,确保字段格式与Postman完全一致(nonce和timestamp每次请求不同,但格式需统一)。
  • 确认请求Endpoint与Postman完全一致,包括Query参数的顺序(OAuth签名对参数顺序敏感)。
  • 验证Salesforce生成的timestamp是UTC时间戳,与Postman使用的时区一致。

内容的提问来源于stack exchange,提问作者Alejandro Ferrante

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 15:25:54