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

Laravel PHP中无法生成Salesforce refresh_token问题求助

Salesforce refresh_token生成失败排查方案

接口报错截图

  • 问题现象:调用Salesforce OAuth接口可正常生成有效期20分钟的access_token,但始终无法获取refresh_token
  • 原有问题代码:
$client = new Client();
$res = $client
->request("POST",
    "https://test.salesforce.com/services/oauth2/token",[
        'body'=> json_encode([
            'grant_type'=>'refresh_token',
            'client_id'=>Config::get('forrest.info.client_id'),
            'client_secret'=>Config::get('forrest.info.client_secret'),
           
            'Authorization'=>'Bearer 00D3H0000008olE!ARYAQOzGGJDDIaygn7GokNk4T319XlDwwBXIDYPkJfej74dfhFT3CMDvBD2pZBQK_x.v2amiRe5Y29ZNXMp9EOA6ZTYyqrTW',
            'access_token'=>'00D3H0000008olE!ARYAQOzGGJDDIaygn7GokNk4T319XlDwwBXIDYPkJfej74dfhFT3CMDvBD2pZBQK_x.v2amiRe5Y29ZNXMp9EOA6ZTYyqrTW',
            
        ])
    ]
);
dd ($res->getStatusCode());

核心错误点

  1. 流程逻辑颠倒:grant_type=refresh_token接口的作用是用已存储的refresh_token换取新的有效access_token,并非生成refresh_token的接口。refresh_token只会在用户首次完成OAuth授权流程时,和access_token一同返回,无法通过已生成的access_token反向兑换。
  2. 请求格式错误:Salesforce OAuth2的token接口仅支持application/x-www-form-urlencoded格式传参,当前代码将参数转为JSON格式放在请求体中,接口无法识别参数。
  3. 参数配置错误:Authorization是HTTP请求头字段,不应放在请求体中;调用refresh_token类型的接口时不需要传access_token,必须传入提前存储的refresh_token值。
  4. 权限配置缺失:如果Connected App侧未开启refresh_token权限、首次授权请求未申请offline_access作用域,接口不会返回refresh_token字段。

正确实现步骤

1. 前置配置

登录Salesforce Sandbox,打开对应Connected App的配置页:

  • 在OAuth策略设置中,开启refresh_token权限,可选择Refresh Token is valid until revoked(永久有效直到手动撤销)或自定义有效期
  • 在允许的OAuth作用域列表中,添加Perform requests on your behalf at any time (refresh_token, offline_access)权限

2. 首次授权获取refresh_token

首次发起授权请求(支持授权码模式、密码模式等)时,必须在scope参数中包含refresh_token offline_access,接口返回结果中会同步返回refresh_token,需要将该值持久化存储。
以Guzzle调用密码模式为例的正确代码:

$client = new Client();
$res = $client->request("POST",
    "https://test.salesforce.com/services/oauth2/token",[
        'form_params' => [ // 必须用form_params传表单格式参数,不能传JSON
            'grant_type' => 'password',
            'client_id' => Config::get('forrest.info.client_id'),
            'client_secret' => Config::get('forrest.info.client_secret'),
            'username' => '你的Salesforce账号用户名',
            'password' => '你的账号密码+个人安全令牌',
            'scope' => 'full refresh_token offline_access' // 必须加该scope申请refresh_token权限
        ]
    ]
);
$result = json_decode($res->getBody(), true);
// 从返回结果中取出两个token,持久化存储refresh_token
$accessToken = $result['access_token'];
$refreshToken = $result['refresh_token'];

3. 用refresh_token刷新access_token

当存储的access_token过期时,再调用grant_type=refresh_token接口换取新的access_token,不需要重复传用户名密码:

$client = new Client();
$res = $client->request("POST",
    "https://test.salesforce.com/services/oauth2/token",[
        'form_params' => [
            'grant_type' => 'refresh_token',
            'client_id' => Config::get('forrest.info.client_id'),
            'client_secret' => Config::get('forrest.info.client_secret'),
            'refresh_token' => '你之前持久化存储的refresh_token值'
        ]
    ]
);
$result = json_decode($res->getBody(), true);
$newAccessToken = $result['access_token'];

排查清单

  • 确认Connected App已开启refresh_token相关权限
  • 确认首次授权请求的scope参数包含refresh_token offline_access
  • 确认所有token接口请求均使用表单格式传参,未使用JSON格式请求体
  • 确认没有尝试通过access_token反向生成refresh_token,refresh_token仅在首次授权时返回

内容的提问来源于stack exchange,提问作者Muhammad Adnan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 02:27:31