모바일에서 결재를 하려니 페이지 연결이나 콜백이 달라 구현

m_redirect_url: "http://localhost:8081/payment/verify" // 모바일 결제 후 리디렉션될 URL

 

pc 처럼 json으로 가격이나 uid나 다른 정보를 받아 오는게 아니고

get 방식으로 uid만 받아와서 이걸 또 iamport에 보내서 토큰 발급 받고 결재 금액 받아오고 검증하고 하는 절차가 따로 필요

 

PaymentController.java - 여기서 uid값을 일단 받고 session에 저장해둔 가격과 요구사항도 받아올 수 있음

    @GetMapping("/payment/verify")
    public String  verifyPayment(@RequestParam("imp_uid") String impUid, HttpSession session) throws IOException {
        // 세션에서 저장된 데이터 가져오기
        int totalPrice = (int) session.getAttribute("totalPrice");
        log.info("impUid = " + impUid);

        // 결제 검증 로직 수행
        boolean isPaymentValid = paymentService.verifyPayment(impUid, totalPrice);

        if (isPaymentValid) {        // 주문 생성 메서드 호출

            // 결제 검증 성공 시, 주문 생성 로직 수행
            PaymentValidationRequest validationRequest = new PaymentValidationRequest();
            validationRequest.setImpUid(impUid);

            OrderResponseDTO orderResponse = createOrders(validationRequest, session);
            messagingTemplate.convertAndSend("/topic/calls", orderResponse);
            return "redirect:/menu/order/" +orderResponse.getId();
        } else {
            // 결제 검증 실패 시, 결제 실패 페이지로 리디렉션
            return "redirect:/menu/main";
        }
    }

 

원래는 gson을 쓰다가 배포시에 버전관련 문제로 꼬여서 삭제하고 jackson 방식으로 변경

 

 

PaymentService.java -  이 부분에서 uid값과 토큰값을 받아 결재된 가격과 db 가격이 같은지 확인

 

그리고 getAccessToken()에서 yml에 저장해둔 api 키와 uid를 통해 토큰값을 받아온다

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<String> entity = new HttpEntity<>("parameters", headers);
        ResponseEntity<String> 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;
    }
}

 

그리고 환불 절차를 httpUrlConnection 방식으로 바꿈

다른방식 쓰다가 자꾸 간혈적으로 실패가 되서 바꾼 뒤로는 환불 잘 됨

환불이 되면 db 에서 order 를 삭제하고 식당 메니저에게 삭제 했다는 메시지를 날림

    // 환불 처리
    public Map<String, Object> requestRefund(Orders order, String reason, String accessToken) {
        try {
            URL url = new URL("https://api.iamport.kr/payments/cancel");
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

            // HTTP 메서드 설정
            connection.setRequestMethod("POST");

            // 헤더 설정
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setRequestProperty("Authorization", accessToken);

            // 요청 본문 전송을 위해 출력 가능으로 설정
            connection.setDoOutput(true);

            // 요청 본문 구성
            String jsonInputString = "{\"imp_uid\": \"" + order.getUid() + "\", \"reason\": \"" + reason + "\"}";

            // 요청 본문 전송
            try (OutputStream os = connection.getOutputStream()) {
                byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
                os.write(input, 0, input.length);
            }

            // 응답 수신
            int responseCode = connection.getResponseCode();
            System.out.println("POST Response Code :: " + responseCode);

            if (responseCode == HttpURLConnection.HTTP_OK) { // 성공적인 응답 처리
                System.out.println("성공");
                ordersService.deleteOrder(order.getId());
                // 응답 본문을 JSON 객체로 파싱하고 필요한 정보를 추출/가공하여 반환
                OrderResponseDTO dto = ordersService.convertToOrderResponseDTO(order);

                messagingTemplate.convertAndSend("/topic/calls", order.getUid());
                return Map.of("success", true);
            } else {
                System.out.println("POST request not worked");
                // 오류 처리
                return Map.of("success", false);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return Map.of("error", e.getMessage());
        }
    }

 

+ Recent posts