결제 환불 및 헤더 부분 구현
유저의 어떤 페이지에서도 home과 장바구니로 가는 버튼을 만들고
결제 오류시 환불이나 주문쪽에서 환불을 할 수 있게 구현
환불처리 완료
그리고 header 부분 추가
관련 코드
bodyHEader.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<header th:fragment="bodyHeader(args)">
<div>
<a class="icon home-icon" th:if="${args.showIcon}" href='/menu/main'>
<i class="fas fa-home"></i>
</a>
</div>
<p th:text="${args.name}" class="center-text"></p>
<div>
<a class="icon cart-icon" th:if="${args.showBasket}" href='/menu/cart'>
<i class="fas fa-shopping-cart"></i>
<!-- 주문 개수 뱃지 -->
<span class="cart-badge" th:if="${session.orders != null and #lists.size(session.orders) > 0}" th:text="${#lists.size(session.orders)}"></span>
</a>
</div>
</header>
</body>
</html>
style.css 에 헤더 부분 스타일 추가
/* menu 쪽 전체에서 아이콘 관련 */
.cart-icon {
position: relative;
display: inline-block;
}
.cart-badge {
position: absolute;
top: -10px;
right: -10px;
padding: 2px 6px;
border-radius: 50%;
background: red;
color: white;
font-size: 12px;
}
그리고 환불 ( orderId값을 들고 와야 한다)
order.js
// 환불처리 스크립트
document.getElementById('refundButton').addEventListener('click', function() {
const restaurantName = document.querySelector('.restaurant-name');
const orderId = restaurantName.dataset.orderId;
if (confirm('정말로 환불하시겠습니까?')) {
fetch('/validRefund', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
orderId: orderId, // 서버 사이드에서 전달받은 주문 ID
}),
})
.then(response => response.json())
.then(data => {
console.log(data.success);
if (data.success) {
alert('환불 처리가 완료되었습니다.');
location.href = "/menu/main";
// 환불 처리 후 페이지 리디렉션 또는 UI 업데이트
} else {
alert('환불 처리에 실패했습니다.');
}
})
.catch(error => {
console.error('Error:', error);
alert('서버와의 통신 중 문제가 발생했습니다.');
});
}
});
PaymentController.java부분 ( 결제 관련은 menu와 orders에서 많이 옴김
// 비동기 환불처리
@PostMapping("/validRefund")
public ResponseEntity<?> refundOrder(@RequestBody Map<String, Object> payload) throws IOException {
String reason = "테스트용"; // 환불 사유
Long orderId = Long.valueOf((String) payload.get("orderId"));
Orders order = ordersService.findById(orderId).get();
System.out.println("order" + order);
String accessToken = refundService.getAccessToken();
Map<String, Object> refundResult = refundService.requestRefund(order.getUid(), reason, accessToken);
System.out.println("refundResult" + refundResult);
System.out.println("order" + order);
// "success" 키의 값이 true인지 확인하여 성공 여부를 판단
Boolean success = (Boolean) refundResult.get("success");
if (Boolean.TRUE.equals(success)) { // 성공 여부 확인
return ResponseEntity.ok().body(Map.of("success", true, "message", "환불 처리가 완료되었습니다."));
} else {
return ResponseEntity.badRequest().body(Map.of("success", false, "message", "환불 처리에 실패했습니다."));
}
}
검증 부분 - 토큰값 받아오고 맞으면 환불하고 db 삭제
PaymentService.java
package kr.ganjuproject.service;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import kr.ganjuproject.config.IamportConfig;
import kr.ganjuproject.dto.IamportDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Collections;
import java.util.Map;
@Service
@Slf4j
@RequiredArgsConstructor
public class PaymentService {
private final IamportConfig iamportConfig;
private final ObjectMapper objectMapper; // ObjectMapper 인스턴스 주입
// 인증 토큰 발급 받기
public String getAccessToken() throws IOException {
IamportDTO iDTO = iamportConfig.iamport();
URL url = new URL("<https://api.iamport.kr/users/getToken>");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
// JSON 객체 생성 및 데이터 추가
String jsonInputString = objectMapper.writeValueAsString(Map.of(
"imp_key", iDTO.getApikey(),
"imp_secret", iDTO.getSecret()
));
try (OutputStream os = conn.getOutputStream()) {
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
}
try (BufferedReader br = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "utf-8"))) {
StringBuilder response = new StringBuilder();
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
JsonNode jsonNode = objectMapper.readTree(response.toString());
String accessToken = jsonNode.path("response").path("access_token").asText();
return accessToken;
}
}
public boolean verifyPayment(String impUid, int totalPrice) throws IOException {
String accessToken = getAccessToken();
RestTemplate restTemplate = new RestTemplate();
String url = "<https://api.iamport.kr/payments/>" + impUid;
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(accessToken);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
HttpEntity entity = new HttpEntity<>("parameters", headers);
ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
JsonNode responseObject = objectMapper.readTree(response.getBody());
JsonNode responsePayment = responseObject.path("response");
int paidAmount = responsePayment.path("amount").asInt();
return paidAmount == totalPrice;
}
}
'공부 > Ganju' 카테고리의 다른 글
| [Spring/AWS] 팀프로젝트 15일차 (0) | 2024.04.20 |
|---|---|
| [Spring/AWS] 팀프로젝트 14일차 (0) | 2024.04.19 |
| [Spring/AWS] 팀프로젝트 12일차 (0) | 2024.04.16 |
| [Spring/AWS] 팀프로젝트 11일차 (0) | 2024.04.16 |
| [Spring/AWS] 팀프로젝트 10일차 (0) | 2024.04.09 |
