TIL - day59

정상화·2023년 5월 15일
0

TIL

목록 보기
39/46
post-thumbnail

토스페이먼츠

PG : 여러 카드사의 서비스를 아우르는 서비스, 각 카드사의 api를 하나하나 따올 필요가 없게 해준다.

토스페이먼츠는 이러한 PG 중 하나다.

예시

      var clientKey = 'test_ck_jkYG57Eba3GwB6eY1dQ3pWDOxmA1';
      var tossPayments = TossPayments(clientKey);
      var button = document.getElementById('payment-button'); // 결제하기 버튼
      button.addEventListener('click', function () {
        tossPayments.requestPayment('카드', {
          amount: 15000,
          orderId: 'Qvz6OPnQ8a22cDm0fxUer',
          orderName: '토스 티셔츠 외 2건',
          customerName: '박토스',
          successUrl: 'http://localhost:8080/success',
          failUrl: 'http://localhost:8080/fail',
        })
      });

이렇게 자바스크립트로 결제정보를 넘기게 된다.

위험하진 않나? => 토스페이먼츠에서 다시한번 백엔드 서비스에 검증을 요청하기 때문에 결제정보 변조의 위험으로부터 안전하다.

계좌이체


requestPayment의 인자에 "계좌이체"를 넣어주면 됨.

이러한 정보는 토스페이먼츠 문서에 자세히 나와있다.
토스페이먼츠-공식문서(결제정보)

클라이언트 키


  • 상점(서비스)를 추가할 때마다 api키가 추가된다.
  • 클라이언트키는 노출이 돼도 괜찮다. 그러나 클라이언트 시크릿키는 절대로 노출돼선 안된다.

클라이언트 코드: 결제를 기획
시크릿 코드: 결제를 승인

백엔드 서버에서 클라이언트로부터의 클라이언트 키에 클라이언트 시크릿을 덧붙혀서 토스 서버로 보낸다.

조작


자바스크립트로부터의 데이터는 너무나도 쉽게 데이터조작이 가능하다.

따라서 해당 결제 데이터가 상점서비스의 데이터와 일치하는지 유효성 검사를 한 후에 토스 api를 호출해야 한다.

컨트롤러에서 이런식으로 검증을 하게 된다.

@GetMapping(value = "success")
    public String paymentResult(
            Model model,
            @RequestParam(value = "orderId") String orderId,
            @RequestParam(value = "amount") Integer amount,
            @RequestParam(value = "paymentKey") String paymentKey) throws Exception {

		// 상품이 50000원이었는데 프론트에서 가격을 조작했을 때 이에 대한 검증로직
        if (orderId.startsWith("sample-") && amount != 50000) {
            throw new Exception("해킹의심");
        }
        ...

결제과정



TDD로 알고리즘문제 풀기

다리를 지나는 트럭

  1. 테스트를 작성
@Test
@DisplayName("100, 100, {10} -> 101")
    void test1() {
        assertThat(s.solution(100, 100, new int[]{10})).isEqualTo(10);
    }
  1. 어떤 수를 써서라도 초록색이 되게 하라
class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights){
        return 101;
    }
}
  1. 삼각측량을 위해 테스트를 추가한다.
@Test
@DisplayName("100, 100, {10,10,10,10,10,10,10,10,10,10} → 110")
    void test2() {
        assertThat(s.solution(100, 100, new int[]{10, 10, 10, 10, 10, 10, 10, 10, 10, 10})).isEqualTo(110);
    }
  1. 논리의 중복을 없앤다. 최대한 빨리 초록막대가 뜨게 한다.
class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights){
        return bridge_length + truck_weights.length;
    }
}
  • 앞의 과정을 계속 반복하여 정답을 찾는다.
  • 다음 초록막대를 뜨게 하는데 필요한 방법이 꽤 오래 걸릴 것 같으면, 더 작은 문제로 나눠서 해결한다.

TDD없이 푼 코드

class Solution {
    public int solution(int bridge_length, int weight, int[] truck_weights) {
        Queue<int[]> Q = new LinkedList<>();
        int latency;
        int popCount = 0;
        int nextIdx = 0;
        for (latency = 1; popCount < truck_weights.length; latency++) {
            if (!Q.isEmpty() && latency - Q.peek()[1] >= bridge_length) {
                weight += Q.poll()[0];
                popCount++;
            }
            if (popCount == truck_weights.length) {
                return latency;
            }
            else if (Q.size() < bridge_length && nextIdx < truck_weights.length  && weight - truck_weights[nextIdx] >= 0) {
                Q.offer(new int[]{truck_weights[nextIdx], latency});
                weight -= truck_weights[nextIdx++];
            }
        }

        return latency;
    }
}
  • 개인적으로 가독성이 너무 안좋다고 생각한다.
  • 조건문의 조건이 의미하는 것을 문맥적으로 파악하기가 힘들다.
  • Q가 아니라 bridge로 명명하는 게 적절하다
  • 인자로 받은 weight이 다리가 앞으로 더 감당가능한 무게라는 것을 알기 힘들다.
profile
백엔드 희망

0개의 댓글