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' 카테고리의 다른 글
스프링 시큐리티 동적 작용 (0) | 2025.02.06 |
---|---|
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 |