Salesforce Open Badges: Cấp credential có thể xác minh từ trigger CRM

Kích hoạt việc cấp Open Badge từ bất kỳ sự kiện đối tượng nào của Salesforce — Lead thắng, Account nâng gói, hoàn thành mốc đào tạo — bằng một Apex callout tới API Badges Ninja.

Nacho Coll Bởi Cập nhật 11 phút đọc
Kích hoạt việc cấp Open Badge từ bất kỳ sự kiện đối tượng nào của Salesforce — Lead thắng, Account nâng gói, hoàn thành mốc đào tạo — bằng một Apex callout tới API Badges Ninja.

Hầu hết các nhóm đào tạo đã ghi nhận ai hoàn thành gì ngay trong Salesforce. Một lượt đăng ký khóa học chuyển sang “Completed”, một tài khoản đối tác đạt cấp chứng nhận, một khách hàng hoàn tất onboarding. Bản ghi thay đổi, rồi một tuần sau ai đó xuất danh sách và gửi chứng chỉ qua email bằng tay.

Hướng dẫn này chỉ bạn cách lấp khoảng trống đó: khi một bản ghi đạt trạng thái bạn quan tâm, Salesforce gọi API https://badges.ninja, một credential Open Badge v2.0 được cấp, và liên kết xác minh được lưu ngược lại vào bản ghi. Sau đó bạn có thể đưa liên kết này vào mẫu email, báo cáo hoặc trang Experience Cloud.

Bạn sẽ cần một quản trị viên Salesforce (hoặc một developer sandbox), một huy hiệu đã được thiết kế sẵn trên https://badges.ninja, và một API key. Nếu bạn chưa từng gọi API này, hãy đọc API quickstart trước; chỉ mất mười phút.

Khi nào trigger CRM là công cụ phù hợp

Trước khi viết Apex, hãy kiểm tra xem bạn có thực sự cần nó không. Nếu bạn cấp credential theo lô mỗi học kỳ hoặc mỗi quý một lần, tính năng tải lên CSV của bảng điều khiển nhanh hơn và hoàn toàn không cần code. Con đường Salesforce đáng giá khi:

  • Việc cấp phải diễn ra ngay khi bản ghi thay đổi, không cần thao tác thủ công.
  • Dữ liệu “ai đã đạt được” đã nằm trong Salesforce và bạn không muốn có nguồn dữ liệu thứ hai.
  • Bạn muốn lưu liên kết credential trên Contact, Lead hoặc bản ghi đào tạo tùy chỉnh để làm báo cáo.

Nếu công cụ quy trình của bạn là Zapier thay vì Apex, cùng một lệnh gọi API cũng dùng được ở đó; xem Zapier Open Badges automation.

Bạn sẽ xây dựng gì

Quy trình gồm bốn phần:

  1. Một huy hiệu được thiết kế trong visual designer. Sao chép id của nó (id do GET /badges trả về).
  2. Một API key được tạo tại trang API Keys trong bảng điều khiển. Key chỉ hiển thị một lần, vì vậy hãy lưu lại ngay.
  3. Một Named Credential trong Salesforce để giữ key, nhờ đó key không bao giờ xuất hiện trong code.
  4. Một Apex trigger cùng một lớp Queueable để cấp award và ghi liên kết award ngược lại vào bản ghi.

Newly created API key revealed once

Bước 1: Lưu key trong Named Credential

Gõ cứng API key trong Apex là lỗi cần tránh. Trong Setup, hãy tạo một External Credential với header tùy chỉnh, sau đó tạo một Named Credential trỏ tới máy chủ API:

  • URL: https://api.badges.ninja
  • Custom header name: X-Api-Key
  • Custom header value: key của bạn, theo dạng bws_YOUR_KEY_HERE
  • Named Credential name: BadgesNinja

Hãy cấp quyền truy cập principal của External Credential cho permission set chạy phần tự động hóa của bạn. Khi đã có Named Credential, bạn không cần Remote Site Setting riêng; Salesforce ủy quyền callout thông qua credential. Nếu org của bạn vẫn dùng Named Credential kiểu cũ hoặc endpoint thông thường, hãy thêm https://api.badges.ninja làm Remote Site Setting và gửi header từ code.

Bước 2: Thêm trường vào bản ghi

Trên đối tượng đại diện cho thành tích (chúng ta sẽ dùng một đối tượng tùy chỉnh tên là Training_Enrollment__c), hãy thêm:

  • Badge_Id__c (Text): huy hiệu cần cấp. Lưu theo từng khóa học cho phép một trigger phục vụ nhiều huy hiệu.
  • Badge_Award_Id__c (Text, unique): id award do API trả về.
  • Badge_Url__c (URL): trang xác minh công khai.
  • Badge_Error__c (Long Text): lỗi gần nhất, để quản trị viên thấy lỗi mà không cần mở debug log.

Trường Badge_Award_Id__c đảm nhiệm hai vai trò. Nó là lớp chống trùng lặp của bạn: trigger chỉ cấp khi trường này trống.

Bước 3: Apex callout

Trigger không thể gọi callout trực tiếp, vì callout không được phép trong cùng giao dịch với DML chưa commit. Hãy giao việc cho một Queueable triển khai Database.AllowsCallouts.

Hợp đồng API cho POST /awards rất ngắn gọn. Body chứa badgeId, một đối tượng recipient lồng bên trong với name và email, cùng issuedOn là trường bắt buộc. Một lệnh gọi thành công trả về HTTP 200 kèm { "awardId": "..." }. Tên người nhận phải có ít nhất năm ký tự, nên một Contact tên “Al Li” sẽ bị từ chối; hãy kiểm tra hợp lệ trước khi gọi.

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

Có hai chi tiết đáng chú ý. Thứ nhất, issuedOn là epoch tính bằng mili giây, đúng với giá trị Datetime.getTime() trả về. Thứ hai, phản hồi không bao gồm URL xác minh, nên code tự dựng URL từ award id: https://badges.ninja/awards/<awardId>.

Bước 4: Trigger

Hãy giữ trigger thật gọn. Nó chỉ quyết định bản ghi nào đủ điều kiện và đưa một job cho mỗi bản ghi vào hàng đợi.

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

Phép kiểm tra wasCompleted rất quan trọng. Thiếu nó, bất kỳ chỉnh sửa nào sau đó trên bản ghi đã hoàn thành đều sẽ kích hoạt lại logic. Kết hợp với lớp chống trùng bằng award id trống bên trong job, một bản ghi chỉ có thể tạo ra đúng một credential.

Một giới hạn cần tôn trọng: Salesforce chỉ cho phép đưa một số ít job Queueable vào hàng đợi từ một giao dịch (50 trong ngữ cảnh đồng bộ). Nếu bạn nạp hàng loạt các lượt hoàn thành, chẳng hạn nhập dữ liệu 2.000 dòng, trigger ở trên sẽ chạm trần này. Với nạp hàng loạt, hãy tải danh sách lên qua tính năng bulk awards CSV của bảng điều khiển, hoặc chuyển sang lớp Batchable với Database.AllowsCallouts xử lý vài bản ghi mỗi scope.

API keys list showing the masked prefix

Xử lý lỗi và thử lại

API trả về các mã trạng thái chuẩn, và mỗi mã đòi hỏi code của bạn phản ứng khác nhau:

StatusÝ nghĩaCần làm gì
400Thiếu hoặc sai một trường, kể cả tên người nhận dưới năm ký tựĐừng thử lại. Sửa dữ liệu và ghi thông báo vào Badge_Error__c.
401API key sai hoặc thiếuKiểm tra Named Credential. Thử lại sẽ không giúp ích cho tới khi sửa xong.
402Hết credential hoặc hạn mức của góiDừng cấp và báo cho quản trị viên; thử lại sau khi nâng gói hoặc khi hạn mức được đặt lại.
404badgeId không tồn tạiSửa Badge_Id__c trên bản ghi hoặc khóa học.
5xx hoặc timeoutLỗi tạm thờiCó thể thử lại sau một cách an toàn.

Vì job ghi lỗi vào bản ghi và để trống Badge_Award_Id__c, việc thử lại đơn giản chỉ là bật một checkbox hoặc lưu lại bản ghi. Một lớp Apex theo lịch nhỏ tìm các enrollment đã hoàn thành nhưng chưa có award id và có lỗi tạm thời, rồi đưa chúng vào hàng đợi lại, sẽ cho bạn một hàng đợi thử lại tự động mà không cần thêm hạ tầng. Hãy giới hạn số lần thử bằng một trường đếm để bản ghi hỏng vĩnh viễn không lặp mãi.

Hãy kiểm tra gói của bạn trước khi đưa vào production. Gói Free bao gồm 1.200 credential mỗi năm; Starter là $9 mỗi tháng và Pro là $29 mỗi tháng. Một trigger kích hoạt trên mọi Lead sẽ nhanh chóng ngốn hết một gói nhỏ, vì vậy hãy giới hạn tiêu chí ở các thành tích thực sự.

Hiển thị credential trong Salesforce

Khi Badge_Url__c đã được điền, bạn có thể dùng nó ở bất cứ đâu:

  • Email alert và mẫu email: ghép trường này vào email “Chúc mừng, đây là credential của bạn”.
  • Báo cáo: một báo cáo trên Badge_Award_Id__c != null cho bạn số lượng đã cấp theo khóa học, khu vực hoặc chủ sở hữu tài khoản.
  • Experience Cloud: hiển thị liên kết trên trang chứng nhận của đối tác để người mua tự xác minh.
  • Page layout: thêm trường URL để nhân viên hỗ trợ trả lời “cô ấy đã nhận huy hiệu chưa?” chỉ trong một cái nhìn.

Trang xác minh là công khai và không cần đăng ký, và đó chính là mục đích. Người nhận, nhà tuyển dụng hoặc bộ phận mua sắm của khách hàng có thể mở liên kết và xác nhận ai đã cấp credential, nó chứng nhận điều gì, và vào khi nào. Với việc kiểm tra bằng máy, Open Badge v2.0 JSON-LD của bất kỳ award nào đều có tại https://api.badges.ninja/certify-badge/award/<awardId>.

Người nhận cũng có các tiện ích thông thường: một URL xác minh duy nhất, mã QR, chứng chỉ PDF khổ A4, và tùy chọn Add to LinkedIn từ cổng người nhận, nơi đăng nhập bằng magic link thay vì mật khẩu.

Vì sao cách này tốt hơn plugin huy hiệu trên AppExchange

Các plugin huy hiệu trên AppExchange thường tính giá theo từng seat Salesforce hoặc theo giấy phép managed package. Chi phí đó tăng theo quy mô đội Salesforce của bạn, không theo số credential bạn cấp, nên một nhóm đào tạo mười người và một chương trình mười nghìn học viên phải trả rất khác nhau cho cùng một kết quả.

Tích hợp API đảo ngược mô hình đó. Bạn trả theo khối lượng credential trên một gói cố định, code trigger là của bạn để đọc và chỉnh sửa, và đầu ra là Open Badge v2.0 chuẩn, nên người nhận không bị khóa vào một trình xem độc quyền. Bạn cũng giữ được tự do thiết kế: visual designer cung cấp 80+ mẫu, hình dạng, biểu tượng và tải lên tùy chỉnh, thay vì một bố cục cố định trong gói.

Đánh đổi thẳng thắn: plugin chỉ cần cài bằng một cú nhấp và không cần Apex. Nếu không ai trong nhóm bạn có thể bảo trì vài chục dòng code, một plugin hoặc một trình kết nối no-code có thể phù hợp hơn. Nếu bạn đang so sánh các nền tảng nói chung chứ không phải các tích hợp, bài phân tích Credly alternative trình bày giá và khác biệt tính năng cạnh nhau.

Kiểm thử trước khi đi vào hoạt động

Hãy chạy toàn bộ quy trình trong sandbox trước.

  1. Tạo một huy hiệu thử và một người nhận thử với địa chỉ email bạn kiểm soát.
  2. Trong các test Apex, triển khai HttpCalloutMock trả về status 200 và {"awardId":"test-award-id"}; Salesforce không cho phép callout thật trong ngữ cảnh test, và bạn cần độ phủ đó để deploy.
  3. Trong sandbox, đặt một enrollment thành Completed và kiểm tra Badge_Award_Id__c cùng Badge_Url__c được điền trong vòng một phút.
  4. Mở URL trong cửa sổ trình duyệt riêng tư để xác nhận trang xác minh công khai hiển thị mà không cần đăng nhập.
  5. Cố ý gây lỗi (để trống badge id, hoặc dùng tên người nhận dưới năm ký tự) và xác nhận lỗi được ghi vào Badge_Error__c.

Hãy xoay vòng API key nếu nó từng bị lộ vào debug log hoặc ảnh chụp màn hình. Việc thu hồi có hiệu lực ngay từ trang API Keys, và bạn chỉ cần cập nhật External Credential, không phải code.

Kết luận

Mô hình này nhỏ gọn: một trigger mỏng quyết định khi nào, một Queueable thực hiện callout, một Named Credential giữ key, và ba trường trên bản ghi lưu kết quả. Nó hoạt động cho các mốc đào tạo, cấp đối tác, việc tham dự sự kiện, hoặc bất kỳ thay đổi trạng thái nào bạn có thể diễn đạt trong Salesforce.

Hãy bắt đầu với một đối tượng và một huy hiệu, theo dõi trong một tuần, và mở rộng khi hành vi thử lại phù hợp với dữ liệu của bạn.

Sẵn sàng cấp credential có thể xác minh đầu tiên của bạn? Bắt đầu miễn phí tại badges.ninja — visual designer, trang xác minh công khai, chứng chỉ PDF, đầu ra Open Badge v2.0. Không cần thẻ tín dụng.

Nacho Coll

Về tác giả

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.

Quay lại Blog

Bài viết liên quan