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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package naverpay;
 
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
 
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
 
 
public class HttpPost {
 
 public static void main(String[] args) {
     HttpPost obj = new HttpPost();
     obj.getHttpsConnection();
 }
 
 public JSONObject getMakeJsonData() {
     
   JSONObject object = new JSONObject();
   object.put("modelVersion""2");   
   object.put("merchantUserKey""");
   object.put("merchantPayKey""");
   object.put("productName""테스트상품");
   object.put("productCount"1);
   object.put("totalPayAmount"1000);   
   object.put("returnUrl""http://localhost:8080/naverpay/");
   object.put("taxScopeAmount"1000);
   object.put("taxExScopeAmount"0);
   object.put("purchaserName""구매자");   
  
   JSONArray list = new JSONArray();
   
   JSONObject productItem = new JSONObject();
   productItem.put("categoryType""INSURANCE");
   productItem.put("categoryId""TRAVELER");
   productItem.put("uid""005");
   productItem.put("name""테스트상품");
   productItem.put("payReferrer""ETC");
   productItem.put("count"1);
   
   list.add(productItem);
   object.put("productItems", list);
   
   return object;
 }
 
 public String UrlEncodeUTF8(String s) {
     try{
         return  URLEncoder.encode(s, "UTF-8");
     } catch(UnsupportedEncodingException ex) {
        throw new UnsupportedOperationException(ex); 
     }
 }
 
 public void getHttpsConnection() {
 
  HttpsURLConnection conn = null;
  try {
   URL url = new URL("https://dev.apis.naver.com/partner-id/naverpay/payments/v2/reserve");
   conn = (HttpsURLConnection) url.openConnection();
   conn.setRequestMethod("POST");
   conn.setRequestProperty("X-Naver-Client-Id""");
   conn.setRequestProperty("X-Naver-Client-Secret""");
   conn.setRequestProperty("Content-Type""application/json");
   conn.setRequestProperty("charset""UTF-8");
   conn.setDoOutput(true);
   conn.setUseCaches(false);
   conn.setConnectTimeout(10000);
   conn.setReadTimeout(10000);
   conn.setHostnameVerifier(new HostnameVerifier() {
 
    @Override
    public boolean verify(String hostname, SSLSession session) {
     return true;
    }
   });
   
   // SSL setting
   SSLContext context = SSLContext.getInstance("TLS");
   context.init(nullnew TrustManager[]{
     new javax.net.ssl.X509TrustManager() {
      
      @Override
      public X509Certificate[] getAcceptedIssuers() {
       return null;
      }
      
      @Override
      public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
      }
      
      @Override
      public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
      }
     }
   }, null);
   conn.setSSLSocketFactory(context.getSocketFactory());
      
   // Connect to host 
   conn.connect(); 
   conn.setInstanceFollowRedirects(true); 
  
   String param = this.getMakeJsonData().toJSONString();
   
   OutputStream wr1 = conn.getOutputStream();
   DataOutputStream wr = new DataOutputStream(conn.getOutputStream());   
   
   wr1.write(param.getBytes("UTF-8"));
   wr1.flush();
   wr1.close();
 
 
   final int responseCode = conn.getResponseCode(); 
   InputStream in = conn.getInputStream(); 
   BufferedReader reader = new BufferedReader(new InputStreamReader(in));
   final StringBuffer buffer = new StringBuffer();
   String line = null
   while ((line = reader.readLine()) != null) { 
 
       buffer.append(line);
   } 
 
   reader.close();
   System.out.println("##########");
   System.out.println("##########");
   System.out.println("##########");
   System.out.println("##########");
   System.out.println("##########");
   System.out.println("result ::: "+buffer.toString());
 
  } catch (Exception e) {
   e.printStackTrace();
  } finally {
   if(conn != null) {
    conn.disconnect();
   }
  }
 
 }
 
}
 
 
cs


네이버페이 결제예약호출 예제시 400에러가 발생하여 해당코드를 위와같이 수정하였다. 

json post 전송시 DataOutputStream 을 통해 전송하였으며 21라인에 UTF-8로 반드시 인코딩해서 데이터를 넘겨준다. 

블로그 이미지

클라인STR

,

이번에 회사에서 업무를 하면서 네이버페이 결제 연동을 하면서 우선적으로 알아야되는 내용을 단계적으로 작성해보았습니다.


1. 별도의 문서없이 네이버페이는  https://developer.pay.naver.com/ 개발자 센터를 통해서 연동내용을 참고 할 수 있습니다.


2. 방화벽 설정에 경우  아웃바운드 포트: 443 포트 허용 해야 합니다. 해당부분이 오픈되지 않는 경우 API 호출이 되지 않습니다. 

 - 개발 : dev.apis.naver.com

 - 운영 : apis.naver.com



https://developer.pay.naver.com/docs/v2/api#getstarted

결제팝업창 호출은 Javascript SDK를 이용할수 있지만 SDK를 사용하지않고 직접 팝업창을 호출하는 방식으로도 가능합니다. 

저는 이번 프로젝트떼 Javascript SDK를 이용하지 않고 직접 결제 팝업창을 호출하는 방식으로 개발을 진행하였습니다. 




3. 네이버페이는 카카오페이 결제랑 다르게 개발검수 과정을 거치고 나서 오픈을 진행할 수 있습니다. 이 검수기간은 최소15일정도 걸리며 진행상황에 따라서 짧아지거나 길어질수 있습니다. 즉 오픈하기위한 일정을 수립할경우 개발완료후 반드시 검수일정까지 추산해서 스케쥴을 산정해야 됩니다. 



직접결제 팝업창을 호출하는 방식 

https://developer.pay.naver.com/docs/v2/api#etc-etc_pay_reserve 해당링크를 참조하여 개발을 하였습니다. 

직접결제 팝업창을 호출하는 방식으로 개발을 한 이유는 제가 작업을 진행하는 개발환경이 패쇄망으로  외부인터넷을 사용할수 없는환경이었습니다. 내부 환경에서 https://nsp.pay.naver.com/sdk/js/naverpay.min.js SDK를 로딩하는 적절한 방법을 찾지 못하였기때문입니다. 현재 이 부분은 얼마전에 js코드르 동적으로 불러오는 코드를 작성하여 테스트 하여 해결하였습니다만, 2개월당시 일정이 빡빡하여 적용하지 못한부분은 아쉬움이 남네요. 


팝업호출방식으로 변경한이유는 간단합니다. 내부에서 웹사이트로 결제전 프로세스를 태우고  팝업이 호출된이후에는 LTE모드로 휴대폰모드를 변경하여 팝업창을 새로고침하여 불러옵니다. 이후에 네이버페이 팝업모듈에서 return URI에 지정된 정보로 리다이렉션 됩니다.

이때 LTE모드에서 WIFI를 켜서 내부망으로 변경하고 새로고침을 하면 정상적으로 진행할 수 있습니다.  이런 방식으로 테스트할 수 있다는걸 찾기가 까지가 오래걸렸던거 같네요.










블로그 이미지

클라인STR

,

<script language="JavaScript" type="text/JavaScript">
<!--
//〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
// 모바일 페이지로 이동.
//〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓

if(  (navigator.userAgent.match(/iphone/i)) || (navigator.userAgent.match(/ipod/i)) || (navigator.userAgent.match(/android/i)) || (navigator.userAgent.match(/Symbian/i)) || (navigator.userAgent.match(/nokia/i)) || (navigator.userAgent.match(/webos/i)) || (navigator.userAgent.match(/opera mini/i)) || (navigator.userAgent.match(/sonyericsson/i)) || (navigator.userAgent.match(/opera mobi/i)) || (navigator.userAgent.match(/iemobile/i)) ) {
  // 모바일 주소 표시줄 숨기기
  window.addEventListener('load', function(){  setTimeout(scrollTo, 0, 0, 1); }, false);

  // 모바일 버전으로 페이지 이동
  document.location = "/m/";
}else{
  // 웹 버전으로 페이지 이동
  document.location = "/web/";
}
//〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓〓
//-->

</script>


출처 : https://blog.naver.com/sm8569/100113041304

블로그 이미지

클라인STR

,