diff --git a/src/content/docs/ko/v2-payment/_assets/v2/webhook-secret-1.png b/src/content/docs/ko/v2-payment/_assets/v2/webhook-secret-1.png
new file mode 100644
index 000000000..833ac144d
Binary files /dev/null and b/src/content/docs/ko/v2-payment/_assets/v2/webhook-secret-1.png differ
diff --git a/src/content/docs/ko/v2-payment/_assets/v2/webhook-secret-2.png b/src/content/docs/ko/v2-payment/_assets/v2/webhook-secret-2.png
new file mode 100644
index 000000000..0878f8017
Binary files /dev/null and b/src/content/docs/ko/v2-payment/_assets/v2/webhook-secret-2.png differ
diff --git a/src/content/docs/ko/v2-payment/confirm-process.mdx b/src/content/docs/ko/v2-payment/confirm-process.mdx
index a8851b063..e6155cb3a 100644
--- a/src/content/docs/ko/v2-payment/confirm-process.mdx
+++ b/src/content/docs/ko/v2-payment/confirm-process.mdx
@@ -84,14 +84,65 @@ import ConfirmProcessImage1 from "./_assets/v2/confirm_process_v2_1.png";
}
```
-해당 URL이 설정되면 포트원에서 결제 승인 요청 직전 해당 URL로 **HTTP 통신**이 진행되며
-아래와 같은 데이터가 POST로 요청됩니다. (Timeout : **10s**)
+## Payload Schema
-> `tx_id`: 포트원 결제번호
->
-> `payment_id`: 고객사 주문번호
->
-> `total_amount`: 결제 요청 금액
+콘솔에서 설정하신 웹훅 버전에 따라 상이한 형식의 payload가 송신됩니다.
-해당 요청에 대한 고객사 응답으로 HTTP Status **200** 응답인 경우에만 결제 승인을 요청합니다.
-**200 응답이 아닌 경우 결제가 진행되지 않으며 `결제 실패` 상태로 남습니다.**
+### `2024-01-01` 사용 시
+
+- `payment_id`: 고객사에서 채번한 결제건의 고유 주문 번호입니다.
+- `tx_id`: 포트원에서 채번한 결제건의 고유 거래 번호입니다.
+- `total_amount`: 결제건의 결제 요청 금액입니다.
+
+**컨펌 웹훅 payload 예시:**
+
+```json
+{
+ "payment_id": "example-payment-id",
+ "tx_id": "55451513-9763-4a7a-bb43-78a4c65be843",
+ "total_amount": 1000
+}
+```
+
+### `2024-04-25` 사용 시
+
+- `type`: 웹훅을 트리거한 이벤트의 타입입니다. 컨펌 웹훅의 경우 `type`의 값은 `Transaction.Confirm`으로 고정됩니다.
+
+- `timestamp`: 해당 웹훅을 트리거한 이벤트의 발생 시각(RFC 3339 형식)입니다.
+
+- `data`: 웹훅을 트리거한 이벤트의 실제 세부 내용입니다. 컨펌 웹훅의 경우 해당 필드의 상세 스키마는 아래와 같습니다.
+ - `paymentId`: 고객사에서 채번한 결제건의 고유 주문 번호입니다.
+ - `transactionId`: 포트원에서 채번한 결제건의 고유 거래 번호입니다.
+ - `totalAmount`: 결제건의 결제 요청 금액입니다.
+
+**컨펌 웹훅 payload 예시:**
+
+```json
+{
+ "type": "Transaction.Confirm",
+ "timestamp": "2024-04-25T10:00:00.000Z",
+ "data": {
+ "paymentId": "example-payment-id",
+ "transactionId": "55451513-9763-4a7a-bb43-78a4c65be843",
+ "totalAmount": 1000
+ }
+}
+```
+
+## SDK 실패 응답에 특정 에러 메세지 포함시키기
+
+고객사는 재고 부족 등의 이유로 포트원이 보낸 컨펌 프로세스 요청에 실패 응답을 보낼 수 있고, 이러한 실패 사유를 서비스를 이용하는 고객들에게 보여주고 싶을 수 있습니다.
+이러한 경우 Response Body에 `errorMessage` 라는 필드를 포함하여 에러 응답을 보내주시면 해당 메세지를 포함해 SDK 응답으로 리턴해드리고 있습니다.
+
+**Error Response Body 예시:**
+
+```json
+{
+ "errorMessage": "재고가 모두 소진되었습니다. 관리자에게 문의하세요."
+}
+```
+
+## 컨펌 웹훅 요청 검증하기
+
+컨펌 프로세스 웹훅 또한 다른 일반적인 웹훅과 동일한 방식으로 검사하시는 것을 권장합니다.
+[웹훅 연동하기 - 웹훅 요청 검증하기](./webhook#웹훅-요청-검증하기)를 참고하셔서 컨펌 웹훅을 신뢰할 수 있는지를 검사하세요.
diff --git a/src/content/docs/ko/v2-payment/pg/tosspay-v2.mdx b/src/content/docs/ko/v2-payment/pg/tosspay-v2.mdx
index 090521922..2ed53b2fd 100644
--- a/src/content/docs/ko/v2-payment/pg/tosspay-v2.mdx
+++ b/src/content/docs/ko/v2-payment/pg/tosspay-v2.mdx
@@ -119,6 +119,7 @@ function requestPayment() {
전달하지 않을경우, 기본값은 GENERAL 입니다.
일반 (default) : `GENERAL` / 문화비 : `CULTURE` / 교통비 : `PUBLIC_TP`
+
@@ -331,7 +332,6 @@ const response = await axios({
**구매자 이메일**
-
## API 빌링키 예약/반복 결제 요청하기
diff --git a/src/content/docs/ko/v2-payment/webhook.mdx b/src/content/docs/ko/v2-payment/webhook.mdx
index 1833259d3..78995bf18 100644
--- a/src/content/docs/ko/v2-payment/webhook.mdx
+++ b/src/content/docs/ko/v2-payment/webhook.mdx
@@ -10,6 +10,8 @@ import Figure from "~/components/Figure.astro";
import Hint from "~/components/Hint.astro";
import image1 from "../result/_assets/webhook_intro.png";
+import image2 from "./_assets/v2/webhook-secret-1.png";
+import image3 from "./_assets/v2/webhook-secret-2.png"
import image0 from "./_assets/v2/webhook-setting.png";
@@ -30,24 +32,109 @@ Webhook을 활용하면 커스텀 기능이나 다른 애플리케이션과 연
인터넷 연결 끊김, 브라우저 자동 새로고침 등의 이유로 클라이언트에서 결제 완료에 대한 응답을 받지 못하는 경우가 간헐적으로 발생합니다.
이런 경우 연동한 웹훅을 통해 누락 없이 결제 정보를 동기화할 수 있습니다.
-## 웹훅 발생 이벤트
-
-포트원 웹훅은 다음과 같은 이벤트에 발생됩니다.
-
-- **결제창이 열렸을 때** - (status: `Ready`)
-- **결제(예약 결제 포함)가 승인**되었을 때 (모든 결제 수단) - (status : `Paid`)
-- **가상계좌가 발급**되었을 때 - (status : `VirtualAccountIssued`)
-- **가상계좌에 결제 금액이 입금**되었을 때 - (status : `Paid`)
-- **결제가 부분 취소**되었을 때 - (status : `PartialCancelled`)
-- **결제가 완전 취소**되었을 때 - (status : `Cancelled`)
-- **결제(예약 결제 포함)가 실패**했을 때 - (status: `Failed`)
-- **결제 승인 대기** 상태가 되었을 때 (페이팔 연동 시 발생) - (status: `PayPending`)
-- (결제 취소가 비동기로 수행되는 경우) **결제 취소를 요청**했을 때 - (status : `CancelPending`)
-- **빌링키 발급이 인증**되었을 때 - (billingKeyStatus : `Ready`)
-- **빌링키가 발급**되었을 때 - (billingKeyStatus : `Issued`)
-- **빌링키 발급이 실패**했을 때 - (billingKeyStatus : `Failed`)
-- **빌링키가 삭제**되었을 때 - (billingKeyStatus : `Deleted`)
-- **빌링키가 업데이트**되었을 때 - (billingKeyStatus : `Updated`)
+## 웹훅 버전에 따른 스키마 안내
+
+웹훅 형식에 하위 호환이 보장되지 않는 변경이 있을 경우 새로운 웹훅 버전이 추가됩니다. 어떤 버전의 웹훅을 받을지 콘솔에서 설정할 수 있습니다.
+
+현재 웹훅 버전은 두 가지입니다.
+
+- `2024-04-25` (최신)
+ - 본문 형식이 Standard Webhooks를 따르도록 변경 (Standard Webhooks 기반 메시지 검증의 경우 기존 버전에서도 사용 가능)
+ - 메시지의 확장성을 명시
+
+- `2024-01-01`
+ - 최초 웹훅 버전
+
+### `2024-04-25` (최신) 사용 시
+
+- `type`: 웹훅을 트리거한 이벤트의 타입입니다. 가능한 `type`의 종류는 아래와 같습니다.
+ - **결제 관련**
+ - `Transaction.Ready`: **결제창이 열렸을 때**
+ - `Transaction.Paid`: **결제(예약 결제 포함)가 승인**되었을 때 (모든 결제 수단)
+ - `Transaction.VirtualAccountIssued`: **가상계좌가 발급**되었을 때
+ - `Transaction.PartialCancelled`: **결제가 부분 취소**되었을 때
+ - `Transaction.Cancelled`: **결제가 완전 취소**되었을 때
+ - `Transaction.Failed`: **결제(예약 결제 포함)가 실패**했을 때
+ - `Transaction.PayPending`: **결제 승인 대기** 상태가 되었을 때
+ - `Transaction.CancelPending`: (결제 취소가 비동기로 수행되는 경우) **결제 취소를 요청**했을 때
+
+ - **빌링키 발급 관련**
+ - `BillingKey.Ready`: **빌링키 발급창이 열렸을 때**
+ - `BillingKey.Issued`: **빌링키가 발급**되었을 때
+ - `BillingKey.Failed`: **빌링키 발급이 실패**했을 때
+ - `BillingKey.Deleted`: **빌링키가 삭제**되었을 때
+ - `BillingKey.Updated`: **빌링키가 업데이트**되었을 때
+
+- `timestamp`: 해당 웹훅을 트리거한 이벤트의 발생 시각(RFC 3339 형식)입니다.
+ 고객사 서버가 웹훅을 수신하는 데 실패하여 재시도가 일어나도 이 값은 동일하게 유지됩니다.
+
+- `data`: 웹훅을 트리거한 이벤트의 실제 세부 내용입니다. `type` 에 따라 해당 필드의 스키마가 달라질 수 있으며, `type` 별 상세 스키마는 아래와 같습니다.
+ - **결제 관련**
+ - `paymentId`: 고객사에서 채번한 결제 건의 고유 주문 번호입니다.
+ - `transactionId`: 포트원에서 채번한 고유 거래 번호입니다. 한 결제 건에 여러 시도가 있을 경우 transactionId가 달라질 수 있습니다.
+ - `cancellationId`: (optional) 포트원에서 채번한 결제건의 취소 고유 번호입니다. `type`이 `Transaction.PartialCancelled` 혹은 `Transaction.Cancelled` 일 때 존재합니다.
+
+ - **빌링키 발급 관련**
+ - `billingKey`: 포트원에서 채번한 빌링키입니다.
+
+
+ **웹훅 메시지에는 별도 안내 없이 `type` 값이나 새로운 필드가 추가될 수 있습니다.**
+
+ - 알지 못하는 `type`을 가진 메시지의 경우 에러를 발생시키지 말고 메시지 전체를 무시해 주세요.
+ - 알지 못하는 필드가 있는 경우 해당 필드를 무시해 주세요.
+
+
+**웹훅 본문 예시 1**: `type`이 `Transaction.Cancelled` 일 때
+
+```json
+{
+ "type": "Transaction.Cancelled",
+ "timestamp": "2024-04-25T10:00:00.000Z",
+ "data": {
+ "paymentId": "example-payment-id",
+ "transactionId": "55451513-9763-4a7a-bb43-78a4c65be843",
+ "cancellationId": "0cdd91e9-4e7c-44a3-a72e-1a6511826c2b"
+ }
+}
+```
+
+**웹훅 본문 예시 2**: `type`이 `BillingKey.Issued` 일 때
+
+```json
+{
+ "type": "BillingKey.Issued",
+ "timestamp": "2024-04-25T10:00:00.000Z",
+ "data": {
+ "billingKey": "billing-key-75ae3cab-6afe-422d-bf34-3a7b1762451d"
+ }
+}
+```
+
+### `2024-01-01` 사용 시
+
+- `payment_id`: 고객사에서 채번한 결제 건의 고유 주문 번호입니다.
+
+- `tx_id`: 포트원에서 채번한 고유 거래 번호입니다. 한 결제 건에 여러 시도가 있을 경우 transactionId가 달라질 수 있습니다.
+
+- `status`: 결제건의 상태입니다. 가능한 `status`의 종류는 아래와 같습니다.
+ - `Ready`: **결제창이 열렸을 때**
+ - `Paid`: **결제(예약 결제 포함)가 승인**되었을 때 (모든 결제 수단, 가상계좌의 경우 계좌에 입금이 완료되는 순간)
+ - `VirtualAccountIssued`: **가상계좌가 발급**되었을 때
+ - `PartialCancelled`: **결제가 부분 취소**되었을 때
+ - `Cancelled`: **결제가 완전 취소**되었을 때
+ - `Failed`: **결제(예약 결제 포함)가 실패**했을 때
+ - `PayPending`: **결제 승인 대기** 상태가 되었을 때 (페이팔 이용 시 발생 가능)
+ - `CancelPending`: (결제 취소가 비동기로 수행되는 경우) **결제 취소를 요청**했을 때
+
+웹훅 payload 예시:
+
+```json
+{
+ "payment_id": "example-payment-id",
+ "tx_id": "55451513-9763-4a7a-bb43-78a4c65be843",
+ "status": "Ready"
+}
+```
## 웹훅 URL 설정
@@ -71,6 +158,8 @@ Webhook을 활용하면 커스텀 기능이나 다른 애플리케이션과 연
- **Content Type**을 설정합니다. `Content Type`은 `application/json` 또는
`application/x-www-form-urlencoded` 중 하나로 설정할 수 있습니다.
+ > **`2024-04-25` 버전부터는 `application/json` 만 지원합니다.**
+
- `저장` 버튼을 클릭합니다.
@@ -90,57 +179,140 @@ PortOne.requestPayment({
});
```
-## 요청 처리
+## 웹훅 요청 검증하기
+
+웹훅 수신 주소는 공개된 URL이기 때문에 고객사 입장에서는 웹훅이 포트원으로부터 전달되었는지를 필수적으로 검사할 필요가 있습니다.
+포트원은 [Standard Webhooks](https://www.standardwebhooks.com/)에 따른 메시지 검증을 지원합니다.
+또한, JVM 및 JS 환경의 경우 메시지 검증 코드를 서버 SDK를 통해 배포하고 있습니다.
-웹훅 POST 요청의 본문은 다음의 정보를 포함합니다. 고객사 서버는 아래 정보를 수신하고
-포트원 서버에서 결제 정보를 조회하여 검증 및 저장할 수 있습니다. (필드는 별도 안내 없이 추가될 수 있습니다.)
+
+ 메시지 검증 지원 이전에 포트원 서버 IP 필터링 방식으로 연동하신 고객사의 경우, 웹훅 엔드포인트에 메시지 검증을 추가하시면 보안 향상 효과를 얻으실 수 있습니다.
+
-- `payment_id`: 주문 ID
-- `status`: 결제 상태
+### 1. 웹훅 시크릿 발급하기
+
+
+
+- 포트원 관리자 콘솔 내 \[결제 연동] → \[연동 관리] → **\[결제알림(Webhook) 관리]** 탭을 선택합니다.
+- \[웹훅 버전] 항목에서 **\[결제모듈 V2]** 를 선택합니다.
+- \[설정 모드] 항목에서 \[실연동] 또는 \[테스트]를 선택합니다. (연동 환경에 따라 웹훅 시크릿을 각각 발급할 수 있습니다.)
+- 우측 하단의 **\[웹훅 시크릿 발급]** 버튼을 클릭합니다.
+
+### 2. 시크릿을 이용해 signature 검사하기
+
+포트원에서 보내는 웹훅에는 **해당 시크릿을 이용해 생성된 시그니처가 요청 헤더를 통해 전달**됩니다.
+포트원에서 제공하는 서버 SDK를 이용하면 고객사 서버에서 웹훅을 수신할 때 시그니처가 유효한지 손쉽게 검증할 수 있습니다.
+현재 제공되고 있는 서버 SDK 목록은 아래와 같습니다.
+
+- JVM (코틀린, 자바 등)
+ - [Maven Central](https://central.sonatype.com/artifact/io.portone/server-sdk)
+ - groupId: `id.portone`, artifactId: `server-sdk`
+
+ - [GitHub](https://github.com/portone-io/server-sdk-jvm)
+
+ - [Javadoc](https://javadoc.io/doc/io.portone/server-sdk/latest/-port-one%20-server%20-s-d-k%20for%20-j-v-m/io.portone.sdk.server.webhook/-webhook-verifier/index.html)
+
+- JS (자바스크립트)
+ - [npm](https://www.npmjs.com/package/@portone/server-sdk)
+ - @portone/server-sdk
+
+ - [GitHub](https://github.com/portone-io/server-sdk-js)
+
+ - [Express 예시 코드](https://github.com/portone-io/server-sdk-js/blob/main/examples/express/index.js)
+
+Server SDK 사용을 원치 않으시거나 SDK가 지원되지 않는 언어를 이용중이시라면 메시지 검증 코드를 직접 작성하실 수 있습니다.
+포트원의 웹훅 검증 절차는 [Standard Webhooks](https://github.com/standard-webhooks/standard-webhooks/blob/main/spec/standard-webhooks.md) 스펙을
+준수하고 있으므로, 해당 스펙에서 안내된 대로 검증 코드를 작성하시면 됩니다. 해당 저장소에는 여러 언어로 레퍼런스 구현도 작성되어 있습니다.
+
+### 3. 무중단으로 시크릿 교체하기
+
+시크릿은 항상 기밀성 있게 관리되어야 하지만, 실수로 인해 타인에게 노출될 수 있고 시크릿을 얻은 누군가는 이를 악용할 수 있습니다.
+이러한 경우에 대비해 포트원에서는 **고객사의 서비스에 영향을 주지 않고 무중단으로 기존 시크릿을 새 시크릿으로 교체**하는 방법을 가이드하고 있습니다.
+
+- 먼저 웹훅 시크릿을 추가로 하나 더 발급합니다. (웹훅 시크릿은 테스트/실연동 환경별로 각각 동시에 **최대 2개까지** 발급 가능합니다.)
+
+- 고객사 서버 코드에서 사용되고 있던 시크릿을 새로 발급한 시크릿으로 교체합니다.
+ (시크릿은 기밀 정보이므로 어플리케이션 내에 하드코딩하지 않고 환경 변수로 관리하시는 것을 권장합니다.)
+
+
+
+- 더 이상 기존 시크릿이 고객사 서버에서 사용되지 않는 것을 확인한 후, 콘솔에서 기존 시크릿을 만료시킵니다.
+
+## 웹훅 요청 처리 코드 예시
+
+다음은 포트원으로부터 보내진 웹훅 요청을 고객사 서버에서 받아 처리하는 예시 코드입니다.
+본 코드는 참고용으로 작성된 코드이며, Server SDK를 이용한 signature verify 과정과
+포트원 서버에서 결제 정보를 조회하여 검증 및 저장하는 과정을 포함하고 있습니다.
```ts title="Express"
+import * as PortOne from "@portone/server-sdk";
+import express from "express";
+
+const app = express();
+
+// 요청 본문을 plaintext로 읽기 위한 middleware
+function rawBody(req, res, next) {
+ req.setEncoding("utf8");
+ req.rawBody = "";
+ req.on("data", (chunk) => (req.rawBody += chunk));
+ req.on("end", () => next());
+}
+
// Content-Type을 application/json으로 설정한 경우
-app.use(bodyParser.json());
+app.use(express.json());
+
// POST 요청을 받는 /portone-webhook
-app.post("/portone-webhook", async (req, res) => {
- try {
- const { payment_id: paymentId } = req.body;
-
- // 1. 포트원 결제내역 단건조회 API 호출
- const paymentResponse = await fetch(
- `https://api.portone.io/payments/${encodeURIComponent(paymentId)}`,
- {
- headers: {
- Authorization: `PortOne ${PORTONE_API_SECRET}`,
+app.post(
+ "/portone-webhook",
+ rawBody, // plaintext 본문이 필요하므로 위에서 정의한 middleware를 사용합니다.
+ async (req, res) => {
+ try {
+ // 웹훅 메시지를 검증합니다.
+ // 시그니처 불일치 등 검증에 실패할 경우 PortOne.Webhook.WebhookVerificationError가 발생합니다.
+ await PortOne.Webhook.verify(
+ process.env.PORTONE_WEBHOOK_SECRET,
+ req.rawBody,
+ req.headers,
+ );
+
+ const { paymentId } = req.body;
+
+ // 1. 포트원 결제내역 단건조회 API 호출
+ const paymentResponse = await fetch(
+ `https://api.portone.io/payments/${encodeURIComponent(paymentId)}`,
+ {
+ headers: {
+ Authorization: `PortOne ${PORTONE_API_SECRET}`,
+ },
},
- },
- );
- if (!paymentResponse.ok)
- throw new Error(`signinResponse: ${await paymentResponse.json()}`);
- const { id, status, amount, method } = await paymentResponse.json();
-
- // 2. 고객사 내부 주문 데이터의 가격과 실제 지불된 금액을 비교합니다.
- const order = await OrderService.findById(id);
- if (order.amount === amount.total) {
- switch (status) {
- case "VIRTUAL_ACCOUNT_ISSUED": {
- // 가상 계좌가 발급된 상태입니다.
- // method에 들어 있는 계좌 정보를 이용해 원하는 로직을 구성하세요.
- break;
- }
- case "PAID": {
- // 모든 금액을 지불했습니다! 완료 시 원하는 로직을 구성하세요.
- break;
+ );
+ if (!paymentResponse.ok)
+ throw new Error(`signinResponse: ${await paymentResponse.json()}`);
+ const { id, status, amount, method } = await paymentResponse.json();
+
+ // 2. 고객사 내부 주문 데이터의 가격과 실제 지불된 금액을 비교합니다.
+ const order = await OrderService.findById(id);
+ if (order.amount === amount.total) {
+ switch (status) {
+ case "VIRTUAL_ACCOUNT_ISSUED": {
+ // 가상 계좌가 발급된 상태입니다.
+ // method에 들어 있는 계좌 정보를 이용해 원하는 로직을 구성하세요.
+ break;
+ }
+ case "PAID": {
+ // 모든 금액을 지불했습니다! 완료 시 원하는 로직을 구성하세요.
+ break;
+ }
}
+ } else {
+ // 결제 금액이 불일치하여 위/변조 시도가 의심됩니다.
}
- } else {
- // 결제 금액이 불일치하여 위/변조 시도가 의심됩니다.
+ } catch (e) {
+ // 결제 검증에 실패했습니다.
+ res.status(400).send(e);
}
- } catch (e) {
- // 결제 검증에 실패했습니다.
- res.status(400).send(e);
- }
-});
+ },
+);
```
@@ -149,17 +321,10 @@ app.post("/portone-webhook", async (req, res) => {
Connection Timeout 및 Read Timeout 모두 30초 입니다.
-### 3. 웹훅 요청 검증하기
-
-웹훅 수신주소는 공개된 URL이기 때문에 요청자 IP가 포트원의 IP인지 반드시 확인해야 합니다. 포트원 웹훅은 다음의 고정된 IP로부터 요청이 생성됩니다.
-
-- **52.78.5.241**
-
**웹훅 처리 전에 브라우저 결제 완료 처리가 진행되는 경우**
기본적으로 포트원 서버는 웹훅을 호출한 뒤 고객사 응답을 기다리지 않고 브라우저에 302 redirect 응답을 보내기 때문에 결과 도달에 대한 순서를 보장하지 않습니다. 다만 고객사 요청이 있을 경우 webhook 호출 이후에 브라우저에 302 redirect 또는 callback 응답을 보내어 순서를 보장해 드리고 있습니다. 웹훅 우선순위 요청은 [support@portone.io](mailto:support@portone.io) 로 고객사 식별코드를 기재하여 요청해 주시면 됩니다.
-
diff --git a/src/content/release-notes/api-sdk/2024-06-17.mdx b/src/content/release-notes/api-sdk/2024-06-17.mdx
new file mode 100644
index 000000000..1780fb97f
--- /dev/null
+++ b/src/content/release-notes/api-sdk/2024-06-17.mdx
@@ -0,0 +1,42 @@
+---
+releasedAt: 2024-06-19
+writtenAt: 2024-06-19
+---
+
+import * as prose from "~/components/prose";
+import { PaymentV1,PaymentV2 } from "~/components/release-note/badges";
+
+## 주요 업데이트 사항
+
+
+
+
+ ✔️ 웹훅 신버전이 추가되었습니다.
+
+
+V2 결제모듈을 이용하시는 경우 빌링키 발급 관련 웹훅을 받아보실 수 있습니다.
+웹훅을 연동하여 이벤트 발생 시 결제 건의 상태를 동기화할 수 있습니다.
+
+웹훅 버전에 대한 자세한 내용은 [웹훅 연동하기](/docs/ko/v2-payment/webhook?v=v2#웹훅-버전에-따른-스키마-안내)에서 확인하실 수 있습니다.
+
+
+
+
+ ✔️ 웹훅 시크릿 기능이 추가되었습니다.
+
+
+V2 결제모듈을 이용하시는 경우 웹훅 시크릿을 사용하여 포트원이 생성한 웹훅 요청인지 출처를 확인할 수 있으며,
+악의적인 공격자가 보낸 웹훅 요청을 차단할 수 있습니다.
+
+웹훅 시크릿에 대한 자세한 내용은 [웹훅 연동하기](/docs/ko/v2-payment/webhook?v=v2#웹훅-요청-검증하기)에서 확인하실 수 있습니다.
+
+## 기타 업데이트 사항
+
+
+
+
+ ✔️ 이니시스 통합인증 시 보안성이 강화되었습니다.
+
+
+이제 포트원을 통한 이니시스 통합인증 이용시 민감정보를 암호화하여 처리할 수 있습니다.
+고객사에서는 별도로 추가 대응 없이 바로 적용되어 사용하실 수 있습니다.