omniphx / forrest
一个用于 Salesforce 的 Laravel 库
Requires
- php: ~7.2 || ~8.0
- firebase/php-jwt: ^5.2|~6.0
- guzzlehttp/guzzle: ~6.0|~7.0
- illuminate/cache: ~6.0|~7.0|~8.0|~9.0|~10.0|~11.0
- illuminate/config: ~6.0|~7.0|~8.0|~9.0|~10.0|~11.0
- illuminate/contracts: ~6.0|~7.0|~8.0|~9.0|~10.0|~11.0
- illuminate/http: ~6.0|~7.0|~8.0|~9.0|~10.0|~11.0
- illuminate/routing: ~6.0|~7.0|~8.0|~9.0|~10.0|~11.0
- nesbot/carbon: ^2.0|^3.0
Requires (Dev)
- phpspec/phpspec: ~6.0|~7.0
- dev-master
- v2.19.1
- v2.19.0
- v2.18.2
- v2.18.1
- v2.18.0
- v2.17.0
- v2.16.2
- v2.16.1
- v2.16.0
- v2.15.0
- v2.14.4
- v2.14.3
- v2.14.2
- v2.14.1
- v2.14
- v2.13.1
- v2.13.0
- v2.12.0
- v2.11.2
- v2.11.1
- v2.11.0
- v2.10.2
- v2.10.1
- 2.10.0
- v2.9.0
- v2.8.0
- v2.7.2
- v2.7.1
- v2.7.0
- v2.6.0
- v2.5.3
- v2.5.2
- v2.5.1
- v2.5.0
- v2.4.7
- v2.4.6
- v2.4.5
- v2.4.4
- v2.4.3
- v2.4.2
- v2.4.1
- v2.4.0
- v2.3.6
- v2.3.5
- v2.3.4
- v2.3.3
- v2.3.2
- v2.3.1
- v2.3.0
- v2.2.0
- v2.1.5
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.5
- v2.0.4
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v1.4.0
- v1.3.0
- v1.2.0
- v1.1.0
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- v1.0.0-beta.3
- v1.0.0-beta.2
- v1.0.0-beta
- v0.3.1
- v0.3.0
- v0.2.1
- v0.2.0
- v0.1.0
- dev-bugfix/lumen-object-store-reference
- dev-feature/multiple-salesforce-instances
- dev-feature/allow-for-bulk-api-requests
- dev-release/2.4
- dev-cwhittl-master
- dev-blocher-master
- dev-bugfix/fix-524-session-dependency
- dev-InfusionWeb-master
- dev-feature/add-invalid-creditials-exception
- dev-bugfix/90
- dev-feature/guzzle6
- dev-bugfix/persist-login-url-across-oath-redirect
- dev-bugfix/81
- dev-analysis-8wjpVo
- dev-code-enhancements
This package is auto-updated.
Last update: 2024-09-02 23:36:53 UTC
README
Forrest 是 Laravel 和 Lumen 的 Salesforce/Force.com REST API 客户端。
对 Eloquent Salesforce 模型感兴趣?查看 @roblesterjr04 的 EloquentSalesForce 项目,它利用 Forrest 作为其 API 层。
安装
如果您正在升级到 2.0 版本,请确保重新发布您的配置文件。
可以通过 composer 安装 Forrest。打开您的 composer.json
文件,并在 require
键中添加以下内容
"omniphx/forrest": "2.*"
接下来,在命令行中运行 composer update
来安装包。
Laravel 安装
对于 Laravel >=5.5,该包将自动注册服务提供者和 Forrest
别名。对于更早的版本,请将服务提供者和别名添加到您的 config/app.php
文件中
Omniphx\Forrest\Providers\Laravel\ForrestServiceProvider::class 'Forrest' => Omniphx\Forrest\Providers\Laravel\Facades\Forrest::class
对于 Laravel 4,在
app/config/app.php
中添加Omniphx\Forrest\Providers\Laravel4\ForrestServiceProvider
。别名保持不变。
Lumen 安装
class_alias('Omniphx\Forrest\Providers\Laravel\Facades\Forrest', 'Forrest'); $app->register(Omniphx\Forrest\Providers\Lumen\ForrestServiceProvider::class); $app->configure('forrest'); $app->withFacades();
然后您将利用 Lumen 服务提供者,通过将其注册到 bootstrap/app.php
文件中来使用它。
配置
您需要一个配置文件来添加您的凭证。使用 artisan
命令发布配置文件
php artisan vendor:publish
这将发布一个 config/forrest.php
文件,它可以切换不同的认证类型以及其他设置。
添加配置文件后,更新您的 .env
文件以包含以下值(获取消费者密钥和秘密的详细信息如下)
SF_CONSUMER_KEY=123455
SF_CONSUMER_SECRET=ABCDEF
SF_CALLBACK_URI=https://test.app/callback
SF_LOGIN_URL=https://login.salesforce.com
# For sandbox: SF_LOGIN_URL=https://test.salesforce.com
SF_USERNAME=mattjmitchener@gmail.com
SF_PASSWORD=password123
对于 Lumen,您应从
src/config/config.php
复制配置文件,并将其添加到您的应用程序根目录下的配置目录中的forrest.php
配置文件中。对于 Laravel 4,运行php artisan config:publish omniphx/forrest
,这将创建app/config/omniphx/forrest/config.php
入门
设置连接应用
- 登录 Salesforce org
- 点击右上角的设置
- 在快速查找框中搜索 App,并选择
App Manager
- 点击“新建连接应用”。
- 为远程应用程序输入以下详细信息
- 连接应用名称
- API 名称
- 联系邮箱
- 在 API 下启用 OAuth 设置
- 回调 URL
- 选择访问范围(如果您需要刷新令牌,请在此处指定)
- 点击
保存
保存后,您现在将获得消费者密钥和消费者密钥。更新您的配置文件,使用 consumerKey
、consumerSecret
、loginURL
和 callbackURI
的值。
设置
创建认证路由
Web 服务器认证流程
Route::get('/authenticate', function() { return Forrest::authenticate(); }); Route::get('/callback', function() { Forrest::callback(); return Redirect::to('/'); });
用户名-密码认证流程
使用用户名密码流程,您可以直接使用 Forrest::authenticate()
方法进行认证。
要使用此认证,您必须将您的用户名和密码添加到配置文件中。除非您的 IP 地址被列入白名单,否则可能需要修改安全令牌。
Route::get('/authenticate', function() { Forrest::authenticate(); return Redirect::to('/'); });
客户端凭证认证流程
使用客户端凭证流程,您可以直接使用 Forrest::authenticate()
方法进行认证。
使用此认证方法只需要您的消费者密钥和密钥。您的 Salesforce 连接应用也必须在设置中启用“客户端凭证流程”。
Route::get('/authenticate', function() { Forrest::authenticate(); return Redirect::to('/'); });
SOAP 认证流程
(当您无法在 Salesforce 中创建连接应用时)
- 销售云允许通过SOAP登录进行个人登录
- 从SOAP登录返回的Bearer访问令牌可以类似于OAuth密钥使用
- 更新您的配置文件并将
authentication
值设置为UserPasswordSoap
- 更新您的配置文件,设置
loginURL
、username
和password
的值。使用用户名密码SOAP流程,您可以直接使用Forrest::authenticate()
方法进行身份验证。
要使用此身份验证,您可以将用户名和密码添加到配置文件中。除非您的IP地址已列入白名单,否则可能需要修改安全令牌。
Route::get('/authenticate', function() { Forrest::authenticate(); return Redirect::to('/'); });
如果您的应用程序需要以不同用户身份登录到销售云,您还可以将登录URL、用户名和密码传递给Forrest::authenticateUser()
方法。
除非您的IP地址已列入白名单,否则可能需要修改安全令牌。
Route::Post('/authenticate', function(Request $request) { Forrest::authenticateUser('https://login.salesforce.com',$request->username, $request->password); return Redirect::to('/'); });
JWT身份验证流程
初始设置
- 在
config/forrest.php
中将authentication
设置为OAuthJWT
- 生成密钥和证书:
openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt
- 在
config/forrest.php
中配置私钥(例如,file_get_contents('./../server.key'),
)
设置连接应用
- 应用管理器 > 创建连接应用
- 启用OAuth设置
- 选中“使用数字签名”
- 添加
server.crt
或您选择的任何名称 - 作用域必须包括“refresh_token, offline_access”
- 点击保存
接下来,您需要预先授权一个配置文件(目前只能在经典版中执行此步骤,但这是重要的)
- 管理应用 > 连接应用
- 点击您的应用程序旁边的“编辑”
- 将“允许用户”设置为“管理员批准的用户已预先授权”
- 保存
- 转到设置 > 管理用户 > 配置文件并编辑关联用户的配置文件(例如,销售云管理员)
- 在“连接应用访问”下检查相应的应用名称
实现方式与用户密码(例如,需要明确指定用户名和密码)完全相同
Route::get('/authenticate', function() { Forrest::authenticate(); return Redirect::to('/'); });
对于连接到Lightning组织,您需要在forrest.php
配置中配置一个instanceUrl
Lightning: https://<YOUR_ORG>.my.salesforce.com Lightning Sandbox: https://<YOUR_ORG>--<SANDBOX_NAME>.sandbox.my.salesforce.com Developer Org: https://<DEV_DOMAIN>.develop.my.salesforce.com
自定义登录URL
有时用户需要连接到沙盒或自定义URL。为此,只需将URL作为参数传递给身份验证方法即可
Route::get('/authenticate', function() { $loginURL = 'https://test.salesforce.com'; return Forrest::authenticate($loginURL); });
注意:您可以在配置文件中指定默认登录URL。
基本用法
身份验证后,您的应用程序将存储一个加密的身份验证令牌,可用于进行API请求。
查询记录
Forrest::query('SELECT Id FROM Account');
示例结果
( [totalSize] => 2 [done] => 1 [records] => Array ( [0] => Array ( [attributes] => Array ( [type] => Account [url] => /services/data/v48.0/sobjects/Account/0013I000004zuIXQAY ) [Id] => 0013I000004zuIXQAY ) [1] => Array ( [attributes] => Array ( [type] => Account [url] => /services/data/v48.0/sobjects/Account/0013I000004zuIcQAI ) [Id] => 0013I000004zuIcQAI ) ) )
如果您查询的记录超过2000条,则您的响应将包括
( [nextRecordsUrl] => /services/data/v20.0/query/01gD0000002HU6KIAW-2000 )
简单地说,调用Forrest::next($nextRecordsUrl)
来返回下一批2000条记录。
创建新记录
可以使用以下格式创建记录。
Forrest::sobjects('Account',[ 'method' => 'post', 'body' => ['Name' => 'Dunder Mifflin'] ]);
更新记录
使用PUT方法更新记录。
Forrest::sobjects('Account/001i000000xxx',[ 'method' => 'put', 'body' => [ 'Name' => 'Dunder Mifflin', 'Phone' => '555-555-5555' ] ]);
Upsert记录
使用PATCH方法更新记录,如果外部ID不存在,则会插入新记录。
$externalId = 'XYZ1234'; Forrest::sobjects('Account/External_Id__c/' . $externalId, [ 'method' => 'patch', 'body' => [ 'Name' => 'Dunder Mifflin', 'Phone' => '555-555-5555' ] ]);
删除记录
使用DELETE方法删除记录。
Forrest::sobjects('Account/001i000000xxx', ['method' => 'delete']);
设置头信息
有时您需要设置自定义头信息(例如,使用分配规则创建潜在客户)
Forrest::sobjects('Lead',[ 'method' => 'post', 'body' => [ 'Company' => 'Dunder Mifflin', 'LastName' => 'Scott' ], 'headers' => [ 'Sforce-Auto-Assign' => '01Q1N000000yMQZUA2' ] ]);
要禁用分配规则,使用
'Sforce-Auto-Assign' => 'false'
XML格式
使用format
密钥将请求/响应格式更改为XML或使其在配置文件中为默认值。
Forrest::sobjects('Account',['format'=>'xml']);
API请求
除了search
和query
资源外,所有资源都是通过方法重载动态请求的。
您可以通过调用资源方法来确定您可以访问哪些资源
Forrest::resources();
本示例输出显示了通过API可以调用的资源
Array ( [sobjects] => /services/data/v30.0/sobjects [connect] => /services/data/v30.0/connect [query] => /services/data/v30.0/query [theme] => /services/data/v30.0/theme [queryAll] => /services/data/v30.0/queryAll [tooling] => /services/data/v30.0/tooling [chatter] => /services/data/v30.0/chatter [analytics] => /services/data/v30.0/analytics [recent] => /services/data/v30.0/recent [process] => /services/data/v30.0/process [identity] => https://login.salesforce.com/id/00Di0000000XXXXXX/005i0000000aaaaAAA [flexiPage] => /services/data/v30.0/flexiPage [search] => /services/data/v30.0/search [quickActions] => /services/data/v30.0/quickActions [appMenu] => /services/data/v30.0/appMenu )
从上面的列表中,我可以通过指定的键来调用资源。
Forrest::theme();
或者...
Forrest::appMenu();
还可以传递额外的资源URL参数
Forrest::sobjects('Account/describe/approvalLayouts/');
以及新的格式化选项、头信息或其他配置
Forrest::theme(['format'=>'xml']);
批量更新多条记录(批量API 2.0)
批量API请求在您需要快速将大量数据加载到Salesforce组织时特别有用。主要区别在于它至少需要三个单独的请求(创建、添加、关闭),并且要加载的数据以CSV格式发送。
以下示例是三个用于更新联系人
记录CSV的请求。
创建
使用POST方法创建批量上传作业,主体包含以下作业属性
object
是您要加载的对象类型(每个作业中必须都是相同类型)externalIdFieldName
是外部ID,如果存在则更新,如果不存在则插入新记录。仅适用于更新操作。contentType
是CSV,这是当前唯一的有效值。operation
设置为upsert
以添加和更新记录。
我们将响应存储在$bulkJob
中,以便在下面的添加和关闭请求中引用唯一的作业ID。
有关此处可用的完整选项列表,请参阅创建作业。
$bulkJob = Forrest::jobs('ingest', [ 'method' => 'post', 'body' => [ "object" => "Contact", "externalIdFieldName" => "externalId", "contentType" => "CSV", "operation" => "upsert" ] ]);
添加数据
使用创建POST请求中的作业ID,您然后通过PUT请求发送要处理的CSV数据。这假设您已将CSV内容加载到$csv
有关其格式应如何设置,请参阅准备CSV文件的详细信息。
Forrest::jobs('ingest/' . $bulkJob['id'] . '/batches', [ 'method' => 'put', 'headers' => [ 'Content-Type' => 'text/csv' ], 'body' => $csv ]);
关闭
您必须关闭作业后才能处理记录,为此您向作业ID发送一个使用PATCH请求的UploadComplete
状态。
有关更多选项和有关如何中止作业的详细信息,请参阅关闭或中止作业。
$response = Forrest::jobs('ingest/' . $bulkJob['id'] . '/', [ 'method' => 'patch', 'body' => [ "state" => "UploadComplete" ] ]);
批量API 2.0在API版本41.0及以后可用。有关Salesforce批量API的更多信息,请参阅官方文档和本教程,了解如何成功执行批量上传。
其他API请求
刷新
如果设置了刷新令牌,服务器可以代表用户刷新访问令牌。刷新令牌仅适用于Web服务器流程。
Forrest::refresh();
如果您需要刷新令牌,请确保在您的连接应用中指定此内容为
access scope
。您也可以通过在配置文件中添加'scope' => 'full refresh_token'
来指定此内容。在配置文件中设置范围访问是可选的,默认范围访问由您的Salesforce组织确定。
撤销
这将撤销授权令牌。会话将继续存储令牌,但它将变得无效。
Forrest::revoke();
版本
返回所有当前支持的版本。包括版本、标签以及每个版本的根链接。
Forrest::versions();
资源
根据登录用户的权限和API版本返回可用的资源列表。
Forrest::resources();
身份
返回有关登录用户的信息。
Forrest::identity();
基本URL
返回包含API信息的Salesforce实例的URL。
Forrest::getBaseUrl(); // https://my-instance.my.salesforce.com/services/data/v50.0
实例 URL
返回 Salesforce 实例的 URL。
Forrest::getInstanceURL(); // https://my-instance.my.salesforce.com
有关 API 资源完整列表,请参阅Force.com REST API 开发者指南
自定义 Apex 端点
如果您使用 Apex 创建了自定义 API,您可以使用 custom()
方法来使用它们。
Forrest::custom('/myEndpoint');
可以通过这种方式传递额外的选项和参数
Forrest::custom('/myEndpoint', [ 'method' => 'post', 'body' => ['foo' => 'bar'], 'parameters' => ['flim' => 'flam']]);
有关更多信息,请阅读使用 Apex REST 创建 REST API。
原始请求
如有需要,您可以向您选择的端点发送原始请求。
Forrest::get('/services/data/v20.0/endpoint'); Forrest::head('/services/data/v20.0/endpoint'); Forrest::post('/services/data/v20.0/endpoint', ['my'=>'param']); Forrest::put('/services/data/v20.0/endpoint', ['my'=>'param']); Forrest::patch('/services/data/v20.0/endpoint', ['my'=>'param']); Forrest::delete('/services/data/v20.0/endpoint');
从 ContentVersion 和 Attachment 获取文件内容
您可以使用 Forrest::getContentVersionBody() 和 Forrest::getAttachmentBody() 来检索上传文件的内容。由于它们返回的是流式响应,因此如果现在用于流,可能会有些繁琐。下面是一个检索上传内容版本内容的示例。
# example $data = Forrest::getContentVersionBody($version->Id); $content = $data->getBody()->getContents();
原始响应输出
默认情况下,此包将返回响应体作为反序列化的 JSON 对象或 SimpleXMLElement 对象。
有时,您可能希望以不同的方式处理。为此,只需使用 'none' 格式,代码将返回整个响应体作为字符串。
$response = Forrest::sobjects($resource, ['format'=> 'none']); echo $response; // Unformatted string
事件监听器
此包使用 Guzzle 的事件监听器。
Event::listen('forrest.response', function($request, $response) { dd((string) $response); });
创建多个 Forrest 实例
可能存在需要向多个 Salesforce org 发起调用的场景。这只能通过 UserPassword 流来实现。
- 在配置文件中将 storage 设置为
object
。这将把令牌存储在对象实例中。
'storage'=> [ 'type' => 'object' ],
- 使用 Laravel 的
app()->make()
辅助函数创建多个实例
$forrest1 = app()->make('forrest'); $forrest1->setCredentials(['username' => 'user@email.com.org1', 'password'=> '1234']); $forrest1->authenticate(); $forrest2 = app()->make('forrest'); $forrest2->setCredentials(['username' => 'user@email.com.org2', 'password'=> '1234']); $forrest2->authenticate();
有关 Guzzle 响应和事件监听器的更多信息,请参阅他们的文档。
创建自定义存储
如果您希望使用除 session
、cache
或 object
之外的存储,您可以通过在 storage.type
中配置自定义类实例来实现自定义实现。
'storage' => [ 'type' => App\Storage\CustomStorage::class, ],
您可以为类命名任何名称,但必须实现 Omniphx\Forrest\Interfaces\StorageInterface
。
<?php namespace App\Storage; use Session; use Omniphx\Forrest\Exceptions\MissingKeyException; use Omniphx\Forrest\Interfaces\StorageInterface; class CustomStorage implements StorageInterface { public $path; public function __construct() { $this->path = 'app.custom.path'; } /** * Store into session. * * @param $key * @param $value * * @return void */ public function put($key, $value) { return Session::put($this->path.$key, $value); } /** * Get from session. * * @param $key * * @return mixed */ public function get($key) { if(!$this->has($key)) { throw new MissingKeyException(sprintf('No value for requested key: %s', $key)); } return Session::get($this->path.$key); } /** * Check if storage has a key. * * @param $key * * @return bool */ public function has($key) { return Session::has($this->path.$key); } }