Open Badges kiadása WordPressből (nehézkes plugin nélkül)

Adj ki Open Badges jelvényeket bármelyik WordPress kurzus-/LMS-pluginból (LearnDash, LifterLMS, Tutor) a Badges Ninja API meghívásával a teljesítéskor — külön jelvényplugin telepítése nélkül.

Nacho Coll Szerző: Frissítve 11 perc olvasás
Adj ki Open Badges jelvényeket bármelyik WordPress kurzus-/LMS-pluginból (LearnDash, LifterLMS, Tutor) a Badges Ninja API meghívásával a teljesítéskor — külön jelvényplugin telepítése nélkül.

Ha kurzusokat futtatsz WordPressen, ismerős a menet: valaki befejez egy modult a LearnDash-ben, LifterLMS-ben vagy Tutor LMS-ben, az LMS „teljesítve”-ként jelöli, majd… semmi ellenőrizhető nem történik. Talán küldesz egy PDF-et emailben. Talán telepítesz egy dedikált WordPress jelvényplugint, amely saját adatbázis-táblákat, saját képkönyvtárat és saját elképzelést ad hozzá arról, mi is az a „jelvény” — amit a site-odon kívül senki sem tud ellenőrizni.

Van egyszerűbb út. A WordPress kurzuspluginok már most is elsütnek egy action hook-ot abban a pillanatban, amikor valaki befejez egy kurzust. Elkaphatod ezt a hook-ot, és egyetlen HTTP-hívást intézhetsz a Badges Ninja API-hoz. Nincs extra plugin, nincs extra tárhely, nincs proprietary jelvényformátum — csak egy szabványoknak megfelelő Open Badge v2.0 hitelesítvény, amit a címzett bárhol ellenőrizhet, hozzáadhat a LinkedIn-hez, és letölthet PDF-ként.

Ez a bejegyzés egyszer végigmegy a mintán, majd megmutatja a konkrét hook-ot LearnDash-hez, LifterLMS-hez és Tutor LMS-hez.

Miért ne használj egyszerűen egy WordPress jelvénypluginot?

A dedikált WordPress jelvénypluginok szűkebb problémát oldanak meg, mint amilyennek látszanak. Jók abban, hogy megjelenítsenek egy képet egy „eredményeim” oldalon, a site-odon belül. Általában sokkal gyengébbek azokban a dolgokban, amik egy hitelesítvénynél tényleg számítanak:

  • Hordozhatóság. Egy jelvény, ami csak shortcode-ként létezik a WordPress site-odon, nem hitelesítvény — dekoráció. Abban a pillanatban, hogy a címzett munkahelyet vált, inboxot vált, vagy a site-od leáll, a „bizonyíték” is eltűnik vele.
  • Ellenőrzés. Bárkinek meg kell tudnia ellenőrizni, hogy egy hitelesítvény valódi, anélkül hogy be kellene jelentkeznie a WordPress admin felületedre. Az Open Badge v2.0 eleve nyilvános ellenőrző URL-t és géppel olvasható JSON-LD-t ad.
  • Karbantartási felület. Minden WordPress plugin még egy dolog, amit patchelni kell, még egy adatbázistábla, amit menteni kell, még egy hibapont egy alaprendszer-frissítés során.

Egy külső API meghívása a kurzus teljesítésekor mindhármat megkerüli. A WordPress felelős marad azért, amiben jó — tartalomkiszolgálás és haladáskövetés —, a hitelesítvény pedig egy olyan rendszerben él, amelyet kifejezetten kiadásra, ellenőrzésre és megosztásra építettek.

A minta: egy hook, egy HTTP-hívás

Minden nagyobb WordPress LMS plugin akciót süt el, amikor egy felhasználó befejez egy kurzust. Az integráció mindig ugyanaz a három lépés:

  1. Csatlakozz a teljesítési akcióhoz, ami a te konkrét LMS-ednek megfelel.
  2. Keresd meg (vagy hozd létre) a címzett identitását — általában csak a WordPress fiók email címe és megjelenített neve.
  3. Hívd meg a POST /awards-t a Badges Ninja API-n a wp_remote_post() segítségével, átadva a jelvény ID-t és a címzett adatait.

Először szükséged lesz egy API kulcsra. Generálj egyet a dashboard-odon, az API Keys alatt — a teljes végigvezetéshez lásd az API kulcsok útmutatót. A kulcsok csak egyszer jelennek meg létrehozáskor, ezért tárold a wp-config.php-ban konstansként, ne az adatbázisban:

define( 'BADGES_NINJA_API_KEY', 'bws_your_32_hex_key_here' );
define( 'BADGES_NINJA_BADGE_ID', 'your-badge-id' );

Newly created key revealed once

Tartsd ezt a kulcsot szerveroldalon. Minden, ami ebben az útmutatóban van, PHP-ban fut a WordPress szervereden — a wp_remote_post() szerveroldali hívás, a wp-config.php pedig sosem kerül elküldésre a böngészőbe. Pontosan ezt akarod: a kulcs szervertől szerverig utazik HTTPS-en keresztül, és egyetlen site-látogató sem tudja elolvasni. Soha ne told át ezt a hívást kliensoldali JavaScriptbe — egy fetch() a böngészőből, a kulccsal beleírva, bárki számára hozzáférhetővé tenné a böngésző fejlesztői eszközein keresztül. Két szokás megéri megtartani: győződj meg róla, hogy a hosztod végrehajtott PHP-ként szolgálja ki a wp-config.php-t (soha nem sima szövegként, és ne hagyj egy wp-config.php.bak másolatot a webroot-ban), és hozz létre egy dedikált API kulcsot ehhez az integrációhoz, hogy függetlenül vissza tudd vonni, ha valaha kompromittálódik — anélkül, hogy elrontanád a többi eszközödet.

Egy közös helper függvény minden LMS hook-ot vékonyan tart:

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

A címzett email címe szerveroldalon SHA-256-tal kerül hashelésre, amint megérkezik a Badges Ninja-hoz, a visszaadott payload pedig tartalmazza az award ellenőrző URL-jét — hasznos, ha rögtön ott, a WordPressben szeretnél mutatni egy „nézd meg a hitelesítványod” linket a hívás sikere után.

LearnDash

A LearnDash elsüti a learndash_course_completed-et egyetlen tömb argumentummal, amely user-t és course-t tartalmaz:

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

A jelvény ID kurzus-metaadatként tárolása (egyetlen globális BADGES_NINJA_BADGE_ID konstans helyett) a helyes döntés, amint egynél több kurzusod van — minden kurzus a saját jelvénydizájnjához rendelődik.

LifterLMS

A LifterLMS elsüti a lifterlms_course_completed-et $user_id-vel és $course_id-vel:

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

A Tutor LMS elsüti a tutor_course_complete_after-t a kurzus ID-val, a jelenlegi felhasználót pedig a munkamenetből olvasod ki:

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

Ha a Tutor LMS beállításod egy háttérfolyamatból (pl. egy kvíz automatikus javításán keresztül) süti el a teljesítést, cseréld le a get_current_user_id()-t arra a felhasználói ID-ra, amit a konkrét hook-od biztosít — ellenőrizd a payload-ot egyszer, a beállítás során, az error_log( print_r( func_get_args(), true ) ) segítségével, hogy megerősítsd az argumentumokat.

A jelvény megtervezése, mielőtt bekötnéd a hook-ot

Mielőtt bármelyik is elsülne, szükséged van egy odaítélhető jelvényre. A vizuális tervező ezt lefedi anélkül, hogy dizájnerre lenne szükség a csapatban — 80+ alaksablon, egyéni színek, ikonkönyvtár és logófeltöltés, mind rácshoz illesztve. Ha új vagy a tervezőben, a Designing Your First Verifiable Digital Certificate végigvezet egy sablon kiválasztásán, és olyasmi elkészítésén, amit a címzettek tényleg meg akarnak majd osztani.

Amint a jelvény létezik, szedd ki az ID-ját a dashboard-ról (vagy a GET /badges-en keresztül), és tedd bele a kurzusod egyéni mezőjébe.

Amit a címzett ténylegesen kap

Ez az a rész, amit egy házilag barkácsolt WordPress jelvényplugin nem tud reprodukálni. Amikor a POST /awards sikeres, a címzett kap:

  • Egy egyedi ellenőrző URL-t, amit bárki megnyithat — WordPress bejelentkezés nélkül —, amely megmutatja, hogy a hitelesítvény valódi, ki adta ki, és mikor.
  • Egy QR-kódot és A4-es PDF tanúsítványt, automatikusan generálva.
  • Egy Add to LinkedIn Profile gombot, ha a kibocsátódnak be van állítva egy LinkedIn szervezeti ID-ja — lásd Add a LinkedIn “Add to Profile” Button az egyszeri beállításhoz.
  • Hozzáférést a saját címzett-portáljukhoz, a badges.ninja/me-n, magic-link bejelentkezéssel — nincs elfelejthető jelszó, nincs külön kezelendő fiók a WordPress site-odon.
  • Szabványoknak megfelelő Open Badge v2.0 JSON-LD-t, így bármely OB-tudatos ellenőrző (nem csak a Badges Ninja) validálni tudja.

Ezek egyikét sem a WordPress dolga megépíteni, és egyik sem élhet csak a WordPress adatbázisodban.

A hibák elegáns kezelése

A kurzus-teljesítési hook-ok élő oldalkérés közben sülnek el, és egy lassú vagy sikertelen API-hívás nem szabadna blokkolja a tanuló „gratulálunk” képernyőjét. Két gyakorlati kiigazítás, amint túllépsz a proof of conceptán:

Ne hagyd, hogy egy sikertelen award blokkolja a felületet. A fenti helper függvény már naplóz és false-t ad vissza dobás helyett — a LearnDash, a LifterLMS és a Tutor mind folytatja a normál teljesítési folyamatát, függetlenül attól, mit ad vissza a badges_ninja_issue_award().

Sorba állítás inline hívás helyett, nagyobb léptékben. Ha nagy kohorszokat futtatsz egyetlen kurzuson keresztül egyszerre (egy kohorsz kezdő dátuma, egy webinárium-visszajátszás feloldása), süss el egy ütemezett WP-Cron eseményt a hook-ból, ahelyett hogy szinkron hívnád az API-t:

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

Ez elosztja a terhelést, és megakadályozza, hogy egyetlen lassú kérés a tanuló problémájává váljon. Igazán nagy kötegek esetén (egy egész múltbeli kohorsz, egyszerre migrálva) hagyd ki teljesen a WordPress hook útvonalat, és használd a tömeges kiadást CSV-ből — egyszer töltesz fel, a platform pedig szerveroldalon lapoz a kiadáson, beépített szüneteltetéssel/folytatással.

Egy megjegyzés az idempotenciáról

Ha az LMS-ed valaha egynél többször süti el a teljesítési hook-ot ugyanahhoz a felhasználóhoz (gyakori LearnDash-szélsőeset kvíz-újrapróbálkozásoknál, vagy egy Tutor LMS újraszinkronizálás), nem akarod ugyanazt a jelvényt kétszer odaítélni. A legegyszerűbb védelem egy WordPress user-meta jelző, amit közvetlenül egy sikeres hívás után állítasz be:

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

Ha valódi volumenben adsz ki, és ezt centralizáltan, nem site-onként szeretnéd kezelni, nézd meg a webhook-alapú eseménykezelést vagy a teljes API gyorsindítást a kérés/válasz formákért minden végponton.

Amikor ez a minta kinövi az egyetlen kurzust

A fenti példák egy jelvényt feltételeznek kurzusonként. Amint egymásra épülő hitelesítványokat futtatsz — egy útvonal-jelvényt, ami több kurzusjelvény után oldódik fel, vagy egy záró (capstone) jelvényt, ami több előfeltételtől függ —, told ki a „melyik jelvény, melyik teljesítéshez” leképezést a post meta-ból egy kis lookup táblába, vagy vezéreld egy táblázat-alapú automatizálásból (Airtable vagy Google Sheets), amely ugyanazt a POST /awards hívást süti el. Maga az API-hívás nem változik; csak az, ami eldönti, mikor hívja meg.

Az integráció hibaelhárítása

Néhány probléma adja a legtöbb súrlódást, amivel az emberek szembesülnek, amikor először kötik be ezt:

A hook sosem sül el. Erősítsd meg, hogy a pluginod tényleges verziójához illő akcióhoz kapcsolódsz — a LearnDash különösen megváltoztatta a teljesítési hook-nevek elnevezését a főbb kiadások során (a régebbi telepítések néha még mindig egy másik kódútvonalból elsülő learndash_course_completed-re támaszkodnak, mint az újabbak). Adj hozzá egy ideiglenes error_log()-ot a callback-ed tetejéhez, és figyeld a wp-content/debug.log-ot, miközben egy teszt kurzust fejezel be egy eldobható felhasználóként.

A wp_remote_post() időtúllépést kap. A megosztott tárhelykörnyezetek néha blokkolják a kimenő HTTPS-t ismeretlen hosztok felé, vagy a fent beállított 15 másodperc alá korlátozzák a kéréseket. Ha a hívások következetesen időtúllépést kapnak, ellenőrizd a hosztodnál, hogy engedélyezettek-e a kimenő kapcsolatok az api.badges.ninja-hoz, és erősítsd meg, hogy a PHP curl bővítményed aktuális CA-tanúsítványokkal rendelkezik — egy elavult tanúsítványcsomag gyakori néma hiba a régebbi megosztott tárhely-stackeken.

400 Bad Request. A payload hiányol egy kötelező mezőt, vagy rossz alakú. A POST /awards badgeId-t vár, egy beágyazott recipient objektumot name-mel és email-lel, valamint egy issuedOn időbélyeget — a fenti helper pontosan ezt küldi. A leggyakoribb buktató a címzett neve: legalább 5 karakternek kell lennie, így egy olyan WordPress megjelenített név, mint a „Jo”, elutasításra kerül. Térj vissza a fiók teljes nevéhez (vagy az email helyi részéhez), ha a megjelenített név túl rövid.

401 Unauthorized. Az API kulcs konstans nem töltődik be, vagy a beállítás után regenerálódott. A kulcsok csak egyszer jelennek meg létrehozáskor, és nem szerezhetők vissza újra — ha elvesztetted a fonalat, melyik kulcs él, töröld a régit, és adj ki egy frisset, ahelyett hogy találgatnál.

A jelvény kiadva, de rossz jelvénydizájnnal. Ez szinte mindig egy elavult badges_ninja_badge_id post-meta érték, ami a tesztelésből maradt. Mivel a leképezés a kurzus posztján él, könnyű elfelejteni, hogy megváltoztattad, miután duplikáltál egy kurzust egy új kohorsz számára — érdemes gyorsan ellenőrizni, amikor csak klónozol egy kurzust.

Duplikált award-ok ugyanannak a személynek. Fentebb lefedve a user-meta védelemmel, de érdemes megismételni: az LMS teljesítési hook-ok elsülése nem garantáltan pontosan egyszeri. Kezeld a „már odaítélve” állapotot ellenőrizendő normál esetként, ne figyelmen kívül hagyandó szélsőesetként.

Gyakran ismételt kérdések

Működik ez WooCommerce kurzuscsomagokkal? Igen — ha egy csomagvásárlásnak jelvényt kellene indítania a kurzus teljesítésétől függetlenül (pl. egy „hitelesített tag” jelvényt bárkinek, aki egy adott csomagot megvásárol), kapcsold a woocommerce_order_status_completed-hez egy LMS teljesítési akció helyett, és a jelvény ID-t a termék metaadataiból, ne egy kurzusból keresd elő.

Kaphatnak a címzettek jelvényt WordPress fiók nélkül? Igen, és pontosan ez a lényeg. Az award az email címükhöz kötött a Badges Ninja-ban, nem egy WordPress felhasználói rekordhoz. Ha a site-od engedélyezi a vendégfizetést vagy az anonim kvíz-teljesítést, csak győződj meg róla, hogy valódi email címet rögzítesz a badges_ninja_issue_award()-nak való átadáshoz.

Mi van, ha át akarom nézni az award-okat, mielőtt kimennek? Hagyd ki, hogy a hívás közvetlenül a teljesítési hook-ból süljön el. Ehelyett írd a függőben lévő award-ot (felhasználó, kurzus, időbélyeg) egy egyéni táblába vagy posttípusba, és adj ki egy ütemezett feladatból vagy egy admin „Approve & Award” gombból, amely ugyanazt a helper függvényt hívja meg igény szerint.

Külön jelvényre van szükségem kurzusonként, vagy egy is lefedhet többet? Mindkettő működik. Néhány kibocsátó kurzusonként egy jelvényt hoz létre a granularitásért; mások egyetlen „program teljesítve” jelvényt hoznak létre, és csak akkor ítélik oda, ha minden szükséges kurzus elkészült, az előfeltétel teljesítését a hook-on belül ellenőrizve, az API meghívása előtt.


Készen állsz az első ellenőrizhető hitelesítványod kiadására? Kezdd el ingyen a badges.ninja-n — vizuális tervező, nyilvános ellenőrző oldal, PDF tanúsítvány, Open Badge v2.0 kimenet. Nincs szükség bankkártyára.

Nacho Coll

A szerzőről

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.

Vissza a Blogra

Kapcsolódó cikkek