결제 완료 알림
내 서버에서 결제가 끝나면 서버 REST API(v2)로 채팅방에 알리고, 페이지 스크립트가 받아 채팅창에 표시하는 예제예요.
마지막 수정 2026년 10월 19일
내 서버에서 결제가 끝나는 순간 채팅방에 있는 모두에게 "구매 완료" 알림을 띄워요. 서버는 서버 REST API로 payment 채널에 데이터를 보내고, 페이지 스크립트는 서버가 보낸 것인지 확인한 뒤 채팅창에 표시해요.
흐름
- 결제 대행사가 내 서버에 결제 완료를 알려요(내 서버의 기존 처리).
- 내 서버가
POST https://api.uchat.io/v2/rooms/{id}/events로payment채널에 보내요. - 지금 채팅방에 접속한 모든 사람의 페이지에서
payment채널로 데이터가 도착해요. - 페이지 스크립트가 보낸 사람의 권한이
4(서버)인지 확인하고room.print로 표시해요.
서버: Node.js
Node.js 18 이상의 내장 fetch를 써요. API 키와 API 채팅방 아이디(room_…)는 관리 페이지 API 메뉴에서 발급·확인하고, 키는 서버 환경 변수에만 둬요. 키 권한에는 이벤트가 있어야 해요.
// notify-payment.mjs
const ROOM = 'room_xxxxxxxxxxxxxxxx'; // API 채팅방 아이디
export async function notifyPayment(productName) {
const res = await fetch(`https://api.uchat.io/v2/rooms/${ROOM}/events`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.UCHAT_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ plugin: 'payment', data: ['paid', productName] }),
});
const result = await res.json();
if (!res.ok) {
// 429 chat_rate_limited: 무료 채팅방 전송 한도 초과 등
console.warn('uchat notify failed', res.status, result.error);
}
return result;
}
// 결제 완료 처리 안에서
// await notifyPayment('프리미엄 이용권');
서버: PHP
<?php
function notify_payment($product_name) {
$ch = curl_init('https://api.uchat.io/v2/rooms/room_xxxxxxxxxxxxxxxx/events');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('UCHAT_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['plugin' => 'payment', 'data' => ['paid', $product_name]], JSON_UNESCAPED_UNICODE),
CURLOPT_TIMEOUT => 5,
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
$result = json_decode($body, true);
if ($status >= 400) {
error_log('uchat notify failed: ' . $status . ' ' . ($result['error']['code'] ?? 'no response'));
}
return $result;
}
// 결제 완료 처리 안에서
// notify_payment('프리미엄 이용권');
성공하면 HTTP 202와 {"data":{"sent":true}}를 돌려줘요. 채팅방에 아무도 없어도 성공이에요(받을 사람이 없을 뿐이에요). 실패하면 HTTP 상태와 {"error":{"code":…,"message":…}}가 와요. 전체 오류 코드는 서버 REST API를 보세요.
페이지: 받아서 표시하기
<script>U=window.U=window.U||{},U.events=U.events||[],U.chat=function(n){return{on:function(e,t){U.events.push([n,e,t])},off:function(e){for(var t=U.events.length;t>0;)U.events[--t][0]==n&&U.events[t][1]==e&&U.events.splice(t,1)}}};</script>
<script async src="https://client.uchat.io/uchat.js"></script>
<u-chat room="my-room" style="display:inline-block;width:100%;max-width:400px;height:500px"></u-chat>
<script>
U.chat('my-room').on('after.create#payment', function (room) {
function esc(value) {
return String(value).replace(/[&<>"']/g, function (c) {
return '&#' + c.charCodeAt(0) + ';';
});
}
room.plugin.add('payment').onReceived(function (room, data) {
// 서버 API가 보낸 것만 믿는다. 사용자도 같은 채널로 보낼 수 있다
if (!data.user || data.user.auth !== 4) return;
if (data.type !== 0) return; // 입장 때 오는 저장값(type 1)은 건너뛴다
var msg = data.data;
if (msg[0] !== 'paid' || typeof msg[1] !== 'string') return;
room.print('🎉 누군가 <b>' + esc(msg[1].slice(0, 50)) + '</b>을(를) 구매했습니다!');
});
});
</script>
짚어 볼 점
room.print는 HTML로 표시하므로 받은 값은 위 코드처럼 꼭 이스케이프해요.- 권한 확인 없이 표시하면 아무 사용자나 같은 채널로 가짜 결제 알림을 띄울 수 있어요.
data.user.auth === 4는 서버 API로 보낸 데이터 또는 부관리자 이상이 저장한 값에만 붙어요. 저장값은 입장할 때type1로 오므로 위 코드는type0(서버 API로 모두에게 보낸 것)만 받아요. 닉네임을 지정해 보낸 서버 API 데이터도type1이라 저장값과 구분할 수 없어요. - REST 요청 본문 앞부분과 요청 IP는 관리 페이지 API 메뉴의 호출 기록에 30일 동안 남아요. 구매자 이름·연락처·카드 정보 같은 개인정보는 보내지 마세요.
- 그냥 보낸 데이터는 지금 접속한 사람에게만 가요. 채팅방에 아무도 없어도 성공으로 답하고, 실패하더라도 결제 처리 자체를 실패로 돌리지 말고 기록만 남겨요. 결제 알림은 지나간 일이라
save로 저장하지 않는 게 맞아요. - 한 사람에게만 보내려면 본문에
"to":"닉네임"을 넣어요(한글 닉네임도 돼요). 이렇게 보낸 데이터는type1로 오므로 위 코드의type확인을 빼야 해요. - 무료 채팅방은 최근 60초 동안 받는 사람 수 합계가 한도를 넘으면 HTTP 429
chat_rate_limited가 나요(채널 API와 한도). - 코드 없이 채팅방에 띄우기만 하려면 이벤트 알림창 플러그인을 켜고
plugin을alertBox,data를["custom", "구매 완료", 상품 이름]으로 보내도 돼요. - 서버 알림을 보내는 일반 흐름은 서버에서 채팅방으로 알림 보내기에 있어요.
봐도 잘 이해가 되지 않나요? 문의 게시판에 질문을 남겨 주세요.