포트원(PortOne) 결제 연동 코드 생성 및 검토 플러그인. V1/V2 API를 지원하며, MCP 서버를 통해 최신 문서와 예시 코드를 활용합니다.
64
81%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
포트원(PortOne) 결제 연동에 필요한 핵심 개념과 MCP 도구 활용법을 안내한다. 구현이 필요하면 payment-code-generator 에이전트를, 검증이 필요하면 integration-validator 에이전트를 사용한다.
포트원은 온라인 결제, 본인인증, 파트너 정산 자동화를 위한 API와 SDK를 제공하는 서비스이다. 다양한 PG사(결제대행사)를 하나의 통합 API로 연동할 수 있어 개발 복잡도를 크게 줄일 수 있다.
포트원에 대해 학습된 지식은 대부분 outdated 이거나 부정확하다. V1과 V2는 SDK 패키지명, 인증 스킴, 요청/응답 스키마가 모두 다르며 학습 데이터에는 두 버전이 자주 혼재되어 있다. PG사별 파라미터, 결제 수단 코드, 웹훅 페이로드 형식도 자주 바뀐다.
포트원 코드를 작성할 때:
mcp__portone__readPortoneV2FrontendCode / readPortoneV2BackendCode 로 공식 예시를 먼저 조회한다. 프레임워크/PG사/결제수단 조합별 최신 예시가 단일 출처다.mcp__portone__readPortoneOpenapiSchema 로 확인한다. 필드명·필수 여부·타입을 추측하지 않는다.mcp__portone__listPortoneDocs + readPortoneDoc 으로 V1 전용 문서를 조회한다. V2 패턴을 V1에 적용하지 않는다.PortOne 스킴이 우선이다 (Authorization: PortOne <secret>). Bearer는 호환용일 뿐, 학습 데이터의 Bearer 예시를 그대로 따르지 않는다.imp_uid, merchant_uid 등 V1 잔재)을 V2 코드에 섞지 않는다.integration-validator 에이전트가 스키마와 대조할 수 있도록, 어떤 API/문서를 참조했는지 코멘트나 응답에 남긴다.조회한 도구·문서로 뒷받침되지 않는 부분이 있으면 추측하지 말고 명시적으로 "확인 필요"라고 표기한다.
PortOne 인증 스킴 우선 사용사용자가 버전을 지정하지 않은 경우, 신규 프로젝트면 V2를, 기존 코드가 있으면 해당 버전을 따른다.
결제 유형을 선택할 때 다음 설명을 참고하여 사용자에게 안내한다:
포트원 MCP 서버가 제공하는 도구들을 적극 활용한다.
V2 코드 작성 전 반드시 예시 코드 조회:
mcp__portone__readPortoneV2FrontendCode
- framework: react, html 중 선택
- pg: toss, nice, inicis 등
- pay_method: card, virtualAccount, easyPay 등
mcp__portone__readPortoneV2BackendCode
- framework: express, fastapi, flask, spring-kotlin 중 선택
- pg: 사용할 PG사
- pay_method: 결제 수단mcp__portone__listPortoneDocs
- 문서 목록 조회
- dev_docs, help_docs, release_notes 필터링
mcp__portone__readPortoneDoc
- 개별 문서 내용 조회
- path, fields 지정
mcp__portone__regexSearchPortoneDocs
- 정규식 기반 문서 검색
- 키워드로 관련 문서 찾기mcp__portone__readPortoneOpenapiSchemaSummary
- V1/V2 API 전체 요약
mcp__portone__readPortoneOpenapiSchema
- 특정 API 상세 스키마
- yaml_path로 경로 지정mcp__portone__listStores
- 연결된 상점 정보
mcp__portone__getChannelsOfStore
- 상점의 채널 목록
mcp__portone__listSharedTestChannels
- 테스트용 공유 채널readPortoneV2FrontendCode, readPortoneV2BackendCode 사용readPortoneDoc으로 관련 문서 조회SDK 로드 (V2):
import * as PortOne from "@portone/browser-sdk/v2";결제 요청:
const response = await PortOne.requestPayment({
storeId: "store-id",
channelKey: "channel-key",
paymentId: `payment-${crypto.randomUUID()}`,
orderName: "주문명",
totalAmount: 1000,
currency: "KRW",
payMethod: "CARD",
});결제 검증 (V2 — 공식 Server SDK 사용 권장):
import * as PortOne from "@portone/server-sdk";
const portoneClient = PortOne.PortOneClient({
secret: process.env.PORTONE_API_SECRET,
});
// 결제 조회 및 검증
const payment = await portoneClient.payment.getPayment({ paymentId });
// payment.amount.total, payment.status 등을 주문 정보와 대조하여 검증SDK는 PortOne 인증 스킴을 자동으로 사용하며, PG별 응답 차이를 정규화한 타입 안전한 결과를 반환한다. 직접 fetch를 호출해야 하는 경우 Authorization: PortOne <SECRET> 헤더를 사용한다 (Bearer는 호환용일 뿐 V2에서는 PortOne 스킴이 우선).
.env 파일).gitignore)if (response.code) {
// 에러 발생
console.error(response.message);
// 사용자에게 적절한 메시지 표시
}웹훅 페이로드를 처리하기 전에 반드시 시그니처를 검증한다. HMAC 검증은 파싱된 JSON이 아닌 원본 raw 바디에 대해 수행해야 하므로, JSON 파서보다 먼저 express.raw() 미들웨어를 적용한다.
import express from "express";
import * as PortOne from "@portone/server-sdk";
app.post(
"/webhook",
express.raw({ type: "application/json" }),
async (req, res, next) => {
try {
// express.raw()는 req.body를 Buffer로 전달하지만,
// @portone/server-sdk의 verify()는 string 페이로드를 요구한다.
// UTF-8로 디코딩해도 HMAC이 계산된 바이트 시퀀스는 보존된다.
const payload =
req.body instanceof Buffer ? req.body.toString("utf8") : req.body;
// 시그니처 검증 — 페이로드 처리보다 먼저 수행
const webhook = await PortOne.Webhook.verify(
process.env.PORTONE_WEBHOOK_SECRET,
payload,
req.headers,
);
// 검증 통과 — 결제 상태 업데이트, 주문 처리 (멱등성 보장)
res.status(200).send("OK");
} catch (e) {
// 검증 실패한 웹훅은 거부
if (e instanceof PortOne.Webhook.WebhookVerificationError) {
return res.status(401).send("Invalid webhook signature");
}
// Express 4의 async 라우트 핸들러는 throw된 에러를 자동으로
// 에러 미들웨어로 전달하지 않으므로 next(e)로 명시 전달한다.
next(e);
}
},
);주의: app.use(express.json())을 전역으로 사용하는 경우, 웹훅 라우트는 반드시 그 이전에 등록해야 한다. Express 바디 파서는 스트림 기반이라 전역 JSON 파서가 먼저 실행되면 바디가 이미 소비되어 라우트 단의 express.raw()로 원본 바이트를 다시 읽을 수 없다. 이 경우 HMAC 검증이 항상 실패한다.
mcp__portone__listSharedTestChannels로 테스트 채널 조회포트원 MCP 서버 도구를 통해 최신 문서와 API 스키마를 항상 조회할 수 있다. 코드 작성 전 반드시 예시 코드와 문서를 확인한다.