코딩하는 문과생

[Web] 차이냐오 API, 중국 알리바바 I/F 삽질기 본문

웹 프로그래밍/Web

[Web] 차이냐오 API, 중국 알리바바 I/F 삽질기

코딩하는 문과생 2022. 7. 7. 20:52

[서론]

2022년 4월 쯤, 관세청이 7월부터 새로운 면세혜택을 도입하는 정책을 발표했다. 정책의 골자는 외국인의 국내 몰 이용 시 면세혜택을 제공하기로 하는 정책인데, 간단히 말해 한국인이 더 저렴하게 구입하기 위해 '직구'를 하는 것 처럼, 외국인이 한국몰을 이용할때 관세 혜택을 부여하는 정책이다. 현장에서는 줄여서 '역직구'라는 단어를 사용한다.

어쨌든, 새로운 신고가 도입되는 만큼 영향도 파악도 해야 했고, 특히 B2C같은 경우 알리바바(차이냐오) 물류 시스템과 I/F 하는 로직을 새롭게 구성해야 했었다. 그걸 어쩌다보니 내가 맡게 됬고, 삽질을 너무 많이 해서 다음의 누군가는 이런 삽질을 안했으면 하는 바람에 삽질기를 정리해보려고 한다.

오늘 마지막 이슈 해결을 끝으로 내일 통합 테스트와 차주 전체 오픈만이 남아있다. 누군가 이 고통을 받지 않았으면 하는 바람에 글을 정리해보려고 한다.

[본론]

맡은 부분은 크게 2가지다. API호출 후 리턴된 정보를 DB에 적재하는 것과 실제 중국 전역으로 배송되기 위한 운송장 출력부를 만드는 것이었다. 보기엔 뭐 그렇게 안 어려워 보여서 나도 슬슬하면 되겠지 했는데, 생각보다 삽질을 많이해서 이직욕구가 스믈스믈 올라오는 경험이었다.

Cainiao API Document
https://global.link.cainiao.com/

 

LINK平台

 

global.link.cainiao.com

 

작성 프로그램 : 배치3, 화면1

 

  • 배치1 - 각 업무단 테이블로부터 I/F에 필요한 정보를 Interface 테이블에 INSERT / 일배치
  • 배치2 - API 호출 후 리턴값 Interface 테이블에 저장 / 일배치
  • 배치3 - 배송상태 수신 / 1시간간격 배치
  • 화면1 - 운송장출력 전용화면

ISSUE)

배치2는 배치1 바로 뒤에 호출되어야 하므로, 바로 호출되도록 crontab 지정

I/F 테이블 저장 배치와 API 호출 배치를 분리한 이유? 영향도 최소화 

 

1. API 호출 삽질

알리바바 물류 시스템 API 문서를 쭉 읽어봤을 때,(한국어도 못하는데, 중국 영어 혼재...) 내가 일반적으로 호출하는 API와는 조금 다른 면이 많았다. 업체간 I/F를 할 때 보통 토큰이나 secret을 부여받고 헤더같은 곳에 넣어서 api를 호출하는 구조로 알고 있는데, 여기 차이냐오 업체는 api 문서가 특이했다.

특이한점

1. 일단 api 문서보고 개발해라.

미팅하면서 제일 당황했던 내용이다. 보통 api 호출부를 개발할 때, 개발url과 운영url을 따로 부여 받아 개발url을 사용하거나, url이 같더라도 개발환경에서는 api호출횟수를 제한하는 등 개발 진행 시 필요한 url을 보통은 부여받는다. 그러나 알리바바(차이냐오) 업체는 이는 불가하다는 답변만 계속해서 회신했는데, 그 이유는 계약서 작성이 어느정도 진행되고 나서야 개발에 필요한 url을 부여해 줄 수 있다고 했다...왜..? 이거 때문에 엄청 고통을 받았는데, 말 그대로 나는 상상코딩을 할 수 밖에 없었고, 실제 오픈일자가 얼마 남지 않은 상황에서 개발 url 부여 받아 급하게 개발을 진행해야만 했다. 파라미터 정의문제와 인코딩문제, 자바버전문제로 진짜 애를 많이 먹었었다.ㅠㅠ 개발 진행 시 curl명령어를 이용하든 PostMan을 이용하든 리턴되는 값을 빨리빨리 확인해야 개발이 수월한데, 오픈일자가 정해져 있는 상황에서 개발url을 늦게 부여줘서 정말 힘들었다. 왜 이렇게 해주는 지는 모르겠으나... 찾아보니 중국 대부분의 업체가 그러하다고 한다...왜지..?

2. Content-type은 x-www-form-urlencoded

보통 post방식에 json을 던지는 데, 여기는 Content-type을 x-www-form-urlencoded을 사용한다.
다른 외부업체나 오픈 api 사용 시 Content-type을 application/json로 지정하고, 아웃바운드 정책 중 포트80(http)이랑 443(https)을 오픈해서 수월하게 개발했었는데, 처음보는 형태의 Content-type이라 개발하는 데 애를 많이 먹었다.

3. 파라미터

차이냐오 API Document
logistics_interface에 들어가는 파라미터 값


크게 4개의 파라미터가 있다. logistics_interface, data_digest, logistic_provider_id,msg_type 가 있다.

  • msg_type: 호출 API명을 적는다. ex. CROSSORDER_ORDER_CONSIGN(운송장 번호 리턴)
  • logistic_provider_id: 생성한 APP 고유값(Console창에서 계정 생성 후 APP을 생성하면 부여받는 값)
  • logistics_interface: 실제 api를 호출하기 위한 파라미터 ex. uesrId, externalOrderId ...
  • data_digest: 서명값인데, MD5라는 단방향 암호화 라이브러리를 이용하여 암호화한 값이 들어간다.



설명은 쉽지만, 현재 시스템 내 Batch 서버 JDK가 버전 7이라 인코딩문제, 그리고 서명값 추출을 위한 기본 데이터 세팅 문제, logistics_interface 구성 문제, 보안문제 등 이를 해결하느라 애를 많이 먹었다...

  • JDK 7으로 인한 인코딩 문제 -> Base64 라이브러리를 사용할 수 없음, 사용가능하나 CRLF문제 발생, 따라서 다른 대체 라이브러리 사용
  • 서명값 추출 -> MD5(logistics_interface + app secret)
  • logistics_interface 구성문제 -> 업체랑 협의하여 json으로 보내는 것으로 협의
  • 보안문제 -> api docu에는 http만 지원하길래 모든 데이터를 암호화해서 보내야 되나 싶었는데, 업체에서 https도 지원가능하다하여 암호화진행하지 않음(docu에 좀 써주지...)



API는 크게 3개를 사용했다.

  • CROSSORDER_ORDER_CONSIGN : 운송장 번호 리턴(실제 중국 세관으로 넘어가는 값들로 DB에 있는 값들과 필요한 값들을 협의하느라 긴시간 모두 고생했다... 다들 고생하셨습니다 ㅜㅡㅜ)
  • CROSSBORDER_LOGISTICS_DETAIL_QUERY : 운송장 배송상태 추적
  • CROSSBORDER_WAYBILL_GET : 운송장 출력을 위한 암호화 데이터 리턴(암호데이터를 프린터 솔루션에 웹소켓으로 만들어 밀어넣는다)

 

4. url정보

회사 정책 상 아웃바운드 방화벽 오픈 시 기안을 작성해야한다. 그래서 나는 중간에 부여받은 개발 url과 운영 url에 해당하는 ip주소를 찾아 방화벽 기안을 올렸는데, 이후 로컬이 아닌 내부 서버에서 접근하려하니 접근이 불가했다. 그 이유는 url에 해당하는 ip주소가 계속해서 변경되서 있데, 업체 확인결과 고정ip가 아닌 유동ip를 사용하여 url 전체 방화벽기안을 올려야 한다는 답변을 회신받았다.

5. 소통의 문제

업체간 소통 시 중국에서 사용하는 딩톡(DingTalk)을 사용했다. 나름 ai 번역기도 있고, 통역사분도 그룹방에 있었지만, 전문가분이 직접 번역하시는 게 아니라서, 소통이 엄청 힘들었다.


2. 운송장 출력

업체에서 프린트를 호출하는 코드 자체를 줘서 별 무리 없이 개발할 수 있을 줄 알았다. 하지만 자바스크립트 문제와 브라우저 버전 및 호환 문제로 애를 먹었고, 마지막 운영배포이후에는 SSL문제로 한번 더 좌절했다.


1. localhost로 웹소켓을 던져야 한다.

처음에 코드를 받자마자 들었던 생각은 자바스크립트말고 자바로 다 바꿔서 호출하면 되겠지 라고 생각했다. 근데 그럴 수가 없었다. 전달받은 코드(스크립트)는 ws://localhost:13528 처럼 로컬에 설치된 프린트 솔루션으로 웹소켓을 보내줘야 하는 코드가 있었지만, 스프링은 이미 WAS위에 있어 스프링에서 localhost를 호출한다 한들 이는 본인 로컬pc가 아닌 서버 자체를 뜻하기 때문에 자바로 구현할 수가 없었다.

Spring은 WAS에 있으므로 localhost를 해도 본인pc가 아닌 서버 자체를 가리킨다.

 

2. 사내 웹솔루션 문제

그래서 자바스크립트 그대로 웹솔루션에 적용하기로 했다. 근데 사내 ERP는 완전 레거시다. 자바스크립트도 내가 아는 자바스크립트는 아닌거 같고, 만약에 맞다면 버전이 엄청 낮은 거 같다. 나는 웹소켓을 만드는 로직이 필요했는데, new WebSocket을 해도 화면은 반응하지 않았고, 결국 웹 솔루션에서 소켓을 못 만든다는 결론이 나서 jsp화면으로 리다이렉트하여 띄우는 방향으로 개발방향을 틀었다.

3. 레지스트리 수정

jsp로 화면을 띄우는 것으로 결정하고 난 후 또 다른 문제가 발생했다. 아키텍처가 사내 웹 솔루션에 탑재된 브라우저만을 호출할 수 있는 구조였는데, 탑재된 기본 브라우저는 크롬이나 edge가 아닌 지원이 종료된 IE만 사용이 가능했다... 그 와중에 솔루션에 탑재된 IE버전은 6버전이다. 하지만 웹소켓을 만들기 위해서는 IE기준으로 10이상이어야 생성이 가능하다. 처음에 웹 솔루션 업체에 전화하니 IE 버전을 높이기 위해서 레지스트리를 직접 건드려야 된다고 했다. 레지스트리를 조금 수정하고 인터넷 옵션을 일부 수정하니 화면이 잘 나왔다. 다만, 기존에 잘되던 화면들이 안나오기 시작했고, 결국 레지스트리를 직접 건드리는 건 팀장님 선에서 기각되었다...ㅜㅜㅜㅜ

4. meta 태그

결국 다른 방안이 필요했고, 구글링을 해본 결과 html내 meta 태그를 통해 쉽게 IE버전업을 시킬 수 있었다. 실제로 버전업을 시키는 건 아니고, IE6이지만 10처럼 사용할 수 있게 만들어 주는 태그이다.

<meta http-equiv="x-ua-compatible" content="IE=11">

 

5. 성공한 줄 알았다.

전달받은 코드를 사용자가 쉽게 OP할 수 있게 화면과 로직을 재구성하고, meta태그 추가와 인터넷 옵션을 일부 조정했다. 그리고 프린트 솔루션에 웹소켓을 만들어 send해보니 잘 전달되었다. 통합테스트 전날 완성이 되었고, 나는 성공한 줄 알았다.

6. HTTP와 HTTPS

운영에 반영되고 나서 웹소켓이 만들어지지 않는 문제가 발생했다. 말 그대로 멘붕이었다. 다음날 바로 통합테스트인데 운영에서 되지않았고, 팀장님과 몇몇분들이 같이 내 pc에 붙어서 같이 원인을 찾아 봤다. 원인은 프로토콜 문제인데 개발기는 http://dev-erp.xxx.xx 라는 도메인을 사용하고 있었고, 운영은 https://erp.xxx.xxx 라는 도메인을 사용하고 있어 SSL이 적용된 화면에서는 ws://localhost:13528이 아닌 wss://localhost:13528 를 사용하여 호출해야만 했었다.

  • HTTP -> WS
  • HTTPS -> WSS

 

7. 포트번호 변경

근데...? wss://localhost:13528을 적용해도 이놈의 jsp는 말썽을 피웠다. 웹소켓은 만들어지는데, 프린트 솔루션에서 소켓을 받지를 못한다. 계속해서 에러만 출력되고, 구글링을 미친듯이 했다. 그 미친 구글링의 결론은 http로 시작하는 도메인을 호출하여 웹소켓을 생성하거나 프린트 솔루션이 wss를 받을 수 있게 설정을 하거나 둘중 하나를 택해야만 했다. 근데 회사 보안 정책상 전자는 이미 불가한 상황이었고, 프린트 솔루션이 wss을 받을 수 있게 해야하는데, 지푸라기 잡는 심정으로 딩톡으로 다시 업체에 문의를 했다. 몇 시간 후 답이 왔고 포트번호를 13528에서 13529로 변경하면 https에서 생성된 웹소켓을 받을 수 있다고 답이 왔다. 나는 마지막 지푸라기 잡는 심정으로 포트번호 변경 후 https가 적용된 통테기에 반영했고, 성공적으로 운송장이 출력되는 것을 확인할 수 있었다.

8. 마지막 운영 반영

통테기에 운송장 출력을 확인하고, 그대로 운영까지 배포했다. 다행히 잘 동작한다... 다행이다... 통합테스트 전에 끝낼수 있어서... 내일 제발 아무일 없기를

 


(+) 추가

 

22.07.08 - 통합 운영테스트

API 1차 호출 : 업체 고정값 오류로 success value false 리턴 -> 고정값 재전달 받음

API 2차 호출 : 상품이 중국 세관에서 승인된 상품이 아니라 success value false 리턴 -> 승인된 상품 수기로 업데이트하여 재호출

API 3차 호출 : 운송장 번호 정상 리턴 확인 및 업체 데이터 송신 확인

 

운송장 1차출력 : 에러 -> 파라미터를 초기화하지 않은 상태로 HashMap의 putAll 메서드 호출, 초기화해서 운영재반영

운송장 2차출력 : 운송장 정상 출력 확인, 인천공항 창고 운송장 정상출력 확인

 

통합테스트 이후 Interface 테이블 전체 데이터 삭제 및 더이상 알리바바 측에서 상품의 이동을 진행하지 못하도록 취소 API 호출

API호출 이후 전체 취소 확인