Loading
Расширение Salesforce с помощью кликов, а не кода
Использование примеров схемы

Использование примеров схемы

Посмотрите, как соответствующие примеры Open API 2.0 и 3.0 внедряются в Apex.

Требуемые версии

Доступно в версиях: Lightning Experience
Доступно в версиях: Enterprise Edition, Performance Edition, Unlimited Edition и Developer Edition

Для примеров 9: allOf Composition и additionalProperties Use in Flow с тестами единицы Apex

MyBank регистрации внешних служб из примера 9 (из примеров OpenAPI 2.0 и 3.0) вызывается типичным потоком, который открывает свойства словаря посредством вызываемого действия Apex. Тестирование единицы потока Apex связывает все вместе.

public class MyBankGetCreditRatings {
    @InvocableMethod(
        label='Get Credit Ratings'
        description='A list of credit ratings for a customer'
        category='MyBank'
    )
    public static List<CustomerCreditRatings>
    getCreditRatings(List<Customer> inCustomers) {   
    
        List<CustomerCreditRatings> outCreditRatingsList = 
            new List<CustomerCreditRatings>();
        for (Customer inCustomer: inCustomers) {
            ExternalService.MyBank_Customer customer = inCustomer.customer;
            CustomerCreditRatings outCreditRatings = new CustomerCreditRatings();
            outCreditRatings.customerId = customer.id;
            outCreditRatings.creditRatings = 
                new List<ExternalService.MyBank_CreditRating>();
            
            Map<String, ExternalService.MyBank_CreditRating> creditRatings = 
                customer.properties;
            for (String ratingProperty: creditRatings.keySet()) {
                ExternalService.MyBank_CreditRating creditRating = 
                    creditRatings.get(ratingProperty);
                outCreditRatings.creditRatings.add(creditRating);
            }
            
            outCreditRatingsList.add(outCreditRatings);
        }
        
        return outCreditRatingsList;
    }
    
    public class Customer {
        @InvocableVariable(
            label='Customer'
            description='Banking customer'
            required=true
        )
        public ExternalService.MyBank_Customer customer;
    }
    
    public class CustomerCreditRatings {
        @InvocableVariable(
            label='Customer ID'
            description='Bank customer ID'
            required=true
        )
        public Integer customerId;
    
        @InvocableVariable(
            label='Credit Ratings'
            description='Credit ratings for a customer'
            required=true
        )
        public List<ExternalService.MyBank_CreditRating> creditRatings;
    }
}

Поток начинается с вызова getCustomerById действий службы внешней MyBank для получения сведений о клиенте с кодом клиента. Вызываемый getCreditRatings действий потока Apex получает список кредитных рейтингов из сведений о клиенте. Сведения о контактах телефона и эл. почты форматируются как список контактов клиента посредством цикла по свойствам phones и emails и назначения отформатированного значения списку contacts.

example_in_flow

Имитация выноски HTTP утверждает ожидаемый запрос и отвечает примером клиента как application/json:

public class MyBankGetCustomerCalloutMock implements HttpCalloutMock {
    public HTTPResponse respond(HTTPRequest request) {
        // Assert expected request test data: customer ID in the request path
        System.assertEquals('GET', request.getMethod());
        System.assertEquals('callout:MyBank/v1/customers/42', request.getEndpoint());
         
        // Send response test data: customer details with sample ratings
        // as additional properties and sample contacts
        HttpResponse response = new HttpResponse();
        response.setHeader('Content-Type', 'application/json');
        response.setBody('{' +
            '"id": 42, "name": "Foo Bar", "phones": [' + 
            '  {"primary": true,  "timeOfDay": "Daytime", ' + 
            '      "typeOfPhone": "Mobile", "phoneNumber": "555-5555"},' +
            '  {"primary": false, "timeOfDay": "Evening", ' + 
            '      "typeOfPhone": "Landline", "phoneNumber": "222-5555"}' +
            '], "emails": [' +
            '  {"primary": true, "timeOfDay": "AllDay", "email": "fooBar@acme.org"}' +
            '],' +
            '"rating1": {"rating": "Rating 1", "score": 0.95}, ' + 
            '"rating2": {"rating": "Rating 2", "score": 0.78}' +
        '}');
        response.setStatusCode(200);
        return response;        
    }
}
Совет
Совет Вы также можете использовать JSON для сериализации образца ответа, соответствующего типу ответа внешней службы, если медиа-тип ответа HTTP является application/json, а свойства JSON соответствуют символам идентификатора Apex:
ExternalService.MyBank_Customer customer = new ExternalService.MyBank_Customer();
customer.id = 42;
...
customer.properties = new Map<String, ExternalService.MyBank_CreditRating>();
ExternalService.MyBank_CreditRating creditRating = new ExternalService.MyBank_CreditRating();
creditRating.rating = 'Rarging 1';
creditRating.score = 0.95;
customer.properties.put('rating1', creditRating);
...
response.setBody(System.JSON.serialize(customer));
....

Тест единицы Apex настраивает муляж выноски HTTP и утверждает ожидаемые кредитные рейтинги и контакты клиента:

@IsTest
public class MyBankFlowTest {
    @IsTest
    static public void testGetCustomer() {
        // Set HTTP callout mock to match flow's external service action invocation
        Test.setMock(HttpCalloutMock.class, new MyBankGetCustomerCalloutMock());
    
        // Set flow input variables and create the flow interview
        Map<String, Object> inputVariables = new Map<String, Object>();
        inputVariables.put('customerId', 42);
        Flow.Interview myBankFlow = Flow.Interview.createInterview('MyBank', inputVariables);
        
        // Start flow interview with set input variables
        myBankFlow.start();
        
        // Assert customer's expected credit ratings
        List<ExternalService.MyBank_CreditRating> creditRatings = 
            (List<ExternalService.MyBank_CreditRating>)myBankFlow.
                getVariableValue('creditRatings');
        System.assertEquals(2, creditRatings == null ? 0 : creditRatings.size());
        ExternalService.MyBank_CreditRating actualRating = creditRatings.get(1);
        ExternalService.MyBank_CreditRating expectedRating = 
            new ExternalService.MyBank_CreditRating();
        expectedRating.rating = 'Rating 2';
        expectedRating.score = 0.78;
        System.assertEquals(expectedRating.toString(), actualRating.toString());
        
        // Assert customer's contacts:
        List<String> contacts = (List<String>)myBankFlow.getVariableValue('*contacts*');
        System.assertEquals(3, contacts == null ? 0 : contacts.size());
        System.assertEquals('Phone Number: 555-5555', contacts.get(0));
        System.assertEquals('Phone Number: 222-5555', contacts.get(1));
        System.assertEquals('Email: fooBar@acme.org', contacts.get(2));
    }
}

Для получения еще одного примера поблочного тестирования Apex потока, см. Тестирование внешних служб.

Для примеров 9: allOf компоновки и additionalProperties Use в Apex с тестами единицы Apex

MyBank регистрации внешних служб из примера 9 (из примеров OpenAPI 2.0 и 3.0) вызывается образцом класса Apex, который открывает свойства словаря. Тестирование единицы Apex связывает всё вместе.

CustomerCreditRating класса собирает сведения о клиенте, пригодные для дальнейшей обработки. Можно напрямую использовать структуру данных вывода ответа внешней службы. Рекомендуем отделить структуру данных, связанных с предприятием, от внешних зависимостей:

public class CustomerCreditRating {
    public Integer Id {get; private set;}
    public String Name {get; private set;}
    
    private List<String> emails;
    private List<String> phoneNumbers;
    private Map<String, Integer> ratings;

    public CustomerCreditRating(Integer customerId, String name) {
        this.Id = customerId;
        this.Name = name;
        this.emails = new List<String>();
        this.phoneNumbers = new List<String>();
        this.ratings = new Map<String, Integer>();
    }

    public void addEmail(String email) {
        emails.add(email);
    }

    public void addPhoneNumber(String phoneNumber) {
        this.phoneNumbers.add(phoneNumber);
    }

    public List<String> getContacts() {
        List<String> contacts = new List<String>();
        for (String phoneNumber: phoneNumbers) {
            contacts.add('Phone Number: ' + phoneNumber);
        }
        for (String email: emails) {
            contacts.add('Email: ' + email);
        }
        return contacts;
    }

    public void addRating(String ratingType, Integer ratingScore) {
        ratings.put(ratingType, ratingScore);
    }

    public Set<String> getRatingTypes() {
        return ratings.keySet();
    }

    public Integer getRatingScore(String ratingType) {
        return ratings.get(ratingType);
    }
}

MyBankCustomerCreditRating класса Apex начинается с вызова getCustomerById действий внешней службы MyBank для получения сведений о клиенте. getCreditRating метода Apex получает кредитный рейтинг из сведений о клиенте. Сведения о контактах телефона и эл. почты форматируются как список контактов клиента посредством цикла свойств phones и emails и назначения отформатированного значения списку контактов:

public class MyBankCustomerCreditRating {
    public class MyBankException extends Exception {}

    public CustomerCreditRating getCreditRating(Integer customerId) {
        // Get customer credit rating from an external bank rating service
        // Construct the external service registration MyBank
        ExternalService.MyBank myBank = new ExternalService.MyBank();
        
        // Make the callout to get the customer by ID.
        // The response is the customer detail for HTTP code 200
        ExternalService.MyBank_Customer customer;
        try {
             ExternalService.MyBank.getCustomersByCustomerId_Request request =
                new ExternalService.MyBank.getCustomersByCustomerId_Request();
             request.customerId = customerId;
             customer = myBank.getCustomersByCustomerId(request).Code200;
        } catch (ExternalService.MyBank.getCustomersByCustomerId_ResponseException e) {
            // An HTTP failure code is thrown as exception - 
            // captured and translated to a meaningful error
            throw new MyBankException(
                'Credit rating not available for customer ID: ' 
                + customerId);
        }

        // Gather the customer name, contacts and credit ratings
        // from the callout's response data
        CustomerCreditRating customerRating = 
            new CustomerCreditRating(customerId, customer.name);
        for (ExternalService.MyBank_Email email: customer.emails) {
            customerRating.addEmail(email.email);
        }
        for (ExternalService.MyBank_Phone phone: customer.phones) {
            customerRating.addPhoneNumber(phone.phoneNumber);
        }
        for (String ratingType: customer.properties.keySet()) {
            ExternalService.MyBank_CreditRating rating = 
                customer.properties.get(ratingType);
            Integer ratingPercent = (Integer)(rating.score * 100.0);
            customerRating.addRating(ratingType, ratingPercent);
        }

        return customerRating;
    }
}

Вы можете предоставить общий доступ к одному классу имитации выноски HTTP для интеграции Apex. Соответствующий класс тестирования единицы Apex тестирует логику кредитного рейтинга Apex:

@IsTest
public class MyBankCustomerRatingTest {
    @IsTest
    static public void testGetCustomerRating() {
        // Set HTTP callout mock to match Apex's external service callout
        Test.setMock(HttpCalloutMock.class, new MyBankGetCustomerCalloutMock());
        
        // Call the Apex MyBankCustomerRating class
        MyBankCustomerCreditRating myBankCreditRating = new MyBankCustomerCreditRating();
        CustomerCreditRating creditRating = myBankCreditRating.getCreditRating(42);
        
        // Assert customer's expected credit ratings
        System.assertEquals(2, creditRating.getRatingTypes().size());
        Integer actualRatingScore = creditRating.getRatingScore('rating2');
        Integer expectedRatingScore = 78;
        System.assertEquals(expectedRatingScore, actualRatingScore);
        
        // Assert customer's contacts:
        List<String> contacts = creditRating.getContacts();
        System.assertEquals(3, contacts.size());
        System.assertEquals('Phone Number: 555-5555', contacts.get(0));
        System.assertEquals('Phone Number: 222-5555', contacts.get(1));
        System.assertEquals('Email: fooBar@acme.org', contacts.get(2));
    }
}

Для примеров 10: Полиморфизм с allOf и Discriminator

Директива discriminator может быть объединена с allOf для определения полиморфного типа композиции. Полиморфные типы помечаются суффиксом _KT_PT в имени объекта Apex. Работайте с полиморфными типами расширений посредством полиморфного типа объекта.

Данный пример иллюстрирует способ взаимодействия с полиморфными типами в Apex посредством характеристики OpenAPI из примера 10. Контакт является базовым типом. Телефон и эл. почта - это полиморфные типы расширений, моделирующие типы контактов, которые могут быть назначены списку контактов клиента:

// The customer
ExternalService.MyBank_Customer customer = new ExternalService.MyBank_Customer();

// The primary phone contact wrapped as polymorphic type Contact_KT_PT
ExternalService.MyBank_Phone mobile = new ExternalService.MyBank_Phone();
mobile.primary = true;
mobile.typeOfPhone = 'Mobile';
mobile.phoneNumber = '555-5555';
ExternalService.MyBank_Contact_KT_PT cMobile =new ExternalService.MyBank_Contact_KT_PT();
cMobile.phone = mobile; // cMobile is a phone contact
        
// Customer's secondary home phone contact
ExternalService.MyBank_Phone home = new ExternalService.MyBank_Phone();
home.primary = false;
home.typeOfPhone = 'Home';
home.phoneNumber = '444-4444';
ExternalService.MyBank_Contact_KT_PT cHome = new ExternalService.MyBank_Contact_KT_PT();
cHome.phone = home; // cHome is a phone contact
        
// Customer's email
ExternalService.MyBank_Email email = new ExternalService.MyBank_Email();
email.primary = true;
email.email = 'someone@somewhere.org';
ExternalService.MyBank_KT_PT cEmail = new ExternalService.MyBank_Contact_KT_PT();
cEmail.email = email; // cEmail is an email contact
        
// Adding mobile, home phone and email as contacts to the customer contacts list
customer.contacts = new List<ExternalService.MyBank_Contact_KT_PT>();
customer.contacts.add(cMobile);
customer.contacts.add(cHome);
customer.contacts.add(cEmail);

// Send an email to a customer's primary email contacts
for (ExternalService.MyBank_Contact_KT_PT contact: customer.contacts) {
  if (contact.email != null && contact.email.primary) {
    String emailAddress = contact.email.email;
    // Sending email to email address
    ...
  }
}

Например, пример 11 (Open API 3.0): AnyOf, OneOf и Discriminator

oneOf или anyOf определяют тип композиции - может использоваться как одна из схем, так и любая из них. Типы схем компоновки доступны посредством свойств соответствующего типа компоновки следующим образом:

  • Именованная Name схемы, называемая компоновочной схемой: anyOfName или oneOfName.
  • Объект встроенной схемы компоновки: anyOfObject или oneOfObject. Если в композиции объявлено более одного встроенного объекта, порядок описания добавляется в качестве суффикса порядкового номера. Например, oneOfObject1, oneOfObject2 для первого и второго типа компоновки соответственно.
  • Массив встроенной схемы компоновки: anyOfArray или oneOfArray. Если в композиции объявлено более одного встроенного массива, порядок описания добавляется в качестве суффикса порядкового номера. Например, oneOfArray1, oneOfArray2.
  • Примитивный тип встроенной компоновки: anyOfTypeName или oneOfTypeName. Если встроенная компоновка ссылается на один и тот же тип, то подобные типы добавляются в спецификацию с суффиксом порядка описания (например anyOfString1, anyOfString2).

Данный пример иллюстрирует способ взаимодействия с типами anyOf и oneOf в Apex посредством характеристики OpenAPI из примера 11. Contact является базовым типом. Phone и Email - это полиморфные типы расширений, моделирующие типы контактов, которые могут быть назначены списку контактов клиента. Клиент может быть идентифицирован по любому номеру социального обеспечения, водительским правам или личному имени и фамилии, а также дополнительному отчеству:

ExternalService.MyBank_Customer customer = new ExternalService.MyBank_Customer();

// Setting the customer ID
customer.id = new ExternalService.MyBank_Customer_id();
// Setting the social security security number
customer.id.anyOfSSN.ssn = '555-55-5555';
// Setting the customer's first and last name without a middle name
customer.id.anyOfFullName = new ExternalService.MyBank_FullName();
customer.id.anyOfFullName.firstName = 'Somefirstname';
customer.id.anyOfFullName.lastName = 'Somelastname';

// Customer contacts
ExternalService.MyBank_Phone mobile = new ExternalService.MyBank_Phone();
mobile.typeOfPhone = 'Mobile';
mobile.phoneNumber = '555-5555';
ExternalService.MyBank_Contact cMobile = new ExternalService.MyBank_Contact();
cMobile.oneOfPhone = mobile;

ExternalService.MyBank_Phone home = new ExternalService.MyBank_Phone();
home.typeOfPhone = 'Home';
home.phoneNumber = '444-4444';
ExternalService.MyBank_Contact cHome = new ExternalService.MyBank_Contact();
cHome.oneOfPhone = home;

ExternalService.MyBank_Email email = new ExternalService.MyBank_Email();
email.email = 'someone@somewhere.org';
ExternalService.MyBank_Contact cEmail = new ExternalService.MyBank_Contact();
cEmail.oneOfEmail = email;

customer.contacts = new List<ExternalService.MyBank_Contact>();
customer.contacts.add(cMobile);
customer.contacts.add(cHome);
customer.contacts.add(cEmail);

// Sending the customer's known identities to the customer's email address
String emailContact = null;
for (ExternalService.MyBank_Contact contact: customer.contacts) {
    if (contact.oneOfEmail != null) {
        emailContact = contact.oneOfEmail.email;
    }
}
if (emailContact != null) {
    String subject = 'Your identity';
    String body = 'These are the identities we\'ve found: \n';
    if (customer.id.anyOfSSN != null) {
        body += '  - Social Security Number: ' + customer.id.anyOfSSN.ssn + '\n';
    }
    if (customer.id.anyOfDriversLicense != null) {
        body += '  - Driver\'s License: ' + customer.id.anyOfDriversLicense.dl + '\n';
    }
    if (customer.id.anyOfFullName != null) {
        body += '  - First name: ' + customer.id.anyOfFullName.firstName + '\n';
        if (customer.id.anyOfFullName.middleName != null) {
            body += '    Middle name: ' + customer.id.anyOfFullName.middleName + '\n';
        }
        body += '    Last name: ' + customer.id.anyOfFullName.lastName + '\n';
    }
    ...
}

Например, пример 13 (Open API 3.0): Загрузка двоичного файла

Примеры типов Apex в данном разделе см. в разделе Пример 13: Загрузка и загрузка файлов (OAS 3.0). Сначала вы регистрируете внешнюю службу посредством операции PUT, содержащей имя файла для загрузки и двоичный requestBody. Здесь регистрация внешней службы в организации называется s3. Данный пример сначала создает экземпляр внешней службы s3, а потом создает экземпляр операции putObject. Он задает следующие значения параметров ввода для объекта request.

  • key—Имя файла после его загрузки во внешнюю систему.
  • Contentx2dType: тип содержимого.
  • body—Код файла (хранящегося как ContentDocument) в организации.

Этот фрагмент можно протестировать, запустив в консоли разработчика. Файл hello.jpeg будет загружен во внешнее расположение.

// Upload File
ExternalService.s3 fileService = new ExternalService.s3();
ExternalService.s3.putObject_Request request = new ExternalService.s3.putObject_Request();
request.key = 'hello.jpeg';
request.Contentx2dType = 'image/jpeg';
request.body = '123ABC00000123PXYZ';

try {
    ExternalService.s3.putObject_Response response = fileService.putObject(request);
    
    if (response.responseCode == 200) {
        System.debug('Success |' + response);
    }
} catch (ExternalService.s3.putObject_ResponseException e) {
    if (e.responseCode == 400) {
        System.debug('Bad request: ' + e.Code400);
    } else if (e.responseCode == 404) {
        System.debug('Object not found: ' + e.Code404);
    } else if (e.responseCode == 500) {
        System.debug('Internal server error: ' + e.Code500);
    } else {
        System.debug('Unexpected error: ' + e.defaultResponse);
    }
}

Например, пример 13 (Open API 3.0): Загрузка двоичного файла

Примеры типов Apex в данном разделе см. в разделе Пример 13: Загрузка и загрузка файлов (OAS 3.0). Сначала вы регистрируете внешнюю службу посредством операции GET, содержащей имя файла для загрузки и двоичный объект content в ответе. Здесь регистрация внешней службы в организации называется s3. Данный пример сначала создает экземпляр внешней службы s3, а потом создает экземпляр операции getObject. Он задает следующие значения параметров ввода для объекта request.

  • key: имя файла для загрузки из внешней системы.

Этот фрагмент можно протестировать, запустив в консоли разработчика. Файл test.jpeg будет загружен из внешнего расположения.

// Download File
ExternalService.s3 fileService = new ExternalService.s3();
ExternalService.s3.getObject_Request request = new ExternalService.s3.getObject_Request();
request.key = 'test.jpeg';

try {
    ExternalService.s3.getObject_Response response = fileService.getObject(request);
    
    if (response.responseCode == 200) {
        System.debug('Success |' + response);
    }
} catch (ExternalService.s3.getObject_ResponseException e) {
    if (e.responseCode == 403) {
        System.debug('Access denied: ' + e.Code403);
    } else if (e.responseCode == 404) {
        System.debug('Object not found: ' + e.Code404);
    } else if (e.responseCode == 500) {
        System.debug('Internal server error: ' + e.Code500);
    } else {
        System.debug('Unexpected error: ' + e.defaultResponse);
    }
}
 
Загрузка
Salesforce Help | Article