위챗 미니프로그램에서 위챗 페이 연동 삽질기(부제.Golang에서 EUC-KR 서버와 HTTP 통신하기)
최근 중국 전자 상거래 동향 중 하나는 모바일 거래와 해외 직구가 크게 성장하고 있다는 것이다.[1] 이런 상황에서 필자는 중국인들이 모바일을 통해 한국 상품을 구매할 수 있는 역직구몰을 만들고 있다.
모바일이라고 하면 안드로이드나 아이폰 앱을 떠올릴 수 있겠지만 앱 스토어 같은 곳에서 다운로드해 설치해야 하는 불편함과 서비스를 이용을 위한 회원 가입을 시키는 것은 쉬운 일이 아니다. 또한 앱을 개발하는 입장에서 안드로이드와 아이폰 코드를 함께 만들고 유지하는 것 역시 쉽지 않다.
위와 같은 문제를 해결하기 위해 선택한 것이 앱을 위챗 미니프로그램으로 만드는 것이었다. 중국에서는 한국의 카카오톡처럼 위챗을 많이 사용하고 있는데 위챗 상에서 동작하는 앱을 위챗 미니프로그램WeChat MiniProgram(小程序)(이하 미니프로그램) 혹은 미니앱이라고 부른다. 미니프로그램은 겉보기에 아이폰/안드로이드 같은 모바일 앱과 차이를 못 느낄 정도의 사용자 경험을 제공한다.
미니프로그램의 장점은 실행과 동시에 설치가 이루어지기 때문에 사용자가 설치하는 과정을 의식하지 못한다. 또한 위챗이 사용자 가입을 자동으로 처리하고, 인증 부분도 처리하기 때문에 사용자 가입도 필요 없다. 그리고 미니프로그램은 위챗 상에서 동작하기 때문에 개발자는 안드로이드나 아이폰용으로 따로 미니프로그램을 개발할 필요 없다.
모바일 앱은 미니프로그램으로 개발하면 되지만 여전히 남는 문제가 있는데 바로 결제이다. 모바일 결제 시장은 2019년 3분기 기준으로 알리페이Alipay(支付宝)와 위챗페이WeChatPay(微信支付)가 양분하고 있다.[2]
미니프로그램에서 알리페이를 사용할 수 없지만 위챗페이는 사용할 수 있다. 하지만 역직구몰의 특징 상 정산이 문제다. 중국인들이 위챗페이로 위안화로 결제하지만 원화로 정산을 받아야 하기 때문이다. 이 문제는 국내 위챗페이 결제 대행사PaymentGateway를 사용함으로써 해결할 수 있다. 판매된 상품에 대한 정산은 소비자가 상품을 위챗페이로 결제하면 국내 위챗페이 결제 대행사가 수수료를 차감하여 판매대금을 원화를 받을 수 있다.
필자가 만든 API Server는 Golang으로 만들었는데 국내 위챗페이 결제 대행사(이하 PG) 서버가 EUC-KR이라 연동 과정에서 글자가 깨지는 현상이 발생했다.
이 글은 Golang에서 EUC-KR 서버와 HTTP 통신할 때 인코딩 및 디코딩 하는 방법을 소개한다.
EUC-KR로 인코딩 및 디코딩 하기
HTTP를 사용하여 PG 서버와 통신하였고 결제에 필요한 정보를 form-data로 넘겨주었다. Golang http 패키지를 사용하여 아래와 같이 구현할 수 있다.
1 2 3 4 5 6 7 8 9 10
func main() { data := url.Values{} data.Add("GoodsName", "한글") // ... response, _ := http.Post("http://example-payment-gateway.kr/process.jsp", "application/x-www-form-urlencoded;charset=euc-kr", bytes.NewBufferString(data.Encode())) defer response.Body.Close() // ... }
위와 같이 결제 정보를 넘기면 PG 서버(example-payment-gateway.kr)에서 한글이 깨지고 만다.
해결 방법은 한글 부분을 EUC-KR 로 인코딩해서 보내는 것이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
import ( // ... "net/http" "net/url" "golang.org/x/text/encoding/korean" "golang.org/x/text/transform" ) func encodeToEUCKR(s string) (string, error) { var buf bytes.Buffer wr := transform.NewWriter(&buf, korean.EUCKR.NewEncoder()) _, err := wr.Write([]byte(s)) if err != nil { return "", err } defer wr.Close() return buf.String(), nil } func main() { data := url.Values{} goodsName, _ := encodeToEUCKR("한글") data.Add("GoodsName", goodsName) // ... response, _ := http.Post("http://euc-kr-server-example.kr/process.jsp", "application/x-www-form-urlencoded;charset=euc-kr", bytes.NewBufferString(data.Encode())) defer response.Body.Close() // ... }
요청에 대한 응답(response.Body)에 한글이 있는 경우에도 깨진다 따라서 EUC-KR로 디코딩한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
import ( // ... "net/http" "net/url" "golang.org/x/text/encoding/korean" "golang.org/x/text/transform" ) func encodeToEUCKR(s string) (string, error) { //... } func decodeToEUCKR(s string) (string, error) { var buf bytes.Buffer wr := transform.NewWriter(&buf, korean.EUCKR.NewDecoder()) _, err := wr.Write([]byte(s)) if err != nil { return "", err } defer wr.Close() return buf.String(), nil } func main() { data := url.Values{} goodsName, _ := encodeToEUCKR("한글") data.Add("GoodsName", goodsName) // ... response, _ := http.Post("http://euc-kr-server-example.kr/process.jsp", "application/x-www-form-urlencoded;charset=euc-kr", bytes.NewBufferString(data.Encode())) defer response.Body.Close() b, _ := ioutil.ReadAll(response.Body) responseBody, _ := decodeToEUCKR(string(b)) // ... }
마치며
국내에서 위챗 미니프로그램이 많이 알려져 있지 않아(특히 개발자들 사이에) 글머리에 소개 글을 자세히 썼다.
위챗페이 PG사와 연동하면서 아쉬운 점은 EUC-KR 부분이다. 위챗페이를 사용하는 대부분은 중국인이다. 중국인은 중국어를 사용한다. 너무나도 당연한 이야기다. 하지만 PG 서버가 EUC-KR이므로 중국어를 사용할 수 없다. 이것이 왜 문제가 될까? 위챗페이로 결제를 하면 위챗은 결제 당사자에게 결제 금액과 상품명이 포함된 결제 메시지로 아래와 같이 보낸다.
문제는 역직구몰에서 중국어로 상품명을 노출하는데 PG사 서버가 EUC-KR만 지원하기 때문에 구매한 상품명(중국어)을 위챗 페이 결제 메시지에 그대로 전달할 수 없다. 결과적으로 상품명이 달라진다.
이 같은 문제를 PG사에 여러 차례 제기했으나, 돌아오는 대답은 우리는 EUC-KR을 바꿀수 없다는 대답이었다. 해당 PG사가 이름이 꽤 알려져 있는 회사였는데도 말이다. 위챗 페이 같은 글로벌 서비스를 개발할 때 위챗 페이의 쓰임새(역직구몰 같은) 고려하지 않고 자사의 인코딩 방식을 고집하는 것은 매우 유감스러운 점이다.
주석
[1] http://news.kotra.or.kr/user/globalAllBbs/kotranews/album/2/globalBbsDataAllView.do?dataIdx=171474
[2] https://www.beinews.net/news/articleView.html?idxno=30407