Если вам комфортно работать с традиционными платформами разработки, такими как Heroku, но теперь вам нужно интегрироваться в данные Salesforce, вы можете обнаружить много неожиданных отличий.

Salesforce не является традиционной программной платформой, с которой могут работать многие разработчики; это управляемая облачная платформа. Это означает:

  • Вам не нужно беспокоиться об управлении своими вычислительными ресурсами, такими как количество ядер ЦП, или о том, стоит ли платить за дополнительную оперативную память или на жесткий диск.
  • Большинство рутинных задач по кодированию выполняются за вас. (Это платформа с низким уровнем кода.)
  • Существуют строгие правила и ограничения, которые вы должны соблюдать при выполнении транзакций с базой данных, выполнении команд вычислений на стороне сервера и управлении асинхронной работой.

В этой статье я покажу, как начать создание интеграции на основе Python с платформой Salesforce, а также как ориентироваться в ее различиях и тонкостях. Мы создадим простое приложение Python, развернем его в Heroku, объясним, как интегрировать это приложение с некоторыми записями в Salesforce с помощью SOQL и как вставлять или обновлять новые записи.

Предпосылки

Вот необходимые предварительные условия, которые вам понадобятся:

  • Базовый синтаксис языка программирования Python и обычная среда выполнения CPython. На момент написания этой статьи использовалась среда выполнения и языковая версия Python 3.8.6.
  • Работа с контролем версий с помощью git.
  • Развертывание на Heroku с помощью git и Heroku CLI.
  • Организация разработчиков Salesforce. Если у вас еще нет организации Salesforce, с которой можно работать, вы можете бесплатно зарегистрироваться здесь.
  • В качестве бонуса: некоторый опыт написания языка структурированных запросов (SQL), хотя мы рассмотрим простой пример, который строго не требует предварительного опыта.

Кроме того, на всех скриншотах и ​​примерах будут показаны инструкции с использованием Visual Studio Code. Предостережение в том, что мы все еще используем в основном команды терминала командной строки. Вы можете использовать любой инструмент командной строки по вашему выбору (при условии, что команды Python работают с вашей локальной средой, указывая на правильный PATH или другой эквивалент операционной системы).

Соображения по поводу пакетов Pip

Как можно догадаться, лучше не беспокоиться о написании собственных интеграций с API-интерфейсами Salesforce; скорее, мы обратимся к пакетам, доступным через pip, Python Package Index. Среди самых популярных пакетов для Salesforce на момент написания этой статьи были simple_salesforce и aiosfstream, которые предназначены для REST / Bulk API и Streaming API для Salesforce соответственно.

Salesforce REST API, вероятно, является первым выбором для большинства интеграций из-за его простоты и универсальности. Как правило, обновления записей, вставки или транзакции, как правило, происходят в небольших размерах одной записи за раз. В этих случаях идеально подходит REST API: просто отправьте полезные данные в конечную точку (или унифицированный идентификатор веб-ресурса [URI]) и получите ответ по всему протоколу HTTP.

Что такое ОТДЫХ?

Если вы раньше не писали интеграцию с REST API, то этот раздел для вас. Кроме того, я рекомендую просмотреть другие ссылки на REST для более глубокого понимания здесь, что является очень поверхностным введением. (Если вам нравится REST, можете пропустить этот раздел.)

REST - это сокращение от «передачи репрезентативного состояния». Это большая сложная фраза, которая просто означает отправку и получение сообщений через HTTP. Когда вы посещаете веб-страницу в своем браузере, ваш браузер выполняет HTTP-запрос GET и получает ответ.

Существуют разные коды состояния HTTP: 200 означает успех, а 404 - не найден. Помимо запросов GET, существуют:

- PUT, обычно для вставки информации
- POST, обычно для обновления информации
- DELETE, для удаления вещей
- HEAD, который возвращает заголовок, своего рода метаинформацию, без тела ответа как обычно получается при запуске GET

Когда дело доходит до этих операций, HTTP взаимодействует с «ресурсами». По этой причине унифицированный указатель ресурса (URL) также называется унифицированным идентификатором ресурса (URI). URL-адрес - это определенный вид URI или подмножество URI.

Общий посыл здесь таков: не позволяйте всему этому жаргону о ресурсах или «полезной нагрузке данных» отвлекать вас от основной идеи - все, что на самом деле делается при интеграции REST, - это отправка сообщений и получение ответов. Помимо этого, у нас повсюду есть технический жаргон, но это основная концепция.

Сказав это, примеры в этой части будут в первую очередь сосредоточены на универсальности интеграции REST.

Когда не использовать REST с Salesforce

Позвольте мне вкратце указать на некоторые ключевые концепции, когда может быть нежелательно использовать REST при интеграции с Salesforce: массовые операции и потоки данных почти в реальном времени.

Для обработки больших объемов данных, обычно от тысяч до миллионов записей, Bulk API имеет больше смысла. По правде говоря, все API-интерфейсы REST, Bulk и Streaming используют принципы HTTP, но они оптимизированы для разных целей в Salesforce. В случае Bulk API он следует другому набору ограничений регулятора, запускает пакеты размером до 2000 записей для транзакций базы данных и имеет существенно отличный от REST API шаблон ответа. С помощью REST вы можете получать ответы на основе отдельных записей. С помощью Bulk вы можете получать ответы после завершения заданий массовой загрузки.

Наконец, Streaming API важен для волны растущей популярности систем, управляемых событиями, с помощью которых действия при интеграции выполняются не на основе запросов и ответов, а вместо этого исходят из широковещательных рассылок событий изменения для слушающих клиентов. События транслируются по отдельным каналам, которые обычно считаются находящимися в «шине событий», а затем принимаются (в отличие от запрошенных) слушателями.

События потоковой передачи важны, поскольку они позволяют преодолеть многие проблемы, связанные с задержкой или задержкой, если они реализованы правильно. Хорошим примером является понятие отслеживания измененных данных: если поле обновляется для данной записи в базе данных, идеально сразу знать, когда это произойдет, поскольку база данных сообщает клиентам, а не клиентам, запрашивающим эту информацию из базы данных. Такая стратегия позволяет избежать проверки штампов даты последнего изменения, сбора где-то старых и новых значений или других подобных проблем, которые затем становятся привязанными к периодическим запросам и ответам. Следовательно, если у вас есть ресурсы для обработки потока данных, то это идеальное решение по сравнению с массовым заданием, поскольку оно доставляет информацию почти в реальном времени, а не доставляет информацию о каком-то запланированном ежедневном запуске процесса (в случае массового выполнения).

Все это говорит о том, что simple_salesforce будет способом начать использовать REST или массовую загрузку. Он предоставляет оболочки в коде Python для формирования безопасного сеанса с проверкой подлинности с Salesforce, выполнения операций с базой данных и выбора, следует ли использовать конечные точки REST для отдельных записей или использовать задания массовой загрузки.

Если вам сложно понять разницу между API, не стесняйтесь возвращаться к этому разделу. Это просто обеспечивает основу, которая должна оказаться полезной для разработки решений в долгосрочной перспективе. Знание API-интерфейсов Salesforce окажется актуальным в будущем, потому что не все решения используют REST или массовые пакеты.

Начните с простого (или как можно проще, правда!)

Хотя есть много статей, в которых предлагается начать с какой-либо веб-инфраструктуры Python, такой как Django или Flask, здесь предлагается начать с простого. Начните с программы в стиле «привет, мир», которая может выполняться в контейнере Heroku, а затем наращивайте ее. Цель этого подхода, особенно в случае подхода к этой проблеме, состоит в том, чтобы уменьшить раздувание или беспорядок в начале, устранение ненужных зависимостей и сохранение управляемости области действия примера.

Получите что-нибудь, напечатанное как можно быстрее

Для начала создайте новый каталог с названием «_sample_app». Эта папка будет содержать все соответствующие программные файлы и может быть источником, на который можно ссылаться при создании для другого варианта использования. Используя терминал, перейдите во вновь созданный каталог. Если полностью следовать этим инструкциям через командную строку, это должно выглядеть так:

mkdir _sample_app
cd _sample_app

Внутри папки инициализируйте новый репозиторий git, используя git init.

Внутри Heroku создайте новое приложение с любым именем. Затем с помощью интерфейса командной строки Heroku убедитесь, что вы вошли в систему, используя heroku login.

В окне терминала, которое находится наготове в каталоге `_sample_app`, установите удаленный репозиторий Heroku с помощью команды CLI Heroku: heroku git:remote -a [app name].

Эти действия, конечно же, выполняют основную настройку для развертывания в приложении Heroku с использованием git, после чего должны быть созданы следующие файлы:

test_start.py

print("This is working!")

requirements.txt - скоро заполнится, просто создайте пустой текстовый файл на потом.

runtime.txt

python-3.8.6

Procfile

web: python test_start.py

.gitignore - в этом случае мой был автоматически сгенерирован с использованием Bitbucket, но копирование этих расширений обычно хорошо для любого репозитория приложений Python.

# These are some examples of commonly ignored file patterns.
# You should customize this list as applicable to your project.
# Learn more about .gitignore:
#     https://www.atlassian.com/git/tutorials/saving-changes/gitignore
# Node artifact files
node_modules/
dist/
# Compiled Java class files
*.class
# Compiled Python bytecode
*.py[cod]
# Log files
*.log
# Package files
*.jar
# Maven
target/
dist/
# JetBrains IDE
.idea/
# Unit test reports
TEST*.xml
# Generated by MacOS
.DS_Store
# Generated by Windows
Thumbs.db

Если вы хотите сохранить это в своей собственной системе управления версиями за пределами Heroku на будущее, вы можете развернуть его в отдельном репозитории.

В противном случае разверните!

git push heroku main

Затем масштабируйте веб-динамик, указанный в файле Procfile, который просто дает команду python запустить test_start.py.

heroku run web=1

После успешного развертывания и масштабирования до одного динамометрического стенда используйте `heroku logs '. В операторе печати из файла test_start.py должно отображаться сообщение: «Это работает!»

На данный момент это простое приложение Heroku, которое мало что делает, кроме как печатать оператор один раз при развертывании.

Вход в Salesforce вручную

Теперь мы готовы к подключению к организации Salesforce. Организация Salesforce - это экземпляр платформы Salesforce, который включает в себя все данные и логику любой компании, группы или организации. Платформа Salesforce сама по себе является собственным продуктом и служит главным центром, с помощью которого добавляются или настраиваются большинство других продуктов Salesforce. Большая часть бизнес-работы в Salesforce выполняется внутри производственной организации, тогда как большая часть работы по разработке выполняется в изолированной или временной организации. В этом примере вы будете использовать организацию Developer Edition, которая рассматривается как производственная организация. Если вам интересно узнать о тонкостях сред разработки Salesforce по сравнению с их« производственными аналогами, см. Их документацию».

Убедитесь, что организация Salesforce готова. Пройдите процесс регистрации на странице https://developer.salesforce.com/signup. Заполните форму, указав соответствующую информацию. Через некоторое время вы получите электронное письмо от Salesforce с данными для входа, уведомляющее о том, что организация создана в соответствии с запросом. Затем, используя учетные данные для имени пользователя и пароля для организации, войдите в систему на странице https://login.salesforce.com.

Имя пользователя и пароль для входа в систему вручную - это та же информация, которая используется для подключения к организации в Python. Каждое подключение к Salesforce происходит в контексте пользователя Salesforce. Когда соединение устанавливается с API, пользовательский контекст определяет доступ пользователя к определенным объектам, полям и другим функциям. Это контролирует, какие данные доступны для чтения или редактирования при подключении к API.

Помимо имени пользователя и пароля необходим токен безопасности. Найдите токен безопасности, перейдя в пользовательские настройки в Salesforce. Он находится от правого значка типа, который вызывает раскрывающийся список. Затем перейдите в «Настройки» и используйте «Сбросить мой токен безопасности».

Salesforce отправит электронное письмо с токеном безопасности. Храните его в надежном месте, так как он понадобится вам для аутентификации с помощью Python позже.

Добавить simple_salesforce через Pip

Обновите файл requirements.txt, чтобы установить simple_salesforce как часть зависимостей этого приложения. Обратите внимание, что в этом примере используется версия 1.10.1 simple_salesforce. Дополнительную информацию о simple_salesforce и исходном коде можно найти здесь: https://github.com/simple-salesforce/simple-salesforce.

requirements.txt

simple_salesforce==1.10.1

Если вы много работали с Python, вы знаете, что делать: `python -m pip install -r requirements.txt`

Интеграция Python с Salesforce: рассмотрение объекта подключения

А теперь самое интересное - давайте интегрируем Python с нашими данными Salesforce.

Обновите test_start.py, чтобы сформировать объект подключения для Salesforce, что очень похоже на пример из документации simple_salesforce. (Теперь вы можете удалить оператор печати, поскольку он в основном служил заполнителем.)

test_start.py

from simple_salesforce import Salesforce
# A general connection object variable can be initialized, 
# which will then be populated with the Salesforce connection
# object as it is returned from simple_salesforce.
production_connection = None
# The content of the string variables below should be replaced
# with your own connection credentials. The API version, 50.0, 
# happens to be the latest Salesforce API version from this writing,
# but there might be changes that happen later from future Salesforce API
# versions. 
#
# The domain, specifies the login domain known from:
# https://login.salesforce.com
#
# Using 'test' for the login domain would point to:
# https://test.salesforce.com
# That domain is used for sandbox environments. A free
# developer org in this example, though, is considered a 
# 'production' Salesforce org and therefore would go to 
# the 'login' domain, not 'test' or something else.
#
# While this example has direct statements of these string
# variables, it is ideal in a production grade solution to
# reference these variables via either an environment 
# configuration or an encrypted vault. The direct statement
# of the username and password here is done for simplicity.
if production_connection is None:
production_connection = Salesforce(username="<username>",
 password="<password>",
 security_token="<security_token>",
 version=50.0, # the API version of Salesforce, for its metadata
 domain='login') # login means: a production org

Работа с записями Salesforce

Чтобы получить записи Salesforce, вам потребуется использовать язык запросов Salesforce Object Query Language (SOQL). SOQL обманчиво очень похож на SQL. Осторожно: SOQL - это не SQL! Существует явный недостаток ряда функций, таких как объединения, хотя можно выполнять агрегированные запросы. В этом примере для простоты используется синтаксис, аналогичный синтаксису SQL, но SOQL - это отдельная совокупность знаний, о которой вы можете узнать больше после прочтения этой статьи. Trailhead, официальная обучающая и обучающая платформа Salesforce, содержит модули на SOQL.

В общем, беспроигрышный вариант - выполнять прямые запросы в стиле SELECT. Вот пример запроса SOQL, который извлекает ряд стандартных полей из объекта учетной записи Salesforce:

SELECT Id, Name, CreatedDate
FROM Account

Опять же, это очень похоже на SQL, но технически работает под управлением механизма, который вообще не является традиционным механизмом SQL. Таким образом, SOQL разработан для работы в общей многопользовательской среде Salesforce, где на одном сервере могут существовать несколько экземпляров организации. Следовательно, он имеет очень жесткие ограничения на количество строк, возвращаемых в любое время, количество времени, в течение которого разрешено выполнение любого данного запроса, и другие ограничения.

Добавьте код в программу test_start.py, которая вставляет запись Account.

# Records can be defined through Python dictionary objects,
# with field values specified as key-value pairs. The field name
# points to its value. In this case, the Name field on the Account
# can be any string value.
# The CreatedDate and Id are returned from the Salesforce database
# upon record insert, so do not assign those an values.
account = {"Name":"Test Account 1"}
production_connection.Account.create(account)
print("account_insert_result: {}".format(account_insert_result))

Когда программа запускается для вставки Учетной записи, Учетная запись может быть получена с автоматически назначенным идентификатором базы данных и датой создания, выполнив запрос SOQL сверху.

# With the record insert done, the record can be queried Using
# SOQL, using this query as an example.
account_soql = "SELECT Id, Name, CreatedDate FROM Account"
account_query_results = production_connection.query(account_soql).get('records')
print("account_query_results: {}".format(len(account_query_results)))

.get(records) необходим, потому что полезная нагрузка, возвращаемая запросом, содержит больше, чем просто записи; это структура данных, которая включает некоторую метаинформацию о результате запроса. Результаты возвращаются в структуре данных OrderedDict (https://docs.python.org/3.8/library/collections.html#collections.OrderedDict).

После объединения всех этих блоков кода и выполнения test_start.py операторы печати, включенные в эти блоки, распечатают длину результатов вставки и запроса. Если вы следуете на своем собственном компьютере, обязательно сравните с полным примером кода.

Заключение

Отсюда все необходимые строительные блоки по существу находятся в синтаксисе Python. Информацию о различных типах операций с базой данных см. В документации simple_salesforce. Ту же базовую методологию можно использовать с REST API для обновлений, удалений и upserts (которые используют ключ для обновления, если запись существует, или вставки, когда ключ записи не существует).

Не забывайте всегда учитывать ограничения API Salesforce, которые также доступны в документации по ограничениям регулятора. Кроме того, существует ряд ограничений, связанных с транзакциями базы данных. К счастью, Salesforce суммировала свои ограничения в документации здесь:
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm#!

Полный пример кода см. В репозитории git здесь:
https://github.com/elegacorp/your-first-python-to-salesforce-app

В этом примере не рассматривается ряд других важных аспектов масштабируемого дизайна приложения. Аспект безопасности хранения учетных данных в исходном коде - не лучшая идея, но здесь он используется для простоты. По всей вероятности, эта программа должна иметь возможность работать в повторяющемся цикле для обработки событий, критериев, опроса для различных условий или аналогичной ситуации. Стиль этого кода также процедурный и совсем не объектно-ориентированный. Тем не менее, остается выбор, как подойти к недостающим частям этого решения в реальных ситуациях. Существуют различные способы реструктуризации программы с использованием этих строительных блоков для реальных случаев использования.

Благодаря надежной экосистеме пакетов сообщества Python и общей поддержке, с Salesforce и Python достаточно легко работать, поскольку Python является жизнеспособным интеграционным решением.