모바일에서 결재를 하려니 페이지 연결이나 콜백이 달라 구현
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());
}
}
'공부 > Ganju' 카테고리의 다른 글
| [Spring/AWS] 팀프로젝트 16일차 (0) | 2024.04.23 |
|---|---|
| [Spring/AWS] 팀프로젝트 15일차 (0) | 2024.04.20 |
| [Spring/AWS] 팀프로젝트 13일차 (0) | 2024.04.18 |
| [Spring/AWS] 팀프로젝트 12일차 (0) | 2024.04.16 |
| [Spring/AWS] 팀프로젝트 11일차 (0) | 2024.04.16 |
