Издаване на Open Badges от WordPress (без тежък плъгин)
Издавайте Open Badges от всеки WordPress плъгин за курсове/LMS (LearnDash, LifterLMS, Tutor), като извиквате Badges Ninja API при завършване — не е нужен отделен плъгин за значки.
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.
Ако провеждате курсове в WordPress, вече знаете процедурата: някой завършва модул в LearnDash, LifterLMS или Tutor LMS, LMS платформата го отбелязва като „завършил”, и после… нищо проверимо не се случва. Може би изпращате PDF по имейл. Може би инсталирате специален WordPress плъгин за значки, който добавя собствени таблици в базата данни, собствена библиотека с изображения и собствена представа за това какво е „значка” — такава, която никой извън вашия сайт не може да провери.
Съществува по-прост път. WordPress плъгините за курсове вече задействат action hook в момента, в който някой завърши курс. Можете да прихванете този hook и да направите едно HTTP извикване към Badges Ninja API. Без допълнителен плъгин, без допълнителен хостинг, без собствен формат за значки — само стандартизиран Open Badge v2.0 сертификат, който получателят може да провери навсякъде, да добави в LinkedIn и да изтегли като PDF.
Тази публикация разглежда модела веднъж, а след това показва конкретния hook за LearnDash, LifterLMS и Tutor LMS.
Защо просто да не използвате WordPress плъгин за значки?
Специализираните WordPress плъгини за значки решават по-тесен проблем, отколкото изглежда на пръв поглед. Те се справят добре с показването на изображение на страница „моите постижения” вътре в сайта ви. Обикновено са много по-слаби по отношение на нещата, които реално имат значение за един сертификат:
- Преносимост. Значка, която съществува само като shortcode на вашия WordPress сайт, не е сертификат — тя е украшение. В момента, в който получателят смени работата си, смени пощенската си кутия или сайтът ви спре да работи, „доказателството” изчезва заедно с него.
- Верификация. Всеки трябва да може да провери, че даден сертификат е истински, без да влиза в администрацията на вашия WordPress. Open Badge v2.0 ви дава публичен URL адрес за верификация и машинно четим JSON-LD по подразбиране.
- Поддръжка. Всеки WordPress плъгин е още едно нещо за кръпки, още една таблица в базата данни за архивиране, още една точка на отказ при основна актуализация.
Извикването на външен API при завършване на курса заобикаля и трите проблема. WordPress остава отговорен за това, в което е добър — доставка на съдържание и проследяване на прогреса — а самият сертификат живее в система, изградена специално за неговото издаване, верификация и споделяне.
Моделът: един hook, едно HTTP извикване
Всеки основен WordPress LMS плъгин задейства action, когато потребител завърши курс. Интеграцията винаги се състои от едни и същи три стъпки:
- Прихванете action-а за завършване за вашия конкретен LMS.
- Намерете (или създайте) идентичността на получателя — обикновено просто имейлът и показваното име на неговия WordPress акаунт.
- Извикайте
POST /awardsкъм Badges Ninja API чрезwp_remote_post(), като подадете ID-то на значката и данните на получателя.
Първо ще ви е нужен API ключ. Генерирайте такъв от таблото си под API Keys — вижте ръководството за API ключове за пълните инструкции. Ключовете се показват само веднъж при създаването им, затова го съхранете в wp-config.php като константа, а не в базата данни:
define( 'BADGES_NINJA_API_KEY', 'bws_your_32_hex_key_here' );
define( 'BADGES_NINJA_BADGE_ID', 'your-badge-id' );

Пазете този ключ на сървъра. Всичко в това ръководство се изпълнява в PHP на вашия WordPress сървър — wp_remote_post() е извикване от страна на сървъра, а wp-config.php никога не се изпраща до браузъра. Точно това искате: ключът пътува от сървър до сървър през HTTPS и никой посетител на сайта не може да го прочете. Никога не премествайте това извикване в клиентски JavaScript — fetch() от браузъра с вграден ключ би го изложил на всеки чрез инструментите за разработчици в браузъра. Две навика си струва да поддържате: уверете се, че хостингът ви обслужва wp-config.php като изпълнен PHP (никога като обикновен текст, и не оставяйте копие wp-config.php.bak в webroot), и създайте отделен API ключ за тази интеграция, за да можете да го отмените независимо, ако бъде компрометиран — без да нарушите останалите си инструменти.
Обща помощна функция поддържа всеки LMS hook лек:
function badges_ninja_issue_award( $recipient_email, $recipient_name, $badge_id ) {
$response = wp_remote_post( 'https://api.badges.ninja/awards', array(
'headers' => array(
'X-Api-Key' => BADGES_NINJA_API_KEY,
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( array(
'badgeId' => $badge_id,
'recipient' => array(
'name' => $recipient_name, // must be at least 5 characters
'email' => $recipient_email,
),
'issuedOn' => round( microtime( true ) * 1000 ), // epoch milliseconds
) ),
'timeout' => 15,
) );
if ( is_wp_error( $response ) ) {
error_log( 'Badges Ninja award failed: ' . $response->get_error_message() );
return false;
}
$code = wp_remote_retrieve_response_code( $response );
if ( $code >= 400 ) {
error_log( 'Badges Ninja award failed with HTTP ' . $code . ': ' . wp_remote_retrieve_body( $response ) );
return false;
}
return json_decode( wp_remote_retrieve_body( $response ), true );
}
Имейлът на получателя се хешира с SHA-256 на сървъра веднага щом достигне Badges Ninja, а върнатият payload включва URL адреса за верификация на наградата — удобно, ако искате да покажете линк „вижте своя сертификат” точно там в WordPress след успешното извикване.
LearnDash
LearnDash задейства learndash_course_completed с един аргумент — масив, съдържащ user и course:
add_action( 'learndash_course_completed', function( $data ) {
$user = $data['user'];
$course = $data['course'];
// Map LearnDash course ID → your Badges Ninja badge ID.
// A simple approach: store the badge ID in a course custom field.
$badge_id = get_post_meta( $course->ID, 'badges_ninja_badge_id', true );
if ( ! $badge_id ) {
return; // no badge configured for this course
}
badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
} );
Съхраняването на ID-то на значката като course meta (вместо единствена глобална константа BADGES_NINJA_BADGE_ID) е правилният избор, щом имате повече от един курс — всеки курс се съпоставя със собствен дизайн на значка.
LifterLMS
LifterLMS задейства lifterlms_course_completed с $user_id и $course_id:
add_action( 'lifterlms_course_completed', function( $user_id, $course_id ) {
$user = get_userdata( $user_id );
$badge_id = get_post_meta( $course_id, 'badges_ninja_badge_id', true );
if ( ! $user || ! $badge_id ) {
return;
}
badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
}, 10, 2 );
Tutor LMS
Tutor LMS задейства tutor_course_complete_after с ID-то на курса, а вие извличате текущия потребител от сесията:
add_action( 'tutor_course_complete_after', function( $course_id ) {
$user_id = get_current_user_id();
$user = get_userdata( $user_id );
$badge_id = get_post_meta( $course_id, 'badges_ninja_badge_id', true );
if ( ! $user || ! $badge_id ) {
return;
}
badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
} );
Ако вашата настройка на Tutor LMS задейства завършването от фонов процес (напр. чрез автоматично оценяване на тест), заменете get_current_user_id() с ID-то на потребителя, което предоставя вашият конкретен hook — проверете payload-а с error_log( print_r( func_get_args(), true ) ) еднократно по време на настройката, за да потвърдите аргументите.
Проектиране на значката, преди да свържете hook-а
Преди каквото и да е от това да се задейства, ви трябва значка, която да присъждате. Визуалният дизайнер покрива това, без да е нужен дизайнер в екипа — над 80 шаблона за форми, персонализирани цветове, библиотека с икони и качване на лого, всичко с прилепване към мрежа. Ако сте нови в дизайнера, Проектиране на вашия първи проверим цифров сертификат разглежда избора на шаблон и създаването на нещо, което получателите наистина ще искат да споделят.
Щом значката съществува, вземете нейното ID от таблото (или чрез GET /badges) и го поставете в персонализираното поле на курса.
Какво реално получава получателят
Това е частта, която самоделен WordPress плъгин за значки не може да възпроизведе. Когато POST /awards успее, получателят получава:
- Уникален URL адрес за верификация, който всеки може да отвори — без нужда от вход в WordPress — показващ, че сертификатът е истински, кой го е издал и кога.
- QR код и PDF сертификат във формат A4, генерирани автоматично.
- Бутон Add to LinkedIn Profile, ако вашият издател има зададен LinkedIn organization ID — вижте Добавяне на бутон „Add to Profile” за LinkedIn за еднократната настройка.
- Достъп до собствен портал за получатели на
badges.ninja/me, чрез вход с magic-link — без парола за забравяне, без отделен акаунт за управление във вашия WordPress сайт. - Стандартизиран Open Badge v2.0 JSON-LD, така че всеки verifier, поддържащ OB (не само Badges Ninja), може да го валидира.
Нищо от това не е задача на WordPress да изгради и нищо от него не трябва да живее единствено във вашата WordPress база данни.
Изящно обработване на грешки
Hook-овете за завършване на курс се задействат по време на активна заявка към страница, а бавно или неуспешно API извикване не трябва да блокира екрана с „поздравления” на обучаемия. Две практични корекции, след като преминете отвъд proof of concept:
Не позволявайте неуспешна награда да блокира интерфейса. Помощната функция по-горе вече логва и връща false, вместо да хвърля изключение — LearnDash, LifterLMS и Tutor продължават нормалния си процес на завършване независимо какво връща badges_ninja_issue_award().
Поставяйте я на опашка, вместо да извиквате инлайн, при мащаб. Ако прекарвате големи кохорти през един курс наведнъж (начална дата на кохорта, отключване на запис от уебинар), задействайте планирано събитие чрез WP-Cron от hook-а, вместо да извиквате API-то синхронно:
add_action( 'learndash_course_completed', function( $data ) {
wp_schedule_single_event( time() + 30, 'badges_ninja_deferred_award', array(
$data['user']->user_email,
$data['user']->display_name,
get_post_meta( $data['course']->ID, 'badges_ninja_badge_id', true ),
) );
} );
add_action( 'badges_ninja_deferred_award', 'badges_ninja_issue_award', 10, 3 );
Това разпределя натоварването и не позволява на едно бавно извикване да се превърне в проблем на обучаемия. За наистина големи партиди (цяла минала кохорта, мигрирана наведнъж), пропуснете изцяло пътя през WordPress hook и използвайте масово присъждане чрез CSV — качвате веднъж, а платформата разпределя издаването на страници на сървъра с вградена функция за пауза/възобновяване.
Бележка относно идемпотентността
Ако вашият LMS някога задейства hook-а за завършване повече от веднъж за един и същи потребител (често срещан граничен случай в LearnDash при повторно взимане на тест, или повторна синхронизация в Tutor LMS), не искате да присъдите една и съща значка два пъти. Най-простата защита е флаг в WordPress user-meta, който задавате веднага след успешно извикване:
if ( get_user_meta( $user_id, 'badges_ninja_awarded_' . $course_id, true ) ) {
return; // already issued
}
$result = badges_ninja_issue_award( $user->user_email, $user->display_name, $badge_id );
if ( $result ) {
update_user_meta( $user_id, 'badges_ninja_awarded_' . $course_id, true );
}
Ако издавате в реален обем и искате това да се обработва централизирано, а не по сайт, разгледайте обработка на събития, задвижвана от webhook или пълния API quickstart за формата на заявките/отговорите за всяка крайна точка.
Когато този модел надрасне един-единствен курс
Примерите по-горе предполагат по една значка на курс. Щом започнете да работите с натрупващи се сертификати — значка за пътека, която се отключва след няколко значки за курсове, или финален сертификат, зависещ от няколко предпоставки — преместете съпоставянето „коя значка, за кое завършване” извън post meta и в малка справочна таблица, или го управлявайте чрез автоматизация, базирана на електронна таблица (Airtable или Google Sheets), която задейства същото извикване POST /awards. Самото API извикване не се променя; променя се само това, което решава кога да го направи.
Отстраняване на проблеми с интеграцията
Шепа проблеми обясняват по-голямата част от затрудненията, с които хората се сблъскват, когато свързват това за първи път:
Hook-ът никога не се задейства. Уверете се, че прихващате правилния action за реалната версия на плъгина си — LearnDash в частност е променял имената на hook-овете за завършване през основните версии (по-старите инсталации понякога все още разчитат на learndash_course_completed, задействан от различен път в кода спрямо по-новите). Добавете временен error_log() в началото на вашия callback и наблюдавайте wp-content/debug.log, докато завършвате тестов курс с временен потребител.
wp_remote_post() изтича по време. Средите за споделен хостинг понякога блокират изходящ HTTPS трафик към непознати хостове или ограничават времето за изчакване под зададените по-горе 15 секунди. Ако извикванията системно изтичат по време, проверете при хостинг доставчика си дали изходящите връзки към api.badges.ninja са разрешени, и потвърдете, че разширението curl на вашия PHP разполага с актуални CA сертификати — остарял пакет със сертификати е честа тиха повреда при по-стари среди за споделен хостинг.
400 Bad Request. На payload-а липсва задължително поле или има грешна форма. POST /awards очаква badgeId, вложен обект recipient с name и email, и timestamp issuedOn — помощната функция по-горе изпраща точно това. Най-честото препъване е името на получателя: то трябва да е поне 5 символа, така че показвано WordPress име като „Jo” бива отхвърлено. Използвайте пълното име на акаунта (или локалната част на имейла) като резервен вариант, когато показваното име е твърде кратко.
401 Unauthorized. Константата с API ключа не се зарежда или ключът е бил регенериран, след като константата е зададена. Ключовете се показват само веднъж при създаване и не могат да бъдат извлечени отново — ако сте загубили следа кой ключ е активен, изтрийте остарелия и издайте нов, вместо да гадаете.
Значката е издадена, но с грешен дизайн. Това почти винаги е остаряла стойност на post-meta badges_ninja_badge_id, останала от тестване. Тъй като съпоставянето живее в записа на курса, лесно е да забравите, че сте я променили след дублиране на курс за нова кохорта — струва си бърза проверка всеки път, когато клонирате курс.
Дублирани награди за едно и също лице. Разгледано по-горе чрез защитата с user-meta, но си струва да се повтори: не е гарантирано, че hook-овете за завършване в LMS се задействат точно веднъж. Третирайте „вече присъдено” като нормален случай, за който да проверявате, а не като граничен случай, който да игнорирате.
Често задавани въпроси
Работи ли това с пакети от курсове на WooCommerce? Да — ако покупката на пакет трябва да задейства значка независимо от завършването на курс (напр. значка „сертифициран член” за всеки, който купи конкретен пакет), прихванете woocommerce_order_status_completed вместо action за завършване в LMS и потърсете ID-то на значката от meta на продукта, а не на курс.
Могат ли получателите да получат значката без WordPress акаунт? Да, и точно в това е смисълът. Наградата е обвързана с техния имейл адрес в Badges Ninja, а не със запис за WordPress потребител. Ако сайтът ви позволява поръчка като гост или анонимно завършване на тест, просто се уверете, че улавяте реален имейл адрес, който да подадете на badges_ninja_issue_award().
Какво, ако искам да прегледам наградите, преди да бъдат изпратени? Пропуснете директното извикване от hook-а за завършване. Вместо това запишете чакащата награда (потребител, курс, времеви печат) в персонализирана таблица или тип запис и я издайте от планирана задача или от административен бутон „Approve & Award”, който извиква същата помощна функция при поискване.
Нужна ли ми е отделна значка за всеки курс, или една значка може да покрие няколко? И двата варианта работят. Някои издатели създават по една значка на курс за по-голяма детайлност; други създават една-единствена значка „завършена програма” и я присъждат само след като всички необходими курсове са завършени, като проверяват завършването на предпоставките в hook-а, преди да извикат API-то.
Готови ли сте да издадете първия си проверим сертификат? Започнете безплатно на badges.ninja — визуален дизайнер, публична страница за верификация, PDF сертификат, изход в Open Badge v2.0. Не се изисква кредитна карта.
Как беше създадена тази статия
Някои публикации в този блог се изготвят с помощта на AI асистент, след което се преглеждат, проверяват и редактират от екипа на Badges Ninja преди публикуване. Всеки примерен код и цена се проверяват спрямо реалния продукт. Прочетете повече за нашия редакционен и AI процес на нашата страница за редакционния процес .

За автора
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.
