본문 바로가기
spring

tosspayment api 사용해보기

by improve 2024. 4. 18.

 

 

payment 개발자 센터에 가서 로그인을 하고 client 키와 secret 키를 얻어온다 ..

 

-> 카카오페이와는 다르게 오픈소스가 너무 잘되어 있어서 react 와 java 로 되어있는 오픈 소스를 다운 받는다.

 

vs code 로 react 파일을 만든다음 -> 오픈소스를 넣어준다. 이러면 프론트의 리엑트 소스는 완성된다.

 

import { useEffect } from "react";
import { useNavigate, useSearchParams } from "react-router-dom";

export function SuccessPage() {
const navigate = useNavigate();
const [searchParams] = useSearchParams();

useEffect(() => {
// TODO: 쿼리 파라미터 값이 결제 요청할 때 보낸 데이터와 동일한지 반드시 확인하세요.
// 클라이언트에서 결제 금액을 조작하는 행위를 방지할 수 있습니다.
const requestData = {
orderId: searchParams.get("orderId"),
amount: searchParams.get("amount"),
paymentKey: searchParams.get("paymentKey"),
};

async function confirm() {
const response = await fetch("/confirm", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(requestData),
});

const json = await response.json();

if (!response.ok) {
// TODO: 결제 실패 비즈니스 로직을 구현하세요.
console.log(json);
navigate(`/fail?message=${json.message}&code=${json.code}`);
return;
}

// TODO: 결제 성공 비즈니스 로직을 구현하세요.
console.log(json);
}
confirm();
}, []);

return (
<div className="result wrapper">
<div className="box_section">
<h2 style={{ padding: "20px 0px 10px 0px" }}>
<img
width="35px"
/>
결제 성공
</h2>
<p>{`주문번호: ${searchParams.get("orderId")}`}</p>
<p>{`결제 금액: ${Number(
searchParams.get("amount")
).toLocaleString()}원`}</p>
<p>{`paymentKey: ${searchParams.get("paymentKey")}`}</p>
</div>
</div>
);
}

 

 

여기서 tosspayment 의존성을 추가해준다.

"@tosspayments/payment-widget-sdk": "^0.10.2",

 

npm install @tosspayments/payment-widget-sdk

이 명령어로 추가를 할 수 있다.

 

react-router-dom 의존성을 추가 해준다.

"react-router-dom": "^6.22.3",

 

npm install react-router-dom  

이 명령어로 추가를 할 수 있다.

 

 

 

여기서 index.js 안에 ./App의 위치를 못찾는다 라고 오류가 뜨는데

확실하게 정해준다.

./App.jsx 로 지정해준다.

 

 

 

 

 

백엔드의 java spring 소스도 인텔리제이에 오픈소스를 넣어준다 

이렇게 실행하게 되면 토스페이 테스트를 해볼 수 있다. 

package com.green.onezo.pay;

import jakarta.servlet.http.HttpServletRequest;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Controller
public class WidgetController {


    @Value("${toss.client.secret}")
    private String widgetSecretKey;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @RequestMapping(value = "/confirm")
    public ResponseEntity<JSONObject> confirmPayment(@RequestBody String jsonBody) throws Exception {

        JSONParser parser = new JSONParser();
        String orderId;
        String amount;
        String paymentKey;
        try {
            // 클라이언트에서 받은 JSON 요청 바디입니다.
            JSONObject requestData = (JSONObject) parser.parse(jsonBody);
            paymentKey = (String) requestData.get("paymentKey");
            orderId = (String) requestData.get("orderId");
            amount = (String) requestData.get("amount");
        } catch (ParseException e) {
            throw new RuntimeException(e);
        };
        JSONObject obj = new JSONObject();
        obj.put("orderId", orderId);
        obj.put("amount", amount);
        obj.put("paymentKey", paymentKey);
        // TODO: 개발자센터에 로그인해서 내 결제위젯 연동 키 > 시크릿 키를 입력하세요. 시크릿 키는 외부에 공개되면 안돼요.
        // @docs https://docs.tosspayments.com/reference/using-api/api-keys
        // 토스페이먼츠 API는 시크릿 키를 사용자 ID로 사용하고, 비밀번호는 사용하지 않습니다.
        // 비밀번호가 없다는 것을 알리기 위해 시크릿 키 뒤에 콜론을 추가합니다.
        // @docs https://docs.tosspayments.com/reference/using-api/authorization#%EC%9D%B8%EC%A6%9D
        Base64.Encoder encoder = Base64.getEncoder();
        byte[] encodedBytes = encoder.encode((widgetSecretKey + ":").getBytes(StandardCharsets.UTF_8));
        String authorizations = "Basic " + new String(encodedBytes);

        // 결제 승인 API를 호출하세요.
        // 결제를 승인하면 결제수단에서 금액이 차감돼요.
        // @docs https://docs.tosspayments.com/guides/payment-widget/integration#3-결제-승인하기
        URL url = new URL("https://api.tosspayments.com/v1/payments/confirm");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestProperty("Authorization", authorizations);
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestMethod("POST");
        connection.setDoOutput(true);


        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(obj.toString().getBytes("UTF-8"));

        int code = connection.getResponseCode();
        boolean isSuccess = code == 200;

        InputStream responseStream = isSuccess ? connection.getInputStream() : connection.getErrorStream();

        // TODO: 결제 성공 및 실패 비즈니스 로직을 구현하세요.
        Reader reader = new InputStreamReader(responseStream, StandardCharsets.UTF_8);
        JSONObject jsonObject = (JSONObject) parser.parse(reader);
        responseStream.close();

        return ResponseEntity.status(code).body(jsonObject);
    }

    /**
     * 인증성공처리
     * @param request
     * @param model
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/success", method = RequestMethod.GET)
    public String paymentRequest(HttpServletRequest request, Model model) throws Exception {
        return "/success";
    }

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String index(HttpServletRequest request, Model model) throws Exception {
        return "/checkout";
    }

    /**
     * 인증실패처리
     * @param request
     * @param model
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fail", method = RequestMethod.GET)
    public String failPayment(HttpServletRequest request, Model model) throws Exception {
        String failCode = request.getParameter("code");
        String failMessage = request.getParameter("message");

        model.addAttribute("code", failCode);
        model.addAttribute("message", failMessage);

        return "/fail";
    }
}

 

 

secret 키 를 yaml 파일에 지정해준다.

 

'spring' 카테고리의 다른 글

SPRING HATEOAS/Security == Intercepter  (0) 2024.03.15
맥북에서 DBeaver spring 으로 연결  (0) 2024.03.01
spring pom.xml  (0) 2024.02.28
spring 등록 출력(복습)  (0) 2024.02.27
spring 으로 게시판  (0) 2024.02.23