플랫폼 사용자 배지 표시

연동 서비스의 플랫폼 사용자 이메일과 recipient.email이 일치하는 발급된 배지를 조회해 openbadgeImageUrlcredentialUrl을 표시합니다. 아래는 Next.js·React 구현 예시입니다.

01
서버

써티 API를 호출할 서버 함수를 준비합니다.

빠른 시작의 Node.js 예시를 사용하거나, 같은 인증·오류 처리 원칙을 사용하는 서버 언어로 구현하세요.

Node.js 예시lib/certi.js
lib/certi.js
// lib/certi.js — 서버에서만 사용합니다.
const BASE_URL = "https://api.certi.world/public/v2";

export async function certi(path, options = {}) {
  const response = await fetch(`https://api.certi.world/public/v2${path}`, {
    ...options,
    headers: {
      "X-API-KEY": process.env.CERTI_API_KEY,
      "Content-Type": "application/json",
      ...options.headers,
    },
  });

  const result = await response.json();
  if (!response.ok) {
    throw new Error(`${result.error?.code ?? response.status}: ${result.error?.message ?? "Certi API request failed"}`);
  }
  return result.data;
}
02
서버 API

플랫폼 사용자의 배지를 가져오는 서버 API를 만듭니다.

email은 앞뒤 공백과 대소문자를 정규화한 뒤 완전 일치로 조회합니다. External API v2는 운영 발급만 반환하며, 상태 필터는 서비스의 화면 표시 정책에 맞게 조정하세요. 목록 응답의 badge.image를 표시용 이미지로 사용할 수 있고, 검증 URL과 OpenBadge 이미지는 상세 응답에서 가져옵니다.

Next.js 예시app/api/my-badges/route.js
플랫폼 사용자 확인브라우저가 보낸 이메일을 그대로 사용하지 말고, 플랫폼의 로그인 세션에서 확인한 이메일을 서버에서 사용하세요.
app/api/my-badges/route.js
// app/api/my-badges/route.js — 홈페이지 서버 API
import { certi } from "@/lib/certi";
import { getCurrentUser } from "@/lib/auth"; // 사용 중인 인증 함수로 바꾸세요.

export async function GET() {
  const user = await getCurrentUser();
  const email = user?.email?.trim().toLowerCase();
  if (!email) return Response.json({ message: "sign in required" }, { status: 401 });

  const page = await certi(
    `/assertions?${new URLSearchParams({ email, page: "1", size: "100" })}`,
  );

  // email은 정규화 후 완전 일치하며 External API v2는 운영 발급만 반환합니다.
  // 아래 상태 필터는 화면 표시 정책 예시입니다.
  const issued = page.items.filter((item) =>
    item.recipient.email?.toLowerCase() === email &&
    ["ISSUED", "RECEIVED", "REISSUED"].includes(item.stateCode),
  );

  const items = await Promise.all(issued.map(async (item) => {
    const detail = await certi(`/assertions/${item.id}`);
    return {
      id: detail.id,
      name: detail.badge.name,
      imageUrl: detail.openbadgeImageUrl ?? item.badge.image?.urls.medium ?? item.badge.image?.urls.original,
      credentialUrl: detail.credentialUrl,
    };
  }));

  return Response.json({ items });
}
03
화면

반환된 데이터를 표시합니다.

프론트엔드는 여러분의 /api/my-badges만 호출합니다. 서버가 선택한 이미지와 검증 링크를 그대로 표시합니다.

React 예시components/BadgeList.jsx
components/BadgeList.jsx
// components/BadgeList.jsx — 홈페이지 화면
export function BadgeList({ badges }) {
  return (
    <ul className="badge-list">
      {badges.map((badge) => (
        <li key={badge.id}>
          <img src={badge.imageUrl} alt={`${badge.name} 디지털 배지`} />
          <strong>{badge.name}</strong>
          <a href={badge.credentialUrl} target="_blank" rel="noreferrer">
            배지 검증
          </a>
        </li>
      ))}
    </ul>
  );
}
인증 플랫폼 로그인 세션에서 이메일을 가져옵니다.
정확한 일치 검색 결과의 recipient.email을 서버에서 다시 비교합니다.
상태 필터 화면에 표시 가능한 상태만 노출합니다.
개인정보 다른 플랫폼 사용자의 발급 결과가 반환되지 않는지 테스트합니다.