Salesforce REST 接口集成服务(二)

在 Salesforce REST 接口集成服务 一文中,主要讲述了如何调用外部服务器的接口,那么该如何开放Salesforce内部接口给外部系统呢?
将Apex类作为Rest Web服务可用非常简单
  • 定义Class 为Global
  • 定义Method为global static
  • 在类和方法上添加注解,比如@HttpGet
类似这样:
@RestResource(urlMapping='/Account/*')
global with sharing class MyRestResource {
    @HttpGet
    global static Account getRecord() {
        // 写入代码
        return null; 
    }
}
在MyRestResource上,我们使用了@RestResource(urlMapping='/Account/*') 进行标注,那么访问该Class的URL路径即
https://yourInstance.salesforce.com/service/apexrest/Account/*
Tips: URL区分大小写,并且可以包含通配符(*)
其中https://yourInstance.salesforce.com为Salesforce组织域名,/service/apexrest是固定关键字,/Account/*是每个开放的接口映射的路径
Tips: 如果是托管包中包含Apex REST方法时,需要加上托管包命名空间,比如MyRestResource类在名为packageNamespace的托管程序包命名空间中,那么通过REST调用这些方法使用的URL格式为 https://instance.salesforce.com/services/apexrest/packageNamespace/Account/*
在每一个Salesforce类中,方法上的注解共有五种,且每种仅能出现一次
简单说,@HttpGet 用于读取检索Salesforce系统中的数据,@HttpPost用于创建记录到Salesforce中,@HttpDelete 用于删除Salesforce中的记录,@HttpPut用于更新Salesforce中的记录,特殊的是,如果有的字段没有传值,会将原本记录上的值置空,类似于Upsert,@HttpPatch 同样用于更新Salesforce中的值,不同于HttpPut的一点是,你传什么字段就更新什么字段,不会说覆盖没有传递的字段值
@RestResource(urlMapping='/Cases/*')
global with sharing class CaseManager {
    @HttpGet
    global static Case getCaseById() {
        RestRequest request = RestContext.request;
        // 从URL末尾获取case Id
        String caseId = request.requestURI.substring(
          request.requestURI.lastIndexOf('/')+1);
        Case result =  [SELECT CaseNumber,Subject,Status,Origin,Priority
                        FROM Case
                        WHERE Id = :caseId];
        return result;
    }
    @HttpPost
    global static ID createCase(String subject, String status,
        String origin, String priority) {
        Case thisCase = new Case(
            Subject=subject,
            Status=status,
            Origin=origin,
            Priority=priority);
        insert thisCase;
        return thisCase.Id;
    }  
    @HttpDelete
    global static void deleteCase() {
        RestRequest request = RestContext.request;
        String caseId = request.requestURI.substring(
            request.requestURI.lastIndexOf('/')+1);
        Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
        delete thisCase;
    }    
    @HttpPut
    global static ID upsertCase(String subject, String status,
        String origin, String priority, String id) {
        Case thisCase = new Case(
                Id=id,
                Subject=subject,
                Status=status,
                Origin=origin,
                Priority=priority);
        // ID区分大小写
        upsert thisCase;
        // 返回case Id
        return thisCase.Id;
    }
    @HttpPatch
    global static ID updateCaseFields() {
        RestRequest request = RestContext.request;
        String caseId = request.requestURI.substring(
            request.requestURI.lastIndexOf('/')+1);
        Case thisCase = [SELECT Id FROM Case WHERE Id = :caseId];
        // 将JSON字符串反序列化
        Map<String, Object> params = (Map<String, Object>)JSON.deserializeUntyped(request.requestbody.tostring());
        // 遍历
        for(String fieldName : params.keySet()) {
            // 赋值
            thisCase.put(fieldName, params.get(fieldName));
        }
        update thisCase;
        return thisCase.Id;
    }   
}
Apex REST支持OAuth2.0 和会话身份验证两种机制,不过在进行接口测试时,Salesforce提供了WorkBench来简化测试流程
 使用Salesforce账号登录WorkBench,然后选择 utilities | REST Explorer,选择 POST方式,如下图:
 

点击Execute后,即可查看接口执行结果如下,点击Show Raw Response可以查看接口返回的原始信息 

其他的GET等标准方式测试方式同POST.

Tips: Workbench是一套功能强大的基于Web的工具套件,供管理员和开发人员通过Lightning Platform API与组织进行交互。通过Workbench,可以使用会话身份验证,并使用用户名和密码登录到Salesforce,从而使用REST资源管理器调用REST服务
如果考虑对API端点进行版本控制,以便可以在不破坏现有代码的情况下提供功能升级,我们可以创建两个类来指定/ Cases / v1 / *和/ Cases / v2 / *的URL映射,实现接口版本的平滑切换
最后,测试Apex REST类与测试任何其他Apex类相似,只需通过传入参数值来调用类方法,然后验证结果。 对于不带参数或依赖REST请求中信息的方法,可以通过模拟REST请求类覆盖测试
// 模拟一个Rest请求
RestRequest request = new RestRequest();
// 模拟REST请求参数
request.requestUri = 'https://yourInstance.salesforce.com/services/apexrest/Cases/' + recordId;
request.httpMethod = 'GET';
request.params.put('status', 'Working');
// 最后分配这个REST请求给RestContext
RestContext.request = request;
所以CaseManager的测试类如下
@IsTest
private class CaseManagerTest {
    @isTest static void testGetCaseById() {
        Id recordId = createTestRecord();
        //  模拟Request 请求
        RestRequest request = new RestRequest();
        request.requestUri = 'https://yourInstance.salesforce.com/services/apexrest/Cases/‘  + recordId;
        request.httpMethod = 'GET';
        RestContext.request = request;
        // 调用测试方法
        Case thisCase = CaseManager.getCaseById();
        //  断言验证结果
        System.assert(thisCase != null);
        System.assertEquals('Test record', thisCase.Subject);
    }
    @isTest static void testCreateCase() {
        ID thisCaseId = CaseManager.createCase('Ferocious chipmunk', 'New', 'Phone', 'Low');
        System.assert(thisCaseId != null);
        Case thisCase = [SELECT Id,Subject FROM Case WHERE Id=:thisCaseId];
        System.assert(thisCase != null);
        System.assertEquals(thisCase.Subject, 'Ferocious chipmunk');
    }
    @isTest static void testDeleteCase() {
        Id recordId = createTestRecord();
        // 模拟Request 请求
        RestRequest request = new RestRequest();
        request.requestUri =  'https://yourInstance.salesforce.com/services/apexrest/Cases/‘  + recordId;
        request.httpMethod = 'GET';
        RestContext.request = request;
        // 调用测试方法
        CaseManager.deleteCase();
        // 验证结果是否删除
        List<Case> cases = [SELECT Id FROM Case WHERE Id=:recordId];
        System.assert(cases.size() == 0);
    }
    @isTest static void testUpsertCase() {
        ID case1Id = CaseManager.upsertCase( 'Ferocious chipmunk', 'New', 'Phone', 'Low', null);
        System.assert(Case1Id != null);
        Case case1 = [SELECT Id,Subject FROM Case WHERE Id=:case1Id];
        System.assert(case1 != null);
        System.assertEquals(case1.Subject, 'Ferocious chipmunk');
        // 更新状态 New → Working
        ID case2Id = CaseManager.upsertCase('Ferocious chipmunk', 'Working', 'Phone', 'Low', case1Id);
        // 验证是否更新
        System.assertEquals(case1Id, case2Id);
        Case case2 = [SELECT Id,Status FROM Case WHERE Id=:case2Id];
        System.assert(case2 != null);
        System.assertEquals(case2.Status, 'Working');
    }   
    @isTest static void testUpdateCaseFields() {
        Id recordId = createTestRecord();
        RestRequest request = new RestRequest();
        request.requestUri = 'https://yourInstance.salesforce.com/services/apexrest/Cases/' + recordId;
        request.httpMethod = 'PATCH';
        request.addHeader('Content-Type', 'application/json');
        request.requestBody = Blob.valueOf('{"status": "Working"}');
        RestContext.request = request;
        ID thisCaseId = CaseManager.updateCaseFields();
        System.assert(thisCaseId != null);
        Case thisCase = [SELECT Id,Status FROM Case WHERE Id=:thisCaseId];
        System.assert(thisCase != null);
        System.assertEquals(thisCase.Status, 'Working');
    } 
    // 测试工具类
    static Id createTestRecord() {
        Case caseTest = new Case(
            Subject='Test record',
            Status='New',
            Origin='Phone',
            Priority='Medium');
        insert caseTest;
        return caseTest.Id;
    }         
} 
参考数据:
 
原文地址:https://www.cnblogs.com/luqinghua/p/12632137.html