Salesforce Open Badges: Mag-issue ng Verifiable Credentials mula sa CRM Triggers

I-trigger ang pag-issue ng Open Badge mula sa kahit anong event ng Salesforce object — Lead won, Account upgraded, training milestone — gamit ang Apex callout sa Badges Ninja API.

Nacho Coll Ni Na-update 10 min basahin
I-trigger ang pag-issue ng Open Badge mula sa kahit anong event ng Salesforce object — Lead won, Account upgraded, training milestone — gamit ang Apex callout sa Badges Ninja API.

Karamihan ng training teams ay nire-record na sa Salesforce kung sino ang nakatapos ng ano. Ang course enrollment ay napupunta sa “Completed”, ang partner account ay umaabot sa isang certification tier, ang customer ay tapos na sa onboarding. Nagbabago ang record, tapos makalipas ang isang linggo, may mag-e-export ng listahan at mano-manong magpapadala ng mga certificate sa email.

Ipinapakita ng gabay na ito kung paano isara ang puwang na iyon: kapag umabot ang isang record sa status na mahalaga sa iyo, tatawagin ng Salesforce ang https://badges.ninja API, mag-i-issue ng Open Badge v2.0 credential, at ise-save pabalik sa record ang verification link. Puwede mo nang ilagay ang link na iyon sa email template, report, o Experience Cloud page.

Kakailanganin mo ng Salesforce admin (o developer sandbox), isang badge na na-design na sa https://badges.ninja, at isang API key. Kung hindi mo pa nata-try tawagin ang API, basahin muna ang API quickstart; sampung minuto lang ito.

Kailan tamang gamitin ang CRM trigger

Bago magsulat ng Apex, tingnan muna kung kailangan mo ito. Kung nag-i-issue ka ng credentials nang batch, minsan kada term o minsan kada quarter, mas mabilis ang CSV upload ng dashboard at walang code na kailangan. Sulit ang Salesforce route kapag:

  • Dapat mag-issue sa mismong sandali na nagbago ang record, nang walang human step.
  • Nasa Salesforce na ang data kung sino ang nakakuha at ayaw mo ng pangalawang source of truth.
  • Gusto mong naka-store ang credential link sa Contact, Lead, o custom training record para sa reporting.

Kung Zapier ang workflow tool mo at hindi Apex, gumagana rin doon ang parehong API call; tingnan ang Zapier Open Badges automation.

Ano ang bubuuin mo

May apat na piraso ang flow:

  1. Isang badge na dinisenyo sa visual designer. Kopyahin ang id nito (ang id na ibinabalik ng GET /badges).
  2. Isang API key na ginawa sa API Keys page ng dashboard mo. Isang beses lang ipinapakita ang key, kaya i-store agad.
  3. Isang Named Credential sa Salesforce na may hawak ng key, para hindi ito lumabas sa code.
  4. Isang Apex trigger at Queueable class na nag-i-issue ng award at nagsusulat ng award link pabalik sa record.

Newly created API key revealed once

Step 1: I-store ang key sa Named Credential

Ang pag-hard-code ng API key sa Apex ang pagkakamaling dapat iwasan. Sa Setup, gumawa ng External Credential na may custom header, tapos Named Credential na tumuturo sa API host:

  • URL: https://api.badges.ninja
  • Custom header name: X-Api-Key
  • Custom header value: ang key mo, sa anyong bws_YOUR_KEY_HERE
  • Named Credential name: BadgesNinja

Bigyan ng access ang permission set na nagpapatakbo ng automation mo sa principal ng External Credential. Kapag may Named Credential, hindi mo na kailangan ng hiwalay na Remote Site Setting; ina-authorize ng Salesforce ang callout sa pamamagitan ng credential. Kung legacy Named Credentials o plain endpoint pa rin ang gamit ng org mo, idagdag ang https://api.badges.ninja bilang Remote Site Setting at ipadala ang header mula sa code.

Step 2: Magdagdag ng fields sa record

Sa object na kumakatawan sa achievement (gagamit tayo ng custom object na tinatawag na Training_Enrollment__c), idagdag ang:

  • Badge_Id__c (Text): ang badge na i-i-issue. Kapag naka-store ito kada course, isang trigger lang ang magseserbisyo sa maraming badges.
  • Badge_Award_Id__c (Text, unique): ang award id na ibinalik ng API.
  • Badge_Url__c (URL): ang public verification page.
  • Badge_Error__c (Long Text): ang huling error, para makita ng admins ang mga pagkabigo nang hindi nagbubukas ng debug logs.

Dalawa ang silbi ng Badge_Award_Id__c. Ito ang duplicate guard mo: nag-i-issue lang ang trigger kapag walang laman ito.

Step 3: Ang Apex callout

Hindi makakagawa ng callout nang direkta ang trigger, dahil hindi pinapayagan ang callouts sa parehong transaction ng uncommitted DML. Ipasa ang trabaho sa Queueable na nag-i-implement ng Database.AllowsCallouts.

Maikli lang ang API contract ng POST /awards. Dala ng body ang badgeId, isang nested na recipient object na may name at email, at required na issuedOn. Ang matagumpay na call ay nagbabalik ng HTTP 200 na may { "awardId": "..." }. Dapat hindi bababa sa limang character ang recipient name, kaya ire-reject ang Contact na pangalang “Al Li”; mag-validate bago tumawag.

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

Dalawang detalyeng dapat pansinin. Una, ang issuedOn ay epoch milliseconds, na eksaktong ibinabalik ng Datetime.getTime(). Pangalawa, hindi kasama sa response ang verification URL, kaya binubuo ito ng code mula sa award id: https://badges.ninja/awards/<awardId>.

Step 4: Ang trigger

Panatilihing manipis ang trigger. Ang trabaho lang nito ay magpasya kung aling records ang kwalipikado at mag-enqueue ng isang job kada record.

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

Mahalaga ang wasCompleted check. Kung wala ito, kahit anong susunod na edit sa completed record ay muling magpapagana ng logic. Kasama ng empty-award-id guard sa loob ng job, isang credential lang ang puwedeng mabuo ng isang record.

Isang limitasyong dapat igalang: pinapayagan ng Salesforce ang kaunting Queueable jobs na ma-enqueue mula sa iisang transaction (50 sa synchronous context). Kung bulk ang pag-load mo ng completions, halimbawa data import na 2,000 rows, aabot sa ceiling na iyon ang trigger sa itaas. Para sa bulk loads, i-upload ang listahan gamit ang CSV bulk awards ng dashboard, o lumipat sa Batchable class na may Database.AllowsCallouts na nagpoproseso ng ilang records kada scope.

API keys list showing the masked prefix

Error handling at retries

Nagbabalik ang API ng standard status codes, at bawat isa ay nangangailangan ng ibang tugon mula sa code mo:

StatusKahuluganAno ang gagawin
400May field na kulang o invalid, kasama ang recipient name na wala pang limang characterHuwag mag-retry. Ayusin ang data at isulat ang mensahe sa Badge_Error__c.
401Mali o walang API keySuriin ang Named Credential. Hindi makakatulong ang retry hangga’t hindi naaayos.
402Ubos na ang credentials o quota ng plan moHuminto sa pag-issue at i-alert ang admin; mag-retry pagkatapos mag-upgrade o mag-reset ang quota.
404Walang badgeId na ganoonItama ang Badge_Id__c sa record o course.
5xx o timeoutPansamantalang pagkabigoLigtas mag-retry mamaya.

Dahil isinusulat ng job ang error sa record at iniiwang walang laman ang Badge_Award_Id__c, kasing-simple lang ng pag-flip ng checkbox o pag-re-save ng record ang retry. Ang maliit na scheduled Apex class na naghahanap ng completed enrollments na walang award id at may transient error, tapos nire-enqueue ulit ang mga ito, ay nagbibigay sa iyo ng automatic retry queue nang walang dagdag na infrastructure. Limitahan ang attempts gamit ang counter field para hindi mag-loop nang walang katapusan ang record na permanenteng may problema.

Suriin ang plan mo bago i-wire sa production. Sakop ng Free plan ang 1,200 credentials kada taon; ang Starter ay $9 kada buwan at ang Pro ay $29 kada buwan. Mabilis uubusin ng trigger na pumuputok sa bawat Lead ang maliit na plan, kaya limitahan ang criteria sa totoong achievements.

Gawing visible ang credential sa Salesforce

Kapag napunan na ang Badge_Url__c, magagamit mo ito kahit saan:

  • Email alerts at templates: i-merge ang field sa “Congratulations, here is your credential” na email.
  • Reports: ang report sa Badge_Award_Id__c != null ay nagbibigay ng issuance counts kada course, region, o account owner.
  • Experience Cloud: ipakita ang link sa certification page ng partner para ma-verify mismo ng mga buyer.
  • Page layouts: idagdag ang URL field para masagot ng support staff ang “nakuha na ba niya ang badge niya?” sa isang tingin.

Public ang verification page at hindi nangangailangan ng signup, na siyang buong punto. Ang recipient, hiring manager, o procurement team ng customer ay puwedeng magbukas ng link at kumpirmahin kung sino ang nag-issue ng credential, ano ang pinatutunayan nito, at kailan. Para sa machine-readable na checks, ang Open Badge v2.0 JSON-LD ng kahit anong award ay available sa https://api.badges.ninja/certify-badge/award/<awardId>.

Nakukuha rin ng recipients ang karaniwang extras: unique verification URL, QR code, A4 PDF certificate, at Add to LinkedIn option mula sa recipient portal, na nagsa-sign in gamit ang magic link sa halip na password.

Bakit mas maganda ito kaysa sa AppExchange badge plugin

Ang badge plugins sa AppExchange ay karaniwang may presyong kada Salesforce seat o kada managed-package license. Lumalaki ang gastos na iyon kasabay ng laki ng Salesforce team mo, hindi ng dami ng credentials na ini-issue mo, kaya magkaiba ang binabayaran ng sampung-taong training team at ng sampung-libong-learner na program para sa parehong output.

Binabaligtad ito ng API integration. Nagbabayad ka ayon sa credential volume sa flat plan, sa iyo ang trigger code na puwede mong basahin at baguhin, at standard Open Badge v2.0 ang output, kaya hindi nakakulong ang recipients sa proprietary viewer. Napapanatili mo rin ang design freedom: nag-aalok ang visual designer ng 80+ templates, shapes, icons, at custom uploads, sa halip na fixed layout sa loob ng package.

Ang tapat na trade-off: click-to-install ang plugin at hindi nangangailangan ng Apex. Kung walang makapag-maintain sa team mo ng ilang dosenang linya ng code, baka mas bagay ang plugin o no-code connector. Kung platforms ang kinukumpara mo sa pangkalahatan at hindi integrations, saklaw ng Credly alternative breakdown ang presyo at pagkakaiba ng features nang magkatabi.

Mag-test bago mag-go live

Patakbuhin muna ang buong flow sa sandbox.

  1. Gumawa ng test badge at test recipient na may email address na hawak mo.
  2. Sa Apex tests, mag-implement ng HttpCalloutMock na nagbabalik ng status 200 at {"awardId":"test-award-id"}; hindi pinapayagan ng Salesforce ang totoong callouts sa test context, at kailangan mo ang coverage na iyon para mag-deploy.
  3. Sa sandbox, itakda sa Completed ang isang enrollment at tingnan kung napupunan ang Badge_Award_Id__c at Badge_Url__c sa loob ng isang minuto.
  4. Buksan ang URL sa private browser window para kumpirmahing lumalabas ang public verification page nang hindi nagsa-sign in.
  5. Pilitin ang failure (iwanang blangko ang badge id, o gumamit ng recipient name na wala pang limang character) at kumpirmahing napupunta ang error sa Badge_Error__c.

I-rotate ang API key kung sakaling tumagas ito sa debug log o screenshot. Agad ang revocation mula sa API Keys page, at External Credential lang ang kailangan mong i-update, hindi ang code mo.

Pagtatapos

Maliit ang pattern: manipis na trigger ang nagpapasya kung kailan, Queueable ang gumagawa ng callout, Named Credential ang may hawak ng key, at tatlong fields sa record ang nag-iimbak ng resulta. Gumagana ito para sa training milestones, partner tiers, event attendance, o kahit anong state change na maipapahayag mo sa Salesforce.

Magsimula sa isang object at isang badge, bantayan ito sa loob ng isang linggo, at palawakin kapag swak na sa data mo ang retry behavior.

Handa ka na bang mag-issue ng una mong verifiable credential? Magsimula nang libre sa badges.ninja — visual designer, public verification page, PDF certificate, Open Badge v2.0 output. Walang credit card na kailangan.

Nacho Coll

Tungkol sa may-akda

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.

Bumalik sa Blog

Kaugnay na Artikulo