tosspay 구현하기 1 (react)

2024. 7. 24. 14:31Springboot-React

1. 토스페이먼츠 개발자 센터에서 클라이언트키, 시크릿 키를 얻어야 함

2. express-react 또는 express-javascript에서 각각의 checkout 파일에서 clientKey 부분에 위에서 받은 클라이언트 키를 삽입

// express-javascript

//위 코드 생략

const clientKey = "내 클라이언트 키";
const customerKey = generateRandomString();
const tossPayments = TossPayments(clientKey);

//이하 코드 생략

 

 

3. server.js에서 시크릿키를 삽입

//server.js

//위 코드 생략

const widgetSecretKey = "test_gsk_docs_OaPz8L5KdmQXkzRz3y47BMw6";
const apiSecretKey = "내 시크릿 키";

//이하 코드 생략

 

 

server.js

 

const express = require("express");
const app = express();
const port = 4000;

app.use(express.static("public"));
app.use(express.json());

// TODO: 개발자센터에 로그인해서 내 결제위젯 연동 키 > 시크릿 키를 입력하세요. 시크릿 키는 외부에 공개되면 안돼요.
// @docs https://docs.tosspayments.com/reference/using-api/api-keys
const widgetSecretKey = "test_gsk_docs_OaPz8L5KdmQXkzRz3y47BMw6";
const apiSecretKey = "test_sk_yZqmkKeP8gyXbZY9pxPpVbQRxB9l";

// 토스페이먼츠 API는 시크릿 키를 사용자 ID로 사용하고, 비밀번호는 사용하지 않습니다.
// 비밀번호가 없다는 것을 알리기 위해 시크릿 키 뒤에 콜론을 추가합니다.
// @docs https://docs.tosspayments.com/reference/using-api/authorization#%EC%9D%B8%EC%A6%9D
const encryptedWidgetSecretKey = "Basic " + Buffer.from(widgetSecretKey + ":").toString("base64");
const encryptedApiSecretKey = "Basic " + Buffer.from(apiSecretKey + ":").toString("base64");

// 결제위젯 승인
app.post("/confirm/widget", function (req, res) {
  const { paymentKey, orderId, amount } = req.body;

  fetch("https://api.tosspayments.com/v1/payments/confirm", {
    method: "POST",
    headers: {
      Authorization: encryptedWidgetSecretKey,
      "Content-Type": "application/json",
    },

    body: JSON.stringify({
      orderId: orderId,
      amount: amount,
      paymentKey: paymentKey,
    }),

    //본문에서 요청한 값을 처리했는지 확인
    /*
    }).then(async function (response) {
    const result = await response.json();
      * await : 대기

    console.log(result);
      -> 결과를 기다리면서 나오는 값, 개발자만 확인 가능

    if (!response.ok) {
      - 송금하는 데 문제가 없다면 잔액, 계좌 오류등 확인

      res.status(response.status).json(result);

      return;
    }
    res.status(response.status).json(result);
      - 고객이 구매한 내용대로 제대로 송금했는지 결과 전달 -> 결제 확인 페이지로 넘어감
    */
  }).then(async function (response) {
    const result = await response.json();
    console.log(result);

    if (!response.ok) {
      // TODO: 결제 승인 실패 비즈니스 로직을 구현하세요.
      res.status(response.status).json(result);

      return;
    }

    // TODO: 결제 완료 비즈니스 로직을 구현하세요.
    res.status(response.status).json(result);
  });
});

// 결제창 승인
app.post("/confirm/payment", function (req, res) {
  const { paymentKey, orderId, amount } = req.body;

  // 결제 승인 API를 호출하세요.
  // 결제를 승인하면 결제수단에서 금액이 차감돼요.
  // @docs https://docs.tosspayments.com/guides/v2/payment-widget/integration#3-결제-승인하기
  fetch("https://api.tosspayments.com/v1/payments/confirm", {
    method: "POST",
    headers: {
      Authorization: encryptedApiSecretKey,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      orderId: orderId,
      amount: amount,
      paymentKey: paymentKey,
    }),
  }).then(async function (response) {
    const result = await response.json();
    console.log(result);

    if (!response.ok) {
      // TODO: 결제 승인 실패 비즈니스 로직을 구현하세요.
      res.status(response.status).json(result);

      return;
    }

    // TODO: 결제 완료 비즈니스 로직을 구현하세요.
    res.status(response.status).json(result);
  });
});

// 이하 생략

 

세부 설명

 

const express = require("express");
const app = express();
const port = 4000;

app.use(express.static("public"));
app.use(express.json());

 

express : 백엔드 자바스크립트에서 많이 사용하는 프레임워크
  = java의 스프링부트

require : js를 쉽게 이용할 수 있게 해주는 node에서 프레임워크를 가져와 백엔드 기능을 할 수 있도록 설정
app : app이라는 객체를 만들어 express 서버를 사용할 수 있는 공간 생성

app.use(express.static("public")); 
  : public이라는 폴더에 static(정적 파일)을 가져와서 html, css, js 등을 사용함을 명시
app.use(express.json());
  : 서버에서 가져온 json 파일을 사용함을 명시
    => html(클라이언트)에서 보낸 json 데이터를 서버에서 사용할 수 있도록 가져온 것

 

====================================================================

app.post("/confirm/widget", function (req, res) {
  const { paymentKey, orderId, amount } = req.body;

 

app.post("/confirm/widget" ... : node에서 post로 들어오는 요청을 가져오는 주소 설정(html과 통신할 주소 url 설정)

function (req, res) = 요청이 들어오면 수행할 기능(req, res) {기능 작성}

req : 서버에 요청하는 값
res : 서버가 html로 보내는 응답(값)

const { paymentKey, orderId, amount } = req.body;
  - req.body : 서버 또는 db에 넣거나 수정을 요청하는 값들을 가지고 있는 body
  - paymentKey : id = paymentKey에 해당하는 값을 갖게 될 변수
  - orderId : id = orderId에 해당하는 값을 갖게 될 변수
  - amount : id = amount에 해당하는 값을 갖게 될 변수

 

=====================================================================

  fetch("https://api.tosspayments.com/v1/payments/confirm", {
    method: "POST",
    headers: {
      Authorization: encryptedWidgetSecretKey,
      "Content-Type": "application/json",
    },

 

fetch("https://api.tosspayments.com/v1/payments/confirm", { ...
  fetch함수는 네트워크 요청을 보내는 데 사용
    -> 결제 승인을 받기 위해서 toss에 결제 확인 전달
    https://api.tosspayments.com/ -> 토스 결제에 관련된 모든 내용이 들어있는 주소
    v1 : 버전 1
    payments : 페이먼트 결제에 관련되어(어떤 종류의 결제인지 판단해서)
    confirm : 확인하는 창구

method: "POST", : 고객이 한 방식을 토스 쪽에 전달 / 토스에서 잔액을 확인하거나 결제 금액을 확인할 때는 get

headers: {
  Authorization: encryptedWidgetSecretKey,
  "Content-Type": "application/json",
: 토스에게 어떤 타입의 데이터인지 사전 전달

  Authorization: encryptedWidgetSecretKey = 위에서 작성한 시크릿 키 가져옴 -> 결제 장소에 대한 인증키 보냄
  "Content-Type": "application/json" 데이터가 이미지인지, 글자인지 등 타입 전달

 

 

=============================================================================

    body: JSON.stringify({
      orderId: orderId,
      amount: amount,
      paymentKey: paymentKey,
    }),

 

body: JSON.stringify({ ...  -> 위에서 사전 점검이 모두 끝나면 본문(body, 목적)확인
orderId: orderId, -> 고객이 결제한 상점
amount: amount, -> 고객이 얼마 보낼 것인지 작성한 값
paymentKey: paymentKey, -> 최종 결제를 위한 비밀번호

 

===============================================================================

 

  }).then(async function (response) {
    const result = await response.json();
    console.log(result);

    if (!response.ok) {
      // TODO: 결제 승인 실패 비즈니스 로직을 구현하세요.
      res.status(response.status).json(result);

      return;
    }

 

본문에서 요청한 값을 처리했는지 확인

console.log(result);
  -> 결과를 기다리면서 나오는 값, 개발자만 확인 가능

if (!response.ok) {
  - 송금하는 데 문제가 있다면 잔액, 계좌 오류등 확인

  res.status(response.status).json(result);

  return;
}
res.status(response.status).json(result);
  - 고객이 구매한 내용대로 제대로 송금했는지 결과 전달 -> 결제 확인 페이지로 넘어감

 

========================================================================

 

원리 요약

// 결제창 승인
app.post("/confirm/payment", function (req, res) { 
  -> node에서 post로 들어오는 요청을 가져오는 주소값 = html과 통신할 url 설정
  (req, res) = (require, response) = (서버에 요청하는 값, 서버가 요청에 응답한 값)

  const { paymentKey, orderId, amount } = req.body;
  -> html에서 id의 이름이 각각 paymentKey, orderId, amount에 해당하는 값을 갖게 될 변수들
  -> 서버 또는 db에 넣거나 수정하고자 하는 값들을 모아놓는 body

  fetch("https://api.tosspayments.com/v1/payments/confirm", {
  -> https://api.tosspayments.com의 버전1의 결제 수단(페이먼트) 중에서 어떤 종류의 결제인지 확인

    method: "POST",
    -> 고객의 결제수단을 토스쪽에 전달 (잔액확인이나 결제 금액 확인 등은 get을 이용)

    headers: {
      Authorization: encryptedApiSecretKey,
      "Content-Type": "application/json",
    },
    -> 결제 인증(Authorization: encryptedWidgetSecretKey) 이후에 
       토스에게 어떤 타입의 데이터인지("Content-Type": "application/json") 사전 전달


    body: JSON.stringify({
      orderId: orderId,
      amount: amount,
      paymentKey: paymentKey,
    }),
    -> header에서의 사전 전달이 끝나면 진행.
       고객의 주문번호(orderId)와 결제 금액(amount), 최종 결제를 위한 비밀번호(paymentKey)를 
       map 형식으로 받음


  }).then(async function (response) {
    const result = await response.json();
    -> 결과 값을 일단 대기시킴

    console.log(result);

    if (!response.ok) {
    -> 잔액부족, 계좌 오류 등의 송금 오류가 있다면
      res.status(response.status).json(result);

      return;
    }

    res.status(response.status).json(result);
    -> 송금하는 데 문제가 없다면 고객에게 결과를 전달하고 결제 확인 페이지로 넘어감
  });
});

'Springboot-React' 카테고리의 다른 글

tosspay구현하기 3 (springboot)  (0) 2024.07.24
tosspay구현하기 2 (springboot)  (0) 2024.07.24
TodoList 만들기 3  (0) 2024.07.18
TodoList 만들기 2  (0) 2024.07.18
TodoList 만들기 1  (0) 2024.07.17