본문 바로가기
PHP

LG 유플러스 전자결제(PG) 사용하기

by ethanjoh 2016. 2. 29.

몇 년 전 처음으로 독립형 쇼핑몰 솔루션에 카드결제를 붙여달라고 해서 LG uplusxpay 전자결제 모듈을 이용한 적이 있다.

이번에도 독립형 쇼핑몰 작업을 하면서 한번 해본 적이 있는 LG 유플러스가 편할 것 같아서 선택했다.

 

처음에 PG사의 모듈을 사용할 때 매뉴얼이 암호처럼 보여서 고생을 했는데, 역시나 이번에도 쉽지 않았다.

(나만 그런가? 문제가 생겼을 때 인터넷 검색을 해봐도 별다른 방법이 없다.)

 

이번에 고생을 한 문제는 다름이 아니라 너무 조심스럽게 사용했다고나 할까?

로컬에서 PHP 옵션에 display errors를 해놓고 실행하다보면 에러를 뿜어내는데 이것을 잡아보겠다고 변수에 빈 값이 들어있는 것을 체크하려다 발생했다.

 

isset() 함수를 if()문에서 사용해야 하는데 로컬에서 에러나는 것을 방지하겠다고 아무 생각없이 변수를 대입할 때도 사용했다가 원인을 몰라  며칠 동안을 고생한 것이었다. (함수의 사용법을 제대로 알지 못한 기초부족...ㅠㅠ)

 

 

 

이전에는 xpay_lite를 사용했었는데 이번에는 그냥 xpay를 사용했는데 기본 컨셉은 동일했지만 사용법이 조금 달랐다.

결제모듈을 사용하기 위해서는 먼저 사업자를 가지고 신청을 해야한다.

 

사용하고자 하는 사이트의 주소를 넣어야 하는데, 이것을 가지고 LG 유플러스에서 자체적인 심사를 먼저 하게 된다.

(현재 정식도메인을 사용 중인 사이트가 가격정보 등이 없는 그냥 카탈로그 수준의 사이트라서 LG 유플러스에서 반려가 됐는데, 현재 작업하고 있는 임시 도메인을 가지고 나중에 재심사를 요청할 예정이다.)

 

사용신청서를 작성할 때 만든 아이디가 상점아이디가 되고, 해당 상점 아이디를 가지고 테스트용 상점관리자로 들어가서 mertkey를 확인해서 이것을 가지고 사용하면 된다.

 

그런데 전에 사용했던 것과는 달리 이번에는 configuration 파일들이 별도로 있어서 해당 파일에서 몇 가지를 셋팅해줘야 하더라.

 

그리고 가장 중요한 것은 핵심 처리파일들을 가지고 있는 lgdacom 디렉토리를 웹에서 접근이 가능한 경로에 두어서는 보안 상 안좋다는 것이다.

 

보통 웹서비스가 public_html 이나 www 같은 디렉토리에서 시작하는데 이 디렉토리의 서브디렉토리로 둔다면 웹 상에서 마음만 먹으면 얼마든지 접근이 가능할 것이다.

그래서 웹서비스 디렉토리 밖에 두고 절대경로를 구해서 이것을 이용해서 사용하는 것이 보안 상 좋다.

 

예를 들어,

 

<?php

 

$relativePath = './';

$absolutePath = realpath($relativePath);

 

echo "<p>상대경로: " . $relativePath . "</p>";

echo "<p>절대경로: " . $absolutePath . "</p>";

 

위와 같이 파일을 작성해서 서버에서 실행시켜 보면 이 파일이 있는 디렉토리의 절대경로를 알 수 있다.

그것을 가지고 호스팅을 받고 있는 웹서버의 절대경로를 알아내서 결제처리 파일들의 $configPath 변수값을 설정하는데 사용할 수 있다.

이렇게 중요한 lgdacom 디렉토리를 웹에서 접근가능한 경로가 아닌 밖에 둠으로써 보안에 좀 더 신경을 쓸 수가 있게 됐다.

 

결제프로세스를 보면 사용자가 결제를 하기 위해 결제하기 버튼을 클릭하게 되면 payreq_crossplaform.php 를 호출하게 된다.

이 때 LGD_CUSTOM_USABLEPAY 옵션을 사용하면 원하는 결제방법만을 사용자에게 보여줄 수 있다.

이 옵션을 사용하지 않을 경우 결제창이 떴을 때 모든 결제수단이 보인다.

그래서, 카드결제/계좌이체/무통장 등 몇 가지의 결제수단만 보여주고 싶을 때는 <select>에 이 옵션을 사용한다.

 

<select name="LGD_CUSTOM_USABLEPAY" id="LGD_CUSTOM_USABLEPAY">

<option value="SC0010">신용카드</option>

<option value="SC0030">실시간 계좌이체</option>

<option value="SC0040">무통장입금(가상계좌 발급)</option>

</select>

 




여기서 한 가지 중요한 옵션은 인코딩과 관련된 것이다.

 

mall.conf 파일에서 output_UTF8 = 1 이라고 서버의 응답을 UTF-8로 받겠다고 설정을 해도 결제창이 떴을 때 전달된 상품명 등의 값의 한글이 깨진다.

이것을 방지하려면 숨김값으로 하나 넣어주고 POST로 전달한다.

 

<input type="hidden" name="LGD_ENCODING" id="LGD_ENCODING" value="UTF-8">

 

자 이제, 만약 카드결제를 선택했다면 결제창에서는 바로 카드결제수단만이 나타난다.

테스트해보니 큰 무리없이 잘 된다.






(상품명에서 한글이 깨지지 않고 잘 나온다.)


 

결제과정은 payreq_crossplatfrom.php returnurl.php payres.php 이런 식으로 전달이 된다.

 

payres.php 에서는 서버의 응답값이 0000으로 성공값이 들어올 경우 DB 처리를 해주면 된다.

 

if ("0000" == $xpay->Response_Code()) {

    // 주문성공 DB 처리

}

 

주문정보와는 별도로 PG 사에서 전달되는 값들은 관련 테이블을 따로 만들어서 주문성공 처리 후에 PG 사 테이블도 업데이트 하게끔 했다.

그래서 결제성공여부 등은 이 테이블의 컬럼값들을 가지고 처리하게 된다.

 

지금까지 실시간계좌이체도 큰 문제없이 테스트가 잘 끝났다.

 

그런데 문제는 가상계좌의 입금확인에서 벌어졌다.

카드결제와 실시간계좌이체는 payres.php에서 모두 처리가 가능하다.

가상계좌 역시 payres.php에서 일단 가상계좌할당 등의 넘어온 값을 알 수 있다.

문제는 DB 처리이다.

 

가상계좌는 cas_noteurl.php 라는 별도의 페이지에서 계좌할당이나 입금, 취소 등의 처리를 따로 한다. 그래서 이 페이지에서 DB 처리도 해주어야 한다.


일단 가상계좌를 할당받게 되면 LGD_CASFLAG 라는 값을 통해 PG사 서버에서 확인값을 전달한다.

계좌할당은 R, 입금확인은 I, 취소는 C 의 값을 백그라운드에서 LGD_CASFLAG 로 넘겨주게 된다.

 

if ("R" == $LGD_CASFLAG) {

    // 계좌할당에 따른 DB 처리

} else if ("I" == $LGD_CASFLAG) {

    //입금성공에 따른 DB 처리

} else if ("C" == $LGD_CASFLAG) {

    // 취소에 따른 DB 처리

}

 

이런 로직으로 처리하면 된다.

어렵지 않다.

 

그런데 이상하게도 계좌할당까지는 되는데 입금처리가 안되는 것이다.

(가상계좌의 입금테스트는 LG 유플러스 홈페이지의 가상계좌 입금테스트를 통해서 할 수 있다.)

 

cas_noteurl.php이 백그라운드에서 실행되다보니 echo로 값을 찍어볼 수도 없고 답답했는데, 이전에 텍스트파일로 저장했던 기억이 나서 변수값을 텍스트파일로 로그파일처럼 만들어서 전달되는 값이 무엇인지 들여다 보았다.

 

그런데 계좌할당을 받으면 당연히 R 값이 들어있어야 할 $LGD_CASFLAG 에 계속 1 값이 찍히는 것이었다.

 

몇 번을 테스트해도 동일한 값이 찍힌다.

도대체 이 1이라는 값은 어디서 전달이 되는 것인지...?

 

그 전에 고객센터를 통해 기술지원을 받았는데 상점관리자의 결제실패조회 페이지를 통해서 어떤 값이 전달됐는지 보면 DB가 성공적으로 처리 된 후 OK 값이 서버로 전달이 되어야 하는데 이상한 값이 전달되는 것이었다.

 


분명히 $resultMSG 변수값에는 “OK”라는 성공문자가 제대로 대입이 되고 있었는데 PG사 서버로는 엉뚱한 값이 전달되고 있으니 PG사 서버에서는 입금확인이 됐다고 내 서버 쪽으로 값을 전달해도 무엇인가 제대로 처리가 되지 못하고 있는 것이었다.

 

어디선다 넘어오는 값에서 변조가 된다는 것이었는데 내가 로컬에서 테스트하면서 에러가 표시되는 것이 싫어서 변수에 값이 할당됐는지 여부를 isset() 함수를 가지고 체크를 하게끔 했는데 이것이 문제였다.

 

$LGD_CASFLAG = isset($_POST['LGD_CASFLAG']);

 

isset() 함수는 값이 있을 경우에는 true , 1을 없을 때는 false, 0을 되돌려주는 함수인데 말 그대로 값이 있는지 여부를 확인한답시고 if() 문이 아닌 변수를 직접 확인하는 것에서 사용한 것이 화근이었다.

그러니 값은 분명히 R, I 등 제대로 전달이 되고 있었으니 isset()1을 리턴할 수 밖에...

 

if(isset($_POST['LGD_CASFLAG'])) {

return $_POST['LGD_CASFLAG'];

}

 

원래는 이런 식으로 처리가 되었어야 하는 로직이었다.

(이렇게 처리하는 함수도 별도로 만들어서 사용하고 있었음에도 원초적인 실수를 함으로써 주말 내내 이 문제를 가지고 골머리를 썩히고 있었던 것이었다.)

 

이것이 해결되고 나니 가상계좌의 입금처리도 깔끔하게 해결이 되어서 앓던 이 빠진 듯 속이 시원해졌다.

 

도저히 내 실력으로는 해결할 수 없었던 것 같던 문제도 며칠을 고민고민하고 소스를 들여다 보고 하니 결국엔 해결이 되더라.

취소처리 등 몇 가지가 더 남아 있지만 고비는 넘긴 것 같아서 이제 속도를 낼 수 있을 것 같다.