결제 환불 및 헤더 부분 구현

 

유저의 어떤 페이지에서도 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;
    }
}

+ Recent posts