Procházet zdrojové kódy

Merge remote-tracking branch 'origin/card007' into xodud1202

# Conflicts:
#	src/main/java/com/style24/persistence/domain/Payment.java
xodud1202 před 5 roky
rodič
revize
c5b101c432

+ 168 - 54
src/main/java/com/style24/core/biz/service/TscKakaoPayService.java

@@ -1,27 +1,18 @@
 package com.style24.core.biz.service;
 
-import java.net.URI;
-
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.env.Environment;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.client.RestTemplate;
 
-import com.gagaframework.web.parameter.GagaMap;
-import com.gagaframework.web.util.GagaFileUtil;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.style24.core.biz.dao.TscPointDao;
+import com.style24.core.biz.thirdparty.KakaoPayApi;
+import com.style24.core.support.message.TscMessageByLocale;
+import com.style24.persistence.domain.KakaoPay;
 import com.style24.persistence.domain.Order;
-import com.style24.persistence.domain.Point;
+import com.style24.persistence.domain.Payment;
 
 import lombok.extern.slf4j.Slf4j;
 
@@ -39,58 +30,181 @@ public class TscKakaoPayService {
 	private Environment env;
 
 	@Autowired
-	private RestTemplate restTemplate;
+	private TscMessageByLocale message;
 
-	public static final String PROTOCOL = "http:";
+	@Autowired
+	private RestTemplate restTemplate;
+	
+	@Autowired
+	private KakaoPayApi kakaoPayApi;
 
 	/**
 	 * 카카오페이 결제준비 처리
 	 * 
 	 * @param Order
-	 * @return GagaMap
+	 * @return KakaoPay
 	 * @author card007
 	 * @since 2021. 03. 03
 	 */
 	@Transactional("shopTxnManager")
-	public GagaMap kakaoPaymentReady(Order order) {
-		GagaMap map = new GagaMap();
+	public KakaoPay kakaoPaymentReady(Order order) {
+		// API 전송 URL 설정
 		String paymentReadyUrl = env.getProperty("kakao.paymentReadyUrl");
-		try {
-			MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
-			params.add("cid", env.getProperty("kakao.cid"));
-			params.add("partner_order_id", order.getOrdNo()+"");
-			params.add("partner_user_id", order.getCustNo()+"");
-			params.add("item_name", order.getGoodsNm());
-			params.add("quantity", order.getOrdQty()+"");
-			params.add("total_amount", order.getRealOrdAmt()+"");
-			params.add("tax_free_amount", "0");
-			params.add("approval_url", PROTOCOL + env.getProperty("domain.front"));
-			params.add("fail_url", PROTOCOL + env.getProperty("domain.front"));
-			params.add("cancel_url", PROTOCOL + env.getProperty("domain.front"));
-
-			// Header
-			HttpHeaders headers = new HttpHeaders();
-			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
-			headers.set("Authorization", "KakaoAK " + env.getProperty("kakao.adminKey"));
-
-			HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
-			URI url = URI.create(paymentReadyUrl);
-
-			// POST방식으로 호출
-			ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
-			log.info("responseEntity.getStatusCode(): {} ", responseEntity.getStatusCode());
-
-			String jsonResult = responseEntity.getBody();
-			log.info("responseEntity.getBody(): {} ", jsonResult);
-
-			Gson gson = new GsonBuilder().create();
-			map = gson.fromJson(jsonResult, GagaMap.class); //access_token, refresh_token
-
-		} catch (Exception e) {
-			log.error(e.getMessage());
+
+		// API 파라메터 설정
+		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+		params.add("cid", env.getProperty("kakao.cid"));
+		params.add("partner_order_id", order.getOrdNo()+"");
+		params.add("partner_user_id", order.getCustNo()+"");
+		params.add("item_name", order.getGoodsNm());
+		params.add("quantity", order.getOrdQty()+"");
+		params.add("total_amount", order.getRealOrdAmt()+"");
+		params.add("tax_free_amount", "0");
+		params.add("approval_url", order.getApprovalUrl());
+		params.add("fail_url", order.getFailUrl());
+		params.add("cancel_url", order.getCancelUrl());
+
+		// 카카오페이 API 전송
+		return kakaoPayApi.kakaoPaymentApi(params, paymentReadyUrl);
+	}
+
+	/**
+	 * 카카오페이 승인 처리
+	 *
+	 * @param Order
+	 * @return Payment
+	 * @author card007
+	 * @since 2021. 03. 04
+	 */
+	@Transactional("shopTxnManager")
+	public Payment approveKakaoPayment(Order order) {
+		// API 전송 URL 설정
+		String approvePaymentUrl = env.getProperty("kakao.approvePaymentUrl");
+
+		// API 파라메터 설정
+		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+		params.add("cid", env.getProperty("kakao.cid"));
+		params.add("tid", order.getPgTid());
+		params.add("partner_order_id", order.getOrdNo()+"");
+		params.add("partner_user_id", order.getCustNo()+"");
+		params.add("pg_token", order.getPgToken());
+
+		// 카카오페이 API 전송
+		KakaoPay kakaoPay = kakaoPayApi.kakaoPaymentApi(params, approvePaymentUrl);
+
+		// 카카오페이 API 전송 결과 처리
+		Payment payment = new Payment();
+		int statusCode = kakaoPay.getStatusCode();
+
+		// 승인 성공일때 200
+		if (statusCode == 200) {
+			payment.setPgTradeNo(kakaoPay.getAid());
+			payment.setPgTid(kakaoPay.getTid());
+			payment.setPgShopId(kakaoPay.getCid());
+			payment.setOrdNo(Integer.parseInt(kakaoPay.getPartner_order_id()));
+			payment.setCustNo(Integer.parseInt(kakaoPay.getPartner_user_id()));
+			payment.setKakaoMethodType(kakaoPay.getPayment_method_type());
+			payment.setPayAmt(kakaoPay.getAmount().getTotal());
+			payment.setKakaoPoint(kakaoPay.getAmount().getPoint());
+			payment.setKakaoDiscount(kakaoPay.getAmount().getDiscount());
+
+			// 카카오페이 카드결제 시 카드정보 설정
+			if ("CARD".equals(kakaoPay.getPayment_method_type())) {
+				payment.setCardKind(kakaoPay.getCard_info().getPurchase_corp());
+				payment.setCardNm(kakaoPay.getCard_info().getIssuer_corp());
+				payment.setCardType("신용".equals(kakaoPay.getCard_info().getCard_type()) ? "N" : "Y");
+				payment.setCardMips(kakaoPay.getCard_info().getInstall_month());
+			}
+			
+			payment.setResCd(String.valueOf(statusCode));
+			payment.setResMsg(message.getMessage("SUCC_0004"));
+		} else {
+			int code = Integer.parseInt(kakaoPay.getCode());
+			String msg = kakaoPay.getMsg();
+			String resultCode = kakaoPay.getExtras().getMethod_result_code();
+			String resultMessage = kakaoPay.getExtras().getMethod_result_message();
+
+			payment.setResCd(String.valueOf(code));
+			payment.setResMsg(resultMessage);
 		}
-		
-		return map;
+
+		return payment;
 	}
-	
+
+	/**
+	 * 카카오페이 주문 조회
+	 *
+	 * @param Order
+	 * @return KakaoPay
+	 * @author card007
+	 * @since 2021. 03. 04
+	 */
+	@Transactional("shopTxnManager")
+	public KakaoPay getKakaoPaymentOrder(Order order) {
+		// API 전송 URL 설정
+		String paymentOrderUrl = env.getProperty("kakao.paymentOrderUrl");
+
+		// API 파라메터 설정
+		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+		params.add("cid", env.getProperty("kakao.cid"));
+		params.add("tid", order.getPgTid());
+
+		// 카카오페이 API 전송
+		KakaoPay pay = kakaoPayApi.kakaoPaymentApi(params, paymentOrderUrl);
+
+		return pay;
+	}
+
+	/**
+	 * 카카오페이 결제 취소
+	 *
+	 * @param Order
+	 * @return KakaoPay
+	 * @author card007
+	 * @since 2021. 03. 05
+	 */
+	@Transactional("shopTxnManager")
+	public Payment cancelKakaoPayment(Order order) {
+		// API 전송 URL 설정
+		String cancelPaymentUrl = env.getProperty("kakao.cancelPaymentUrl");
+
+		// API 파라메터 설정
+		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
+		params.add("cid", env.getProperty("kakao.cid"));
+		params.add("tid", order.getPgTid());
+		params.add("cancel_tax_free_amount", "0");
+
+		// 전체 취소의 경우 카카오페이에 취소가능금액으로 취소금액 설정
+		if ("Y".equals(order.getAllCanYn())) {
+			KakaoPay orderInfo = getKakaoPaymentOrder(order);
+			params.add("cancel_amount", String.valueOf(orderInfo.getCancel_available_amount().getTotal()));
+		} else {
+			params.add("cancel_amount", String.valueOf(order.getCnclRtnAmt()));
+		}
+
+		// 카카오페이 API 전송
+		KakaoPay kakaoPay = kakaoPayApi.kakaoPaymentApi(params, cancelPaymentUrl);
+
+		// 카카오페이 API 전송 결과 처리
+		Payment payment = new Payment();
+		int statusCode = kakaoPay.getStatusCode();
+
+		// 승인 성공일때 200
+		if (statusCode == 200) {
+			payment.setPgTradeNo(kakaoPay.getAid());
+			payment.setPgTid(kakaoPay.getTid());
+			payment.setPgShopId(kakaoPay.getCid());
+			payment.setStatus(kakaoPay.getStatus());
+			payment.setOrdNo(Integer.parseInt(kakaoPay.getPartner_order_id()));
+			payment.setCustNo(Integer.parseInt(kakaoPay.getPartner_user_id()));
+			payment.setKakaoMethodType(kakaoPay.getPayment_method_type());
+			payment.setPayAmt(Integer.parseInt(params.getFirst("cancel_amount")));
+			
+		} else {
+			
+		}
+
+		return payment;
+	}
+
 }

+ 79 - 0
src/main/java/com/style24/core/biz/thirdparty/KakaoPayApi.java

@@ -0,0 +1,79 @@
+package com.style24.core.biz.thirdparty;
+
+import java.net.URI;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.Environment;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import com.gagaframework.web.parameter.GagaMap;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.style24.core.support.message.TscMessageByLocale;
+import com.style24.persistence.domain.KakaoPay;
+import com.style24.persistence.domain.Order;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * 카카오페이 API
+ *
+ * @author card007
+ * @since 2021. 03. 04
+ */
+@Component
+@Slf4j
+public class KakaoPayApi {
+
+	@Autowired
+	private Environment env;
+
+	@Autowired
+	private TscMessageByLocale message;
+
+	@Autowired
+	private RestTemplate restTemplate;
+
+	/**
+	 * 카카오페이 API
+	 *
+	 * @param Order
+	 * @return GagaMap
+	 * @author card007
+	 * @since 2021. 03. 03
+	 */
+	public KakaoPay kakaoPaymentApi(MultiValueMap<String, String> params, String apiUrl) {
+		KakaoPay pay;
+		try {
+			HttpHeaders headers = new HttpHeaders();
+			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+			headers.set("Authorization", "KakaoAK " + env.getProperty("kakao.adminKey"));
+
+			HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
+			URI url = URI.create(apiUrl);
+
+			ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, request, String.class);
+			log.info("responseEntity.getStatusCode(): {} ", responseEntity.getStatusCode());
+
+			String jsonResult = responseEntity.getBody();
+			log.info("responseEntity.getBody(): {} ", jsonResult);
+
+			Gson gson = new GsonBuilder().create();
+			pay = gson.fromJson(jsonResult, KakaoPay.class);
+			pay.setStatusCode(responseEntity.getStatusCode().value());
+
+		} catch (Exception e) {
+			throw new IllegalStateException(message.getMessage("FAIL_0004"));
+		}
+
+		return pay;
+	}
+}

+ 1 - 1
src/main/java/com/style24/core/support/env/TscConstants.java

@@ -825,7 +825,7 @@ public class TscConstants {
 
 	// 프론트 구분
 	public enum FrontGb {
-		MOBIEL("M"),
+		MOB("M"),
 		PC("P");
 
 		private String value;

+ 0 - 3
src/main/java/com/style24/persistence/domain/Customer.java

@@ -129,18 +129,15 @@ public class Customer extends TscBaseDomain {
 	}
 
 	public String getMaskingCustNm() {
-		this.custNm = CryptoUtils.decryptAES(this.custNm);
 		return TscSession.getAttribute("maskingYn").equals("Y") ? MaskingUtils.name(this.custNm) : this.custNm;
 
 	}
 
 	public String getMaskingCellPhnno() {
-		this.cellPhnno = CryptoUtils.decryptAES(this.cellPhnno);
 		return TscSession.getAttribute("maskingYn").equals("Y") ? MaskingUtils.phoneNo(this.cellPhnno) : this.cellPhnno;
 	}
 
 	public String getMaskingEmail() {
-		this.email = CryptoUtils.decryptAES(this.email);
 		return TscSession.getAttribute("maskingYn").equals("Y") ? MaskingUtils.email(this.email) : this.email;
 	}
 

+ 122 - 0
src/main/java/com/style24/persistence/domain/KakaoPay.java

@@ -0,0 +1,122 @@
+package com.style24.persistence.domain;
+
+import java.util.Collection;
+
+import com.style24.persistence.TscBaseDomain;
+
+import lombok.Data;
+
+/**
+ * 카카오페이 도메인
+ * 
+ * @author card007
+ * @since 2021. 03. 05
+ */
+@SuppressWarnings("serial")
+@Data
+public class KakaoPay extends TscBaseDomain {
+
+	private String aid;													// 요청 고유 번호
+	private String tid;													// 결제 고유 번호, 20자
+	private String cid;													// 가맹점 코드, 10자
+	private String cid_secret;											// 가맹점 코드 인증키, 24자, 숫자+영문 소문자 조합
+	private String sid;													// 정기결제용 ID, 정기결제 CID로 단건결제 요청 시 발급
+	private String status;												// 결제 상태
+	private String partner_order_id;									// 가맹점 주문번호, 최대 100자
+	private String partner_user_id;										// 가맹점 회원 id, 최대 100자
+	private String payment_method_type;									// 결제 수단, CARD 또는 MONEY 중 하나
+	private String item_name;											// 상품명, 최대 100자
+	private String item_code;											// 상품코드, 최대 100자
+	private int quantity;												// 상품 수량
+	private Amount amount;												// 결제 금액 정보
+	private CanceledAmount canceled_amount;								// 취소된 금액
+	private CancelAvailableAmount cancel_available_amount;				// 취소 가능 금액
+	private String created_at;											// 결제 준비 요청 시간
+	private String approved_at;											// 결제 승인 시각
+	private SelectedCardInfo selected_card_info;						// 결제 카드 정보
+	private Collection<PaymentActionDetails> payment_action_details;	// 결제/취소 상세
+	private int statusCode;
+	private String next_redirect_app_url;								// 카카오톡 결제 페이지 Redirect URL (모바일 앱)
+	private String next_redirect_mobile_url;							// 카카오톡 결제 페이지 Redirect URL (모바일 웹)
+	private String next_redirect_pc_url;								// 카카오톡 결제 페이지 Redirect URL (PC 웹)
+	private String android_app_scheme;									// 카카오페이 결제 화면으로 이동하는 Android 앱 스킴(Scheme)
+	private String ios_app_scheme;										// 카카오페이 결제 화면으로 이동하는 iOS 앱 스킴
+	private String payload;												// 결제 승인 요청에 대해 저장한 값, 요청 시 전달된 내용
+	private int total_amount;											// 상품 총액
+	private CardInfo card_info;											// 결제 상세 정보, 결제수단이 카드일 경우만 포함
+	private String code;
+	private String msg;
+	private Extras extras;
+
+	@Data
+	public class Amount {
+		private int total;												// 전체 결제 금액
+		private int tax_free;											// 비과세 금액
+		private int vat;												// 부가세 금액
+		private int point;												// 사용한 포인트 금액
+		private int discount;											// 할인 금액
+	}
+
+	@Data
+	public class CanceledAmount {
+		private int total;												// 전체 취소 금액
+		private int tax_free;											// 취소된 비과세 금액
+		private int vat;												// 취소된 부가세 금액
+		private int point;												// 취소된 포인트 금액
+		private int discount;											// 취소된 할인 금액
+	}
+
+	@Data
+	public class CancelAvailableAmount {
+		private int total;												// 전체 취소 가능 금액
+		private int tax_free;											// 취소 가능한 비과세 금액
+		private int vat;												// 취소 가능한 부가세 금액
+		private int point;												// 취소 가능한 포인트 금액
+		private int discount;											// 취소 가능한 할인 금액
+	}
+	
+	@Data
+	public class SelectedCardInfo {
+		private String card_bin;										// 카드 BIN
+		private int install_month;										// 할부 개월 수
+		private String card_corp_name;									// 카드사 정보
+		private String interest_free_install;							// 무이자할부 여부(Y/N)
+	}
+
+	@Data
+	public class PaymentActionDetails {
+		private String aid;												// Request 고유 번호
+		private String payment_action_type;								// 결제 타입 PAYMENT(결제), CANCEL(결제취소), ISSUED_SID(SID 발급) 중 하나
+		private String payment_method_type;								// 결제 수단, CARD 또는 MONEY 중 하나
+		private int amount;												// 결제/취소 총액
+		private int point_amount;										// 결제/취소 포인트 금액
+		private int discount_amount;									// 할인 금액
+		private String approved_at;										// 거래시간
+		private String payLoad;											// Request로 전달한 값
+	}
+	
+	@Data
+	public class CardInfo {
+		private String purchase_corp;									// 매입 카드사 한글명
+		private String purchase_corp_code;								// 매입 카드사 코드
+		private String issuer_corp;										// 카드 발급사 한글명
+		private String issuer_corp_code;								// 카드 발급사 코드
+		private String kakaopay_purchase_corp;							// 카카오페이 매입사명
+		private String kakaopay_purchase_corp_code;						// 카카오페이 매입사 코드
+		private String kakaopay_issuer_corp;							// 카카오페이 발급사명
+		private String kakaopay_issuer_corp_code;						// 카카오페이 발급사 코드
+		private String bin;												// 카드 BIN
+		private String card_type;										// 카드 타입
+		private String install_month;									// 할부 개월 수
+		private String approved_id;										// 카드사 승인번호
+		private String card_mid;										// 카드사 가맹점 번호
+		private String interest_free_install;							// 무이자할부 여부(Y/N)
+		private String card_item_code;									// 카드 상품 코드
+	}
+	
+	@Data
+	public class Extras {
+		private String method_result_code;								// 실패 코드
+		private String method_result_message;							// 실패 메세지
+	}
+}

+ 7 - 0
src/main/java/com/style24/persistence/domain/Order.java

@@ -520,6 +520,12 @@ public class Order extends TscBaseDomain {
 	private int cancelCount;
 	private int exchangeCount;
 	private int returnCount;
+	
+	// 카카오페이
+	private String approvalUrl;
+	private String failUrl;
+	private String cancelUrl;
+	private String pgToken;
 
 	// 암호화 대상 복호화 처리
 	public String getCustNm() {
@@ -547,5 +553,6 @@ public class Order extends TscBaseDomain {
 		return this.recipDtlAddr;
 	}
 	
+	private String dispYn;
 	
 }

+ 8 - 0
src/main/java/com/style24/persistence/domain/Payment.java

@@ -72,4 +72,12 @@ public class Payment extends TscBaseDomain {
 	private String tranCd;
 	private String resCd;			// 결과코드
 	private String resMsg;			// 결과메세지
+	
+	// KAKAOPAY
+	private String kakaoMethodType;	// 결제 수단, CARD 또는 MONEY 중 하나
+	private int kakaoPoint;			// 사용한 포인트 금액
+	private int kakaoDiscount;		// 할인 금액
+	private String createDt;		// 결제 준비 요청 시각
+	private String approveDt;		// 결제 승인 시각
+	private String status;			// 카카오페이 결제 상태
 }

+ 4 - 0
src/main/java/com/style24/persistence/mybatis/shop/TscOrder.xml

@@ -1798,7 +1798,11 @@
 		     , CDA.RECIP_DTL_ADDR
 		     , CDA.RECIP_PHNNO
 		     , CDA.DELV_MEMO
+		     , CU.CUST_NM
+		     , CU.CELL_PHNNO
 		  FROM TB_CUST_DELIVERY_ADDR CDA
+		 INNER JOIN TB_CUSTOMER CU
+		    ON CDA.CUST_NO = CU.CUST_NO
 		 WHERE 1=1
 		   AND CDA.CUST_NO = #{custNo}
 		   AND CDA.DEL_YN = 'N'