티스토리 뷰

토스페이먼츠 서브몰 관련 문제를 해결하여 등록은 완성되었으니 추가적으로 조회, 수정, 삭제까지 구현해보겠다.

서브몰 조회

Controller Submall 조회

@GetMapping
@ApiOperation(value = "서브몰 조회", notes = "판매자의 서브몰을 조회합니다.")
public SingleResult<SubmallResDto> registSubmall(
        @ApiParam(value = "코디네이터 이메일", required = true) @RequestParam String crdiEmail
) {
    try {
        return responseService.getSingleResult(
                submallService.getSubmall(crdiEmail)
        );
    } catch (Exception e) {
        e.printStackTrace();
        throw new BussinessException(e.getMessage());
    }
}
  • 이 부분은 토스페이먼츠의 API를 사용하는건 아니고 DB에 저장된 회원의 서브몰을 반환하는 api이다.

Service Submall 조회 로직

@Transactional(readOnly = true)
public SubmallResDto getSubmall(String crdiEmail) {
    return submallRepository.findByCrdiEmailAndActivateTrue(crdiEmail)
            .orElseThrow(() -> new BussinessException(ExMessage.SUBMALL_ERROR_NONE))
            .toDto();
}
  • crdiEmail + 활성화 여부를 통해 submall을 조회한다. 조회 후 dto로 변환해서 반환한다.

조회 결과

조회 결과

위와 같이 전 포스트에서 저장한 서브몰이 반환되는 것을 볼 수 있다.


서브몰 전체 조회

전체 조회는 토스페이먼츠의 API를 호출해서 가져오게 된다.

Controller 서브몰 전체 조회

@GetMapping("/all")
@ApiOperation(value = "모든 서브몰 조회", notes = "토스페이먼츠 API를 통해 모든 서브몰을 조회합니다.")
public ListResult<TosspaymentSubmallRes> getAllSubmall() {
    try {
        return responseService.getListResult(
                submallService.getAllSubmall()
        );
    } catch (Exception e) {
        e.printStackTrace();
        throw new BussinessException(e.getMessage());
    }
}

Service 서브몰 전체 조회 로직

@Transactional(readOnly = true)
public List<TosspaymentSubmallRes> getAllSubmall() {
    RestTemplate rest = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    String encodedAuth = new String(Base64.getEncoder().encode((testSecretApiKey + ":").getBytes(StandardCharsets.UTF_8)));
    headers.setBasicAuth(encodedAuth);
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

    TosspaymentSubmallRes[] submallRes;
    try {
        submallRes = rest.exchange(
                tossOriginUrl + "/payouts/sub-malls",
                HttpMethod.GET,
                new HttpEntity<>(headers),
                TosspaymentSubmallRes[].class
        ).getBody();
    } catch (Exception e) {
        e.printStackTrace();
        String errorResponse = e.getMessage().split(": ")[1];
        String errorMessage = new Gson()
                .fromJson(
                        errorResponse.substring(1, errorResponse.length() - 1),
                        TossErrorDto.class
                ).getMessage();
        throw new BussinessException(errorMessage);
    }

    if (submallRes == null || submallRes.length == 0) {
        return new ArrayList<>();
    }

    return Arrays.asList(submallRes);
}

전체 조회 결과

현재는 전체조회 시 테스트 유저들이 등록했던 모든 서브몰을 가져오는데 실제 운영 계정은 아마 등록된 서브몰만 가져오지 않을까 싶다. 그리고 계좌 소유주 명이 이상하게 나오는데 이부분은 테스트라서 이상하게 그냥 주는거 같다.


서브몰 삭제

Controller 서브몰 삭제

@DeleteMapping
@ApiOperation(value = "서브몰 삭제", notes = "판매자가 자신의 서브몰을 삭제합니다.")
public SingleResult<String> deleteSubmall(
        @ApiParam(value = "코디네이터 이메일", required = true) @RequestParam String crdiEmail
) {
    try {
        return responseService.getSingleResult(
                submallService.deleteSubmall(crdiEmail)
        );
    } catch (Exception e) {
        e.printStackTrace();
        throw new BussinessException(e.getMessage());
    }
}

Service Submall 삭제 로직

@Transactional
public String deleteSubmall(String crdiEmail) {
    Submall submall = submallRepository.findByCrdiEmailAndActivateTrue(crdiEmail)
            .orElseThrow(() -> new BussinessException("고객 앞으로 등록된 서브몰이 없습니다."));
    String submallId = submall.getSubmallId();

    RestTemplate rest = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    String encodedAuth = new String(Base64.getEncoder().encode((testSecretApiKey + ":").getBytes(StandardCharsets.UTF_8)));
    headers.setBasicAuth(encodedAuth);
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

    String responseSubmallId;
    try {
        responseSubmallId = rest.exchange(
                tossOriginUrl + "/payouts/sub-malls/" + submallId + "/delete",
                HttpMethod.POST,
                new HttpEntity<>(headers),
                String.class
        ).getBody();
        if (responseSubmallId == null) throw new BussinessException("NULL");
    } catch (Exception e) {
        String errorResponse = e.getMessage().split(": ")[1];
        String errorMessage = new Gson()
                .fromJson(
                        errorResponse.substring(1, errorResponse.length() - 1),
                        TossErrorDto.class
                ).getMessage();
        throw new BussinessException(errorMessage);
    }

    if (!responseSubmallId.equals(submallId)) {
        throw new BussinessException("제거된 서브몰이 일치하지 않습니다.");
    }
    submall.setActivate(false);

    return responseSubmallId;
}
  • 서브몰 삭제 시 토스페이먼츠에 POST 요청을 보내야하는데 이때 PathUrl에 삭제할 서브몰ID를 넣어줘야 한다.
  • 나의 레포지토리에는 한 고객 당 여러개의 서브몰을 가질 수 있지만 활성화된 서브몰은 하나만 가지도록 해놓았다. 따라서 삭제 요청이 오면 해당 서브몰의 Activate를 false로만 변경하고 따로 추가적인 조치는 하지 않았다.
  • 토스페이먼츠에 삭제를 요청 후 정상처리 시 subMallId를 반환하므로 이 값과 요청 시 값이 일치하는지 확인 후 일치 시 나의 서비스에서도 비활성화 후 해당 ID를 반환토록 했다.

삭제 요청 결과

DELETE 요청에 정상적으로 응답이 오고 DB에 해당 서브몰 ID의 activate도 false가 된 것을 확인할 수 있다.


서브몰 수정

서브몰 수정은 서브몰 등록과 매우 유사하다. 다만 요청 URL에 수정할 서브몰의 서브몰ID를 넣어줘야 한다. 토스측에서 요청 시 전달받은 값들로 기존 값들을 모두 변경하고 반환해준다.

Controller 서브몰 수정

@PutMapping
@ApiOperation(value = "서브몰 수정", notes = "판매자가 자신의 서브몰을 수정합니다.")
public SingleResult<SubmallResDto> updateSubmall(
        @ApiParam(value = "요청자 이메일") @RequestParam String crdiEmail,
        @ApiParam(value = "요청 객체") @ModelAttribute SubmallReqDto submallReqDto
) {
    try {
        return responseService.getSingleResult(
                submallService.updateSubmall(crdiEmail, submallReqDto)
        );
    } catch (Exception e) {
        e.printStackTrace();
        throw new BussinessException(e.getMessage());
    }
}

Service 서브몰 수정 로직

@Transactional
public SubmallResDto updateSubmall(String crdiEmail, SubmallUpdateReq submallReqDto)
{
    Submall submall = submallRepository.findByCrdiEmailAndActivateTrue(crdiEmail)
            .orElseThrow(() -> new BussinessException(ExMessage.SUBMALL_ERROR_NONE));

    RestTemplate rest = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    String authorization = new String(Base64.getEncoder().encode((testSecretApiKey + ":").getBytes(StandardCharsets.UTF_8)));
    headers.setBasicAuth(authorization);
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

    TosspaymentSubmallUpdateReq tosspaymentSubmallReq = submallReqDto.toTossReq();
    TosspaymentSubmallRes tosspaymentSubmallRes;
    try {
        tosspaymentSubmallRes = rest.postForObject(
                tossOriginUrl + "/payouts/sub-malls/" + submall.getSubmallId(),
                new HttpEntity<>(new Gson().toJson(tosspaymentSubmallReq), headers),
                TosspaymentSubmallRes.class
        );
        if (tosspaymentSubmallRes == null) throw new BussinessException("NULL");
    } catch (Exception e) {
        String errorResponse = e.getMessage().split(": ")[1];
        String errorMessage = new Gson()
                .fromJson(
                        errorResponse.substring(1, errorResponse.length() - 1),
                        TossErrorDto.class
                ).getMessage();
        throw new BussinessException(errorMessage);
    }

    submall.setBank(submallReqDto.getAccount().getBank().getName());
    submall.setAccountNumber(submallReqDto.getAccount().getAccountNumber());
    submall.setBusinessNumber(submallReqDto.getBusinessNumber());
    submall.setRepresentativeName(submallReqDto.getRepresentativeName());
    submall.setCompanyName(submallReqDto.getCompanyName());

    return submall.toDto();
}
  • 요청 데이터를 받고 해당 데이터들로 기존 데이터들을 대체하도록 했다.

수정 결과

서브몰 ID는 유지한 채 그 외 정보들만 바껴서 들어간것을 확인할 수 있다.


은행 등록 시 오류 정리

이유는 모르겠지만 국민은행을 제외한 타 은행들로 서브몰을 생성하는데 계속 실패하고 있다.

 

내 로직이 문제인가 싶어서 토스페이먼츠 API 테스트를 통해서도 해보고 토스측 API로 바로 요청도 넣어봤는데 지속적으로 오류를 내뱉고 있다.

좌) 토스뱅크 계좌번호로 서브몰 등록 요청   우) 필자의 토스뱅크 계좌

즉, 오류는 해당 계좌번호를 찾을 수 없다는 것인데 명확하게 볼 수 있지만 필자의 정상적인 토스뱅크 계좌번호임을 알 수 있다. 

토스 API 테스트

토스페이먼츠의 API 테스트를 통해서 해봐도 계좌를 찾을 수 없다고 나온다. 내가 모르는 사람이 나의 계좌의 주인인건지 모르겠지만 도통 오류의 이유를 알 수가 없어서 문의를 남겼다.

일단은 타 은행이 아닌 국민은행으로 변경을 요청하면 제대로 되고, 그외 정보들도 변경이 잘 되어서 일단은 해당 이슈는 미뤄놓고 계속 진행했다. 나중에 토스페이먼츠에서 연락이 오면 추가적으로 수정하고 포스팅하도록 하겠다.

 

토스측에서 답변이 왔는데 생각보다 허무한 내용이다.

테스트 계정이라 안된다는 내용이다. 실 계정에서는 제대로 될테니 이렇게 오류는 마무리하도록 하겠다.


Reference

https://docs.tosspayments.com/guides/apis/payout-submall#%EC%84%9C%EB%B8%8C%EB%AA%B0-%EC%A0%95%EB%B3%B4-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0

 

반응형
Comments
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday