Salesforce Open Badges: utfärda verifierbara meriter från CRM-triggers

Utlös utfärdande av Open Badge från vilken Salesforce-objekthändelse som helst — vunnen Lead, uppgraderad Account, utbildningsmilstolpe — med ett Apex-anrop till Badges Ninja-API:et.

Nacho Coll Av Uppdaterad 9 min läsning
Utlös utfärdande av Open Badge från vilken Salesforce-objekthändelse som helst — vunnen Lead, uppgraderad Account, utbildningsmilstolpe — med ett Apex-anrop till Badges Ninja-API:et.

De flesta utbildningsteam registrerar redan i Salesforce vem som har slutfört vad. En kursanmälan går till ”Completed”, ett partnerkonto når en certifieringsnivå, en kund blir klar med onboardingen. Posten ändras, och en vecka senare exporterar någon en lista och mejlar certifikat för hand.

Den här guiden visar hur du stänger det glappet: när en post når den status du bryr dig om anropar Salesforce https://badges.ninja-API:et, en Open Badge v2.0-merit utfärdas och verifieringslänken sparas tillbaka på posten. Sedan kan du lägga länken i en e-postmall, en rapport eller en Experience Cloud-sida.

Du behöver en Salesforce-administratör (eller en utvecklar-sandbox), ett märke som redan är designat på https://badges.ninja och en API-nyckel. Om du aldrig har anropat API:et förut, läs först snabbstarten för API:et; den tar tio minuter.

När en CRM-trigger är rätt verktyg

Innan du skriver Apex bör du kontrollera om du behöver det. Om du utfärdar meriter i omgångar en gång per termin eller kvartal är CSV-uppladdningen i instrumentpanelen snabbare och kräver ingen kod alls. Salesforce-vägen lönar sig när:

  • Utfärdandet ska ske i samma stund som en post ändras, utan något mänskligt steg.
  • Uppgifterna om ”vem som har förtjänat det” redan finns i Salesforce och du inte vill ha en andra sanningskälla.
  • Du vill lagra merit-länken på Contact, Lead eller en egen utbildningspost för rapportering.

Om ditt arbetsflödesverktyg är Zapier snarare än Apex fungerar samma API-anrop där också; se Zapier-automatisering för Open Badges.

Vad du bygger

Flödet består av fyra delar:

  1. Ett märke designat i den visuella designern. Kopiera dess id (det id som GET /badges returnerar).
  2. En API-nyckel som skapas på sidan API Keys i din instrumentpanel. Nyckeln visas bara en gång, så spara den direkt.
  3. En Named Credential i Salesforce som håller nyckeln, så att den aldrig syns i koden.
  4. En Apex-trigger plus en Queueable-klass som utfärdar utmärkelsen och skriver tillbaka utmärkelsens länk till posten.

Nyligen skapad API-nyckel som visas en enda gång

Steg 1: Lagra nyckeln i en Named Credential

Att hårdkoda en API-nyckel i Apex är misstaget du ska undvika. Skapa i Setup en External Credential med en anpassad header, och sedan en Named Credential som pekar på API-värden:

  • URL: https://api.badges.ninja
  • Namn på anpassad header: X-Api-Key
  • Värde på anpassad header: din nyckel, i formen bws_YOUR_KEY_HERE
  • Namn på Named Credential: BadgesNinja

Ge den permission set som kör din automatisering åtkomst till External Credentialens principal. Med en Named Credential på plats behöver du ingen separat Remote Site Setting; Salesforce auktoriserar anropet via credentialen. Om din org fortfarande använder äldre Named Credentials eller en vanlig endpoint, lägg till https://api.badges.ninja som Remote Site Setting och skicka headern från koden.

Steg 2: Lägg till fält på posten

På objektet som representerar prestationen (vi använder ett eget objekt som heter Training_Enrollment__c), lägg till:

  • Badge_Id__c (Text): märket som ska utfärdas. Lagrar du det per kurs kan en enda trigger hantera många märken.
  • Badge_Award_Id__c (Text, unik): utmärkelse-id:t som API:et returnerar.
  • Badge_Url__c (URL): den publika verifieringssidan.
  • Badge_Error__c (Long Text): det senaste felet, så att administratörer ser fel utan att öppna debug logs.

Fältet Badge_Award_Id__c har två uppgifter. Det är ditt dubblettskydd: triggern utfärdar bara när det är tomt.

Steg 3: Apex-anropet

En trigger kan inte göra ett externt anrop direkt, eftersom anrop inte tillåts i samma transaktion som ej committad DML. Lämna över arbetet till en Queueable som implementerar Database.AllowsCallouts.

API-kontraktet för POST /awards är kort. Bodyn innehåller badgeId, ett nästlat recipient-objekt med name och email, samt ett obligatoriskt issuedOn. Ett lyckat anrop returnerar HTTP 200 med { "awardId": "..." }. Mottagarens namn måste vara minst fem tecken, så en Contact som heter ”Al Li” skulle avvisas; validera innan du anropar.

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;
    }
}

Två detaljer värda att lägga märke till. För det första är issuedOn epok-millisekunder, precis vad Datetime.getTime() returnerar. För det andra innehåller svaret inte verifierings-URL:en, så koden bygger den från utmärkelse-id:t: https://badges.ninja/awards/<awardId>.

Steg 4: Triggern

Håll triggern tunn. Den avgör bara vilka poster som kvalificerar sig och köar ett jobb per post.

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));
        }
    }
}

Kontrollen wasCompleted är viktig. Utan den skulle varje senare ändring av en slutförd post köra om logiken. Tillsammans med skyddet för tomt utmärkelse-id inne i jobbet kan en post bara någonsin ge upphov till en enda merit.

En gräns att respektera: Salesforce tillåter bara ett litet antal Queueable-jobb som köas från en enskild transaktion (50 i synkron kontext). Om du laddar in slutföranden i bulk, säg en dataimport på 2 000 rader, når triggern ovan det taket. För bulkladdningar kan du antingen ladda upp listan via instrumentpanelens CSV-baserade massutmärkelser, eller byta till en Batchable-klass med Database.AllowsCallouts som bearbetar några få poster per scope.

Lista över API-nycklar med det maskerade prefixet

Felhantering och omförsök

API:et returnerar standardstatuskoder, och var och en kräver olika respons från din kod:

StatusBetydelseVad du gör
400Ett fält saknades eller var ogiltigt, inklusive ett mottagarnamn under fem teckenFörsök inte igen. Rätta datan och skriv meddelandet till Badge_Error__c.
401Felaktig eller saknad API-nyckelKontrollera Named Credential. Omförsök hjälper inte förrän det är åtgärdat.
402Slut på meriter eller kvot för din planSluta utfärda och larma en administratör; försök igen efter uppgradering eller när kvoten återställs.
404badgeId finns inteRätta Badge_Id__c på posten eller kursen.
5xx eller timeoutTillfälligt felSäkert att försöka igen senare.

Eftersom jobbet skriver felet till posten och lämnar Badge_Award_Id__c tomt är ett omförsök lika enkelt som att slå på en kryssruta eller spara om posten. En liten schemalagd Apex-klass som letar efter slutförda anmälningar utan utmärkelse-id och med ett tillfälligt fel, och köar dem på nytt, ger dig en automatisk omförsökskö utan extra infrastruktur. Begränsa antalet försök med ett räknarfält så att en permanent felaktig post inte loopar för evigt.

Kontrollera din plan innan du kopplar detta till produktion. Free-planen täcker 1 200 meriter per år; Starter kostar $9 i månaden och Pro $29 i månaden. En trigger som avfyras på varje Lead skulle snabbt göra slut på en liten plan, så avgränsa kriterierna till verkliga prestationer.

Gör meriten synlig i Salesforce

När Badge_Url__c är ifyllt kan du använda det var som helst:

  • E-postaviseringar och mallar: foga in fältet i ett ”Grattis, här är din merit”-mejl.
  • Rapporter: en rapport på Badge_Award_Id__c != null ger dig antal utfärdanden per kurs, region eller kontoägare.
  • Experience Cloud: visa länken på en partners certifieringssida så att köpare kan verifiera den själva.
  • Page layouts: lägg till URL-fältet så att supporten kan svara på ”fick hon sitt märke?” med en blick.

Verifieringssidan är publik och kräver ingen registrering, vilket är hela poängen. En mottagare, en rekryterande chef eller en kunds inköpsteam kan öppna länken och bekräfta vem som utfärdade meriten, vad den intygar och när. För maskinläsbara kontroller finns Open Badge v2.0 JSON-LD för varje utmärkelse på https://api.badges.ninja/certify-badge/award/<awardId>.

Mottagarna får också de vanliga extrafunktionerna: en unik verifierings-URL, en QR-kod, ett A4-PDF-certifikat och ett Add to LinkedIn-alternativ från mottagarportalen, som loggar in med en magic link i stället för ett lösenord.

Därför slår detta ett AppExchange-tillägg för märken

Märkestillägg på AppExchange prissätts oftast per Salesforce-användare eller per managed package-licens. Den kostnaden växer med storleken på ditt Salesforce-team, inte med antalet meriter du utfärdar, så ett utbildningsteam på tio personer och ett program med tiotusen deltagare betalar mycket olika för samma resultat.

En API-integration vänder på modellen. Du betalar efter meritvolym på en fast plan, triggerkoden är din att läsa och ändra, och resultatet är standard Open Badge v2.0, så mottagarna är inte inlåsta i en proprietär visare. Du behåller också din designfrihet: den visuella designern erbjuder över 80 mallar, former, ikoner och egna uppladdningar, i stället för en fast layout inuti ett paket.

Den ärliga avvägningen: ett tillägg installeras med ett klick och kräver ingen Apex. Om ingen i ditt team kan underhålla några dussin rader kod kan ett tillägg eller en no-code-koppling vara det bättre valet. Om du jämför plattformar i allmänhet snarare än integrationer går genomgången av Credly-alternativet igenom pris och funktionsskillnader sida vid sida.

Testa innan du går live

Kör hela flödet i en sandbox först.

  1. Skapa ett testmärke och en testmottagare med en e-postadress du kontrollerar.
  2. Implementera i Apex-tester en HttpCalloutMock som returnerar status 200 och {"awardId":"test-award-id"}; Salesforce tillåter inga riktiga anrop i testkontext, och du behöver den täckningen för att kunna deploya.
  3. Sätt en anmälan till Completed i sandboxen och kontrollera att Badge_Award_Id__c och Badge_Url__c fylls i inom en minut.
  4. Öppna URL:en i ett privat webbläsarfönster för att bekräfta att den publika verifieringssidan visas utan inloggning.
  5. Framkalla ett fel (töm märkes-id:t eller använd ett mottagarnamn under fem tecken) och bekräfta att felet hamnar i Badge_Error__c.

Rotera API-nyckeln om den någonsin läcker i en debug log eller en skärmbild. Återkallandet sker omedelbart från sidan API Keys, och du behöver bara uppdatera External Credential, inte din kod.

Sammanfattning

Mönstret är litet: en tunn trigger avgör när, en Queueable gör anropet, en Named Credential håller nyckeln och tre fält på posten lagrar utfallet. Det fungerar för utbildningsmilstolpar, partnernivåer, eventnärvaro eller vilken tillståndsändring som helst som du kan uttrycka i Salesforce.

Börja med ett objekt och ett märke, följ det i en vecka och bygg ut när omförsöksbeteendet passar din data.

Redo att utfärda din första verifierbara merit? Börja gratis på badges.ninja — visuell designer, publik verifieringssida, PDF-certifikat, Open Badge v2.0-utdata. Inget kreditkort krävs.

Nacho Coll

Om författaren

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.

Tillbaka till Bloggen

Relaterade artiklar