๐Ÿ“• Spring Framework/Spring Project

2022.06.01 ใ€Œ๊ฒฐ์ œ API - Ver.2ใ€

GroovyArea 2022. 6. 1. 13:54

์ง€๋‚œ๋ฒˆ ํฌ์ŠคํŒ…์— ์ด์–ด ์ž‘์„ฑํ•˜๊ฒ ๋‹ค!

https://sweeeetgoguma.tistory.com/entry/20220529-%E3%80%8C%EA%B2%B0%EC%A0%9C-API%E3%80%8D

 

2022.05.29 ใ€Œ๊ฒฐ์ œ APIใ€

์žฅ๋ฐ”๊ตฌ๋‹ˆ crud ์ž‘์—…ํ•œ ๊ฒƒ์„ ์ˆ˜์ • ๋ฐ ํ…Œ์ŠคํŠธ๋ฅผ ์ด๋ฒˆ ์ฃผ์— ๋๋‚ด๊ณ  ๋‚˜์„œ, ๋’ค๋Šฆ๊ฒŒ ๊ฒฐ์ œ API๋ฅผ ์„ค๊ณ„ํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค. ์นด์นด์˜ค ํŽ˜์ด API๋ฅผ ์‚ฌ์šฉํ•ด์„œ ํ•ด๋ณด๋ ค๊ณ  ํ•˜๋Š”๋ฐ, ์ƒ๊ฐ๋งŒํผ ์‰ฝ์ง€ ์•Š์•˜๋‹ค. ์–ด๋””์„œ ๋ณธ ๊ฑด๋ฐ

sweeeetgoguma.tistory.com

์นด์นด์˜คํŽ˜์ด Rest API๋ฅผ ์ด์šฉํ•ด ๊ฒฐ์ œ ์ค€๋น„์— ํ•„์š”ํ•œ ๊ฐ์ฒด๋ฅผ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ๊นŒ์ง€ ์™„๋ฃŒํ–ˆ๋‹ค. ์นด์นด์˜ค ํŽ˜์ด ํ”„๋กœ์„ธ์Šค์— ๋”ฐ๋ผ ์ค€๋น„์™€ ๊ฒฐ์ œ ๋ฐ ์Šน์ธ์„ ์œ„ํ•œ ํ†ต์‹  ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค. ์ด ๊ณผ์ • ์†์—์„œ ์ˆ˜๋งŽ์€ ์‚ฝ์งˆ์ด ์žˆ์—ˆ๋‹ค. ์‚ฌ์‹ค ์‚ฝ์งˆ์ด๋ผ๊ธฐ๋ณด๋‹ค๋„ ๋‚ด๊ฐ€ ์ •ํ™•ํžˆ ๊ฐœ๋…์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๊ณ  API๋ฅผ ์ ์šฉ์‹œํ‚จ ๊ฒƒ์ด๋‹ค. API๋ฅผ ๋Œ์–ด๋‹ค ์“ฐ๋Š” ๊ฒƒ์€ ๋งŒ๋งŒํ•œ ๊ฒŒ ์•„๋‹Œ ๊ฒƒ ๊ฐ™๋‹ค.
์ด์ œ ๊ฒฐ์ œ ์Šน์ธ๊นŒ์ง€์˜ ๊ณผ์ •์„ ๋‚˜์—ดํ•ด ๋ณด๊ฒ ๋‹ค.

์ด๋ฒˆ ๊ฒฐ์ œ ๊ณผ์ •์€ ์žฅ๋ฐ”๊ตฌ๋‹ˆ๋ฅผ ํ†ตํ•œ ์ฃผ๋ฌธ ๋ฐ ๊ฒฐ์ œ๋กœ ์ง„ํ–‰ํ•ด๋ณด๊ฒ ๋‹ค.

Postman tool ์‚ฌ์šฉ

1. ๊ฒฐ์ œ ์ค€๋น„


๊ฒฐ์ œ๋ฅผ ์œ„ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‚ด ์„œ๋ฒ„์— ๋„˜๊ธฐ๋ฉฐ, ๋‚ด ์„œ๋ฒ„์—์„œ ์นด์นด์˜คํŽ˜์ด๋กœ ํ•„์š”ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋“ค์„ ๋‹ด์•„ ์š”์ฒญํ•˜๋Š” ์ผ์ด๋‹ค.

 

์„œ๋ฒ„ ์‹คํ–‰!

์šฐ์„  ๋กœ๊ทธ์ธ ๋จผ์ € ํ•ด๋ณด์ž!

๋กœ๊ทธ์ธ์„ ์š”์ฒญํ•˜๋ฉด ํ† ํฐ ๊ฐ’์„ data๋กœ ๋ฐ›๋Š”๋‹ค. 

 

=> ํ† ํฐ ๊ฐ’ ์ €์žฅ

 

์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ƒํ’ˆ ์ถ”๊ฐ€

 

=> ํ˜„์žฌ ์žฅ๋ฐ”๊ตฌ๋‹ˆ๊ฐ€ ์—†๋‹ค.

 

์ƒํ’ˆ์„ ์ถ”๊ฐ€ํ•ด๋ณด์ž.

 

=> ์žฅ๋ฐ”๊ตฌ๋‹ˆ ๋ชฉ๋ก ์กฐํšŒ

 

์ด์ œ ์ด ์žฅ๋ฐ”๊ตฌ๋‹ˆ ์ƒํ’ˆ์„ ๊ฐ€์ง€๊ณ  ๊ฒฐ์ œ ์ค€๋น„๋ฅผ ํ•ด๋ณด๊ฒ ๋‹ค

 

์šฐ์„  ๋‚ด ์„œ๋ฒ„๋กœ ๊ฒฐ์ œ ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.

@Auth(role = Auth.Role.BASIC_USER)
@PostMapping("/cart")
public Message cartOrderAction(HttpServletRequest request) throws UnsupportedEncodingException {
    Cookie[] cookies = request.getCookies();
    Optional<Cookie> cartCookie = CookieUtil.getCartCookie(cookies);

    if (cartCookie.isEmpty()) {
        return new Message
                .Builder(EMPTY_CART_DATA)
                .httpStatus(HttpStatus.BAD_REQUEST)
                .build();
    }

    String url = kakaoPayService.getCartKakaoPayUrl(CookieUtil.getItemNoArr(cartCookie.get()),
            request,
            CookieUtil.getTotalAmount(cartCookie.get()));

    if (url == null) {
        return getFailedPayMessage();
    }

    return new Message
            .Builder(url)
            .httpStatus(HttpStatus.OK)
            .message(PAY_URI_MSG)
            .build();
}
public String getCartKakaoPayUrl(String[] productNoArr, HttpServletRequest request, int totalAmount) {

    /* ์„œ๋ฒ„๋กœ ์š”์ฒญํ•  ํ—ค๋”*/
    HttpHeaders headers = new HttpHeaders();
    setHeaders(headers);

    user = userService.findById((String) request.getAttribute("tokenUserId"));
    itemName = productService.findByNumber(Integer.parseInt(productNoArr[0])).getProductName() + " ๊ทธ ์™ธ " + (productNoArr.length - 1) + "๊ฐœ";
    orderId = user.getUserId() + ", " + itemName;
    userId = user.getUserId();
    this.totalAmount = totalAmount;

    /* ์„œ๋ฒ„๋กœ ์š”์ฒญํ•  body */
    MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
    setParams(params, request);
    params.add("partner_order_id", orderId);
    params.add("partner_user_id", userId);
    params.add("item_name", itemName);
    params.add("item_code", String.join(", ", productNoArr));
    params.add("quantity", String.valueOf(productNoArr.length));
    params.add("total_amount", String.valueOf(totalAmount));
    params.add("tax_free_amount", String.valueOf(TAX_FREE_AMOUNT));

    return getPayUrl(headers, params);
}
private void setHeaders(HttpHeaders headers) {
    restTemplate = new RestTemplate();
    restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());

    headers.add("Authorization", "KakaoAK " + ADMIN_KEY);
    headers.add("Accept", MediaType.APPLICATION_JSON_VALUE);
    headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED_VALUE + ";charset=UTF-8");
}

private void setParams(MultiValueMap<String, String> params, HttpServletRequest request) {
    params.add("cid", TEST_CID);
    params.add("approval_url", getUrl(request) + APPROVAL_URI);
    params.add("cancel_url", getUrl(request) + CANCEL_URI);
    params.add("fail_url", getUrl(request) + FAIL_URI);
}

private String getPayUrl(HttpHeaders headers, MultiValueMap<String, String> params) {
    HttpEntity<MultiValueMap<String, String>> body = new HttpEntity<>(params, headers);

    try {
        /* ์„œ๋ฒ„ ์š”์ฒญ ํ›„ ์‘๋‹ต ๊ฐ์ฒด ๋ฐ›๊ธฐ */
        kakaoPayReadyDTO = restTemplate.postForObject(HOST + KAKAO_PAY_READY,
                body, KakaoPayReadyDTO.class);

        return kakaoPayReadyDTO != null ? kakaoPayReadyDTO.getNext_redirect_pc_url() : null;
    } catch (RestClientException e) {
        log.error(e.getMessage());
    }
    return null;
}

private String getUrl(HttpServletRequest request) {
    return request.getRequestURL().toString().replace(request.getRequestURI(), "");
}

public class KakaoPayReadyVO {

    private String tid, next_redirect_pc_url;
    private Date created_at;

    @ConstructorProperties({"tid","next_redirect_pc_url","created_at"})
    public KakaoPayReadyVO(String tid, String next_redirect_pc_url, Date created_at) {
        this.tid = tid;
        this.next_redirect_pc_url = next_redirect_pc_url;
        this.created_at = created_at;
    }

=> ์š”์ฒญ์„ ํ•˜๋ฉด ์นด์นด์˜ค ํŽ˜์ด๋Š” ์ด ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ json ํ˜•ํƒœ์—์„œ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•ด ์‘๋‹ตํ•ด์ค€๋‹ค. ์ €๊ธฐ ์žˆ๋Š” next_redirect_url์ด ๊ฒฐ์ œ ์š”์ฒญ url!

 

2. ๊ฒฐ์ œ ์Šน์ธ


์ด์ œ ์ € URL๋กœ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์š”์ฒญํ•ด๋ณด์ž!

=> ๋ธŒ๋ผ์šฐ์ €์—์„œ ์š”์ฒญ์„ ํ•˜๋ฉด ๋ฐ๋ชจ QR ์ฝ”๋“œ๊ฐ€ ๋œฌ๋‹ค. ์ด๊ฒƒ์„ ํœด๋Œ€ํฐ์œผ๋กœ ๊ฒฐ์ œํ•ด๋ณด์ž

 

=> ํœด๋Œ€ํฐ์œผ๋กœ ํ…Œ์ŠคํŠธ ๊ฒฐ์ œ๋ฅผ ๋งˆ์น˜๊ณ  ๋‚˜๋ฉด ๊ฒฐ์ œ ์„ฑ๊ณต URL๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ๋œ๋‹ค. 

ํ•˜์ง€๋งŒ ๋‚˜๋Š” RESTAPI ๋งŒ์„ ์„ค๊ณ„ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ ๋ณด์—ฌ์ค„ Front๊ฐ€ ์—†๋‹ค. ๊ทธ๋ž˜์„œ Postman์—์„œ ์ € URL๋กœ ์š”์ฒญ์„ ํ•ด๋ณด๊ฒ ๋‹ค.

 

=> ์ด๋ ‡๊ฒŒ ๊ฒฐ์ œ ์Šน์ธ ๋ฐ ๊ฒฐ์ œ ์ •๋ณด๋ฅผ ์ข…ํ•ฉ์ ์œผ๋กœ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ ์ด ๊ฒƒ์„ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด DB์— ์ €์žฅ์„ ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค. 

 

๋ฆฌํŒฉํ† ๋ง!

https://sweeeetgoguma.tistory.com/entry/%EA%B2%B0%EC%A0%9C-API-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-2-feat-WebClient

 

๊ฒฐ์ œ API ๋ฆฌํŒฉํ† ๋ง - [2] (feat. WebClient)

https://sweeeetgoguma.tistory.com/entry/%EA%B2%B0%EC%A0%9C-API-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-1-feat-%EC%A0%84%EB%9E%B5-%ED%8C%A8%ED%84%B ๊ฒฐ์ œ API ๋ฆฌํŒฉํ† ๋ง - [1] (feat. ์ „๋žต ํŒจํ„ด) ๊ฒฐ์ œ API๋ฅผ ๋ฆฌํŒฉํ† ๋ง ์‹œ์ž‘ํ•˜๋ฉฐ ์™ธ๋ถ€ API๋ฅผ ์—ฐ๋™

sweeeetgoguma.tistory.com

 

๋ฐ˜์‘ํ˜•