티스토리 뷰
페이팔과 연동해서 구매자가 결제한 상세정보를 상점에서 DB처리 및 작업을 하기 위해 페이팔에서 제공하는 주요 기능이 있는데
그게 바로 PDT방식과 IPN방식이다. 두 가지 방식의 특징을 살펴보자.
PDT
- 실시간으로 결제결과를 상점서비스로 전송해준다.(동기방식)
- 동기방식이므로 만약 구매자가 결제를 완료 후 페이팔서버에서 상점서비스로
결제정보를 전송전에 브라우저를 닫아버리면 해당 이벤트가 사라지고 다시 결제결과를 받을 수 있는 방법이 없다.
IPN
- 결제가 완료되면 결제결과를 페이팔서버에 보관해두었다가 상점서비스로 전송해준다.(비동기방식)
- 비동기방식이므로 구매자가 결제를 완료 후에 바로 페이팔서버에서 상점서비스로 전송해준다는 보장이 없다.
- 구매자가 결제 완료 후 브라우저를 닫아버려도 페이팔서버는 상점서버가 수신을 할때까지 몇번이고 재전송을 해주므로
결제결과를 무조건 다시 받을 수 있다.
이런 두가지의 특성때문에 사용자가 상품을 구매시 결제결과를
바로 알려주지 않아도 되는 서비스를 제외하면 PDT, IPN 두가지 방식을 동시에 사용해야한다.
먼저 그 첫번째 PDT 방식을 적용해보자.
PDT를 사용하기 위해선 먼저 페이팔사이트에 접속해서 아래와 같이 PDT사용설정을 해야한다.
My Account > Profile > My Selling Tools 메뉴를 클릭한다.
My selling tools > My business setup > Website preferences의 update를 누르면 PDT를 설정할 수 있는 페이지가 나온다.
Auto Return을 On으로 설정하고
Payment Data Transfer도 On으로 설정한 후
가장 중요한건 Return URL에 입력하는건데 이 URL로 페이팔서버가 결제정보를 전송해주고 해당 URL에 PDT를 처리하는 핸들러를 구현하면된다.
마지막으로 Save버튼을 누르면 설정 적용이 완료되는데 다시 이 설정페이지로 가서 Payment Data Transfer 영역 아래를 살펴보면
Identity token에 값이 나올텐데 이 값은 PDT처리핸들러에 구현할때 필요하므로 기억해두자.
이렇게 하면 사이트에서 PDT 사용설정을 끝냈고 이제 상점에서 실제로 연동작업하는 처리를 해보자.
먼저 PDT의 처리하는 과정을 살펴보면서 설명을 시작하겠다.
초록색 배경 : 회원이 눈으로 볼 수 있는 페이지
구름안에 있는 요소들은 내부적으로 페이팔과 상점 서버들이 요청과 응답을 통해서 결제결과에 대한 작업을 진행한다.
그림으로 봤을때 상점결제페이지 -> 페이팔결제팝업 -> 페이팔서버 까지가 이전 포스팅에서 했던 처리 프로세스다.
결제가되면 PDT설정정보의 Return URL로 tx값을 포함한 정보를 전송해주는데
PDT핸들러에서 응답받은 tx값과 아까 기억해둔 Identity token값을 포함해서 다시 페이팔서버로 POST전송하게되면
페이팔서버는 인증 확인 후 결제에 대한 상세한 내용을 다시 리턴해준다. 그러면 리턴된 정보를 통해서
상점은 DB처리와 성공/실패여부처리등의 작업을 진행한 후 사용자에게 알맞은 페이지를 띄워주면 된다.
아래는 자바로 작성된 PDT를 처리하는 핸들러 샘플 소스다.
public class VerifyPaymentByPayPal {
private Logger logger = LoggerFactory.getLogger(getClass());
private static String URL_PAYPAL_VALIDATE; // PDT데이터를 페이팔로 보낼 서버주소
// PDT 첫번째 응답 변수 선
private static final String PARAM_TX = "tx";
private static final String PARAM_CMD = "cmd";
private static final String PARAM_CMD_VALUE = "_notify-synch";
private static final String PARAM_AT = "at";
private static String PARAM_AT_VALUE;
private static final String RESPONSE_SUCCESS = "SUCCESS";
private static final String RESPONSE_FAIL = "FAIL";
static
{
URL_PAYPAL_VALIDATE = "https://www.sandbox.paypal.com/cgi-bin/webscr";
PARAM_AT_VALUE = "페이팔사이트에서 나와있는 Identity token값";
}
private static final String PARAM_ITEM_NAME = "item_name"; // 상품이름
private static final String PARAM_ITEM_NUMBER = "item_number"; // 상품번호
private static final String PARAM_PAYMENT_STATUS = "payment_status"; // 결제 상태
private static final String PARAM_MC_GROSS = "mc_gross"; // 페이팔 결제금액
private static final String PARAM_MC_FEE = "mc_fee"; // 페이팔 수수료금액
private static final String PARAM_MC_CURRENCY = "mc_currency"; // 화폐
private static final String PARAM_TXN_ID = "txn_id"; // 거래번호
private static final String PARAM_RECEIVER_EMAIL = "receiver_email"; // 페이팔 판매자계정 이메일
private static final String PARAM_PAYER_EMAIL = "payer_email"; // 페이팔 구매자계정 이메일
private static final String PARAM_CUSTOM = "custom"; // 상점회원번호
/** 페이팔 결제 PDT정보 핸들링 */
public void handleRequestPDT(HttpServletRequest request) throws Exception {
// PayPal로부터온 파라미터를 표시한다.
Enumeration en = request.getParameterNames();
String readString = "";
while (en.hasMoreElements()) {
String paramName = (String) en.nextElement();
String paramValue = request.getParameter(paramName);
readString = readString + "&" + paramName + "=" + URLDecoder.decode(paramValue, "UTF-8");
}
logger.info("Received PDT from PayPal:" + readString);
// 다시 PayPal로 게시하기 위해 파라미터를 구성한다.
String str = PARAM_CMD + "=" + PARAM_CMD_VALUE;
en = request.getParameterNames();
while (en.hasMoreElements()) {
String paramName = (String) en.nextElement();
String paramValue = request.getParameter(paramName);
str = str + "&" + paramName + "=" + URLEncoder.encode(paramValue, "UTF-8");
}
str = str + "&" + PARAM_AT + "=" + PARAM_AT_VALUE;
logger.info("Sending PDT to PayPal:" + str);
// 유효성을 검사하기 위해 PayPal로 다시 전송시작.
URL u = new URL(URL_PAYPAL_VALIDATE);
HttpURLConnection uc = (HttpURLConnection) u.openConnection();
uc.setDoOutput(true);
uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
PrintWriter pw = new PrintWriter(uc.getOutputStream());
pw.println(str);
pw.close();
BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String res = in.readLine();
if (res.equals(RESPONSE_SUCCESS)) {
logger.info("페이팔서버로 부터 PDT유효성 요청이 성공했습니다.");
String[] temp;
HashMap vars = new HashMap();
while ((res = in.readLine()) != null) {
temp = res.split("=");
if (temp.length == 2) {
vars.put(temp[0], URLDecoder.decode(temp[1], "UTF-8"));
} else {
vars.put(temp[0], "");
}
logger.info("{}{}{}",new Object[]{temp[0],":",temp[1]});
}
String itemName = (String) vars.get(PARAM_ITEM_NAME);
int itemNumber = Integer.parseInt((String) vars.get(PARAM_ITEM_NUMBER));
String paymentStatus = (String) vars.get(PARAM_PAYMENT_STATUS);
double paymentAmount = Double.parseDouble((String) vars.get(PARAM_MC_GROSS));
double paymentFee = Double.parseDouble((String) vars.get(PARAM_MC_FEE));
String paymentCurrency = (String) vars.get(PARAM_MC_CURRENCY);
String txnId = (String) vars.get(PARAM_TXN_ID);
String receiverEmail = (String) vars.get(PARAM_RECEIVER_EMAIL);
String payerEmail = (String) vars.get(PARAM_PAYER_EMAIL);
int userseq = Integer.parseInt((String) vars.get(PARAM_CUSTOM));
.. DB 작업 및 응답페이지 호출 등등 작업을 한다..
} else if (res.equals(RESPONSE_FAIL)) {
logger.warn("페이팔서버로 부터 PDT유효성 요청이 실패했습니다. 상태:"+res);
} else {
logger.error("페이팔서버로 부터 PDT유효성 요청이 실패했습니다. 상태:"+res);
}
}
}
'프로그래밍' 카테고리의 다른 글
MariaDB 10 설치 및 셋팅 정리 (Amazon Linux 2) (0) | 2022.02.22 |
---|---|
랜섬웨어 예방, 방지하기 (0) | 2017.05.15 |
이클립스 workspace 변경하기 (0) | 2017.03.04 |
페이팔 결제 연동 정리 - 2. 결제 테스트 (0) | 2017.03.03 |
페이팔 결제 연동 정리 - 1. 테스트 환경 구성 (0) | 2017.03.03 |
- Total
- Today
- Yesterday
- 주택임대사업자
- 워크스페이스
- 안드로이드
- AWS
- 유효성검사
- 페이팔 연동
- 톰캣
- 이클립스
- 페이팔 테스트
- 리눅스
- apache
- db
- mysql
- 페이팔 결제
- Linux
- Sandbox
- EC2
- Eclipse
- paypal
- 페이팔
- 주택임대사업자 등록
- 취득세 감면
- 포트
- Java
- Tomcat
- sample
- Workspace
- 설치
- 샌드박스
- 자바스크립트
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |