Salesforce Open Badges: издаване на верифицируеми удостоверения от CRM тригери

Задействайте издаването на Open Badge при всяко събитие на обект в Salesforce — спечелен Lead, надграден Account, учебен етап — с Apex callout към API на Badges Ninja.

Nacho Coll От Обновено 9 мин четене
Задействайте издаването на Open Badge при всяко събитие на обект в Salesforce — спечелен Lead, надграден Account, учебен етап — с Apex callout към API на Badges Ninja.

Повечето обучителни екипи вече записват в Salesforce кой какво е завършил. Записването в курс преминава в „Completed“, партньорски акаунт достига ниво на сертификация, клиент приключва онбординга. Записът се променя, а седмица по-късно някой експортира списък и изпраща сертификатите на ръка по имейл.

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

Ще ви трябват администратор на Salesforce (или developer sandbox), вече изработена значка в https://badges.ninja и API ключ. Ако никога не сте викали API, първо прочетете бързия старт за API; отнема десет минути.

Кога CRM тригерът е правилният инструмент

Преди да пишете Apex, проверете дали изобщо ви е нужен. Ако издавате удостоверения на партиди веднъж на срок или на тримесечие, качването на CSV от таблото е по-бързо и изобщо не изисква код. Пътят през Salesforce си заслужава, когато:

  • Издаването трябва да се случи в момента, в който записът се промени, без човешка стъпка.
  • Данните за това „кой го е заслужил“ вече живеят в Salesforce и не искате втори източник на истина.
  • Искате връзката към удостоверението да се пази в Contact, Lead или персонализиран запис за обучение, за целите на отчетите.

Ако инструментът ви за работни процеси е Zapier, а не Apex, същото API извикване работи и там; вижте автоматизация на Open Badges със Zapier.

Какво изграждате

Потокът се състои от четири части:

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

Newly created API key revealed once

Стъпка 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

Дайте на permission set-а, който изпълнява автоматизацията ви, достъп до principal-а на External Credential. При наличие на Named Credential не ви трябва отделна Remote Site Setting; Salesforce разрешава callout-а чрез credential-а. Ако организацията ви още ползва стари Named Credentials или обикновен endpoint, добавете https://api.badges.ninja като Remote Site Setting и изпращайте хедъра от кода.

Стъпка 2: Добавете полета към записа

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

  • Badge_Id__c (Text): значката за издаване. Ако я пазите за всеки курс, един тригер обслужва много значки.
  • Badge_Award_Id__c (Text, unique): id на наградата, върнато от API.
  • Badge_Url__c (URL): публичната страница за верификация.
  • Badge_Error__c (Long Text): последната грешка, за да виждат администраторите неуспехите без да отварят debug логове.

Полето Badge_Award_Id__c върши двойна работа. То е вашата защита от дубликати: тригерът издава само когато то е празно.

Стъпка 3: Apex callout

Тригерът не може да прави callout директно, защото callout-ите не са позволени в същата транзакция с неотразен 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 за верификация, затова кодът го съставя от id на наградата: 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 има значение. Без нея всяка по-късна редакция на завършен запис би задействала логиката отново. Заедно със защитата за празно award id вътре в задачата, един запис може да породи само едно удостоверение.

Едно ограничение, което трябва да спазвате: Salesforce позволява малък брой Queueable задачи да бъдат поставени в опашката от една транзакция (50 в синхронен контекст). Ако зареждате завършвания на едро, да речем импорт на 2 000 реда, горният тригер ще удари този таван. При масови зареждания или качете списъка през масовите награди с CSV в таблото, или преминете към Batchable клас с Database.AllowsCallouts, който обработва по няколко записа на обхват.

API keys list showing the masked prefix

Обработка на грешки и повторни опити

API връща стандартни статус кодове и всеки изисква различна реакция от вашия код:

СтатусЗначениеКакво да направите
400Липсващо или невалидно поле, включително име на получател под пет знакаНе повтаряйте. Поправете данните и запишете съобщението в Badge_Error__c.
401Грешен или липсващ API ключПроверете Named Credential. Повторните опити няма да помогнат, докато не се поправи.
402Изчерпани удостоверения или квота за вашия планСпрете издаването и известете администратор; опитайте отново след надграждане или след нулиране на квотата.
404badgeId не съществуваПоправете Badge_Id__c в записа или курса.
5xx или timeoutВременен сривБезопасно е да опитате по-късно.

Тъй като задачата записва грешката в записа и оставя Badge_Award_Id__c празно, повторният опит е толкова прост, колкото превключване на чекбокс или повторно запазване на записа. Малък планиран Apex клас, който търси завършени записвания без award id и с временна грешка и ги поставя отново в опашката, ви дава автоматична опашка за повторни опити без допълнителна инфраструктура. Ограничете опитите с поле-брояч, за да не се върти безкрайно трайно повреден запис.

Проверете плана си, преди да свържете това с продукцията. Планът Free покрива 1 200 удостоверения годишно; Starter е $9 на месец, а Pro е $29 на месец. Тригер, който се задейства за всеки Lead, бързо би изчерпал малък план, затова ограничете критериите до реални постижения.

Как да направите удостоверението видимо в Salesforce

След като Badge_Url__c е попълнено, можете да го ползвате навсякъде:

  • Имейл известия и шаблони: вмъкнете полето в имейл „Поздравления, ето вашето удостоверение“.
  • Отчети: отчет по Badge_Award_Id__c != null ви дава броя издадени по курс, регион или собственик на акаунт.
  • Experience Cloud: покажете връзката на страницата за сертификация на партньора, за да могат купувачите сами да я верифицират.
  • Page layouts: добавете URL полето, за да може поддръжката да отговори на „получи ли тя значката си?“ с един поглед.

Страницата за верификация е публична и не изисква регистрация, което е целият смисъл. Получател, работодател или отделът по доставки на клиент може да отвори връзката и да потвърди кой е издал удостоверението, какво удостоверява и кога. За машинно четими проверки Open Badge v2.0 JSON-LD за всяка награда е достъпен на https://api.badges.ninja/certify-badge/award/<awardId>.

Получателите получават и обичайните допълнения: уникален URL за верификация, QR код, PDF сертификат във формат A4 и опция Add to LinkedIn от портала за получатели, който влиза с magic link, а не с парола.

Защо това е по-добре от плъгин за значки от AppExchange

Плъгините за значки в AppExchange обикновено се таксуват на потребител на Salesforce или на лиценз на managed пакет. Тази цена расте с размера на вашия Salesforce екип, а не с броя издадени удостоверения, така че екип от десет души и програма с десет хиляди обучаеми плащат много различно за един и същ резултат.

API интеграцията обръща този модел. Плащате според обема удостоверения по плосък план, кодът на тригера е ваш за четене и промяна, а резултатът е стандартен Open Badge v2.0, така че получателите не са заключени в собствен прегледник. Запазвате и свободата си в дизайна: визуалният дизайнер предлага 80+ шаблона, форми, икони и собствени качвания, вместо фиксиран изглед в пакет.

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

Тестване преди да тръгнете в продукция

Първо пуснете целия поток в sandbox.

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

Сменете API ключа, ако някога изтече в debug лог или екранна снимка. Отмяната е незабавна от страницата API Keys и трябва да обновите само External Credential, не кода си.

В заключение

Моделът е малък: тънък тригер решава кога, Queueable прави callout-а, 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.

Назад към блога

Свързани статии