用于Salesforce的Laravel库

资助包维护!
omniphx

2.15 2022-02-25 10:10 UTC

README

Laravel Latest Stable Version Total Downloads License Actions Status

Forrest是Laravel和Lumen的Salesforce/Force.com REST API客户端。

对Eloquent Salesforce模型感兴趣?请查看@roblesterjr04EloquentSalesForce项目,该项目使用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();

然后您可以通过在bootstrap/app.php文件中注册它来使用Lumen服务提供者。

配置

您需要一个配置文件来添加您的凭证。使用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

入门

设置连接应用程序

  1. 登录到您的Salesforce组织
  2. 点击右上角的设置菜单
  3. 在快速查找框中搜索App,并选择App Manager
  4. 点击新建连接应用程序。
  5. 输入以下远程应用程序的详细信息
    • 连接应用程序名称
    • API名称
    • 联系邮箱
    • 在API下拉菜单下启用OAuth设置
    • 回调URL
    • 选择访问范围(如果您需要刷新令牌,请在此处指定)
  6. 点击保存

保存后,您现在将获得一个消费者密钥和消费者密钥。更新您的配置文件,为consumerKeyconsumerSecretloginURLcallbackURI设置值。

设置

创建身份验证路由

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('/');
});

SOAP身份验证流程

(当您无法在Salesforce中创建连接应用程序时)

  1. Salesforce允许通过SOAP登录进行单独登录
  2. 从SOAP登录返回的Bearer访问令牌可以类似于OAuth密钥使用
  3. 更新您的配置文件,将authentication值设置为UserPasswordSoap
  4. 更新您的配置文件,为loginURLusernamepassword设置值。使用用户名密码SOAP流程,您可以直接使用Forrest::authenticate()方法进行身份验证。

要使用此认证,您可以将用户名和密码添加到配置文件中。除非您的IP地址被列入白名单,否则可能需要修改安全令牌。

Route::get('/authenticate', function()
{
    Forrest::authenticate();
    return Redirect::to('/');
});

如果您的应用程序需要以不同用户登录Salesforce,您可以选择将登录URL、用户名和密码传递给Forrest::authenticateUser()方法。

除非您的IP地址被列入白名单,否则可能需要修改安全令牌。

Route::Post('/authenticate', function(Request $request)
{
    Forrest::authenticateUser('https://login.salesforce.com',$request->username, $request->password);
    return Redirect::to('/');
});

JWT认证流程

初始设置

  1. config/forrest.php中将authentication设置为OAuthJWT
  2. 生成密钥和证书:openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt
  3. config/forrest.php中配置私有密钥(例如,file_get_contents('./../server.key')

设置连接应用程序

  1. App Manager > 创建连接应用
  2. 启用Oauth设置
  3. 勾选“使用数字签名”
  4. 添加server.crt或您选择的任何名称
  5. 作用域必须包括“refresh_token, offline_access”
  6. 点击保存

接下来,您需要预授权一个配置文件(目前只能在经典版中执行此步骤,但这是很重要的)

  1. 管理应用 > 连接应用
  2. 点击您应用旁边的“编辑”
  3. 将“允许用户”设置为“管理员批准用户已预授权”
  4. 保存
  5. 转到设置 > 管理用户 > 配置文件,并编辑关联用户的配置文件(即Salesforce管理员)
  6. 在“连接应用访问”下,检查相应的应用名称

实现方式与UserPassword完全相同

Route::get('/authenticate', function()
{
    Forrest::authenticate();
    return Redirect::to('/');
});

自定义登录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请求

searchquery资源外,所有资源都通过方法重载动态请求。

您可以通过调用资源方法来确定您可以访问哪些资源

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']);

批量Upsert多个记录(Bulk API 2.0)

当您需要快速将大量数据加载到Salesforce org时,批量API请求特别有用。关键区别在于它至少需要三个单独的请求(创建、添加、关闭),并且要加载的数据以CSV格式发送。

为了说明,以下是三个用于upsert CSV Contacts记录的请求。

创建

使用POST方法创建批量上传作业,正文包含以下作业属性

  • object 是您正在加载的对象类型(每个工作必须都是同一类型)。
  • externalIdFieldName 是外部 ID,如果存在,则更新;如果不存在,则插入新记录。仅适用于 upsert 操作。
  • contentType 是 CSV,目前这是唯一有效的值。
  • operation 设置为 upsert 以添加和更新记录。

我们将响应存储在 $bulkJob 中,以便在下面的添加和关闭请求中引用唯一的 Job ID。

有关这里可用选项的完整列表,请参阅 创建作业

$bulkJob = Forrest::jobs('ingest', [
    'method' => 'post',
    'body' => [
        "object" => "Contact",
        "externalIdFieldName" => "externalId",
        "contentType" => "CSV",
        "operation" => "upsert"
    ]
]);

添加数据

使用创建 POST 请求中的 Job ID,然后通过 PUT 请求发送要处理的 CSV 数据。这假设您已将 CSV 内容加载到 $csv

有关格式化详情,请参阅 准备 CSV 文件

Forrest::jobs('ingest/' . $bulkJob['id'] . '/batches', [
    'method' => 'put',
    'headers' => [
        'Content-Type' => 'text/csv'
    ],
    'body' => $csv
]);

关闭

在处理记录之前,您必须关闭作业,为此您需要通过 PATCH 请求向 Job ID 发送 UploadComplete 状态。

有关更多选项和如何取消作业的详情,请参阅 关闭或取消作业

$response = Forrest::jobs('ingest/' . $bulkJob['id'] . '/', [
    'method' => 'patch',
    'body' => [
        "state" => "UploadComplete"
    ]
]);

Bulk API 2.0 在 API 版本 41.0 及以后可用。有关 Salesforce Bulk 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');

原始响应输出

默认情况下,此包将响应体作为反序列化 JSON 对象或 SimpleXMLElement 对象返回。

可能存在您希望以不同方式处理的情况。为此,只需使用除 'json' 或 'xml' 之外的任何格式,代码将返回一个 Guzzle 响应对象。

$response = Forrest::sobjects($resource, ['format'=> 'none']);
$content = (string) $response->getBody(); // Guzzle response

事件监听器

此包利用了 Guzzle 的事件监听器

Event::listen('forrest.response', function($request, $response) {
    dd((string) $response);
});

创建多个 Forrest 实例

可能存在需要调用多个 Salesforce org 的情况。这只能通过 UserPassword 流来实现。

  1. 在配置文件中将 storage 设置为 object。这将将在对象实例中存储令牌
'storage'=> [
    'type' => 'object'
],
  1. 使用 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 响应和事件监听器的更多信息,请参阅它们的 文档