Salesforce Open Badges: видача верифікованих посвідчень із тригерів CRM

Запускайте видачу Open Badge за будь-якою подією об’єкта Salesforce — Lead виграно, Account підвищено, етап навчання пройдено — за допомогою виклику Apex до API Badges Ninja.

Nacho Coll Автор Оновлено 8 хв читання
Запускайте видачу Open Badge за будь-якою подією об’єкта Salesforce — Lead виграно, Account підвищено, етап навчання пройдено — за допомогою виклику Apex до API Badges Ninja.

Більшість команд навчання вже фіксують у Salesforce, хто що завершив. Запис на курс переходить у статус «Completed», акаунт партнера досягає рівня сертифікації, клієнт завершує онбординг. Запис змінюється, а за тиждень хтось експортує список і вручну розсилає сертифікати електронною поштою.

Цей посібник показує, як закрити цю прогалину: коли запис досягає потрібного вам статусу, Salesforce викликає API https://badges.ninja, видається посвідчення Open Badge v2.0, а посилання для верифікації зберігається назад у записі. Потім ви можете вставити це посилання в шаблон листа, звіт або сторінку Experience Cloud.

Вам знадобляться адміністратор Salesforce (або пісочниця розробника), значок, уже створений на https://badges.ninja, і ключ API. Якщо ви ніколи раніше не викликали цей API, спершу прочитайте швидкий старт з API; це займе десять хвилин.

Коли тригер CRM — правильний інструмент

Перш ніж писати Apex, перевірте, чи він вам потрібен. Якщо ви видаєте посвідчення пакетами раз на семестр чи раз на квартал, завантаження CSV у панелі швидше й не потребує жодного коду. Шлях через Salesforce виправдовує себе, коли:

  • Видача має відбуватися в момент зміни запису, без участі людини.
  • Дані про те, «хто це здобув», уже зберігаються в Salesforce, і ви не хочете другого джерела істини.
  • Ви хочете зберігати посилання на посвідчення в записі Contact, Lead або власному навчальному записі для звітності.

Якщо ваш інструмент — Zapier, а не Apex, той самий виклик API працює і там; дивіться автоматизацію Open Badges у Zapier.

Що ви будуєте

Потік складається з чотирьох частин:

  1. Значок, створений у візуальному дизайнері. Скопіюйте його ідентифікатор (поле id, яке повертає GET /badges).
  2. Ключ API, створений на сторінці API Keys у вашій панелі. Ключ показується один раз, тож збережіть його одразу.
  3. Named Credential у Salesforce, що зберігає ключ, щоб він ніколи не потрапляв у код.
  4. Тригер Apex і клас Queueable, які видають нагороду та записують посилання на неї в запис.

Щойно створений ключ API, показаний лише один раз

Крок 1: Збережіть ключ у Named Credential

Жорстке вшивання ключа API в Apex — помилка, якої слід уникати. У Setup створіть External Credential із власним заголовком, а потім Named Credential, що вказує на хост API:

  • URL: https://api.badges.ninja
  • Назва власного заголовка: X-Api-Key
  • Значення власного заголовка: ваш ключ у форматі bws_YOUR_KEY_HERE
  • Назва Named Credential: BadgesNinja

Надайте набору дозволів, який запускає вашу автоматизацію, доступ до принципала External Credential. Коли Named Credential налаштовано, окремий Remote Site Setting не потрібен; Salesforce авторизує виклик через це посвідчення. Якщо ваша організація досі використовує застарілі Named Credentials або звичайну кінцеву точку, додайте https://api.badges.ninja як Remote Site Setting і надсилайте заголовок із коду.

Крок 2: Додайте поля до запису

В об’єкті, що відображає досягнення (ми використаємо власний об’єкт Training_Enrollment__c), додайте:

  • Badge_Id__c (Text): значок, який потрібно видати. Зберігання його для кожного курсу дає змогу одному тригеру обслуговувати багато значків.
  • Badge_Award_Id__c (Text, unique): ідентифікатор нагороди, який повертає API.
  • Badge_Url__c (URL): публічна сторінка верифікації.
  • Badge_Error__c (Long Text): остання помилка, щоб адміністратори бачили збої без відкриття журналів налагодження.

Поле Badge_Award_Id__c виконує подвійну роль. Це ваш захист від дублікатів: тригер видає посвідчення, лише коли воно порожнє.

Крок 3: Виклик Apex

Тригер не може виконувати виклик безпосередньо, оскільки зовнішні виклики заборонені в одній транзакції з незафіксованим DML. Передайте роботу класу Queueable, що реалізує Database.AllowsCallouts.

Контракт API для POST /awards короткий. Тіло містить badgeId, вкладений об’єкт recipient з полями name та email і обов’язкове issuedOn. Успішний виклик повертає HTTP 200 з { "awardId": "..." }. Ім’я отримувача має містити щонайменше п’ять символів, тож Contact на ім’я «Al Li» буде відхилено; перевіряйте дані перед викликом.

public class BadgeIssueJob implements Queueable, Database.AllowsCallouts {
    private Id enrollmentId;
    public BadgeIssueJob(Id enrollmentId) { this.enrollmentId = enrollmentId; }

    public void execute(QueueableContext ctx) {
        Training_Enrollment__c e = [
            SELECT Id, Badge_Id__c, Badge_Award_Id__c, Contact__r.Name, Contact__r.Email
            FROM Training_Enrollment__c WHERE Id = :enrollmentId LIMIT 1
        ];
        if (e.Badge_Award_Id__c != null) { return; }   // already issued

        Map<String, Object> recipient = new Map<String, Object>{
            'name' => e.Contact__r.Name,
            'email' => e.Contact__r.Email
        };
        Map<String, Object> body = new Map<String, Object>{
            'badgeId' => e.Badge_Id__c,
            'recipient' => recipient,
            'issuedOn' => Datetime.now().getTime()
        };

        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:BadgesNinja/awards');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setBody(JSON.serialize(body));

        HttpResponse res = new Http().send(req);
        if (res.getStatusCode() == 200) {
            Map<String, Object> out = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
            String awardId = (String) out.get('awardId');
            e.Badge_Award_Id__c = awardId;
            e.Badge_Url__c = 'https://badges.ninja/awards/' + awardId;
            e.Badge_Error__c = null;
        } else {
            e.Badge_Error__c = res.getStatusCode() + ': ' + res.getBody();
        }
        update e;
    }
}

Варто звернути увагу на дві деталі. По-перше, issuedOn — це epoch у мілісекундах, саме те, що повертає Datetime.getTime(). По-друге, відповідь не містить URL верифікації, тож код будує його з ідентифікатора нагороди: https://badges.ninja/awards/<awardId>.

Крок 4: Тригер

Нехай тригер буде тонким. Він лише вирішує, які записи підходять, і ставить у чергу одне завдання на запис.

trigger TrainingEnrollmentBadge on Training_Enrollment__c (after insert, after update) {
    for (Training_Enrollment__c e : Trigger.new) {
        Boolean completed = e.Status__c == 'Completed';
        Boolean wasCompleted = Trigger.isUpdate && Trigger.oldMap.get(e.Id).Status__c == 'Completed';
        if (completed && !wasCompleted && e.Badge_Award_Id__c == null && e.Badge_Id__c != null) {
            System.enqueueJob(new BadgeIssueJob(e.Id));
        }
    }
}

Перевірка wasCompleted важлива. Без неї будь-яке пізніше редагування завершеного запису знову запускало б логіку. У поєднанні з перевіркою порожнього ідентифікатора нагороди всередині завдання запис може створити лише одне посвідчення.

Одне обмеження варто враховувати: Salesforce дозволяє ставити в чергу з однієї транзакції невелику кількість завдань Queueable (50 у синхронному контексті). Якщо ви завантажуєте завершення масово, скажімо, імпортом 2000 рядків, наведений тригер досягне цієї стелі. Для масових завантажень або завантажте список через масові нагороди CSV у панелі, або перейдіть на клас Batchable з Database.AllowsCallouts, що обробляє кілька записів за один блок.

Список ключів API із замаскованим префіксом

Обробка помилок і повторні спроби

API повертає стандартні коди стану, і кожен із них потребує іншої реакції вашого коду:

СтатусЗначенняЩо робити
400Поле відсутнє або недійсне, зокрема ім’я отримувача коротше за п’ять символівНе повторюйте. Виправте дані й запишіть повідомлення в Badge_Error__c.
401Хибний або відсутній ключ APIПеревірте Named Credential. Повтор не допоможе, доки це не виправлено.
402Вичерпано посвідчення або квоту вашого плануПрипиніть видачу та сповістіть адміністратора; повторіть після оновлення плану або скидання квоти.
404badgeId не існуєВиправте Badge_Id__c у записі чи курсі.
5xx або тайм-аутТимчасовий збійМожна безпечно повторити пізніше.

Оскільки завдання записує помилку в запис і залишає Badge_Award_Id__c порожнім, повторна спроба зводиться до перемикання прапорця або повторного збереження запису. Невеликий запланований клас Apex, що шукає завершені записи без ідентифікатора нагороди з тимчасовою помилкою й знову ставить їх у чергу, дає автоматичну чергу повторів без додаткової інфраструктури. Обмежте кількість спроб полем-лічильником, щоб назавжди хибний запис не зациклювався.

Перевірте свій план, перш ніж підключати це до продакшну. План Free покриває 1200 посвідчень на рік; Starter коштує $9 на місяць, а Pro — $29 на місяць. Тригер, що спрацьовує на кожен Lead, швидко вичерпав би малий план, тож обмежте критерії справжніми досягненнями.

Як зробити посвідчення видимим у Salesforce

Коли Badge_Url__c заповнено, ви можете використовувати його будь-де:

  • Сповіщення й шаблони листів: вставте поле в лист «Вітаємо, ось ваше посвідчення».
  • Звіти: звіт за умовою Badge_Award_Id__c != null дає кількість видач за курсом, регіоном чи власником акаунта.
  • Experience Cloud: покажіть посилання на сторінці сертифікації партнера, щоб покупці могли самі його перевірити.
  • Макети сторінок: додайте поле URL, щоб служба підтримки могла відповісти на питання «вона отримала свій значок?» одним поглядом.

Сторінка верифікації публічна й не потребує реєстрації, і в цьому весь сенс. Отримувач, рекрутер або відділ закупівель клієнта може відкрити посилання й підтвердити, хто видав посвідчення, що воно засвідчує і коли. Для машинних перевірок JSON-LD Open Badge v2.0 для будь-якої нагороди доступний за адресою https://api.badges.ninja/certify-badge/award/<awardId>.

Отримувачі також отримують звичні додатки: унікальну URL-адресу верифікації, QR-код, PDF-сертифікат формату A4 і опцію Add to LinkedIn з порталу отримувача, який входить за магічним посиланням, а не за паролем.

Чому це краще за плагін значків з AppExchange

Плагіни значків в AppExchange зазвичай оцінюються за місце Salesforce або за ліцензію керованого пакета. Ця вартість зростає разом із розміром вашої команди Salesforce, а не з кількістю виданих посвідчень, тож команда навчання з десяти людей і програма для десяти тисяч слухачів платять за один і той самий результат зовсім по-різному.

Інтеграція через API перевертає цю модель. Ви платите за обсяг посвідчень за фіксованим планом, код тригера можна читати й змінювати, а результат — стандартний Open Badge v2.0, тож отримувачі не прив’язані до власницького засобу перегляду. Ви також зберігаєте свободу дизайну: візуальний дизайнер пропонує понад 80 шаблонів, форм, піктограм і власні завантаження замість фіксованого макета всередині пакета.

Чесний компроміс: плагін встановлюється одним кліком і не потребує Apex. Якщо ніхто у вашій команді не зможе підтримувати кілька десятків рядків коду, кращим вибором може бути плагін або no-code конектор. Якщо ви порівнюєте платформи загалом, а не інтеграції, огляд альтернативи Credly зіставляє відмінності в цінах і можливостях.

Тестування перед запуском

Спершу прогоніть увесь потік у пісочниці.

  1. Створіть тестовий значок і тестового отримувача з адресою електронної пошти, яку ви контролюєте.
  2. У тестах Apex реалізуйте HttpCalloutMock, що повертає статус 200 і {"awardId":"test-award-id"}; Salesforce не дозволяє реальних викликів у тестовому контексті, а це покриття потрібне для розгортання.
  3. У пісочниці встановіть один запис у Completed і перевірте, що Badge_Award_Id__c та Badge_Url__c заповнюються протягом хвилини.
  4. Відкрийте URL у приватному вікні браузера, щоб переконатися, що публічна сторінка верифікації відображається без входу.
  5. Спровокуйте збій (очистіть ідентифікатор значка або використайте ім’я отримувача коротше за п’ять символів) і переконайтеся, що помилка потрапляє в Badge_Error__c.

Змініть ключ API, якщо він колись потрапить у журнал налагодження чи на знімок екрана. Відкликання відбувається миттєво на сторінці API Keys, а оновити потрібно лише External Credential, а не ваш код.

Підсумок

Шаблон невеликий: тонкий тригер вирішує, коли, Queueable виконує виклик, Named Credential зберігає ключ, а три поля в записі фіксують результат. Він працює для етапів навчання, рівнів партнерів, відвідування подій та будь-якої зміни стану, яку можна виразити в Salesforce.

Почніть з одного об’єкта й одного значка, спостерігайте за ним тиждень і розширюйте, коли поведінка повторних спроб підійде вашим даним.

Готові видати своє перше верифіковане посвідчення? Почніть безкоштовно на badges.ninja — візуальний дизайнер, публічна сторінка верифікації, PDF-сертифікат, вивід Open Badge v2.0. Кредитна картка не потрібна.

Nacho Coll

Про автора

Founder & Engineer at Badges Ninja

Nacho founded Badges Ninja to make issuing verifiable digital credentials as simple as a single API call — Open Badge v2.0 badges and certificates, minted, hosted, and verifiable without standing up your own issuer infrastructure. Writes about the Open Badges spec, credential verification, and running a credentialing platform serverless on AWS, from the operator side of the wire.

Назад до Блогу

Схожі статті