본문으로

가이드

크레딧 판매

API나 AI 서비스용 선불 크레딧: 구매자가 직접 충전하고, 내 서버가 호출마다 차감합니다. 충전에서 떼어 가는 것은 없습니다.

Markdown으로 열기

크레딧은 사용량으로 파는 모든 것에 맞습니다: 토큰, 이미지, 분, 검색. 구매자가 암호화폐로 패키지를 사고, 호출마다 거기서 차감하며, 크레딧이 떨어지면 구매자가 자기 페이지에서 충전합니다. 자동으로 청구되는 것은 없습니다 — 구매자가 항상 직접 결제합니다 — 그리고 Perly는 충전에서 아무것도 떼지 않습니다.

설정

  1. 1

    상품과 패키지 만들기

    Dashboard → Products → New, 그다음 New price → Credit pack: 예를 들어 $10에 1,000크레딧, $40에 5,000크레딧. 또는 pay.prices.create({ product, model: "credit_pack", unit_amount: 1000, credits: 1000 }).

  2. 2

    구매자가 잔액을 알게 되는 시점 정하기

    상품 페이지의 Credits 섹션에서: 경고 기준값, 구매자 이메일, 그리고 Any amount — 패키지 하나의 N배로, 구매자가 고정 패키지가 아닌 $25도 충전할 수 있게.

  3. 3

    구매자마다 고객 만들기

    사용자마다 내 id로 하나씩: pay.customers.create({ email, external_id: user.id }). 이후 SDK는 그 id를 받습니다.

차감, 확인, 충전

import { PerlyPay, InvalidRequestError } from "perly-pay";
const pay = new PerlyPay(process.env.PERLY_PAY_SECRET_KEY);

// Before the work: enough left?
const { balance, top_up_url } = await pay.credits.balance(user.id);

// After it: spend. The same idempotencyKey never spends twice.
try {
  await pay.credits.consume(user.id, 3, { action: "chat", idempotencyKey: request.id });
} catch (e) {
  if (e instanceof InvalidRequestError && e.code === "insufficient_credits") {
    return { error: "Out of credits", topUp: await pay.credits.topUpUrl(user.id) };
  }
  throw e;
}
  • 고객은 cus_… id, 이메일, 또는 내가 붙인 id(external_id)입니다. 여러 상품에 크레딧을 판다면 product를 지정하세요.
  • 차감은 원자적이며 절대 0 아래로 가지 않습니다: 같은 크레딧에 동시에 두 번 차감되지 않습니다. 부족하면 insufficient_credits(409)이고, 아무것도 차감되지 않습니다.
  • 요청 id를 멱등성 키로 넘기세요. 타임아웃, 장애 뒤, 심지어 다음 날 재시도해도 첫 차감이 돌아올 뿐 다시 차감되지 않습니다.
  • action은 내 라벨입니다(chat, image.hd, api/search). 상품 페이지가 동작별·고객별 사용량을 합산합니다.

충전 페이지

top_up_url은 구매자 전용 페이지로, 항상 같습니다: 내 결제창 스타일로 잔액과 패키지를 보여 주고, 구매자가 패키지를 고르면 일반 청구서를 엽니다. 결제되면 크레딧이 잔액에 한 번 더해집니다. 앱 안에, '크레딧 소진' 오류에 링크를 보여 주거나 보내 주세요 — 구매자 포털에도 충전 버튼이 있습니다.

크레딧이 떨어질 때

이벤트시점
credits.low잔액이 상품의 기준값까지 내려감. 넘을 때마다 한 번: 충전으로 다시 올라간 뒤에야 다시 옵니다.
credits.depleted잔액이 0이 됨. 넘을 때마다 한 번.

둘 다 고객을 data.object로, 그리고 data.product와 data.balance를 담습니다. 기준값이 있고 이메일이 켜져 있으면 구매자도 충전 링크가 담긴 이메일을 한 통 받습니다 — 하루 한 번 이하. 테스트 모드에서는 이메일이 내 팀에게만 갑니다.

여러 패키지의 크레딧은 합산됩니다. 차감은 가장 오래된 패키지부터.