headerMap = new HashMap<>();
43 | private IAmPortPackage aPackage;
44 | private Activity activity;
45 | private ThemedReactContext reactContext;
46 |
47 | @VisibleForTesting
48 | public static final String REACT_CLASS = "IAmPortViewManager";
49 |
50 | @Override
51 | public String getName() {
52 |
53 | return REACT_CLASS;
54 | }
55 |
56 | @Override
57 | public IAmPortWebView createViewInstance(ThemedReactContext context) {
58 |
59 | IAmPortWebView webView = new IAmPortWebView(this, context);
60 |
61 | reactContext = context;
62 |
63 | activity = context.getCurrentActivity();
64 |
65 | // Fixes broken full-screen modals/galleries due to body
66 | // height being 0.
67 | webView.setLayoutParams(
68 | new LayoutParams(LayoutParams.MATCH_PARENT,
69 | LayoutParams.MATCH_PARENT)
70 | );
71 | CookieManager.getInstance().setAcceptCookie(true); // add default cookie support
72 | CookieManager.getInstance().setAcceptFileSchemeCookies(true); // add default cookie support
73 |
74 | return webView;
75 | }
76 |
77 | public void setPackage(IAmPortPackage aPackage) {
78 |
79 | this.aPackage = aPackage;
80 | }
81 |
82 | public IAmPortPackage getPackage() {
83 |
84 | return this.aPackage;
85 | }
86 |
87 | public void emitPaymentEvent(String result, String imp_uid, String merchant_uid){
88 |
89 | WritableMap params = Arguments.createMap();
90 | params.putString("result", result);
91 | params.putString("imp_uid", imp_uid);
92 | params.putString("merchant_uid", merchant_uid);
93 |
94 | reactContext.getJSModule(RCTDeviceEventEmitter.class).emit("paymentEvent", params);
95 | }
96 |
97 | @ReactProp(name = "html")
98 | public void setHtml(IAmPortWebView view, @Nullable String html) {
99 | Log.i("iamport", "setHtml: " + html);
100 | view.loadDataWithBaseURL(view.getBaseUrl(), html, HTML_MIME_TYPE, view.getCharset(), null);
101 | }
102 |
103 | @ReactProp(name = "appScheme")
104 | public void setAppScheme(IAmPortWebView view, @Nullable String appScheme) {
105 |
106 | view.setAppScheme(appScheme);
107 | }
108 |
109 | @ReactProp(name = "source")
110 | public void setSource(IAmPortWebView view, @Nullable String source) {
111 |
112 | setHtml(view, source);
113 | }
114 |
115 | @ReactProp(name = "pg")
116 | public void setPG(IAmPortWebView view, @Nullable String pg) {
117 |
118 | Log.i("iamport", "PG - " + pg);
119 |
120 | if(pg.equals("nice")){
121 | NiceWebViewClient webViewClient = new NiceWebViewClient(activity, view, new UrlLoadingCallBack() {
122 |
123 | @Override
124 | public void shouldOverrideUrlLoadingCallBack(String s) {
125 | Log.i("iamport", "NiceWebViewClient.shouldOverrideUrlLoadingCallBack - " + s);
126 | emitPaymentEvent(s, s, s);
127 | }
128 |
129 | });
130 | view.setWebViewClient(webViewClient);
131 | } else if(pg.equals("kakaopay")){
132 | view.setWebViewClient(new KakaoWebViewClient(activity, view));
133 | } else if(pg.equals("payco")){
134 | PaycoWebViewClient webViewClient = new PaycoWebViewClient(activity, view, new UrlLoadingCallBack() {
135 |
136 | @Override
137 | public void shouldOverrideUrlLoadingCallBack(String s) {
138 | Log.i("iamport", "PaycoWebViewClient.shouldOverrideUrlLoadingCallBack - " + s);
139 | emitPaymentEvent(s, s, s);
140 | }
141 |
142 | });
143 | view.setWebViewClient(webViewClient);
144 | } else if(pg.equals("kcp")){
145 | KcpWebViewClient webViewClient = new KcpWebViewClient(activity, view, new UrlLoadingCallBack() {
146 | @Override
147 | public void shouldOverrideUrlLoadingCallBack(String s) {
148 | Log.i("iamport", "KcpWebViewClient.shouldOverrideUrlLoadingCallBack - " + s);
149 | emitPaymentEvent(s, s, s);
150 | }
151 | });
152 | view.setWebViewClient(webViewClient);
153 | } else {
154 | CallbackWebViewClient defaultWebViewClient = new CallbackWebViewClient(activity, view, new UrlLoadingCallBack() {
155 | @Override
156 | public void shouldOverrideUrlLoadingCallBack(String s) {
157 | Log.i("iamport", "CallbackWebViewClient.shouldOverrideUrlLoadingCallBack - " + s);
158 | emitPaymentEvent(s, s, s);
159 | }
160 | });
161 | view.setWebViewClient(defaultWebViewClient);
162 | }
163 | }
164 |
165 | @Override
166 | public void onDropViewInstance(IAmPortWebView webView) {
167 |
168 | super.onDropViewInstance(webView);
169 | ((ThemedReactContext) webView.getContext()).removeLifecycleEventListener(webView);
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/android/src/main/java/com/jeongjuwon/iamport/IAmPortWebView.java:
--------------------------------------------------------------------------------
1 | package com.jeongjuwon.iamport;
2 |
3 | import android.annotation.SuppressLint;
4 |
5 | import android.net.Uri;
6 | import android.webkit.WebView;
7 | import android.webkit.WebSettings;
8 | import android.webkit.WebViewClient;
9 | import android.webkit.JavascriptInterface;
10 | import android.os.Bundle;
11 | import android.util.Log;
12 | import android.app.Activity;
13 | import android.content.Intent;
14 |
15 |
16 | import com.facebook.react.bridge.WritableMap;
17 | import com.facebook.react.bridge.Arguments;
18 | import com.facebook.react.bridge.LifecycleEventListener;
19 | import com.facebook.react.uimanager.ThemedReactContext;
20 | import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;
21 |
22 | class IAmPortWebView extends WebView implements LifecycleEventListener {
23 |
24 | private final IAmPortViewManager mViewManager;
25 | private final ThemedReactContext mReactContext;
26 |
27 | private Activity activity;
28 |
29 | private String appScheme = "appScheme";
30 | private String charset = "UTF-8";
31 | private String baseUrl = "file:///";
32 | private String injectedJavaScript = null;
33 | private boolean allowUrlRedirect = false;
34 |
35 | private class IAmPortWebViewBridge {
36 |
37 | IAmPortWebView mContext;
38 |
39 | IAmPortWebViewBridge(IAmPortWebView c) {
40 | mContext = c;
41 | }
42 |
43 | @JavascriptInterface
44 | public void receiveResult(String result, String imp_uid, String merchant_uid) {
45 |
46 | mContext.emitPaymentEvent(result, imp_uid, merchant_uid);
47 | }
48 | }
49 |
50 | public IAmPortWebView(IAmPortViewManager viewManager, ThemedReactContext reactContext) {
51 |
52 | super(reactContext);
53 |
54 | mViewManager = viewManager;
55 | mReactContext = reactContext;
56 |
57 | activity = reactContext.getCurrentActivity();
58 |
59 | this.getSettings().setJavaScriptEnabled(true);
60 | this.getSettings().setBuiltInZoomControls(false);
61 | this.getSettings().setDomStorageEnabled(true);
62 | this.getSettings().setGeolocationEnabled(false);
63 | this.getSettings().setPluginState(WebSettings.PluginState.ON);
64 | this.getSettings().setAllowFileAccess(true);
65 | this.getSettings().setAllowFileAccessFromFileURLs(true);
66 | this.getSettings().setAllowUniversalAccessFromFileURLs(true);
67 | this.getSettings().setLoadsImagesAutomatically(true);
68 | this.getSettings().setBlockNetworkImage(false);
69 | this.getSettings().setBlockNetworkLoads(false);
70 |
71 | reactContext.addLifecycleEventListener(this);
72 |
73 | this.addJavascriptInterface(new IAmPortWebViewBridge(this), "iamport");
74 | }
75 |
76 | public void setAppScheme(String appScheme){
77 |
78 | this.appScheme = appScheme;
79 | }
80 |
81 | public String getAppScheme(){
82 |
83 | return this.appScheme;
84 | }
85 |
86 | public void setBaseUrl(String baseUrl) {
87 |
88 | this.baseUrl = baseUrl;
89 | }
90 |
91 | public String getBaseUrl() {
92 |
93 | return this.baseUrl;
94 | }
95 |
96 | public String getCharset() {
97 |
98 | return this.charset;
99 | }
100 |
101 | public void emitPaymentEvent(String result, String imp_uid, String merchant_uid){
102 |
103 | WritableMap params = Arguments.createMap();
104 | params.putString("result", result);
105 | params.putString("imp_uid", imp_uid);
106 | params.putString("merchant_uid", merchant_uid);
107 |
108 | mReactContext.getJSModule(RCTDeviceEventEmitter.class).emit("paymentEvent", params);
109 | }
110 |
111 | @Override
112 | public void onHostResume() {
113 |
114 | Intent intent = activity.getIntent();
115 |
116 | if ( intent != null ) {
117 |
118 | Uri intentData = intent.getData();
119 |
120 | if ( intentData != null ) {
121 |
122 | //카카오페이 인증 후 복귀했을 때 결제 후속조치
123 | String url = intentData.toString();
124 |
125 | Log.i("iamport", "onHostResume URL - " + url);
126 |
127 | if ( url.startsWith(this.getAppScheme() + "://process") ) {
128 |
129 | Log.i("iamport", "process");
130 | this.loadUrl("javascript:IMP.communicate({result:'process'})");
131 | }
132 | else if ( url.startsWith(this.getAppScheme() + "://cancel") ) {
133 |
134 | Log.i("iamport", "cancel");
135 | this.loadUrl("javascript:IMP.communicate({result:'cancel'})");
136 | }
137 | else if ( url.startsWith(this.getAppScheme() + "://success") ) {
138 |
139 | Log.i("iamport", "success");
140 |
141 | Uri uri = Uri.parse(url);
142 | String imp_uid = uri.getQueryParameter("imp_uid");
143 | String merchant_uid = uri.getQueryParameter("merchant_uid");
144 |
145 | this.emitPaymentEvent("success", imp_uid, merchant_uid);
146 | }
147 |
148 | //TODO
149 | this.emitPaymentEvent("onHostResume", url, url);
150 |
151 | intent.replaceExtras(new Bundle());
152 | intent.setAction("");
153 | intent.setData(null);
154 | intent.setFlags(0);
155 | }
156 | }
157 | }
158 |
159 | @Override
160 | public void onHostPause() {
161 |
162 | Log.i("iamport", "onHostPause - IAmPortWebView");
163 | }
164 |
165 | @Override
166 | public void onHostDestroy() {
167 |
168 | Log.i("iamport", "onHostDestroy - IAmPortWebView");
169 | destroy();
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/android/src/main/java/com/jeongjuwon/iamport/UrlLoadingCallBack.java:
--------------------------------------------------------------------------------
1 | package com.jeongjuwon.iamport;
2 |
3 | public interface UrlLoadingCallBack {
4 |
5 | public void shouldOverrideUrlLoadingCallBack(String url);
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/android/src/main/java/com/siot/iamportsdk/CallbackWebViewClient.java:
--------------------------------------------------------------------------------
1 | package com.siot.iamportsdk;
2 |
3 | import android.app.Activity;
4 | import android.util.Log;
5 | import android.webkit.WebView;
6 | import android.webkit.WebViewClient;
7 |
8 | import com.jeongjuwon.iamport.UrlLoadingCallBack;
9 |
10 | /**
11 | * Created by jang on 2018. 5. 31..
12 | */
13 |
14 | public class CallbackWebViewClient extends WebViewClient {
15 |
16 | private Activity activity;
17 | UrlLoadingCallBack mCallBack;
18 |
19 | public CallbackWebViewClient(Activity activity, WebView target, UrlLoadingCallBack callBack) {
20 | this.activity = activity;
21 | this.mCallBack = callBack;
22 | }
23 |
24 | @Override
25 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
26 | Log.i("iamport", "CallbackWebViewClient.shouldOverrideUrlLoading: " + url);
27 | mCallBack.shouldOverrideUrlLoadingCallBack(url);
28 |
29 | return super.shouldOverrideUrlLoading(view, url);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/android/src/main/java/com/siot/iamportsdk/KakaoWebViewClient.java:
--------------------------------------------------------------------------------
1 | package com.siot.iamportsdk;
2 |
3 | import java.net.URISyntaxException;
4 |
5 | import android.app.Activity;
6 | import android.content.ActivityNotFoundException;
7 | import android.content.Intent;
8 | import android.net.Uri;
9 | import android.webkit.WebView;
10 | import android.webkit.WebViewClient;
11 | import android.util.Log;
12 |
13 | public class KakaoWebViewClient extends WebViewClient {
14 |
15 | private Activity activity;
16 |
17 | public KakaoWebViewClient(Activity activity, WebView target) {
18 | this.activity = activity;
19 | }
20 |
21 | @Override
22 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
23 | Log.i("iamport", "KakaoWebViewClient.shouldOverrideUrlLoading - " + url);
24 |
25 | if (!url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith("javascript:")) {
26 | Intent intent = null;
27 |
28 | try {
29 | intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); //IntentURI처리
30 | Uri uri = Uri.parse(intent.getDataString());
31 |
32 | Log.e("iamport", uri.toString());
33 |
34 | activity.startActivity(new Intent(Intent.ACTION_VIEW, uri));
35 | return true;
36 | } catch (URISyntaxException ex) {
37 | return false;
38 | } catch (ActivityNotFoundException e) {
39 | if ( intent == null ) return false;
40 |
41 | String packageName = intent.getPackage(); //packageName should be com.kakao.talk
42 | if (packageName != null) {
43 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageName)));
44 | return true;
45 | }
46 |
47 | return false;
48 | }
49 | }
50 |
51 | return false;
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/android/src/main/java/com/siot/iamportsdk/KcpWebViewClient.java:
--------------------------------------------------------------------------------
1 | package com.siot.iamportsdk;
2 |
3 | import android.app.Activity;
4 | import android.content.ActivityNotFoundException;
5 | import android.content.Intent;
6 | import android.net.Uri;
7 | import android.util.Log;
8 | import android.webkit.WebView;
9 | import android.webkit.WebViewClient;
10 |
11 | import java.io.UnsupportedEncodingException;
12 | import java.net.URISyntaxException;
13 | import java.net.URLDecoder;
14 | import java.net.URLEncoder;
15 | import java.util.Arrays;
16 | import java.util.List;
17 | import java.util.Set;
18 |
19 | import com.jeongjuwon.iamport.UrlLoadingCallBack;
20 |
21 | /**
22 | * from https://github.com/iamport/kcp-android-graddle/blob/master/app/src/main/java/kr/iamport/sdk/KcpWebViewClient.java
23 | * Created by jang on 2017. 9. 14..
24 | */
25 |
26 | public class KcpWebViewClient extends WebViewClient {
27 |
28 | private Activity activity;
29 | private WebView target;
30 | final String KTFC_PACKAGE = "com.kftc.bankpay.android";
31 | UrlLoadingCallBack mCallBack;
32 |
33 | public KcpWebViewClient(Activity activity, WebView target, UrlLoadingCallBack callBack) {
34 | this.activity = activity;
35 | this.target = target;
36 | this.mCallBack = callBack;
37 | }
38 |
39 | @Override
40 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
41 | Log.i("iamport", "KcpWebViewClient.shouldOverrideUrlLoading - " + url);
42 | mCallBack.shouldOverrideUrlLoadingCallBack(url);
43 |
44 | if (!url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith("javascript:")) {
45 | Intent intent = null;
46 |
47 | try {
48 | intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); //IntentURI처리
49 | Uri uri = Uri.parse(intent.getDataString());
50 |
51 | activity.startActivity(new Intent(Intent.ACTION_VIEW, uri));
52 | return true;
53 | } catch (URISyntaxException ex) {
54 | return false;
55 | } catch (ActivityNotFoundException e) {
56 | if (intent == null) return false;
57 |
58 | if (handleNotFoundPaymentScheme(intent.getScheme())) return true;
59 |
60 | String packageName = intent.getPackage();
61 | if (packageName != null) {
62 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageName)));
63 | return true;
64 | }
65 |
66 | return false;
67 | }
68 | }
69 |
70 | return false;
71 | }
72 |
73 | /**
74 | * @param scheme
75 | * @return 해당 scheme에 대해 처리를 직접 하는지 여부
76 | *
77 | * 결제를 위한 3rd-party 앱이 아직 설치되어있지 않아 ActivityNotFoundException이 발생하는 경우 처리합니다.
78 | * 여기서 handler되지않은 scheme에 대해서는 intent로부터 Package정보 추출이 가능하다면 다음에서 packageName으로 market이동합니다.
79 | */
80 | protected boolean handleNotFoundPaymentScheme(String scheme) {
81 | //PG사에서 호출하는 url에 package정보가 없어 ActivityNotFoundException이 난 후 market 실행이 안되는 경우
82 | if (PaymentScheme.ISP.equalsIgnoreCase(scheme)) {
83 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + PaymentScheme.PACKAGE_ISP)));
84 | return true;
85 | } else if (PaymentScheme.BANKPAY.equalsIgnoreCase(scheme)) {
86 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + PaymentScheme.PACKAGE_BANKPAY)));
87 | return true;
88 | }
89 |
90 | return false;
91 | }
92 |
93 | }
--------------------------------------------------------------------------------
/android/src/main/java/com/siot/iamportsdk/NiceWebViewClient.java:
--------------------------------------------------------------------------------
1 | package com.siot.iamportsdk;
2 |
3 |
4 | import java.net.URI;
5 | import java.net.URISyntaxException;
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | import org.apache.http.NameValuePair;
10 | import org.apache.http.client.utils.URLEncodedUtils;
11 | import org.apache.http.util.EncodingUtils;
12 |
13 | import android.app.Activity;
14 | import android.content.ActivityNotFoundException;
15 | import android.content.ComponentName;
16 | import android.content.Intent;
17 | import android.net.Uri;
18 | import android.webkit.WebView;
19 | import android.webkit.WebViewClient;
20 | import android.webkit.WebResourceRequest;
21 | import android.webkit.WebResourceResponse;
22 | import android.util.Log;
23 | import com.jeongjuwon.iamport.UrlLoadingCallBack;
24 |
25 | public class NiceWebViewClient extends WebViewClient {
26 |
27 | private Activity activity;
28 | private WebView target;
29 | private String BANK_TID = "";
30 | UrlLoadingCallBack mCallBack;
31 |
32 | final int RESCODE = 1;
33 | final String NICE_URL = "https://web.nicepay.co.kr/smart/interfaceURL.jsp"; // NICEPAY SMART 요청 URL
34 | final String NICE_BANK_URL = "https://web.nicepay.co.kr/smart/bank/payTrans.jsp"; // 계좌이체 거래 요청 URL
35 | final String KTFC_PACKAGE = "com.kftc.bankpay.android";
36 |
37 | public NiceWebViewClient(Activity activity, WebView target, UrlLoadingCallBack callBack) {
38 | this.activity = activity;
39 | this.target = target;
40 | this.mCallBack = callBack;
41 | }
42 |
43 | public void bankPayPostProcess(String bankpayCode, String bankpayValue) {
44 | String postData = "callbackparam2="+BANK_TID+"&bankpay_code="+bankpayCode+"&bankpay_value="+bankpayValue;
45 | target.postUrl(NICE_BANK_URL,EncodingUtils.getBytes(postData,"euc-kr"));
46 | }
47 |
48 | @Override
49 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
50 |
51 | // TODO: emit event
52 | Log.i("iamport", "NiceWebViewClient.shouldOverrideUrlLoading: " + url);
53 | mCallBack.shouldOverrideUrlLoadingCallBack(url);
54 |
55 | if (!url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith("javascript:")) {
56 | Intent intent = null;
57 |
58 | try {
59 | /* START - BankPay(실시간계좌이체)에 대해서는 예외적으로 처리 */
60 | if ( url.startsWith(PaymentScheme.BANKPAY) ) {
61 | try {
62 | String reqParam = makeBankPayData(url);
63 |
64 | intent = new Intent(Intent.ACTION_MAIN);
65 | intent.setComponent(new ComponentName("com.kftc.bankpay.android","com.kftc.bankpay.android.activity.MainActivity"));
66 | intent.putExtra("requestInfo",reqParam);
67 | activity.startActivityForResult(intent,RESCODE);
68 |
69 | return true;
70 | } catch (URISyntaxException e) {
71 | return false;
72 | }
73 | }
74 | /* END - BankPay(실시간계좌이체)에 대해서는 예외적으로 처리 */
75 |
76 | intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); //IntentURI처리
77 | Uri uri = Uri.parse(intent.getDataString());
78 |
79 | activity.startActivity(new Intent(Intent.ACTION_VIEW, uri));
80 | return true;
81 | } catch (URISyntaxException ex) {
82 | return false;
83 | } catch (ActivityNotFoundException e) {
84 | if ( intent == null ) return false;
85 |
86 | if ( handleNotFoundPaymentScheme(intent.getScheme()) ) return true;
87 |
88 | String packageName = intent.getPackage();
89 | if (packageName != null) {
90 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageName)));
91 | return true;
92 | }
93 |
94 | return false;
95 | }
96 | }
97 |
98 | return false;
99 | }
100 |
101 | /**
102 | * @param scheme
103 | * @return 해당 scheme에 대해 처리를 직접 하는지 여부
104 | *
105 | * 결제를 위한 3rd-party 앱이 아직 설치되어있지 않아 ActivityNotFoundException이 발생하는 경우 처리합니다.
106 | * 여기서 handler되지않은 scheme에 대해서는 intent로부터 Package정보 추출이 가능하다면 다음에서 packageName으로 market이동합니다.
107 | *
108 | */
109 | protected boolean handleNotFoundPaymentScheme(String scheme) {
110 | //PG사에서 호출하는 url에 package정보가 없어 ActivityNotFoundException이 난 후 market 실행이 안되는 경우
111 | if ( PaymentScheme.ISP.equalsIgnoreCase(scheme) ) {
112 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + PaymentScheme.PACKAGE_ISP)));
113 | return true;
114 | } else if ( PaymentScheme.BANKPAY.equalsIgnoreCase(scheme) ) {
115 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + PaymentScheme.PACKAGE_BANKPAY)));
116 | return true;
117 | }
118 |
119 | return false;
120 | }
121 |
122 | private String makeBankPayData(String url) throws URISyntaxException {
123 | BANK_TID = "";
124 | List params = URLEncodedUtils.parse(new URI(url), "UTF-8");
125 |
126 | StringBuilder ret_data = new StringBuilder();
127 | List keys = Arrays.asList(new String[] {"firm_name", "amount", "serial_no", "approve_no", "receipt_yn", "user_key", "callbackparam2", ""});
128 |
129 | String k,v;
130 | for (NameValuePair param : params) {
131 | k = param.getName();
132 | v = param.getValue();
133 |
134 | if ( keys.contains(k) ) {
135 | if ( "user_key".equals(k) ) {
136 | BANK_TID = v;
137 | }
138 | ret_data.append("&").append(k).append("=").append(v);
139 | }
140 | }
141 |
142 | ret_data.append("&callbackparam1="+"nothing");
143 | ret_data.append("&callbackparam3="+"nothing");
144 |
145 | return ret_data.toString();
146 | }
147 |
148 | }
149 |
--------------------------------------------------------------------------------
/android/src/main/java/com/siot/iamportsdk/PaycoWebViewClient.java:
--------------------------------------------------------------------------------
1 | package com.siot.iamportsdk;
2 |
3 | import java.net.URISyntaxException;
4 |
5 | import android.app.Activity;
6 | import android.content.ActivityNotFoundException;
7 | import android.content.Intent;
8 | import android.net.Uri;
9 | import android.webkit.WebView;
10 | import android.webkit.WebViewClient;
11 | import android.util.Log;
12 |
13 | import android.webkit.WebResourceRequest;
14 | import android.webkit.WebResourceResponse;
15 | import com.jeongjuwon.iamport.UrlLoadingCallBack;
16 |
17 | public class PaycoWebViewClient extends WebViewClient {
18 |
19 | private Activity activity;
20 | UrlLoadingCallBack mCallBack;
21 |
22 | public PaycoWebViewClient(Activity activity, WebView target, UrlLoadingCallBack callBack) {
23 | this.activity = activity;
24 | this.mCallBack = callBack;
25 | }
26 |
27 | @Override
28 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
29 |
30 | // TODO: emit event
31 | Log.i("iamport", "PaycoWebViewClient.shouldOverrideUrlLoading: " + url);
32 | mCallBack.shouldOverrideUrlLoadingCallBack(url);
33 |
34 | if (!url.startsWith("http://") && !url.startsWith("https://") && !url.startsWith("javascript:")) {
35 | Intent intent = null;
36 |
37 | try {
38 | intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); //IntentURI처리
39 | Uri uri = Uri.parse(intent.getDataString());
40 |
41 | Log.e("iamport", uri.toString());
42 |
43 | activity.startActivity(new Intent(Intent.ACTION_VIEW, uri));
44 | return true;
45 | } catch (URISyntaxException ex) {
46 | return false;
47 | } catch (ActivityNotFoundException e) {
48 | if ( intent == null ) return false;
49 |
50 | String packageName = intent.getPackage(); //packageName should be com.kakao.talk
51 | if (packageName != null) {
52 | activity.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + packageName)));
53 | return true;
54 | }
55 |
56 | return false;
57 | }
58 | }
59 |
60 | return false;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/android/src/main/java/com/siot/iamportsdk/PaymentScheme.java:
--------------------------------------------------------------------------------
1 | package com.siot.iamportsdk;
2 |
3 | public class PaymentScheme {
4 |
5 | public final static String ISP = "ispmobile"; // ISP모바일 : ispmobile://TID=nictest00m01011606281506341724
6 | public final static String BANKPAY = "kftc-bankpay";
7 |
8 | public final static String LOTTE_APPCARD = "lotteappcard"; // 롯데앱카드 : intent://lottecard/data?acctid=120160628150229605882165497397&apptid=964241&IOS_RETURN_APP=#Intent;scheme=lotteappcard;package=com.lcacApp;end
9 | public final static String HYUNDAI_APPCARD = "hdcardappcardansimclick"; // 현대앱카드 : intent:hdcardappcardansimclick://appcard?acctid=201606281503270019917080296121#Intent;package=com.hyundaicard.appcard;end;
10 | public final static String SAMSUNG_APPCARD = "mpocket.online.ansimclick"; // 삼성앱카드 : intent://xid=4752902#Intent;scheme=mpocket.online.ansimclick;package=kr.co.samsungcard.mpocket;end;
11 | public final static String NH_APPCARD = "nhappcardansimclick"; // NH 앱카드 : intent://appcard?ACCTID=201606281507175365309074630161&P1=1532151#Intent;scheme=nhappcardansimclick;package=nh.smart.mobilecard;end;
12 | public final static String KB_APPCARD = "kb-acp"; // KB 앱카드 : intent://pay?srCode=0613325&kb-acp://#Intent;scheme=kb-acp;package=com.kbcard.cxh.appcard;end;
13 | public final static String MOBIPAY = "cloudpay"; // 하나(모비페이) : intent://?tid=2238606309025172#Intent;scheme=cloudpay;package=com.hanaskcard.paycla;end;
14 |
15 | public final static String PACKAGE_ISP = "kvp.jjy.MispAndroid320";
16 | public final static String PACKAGE_BANKPAY = "com.kftc.bankpay.android";
17 |
18 | public final static String KAKAO = "kakaotalk";
19 | public final static String PACKAGE_KAKAO = "com.kakao.talk";
20 | }
21 |
--------------------------------------------------------------------------------
/etc/scheme_ios.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rm3rdmodules/react-native-iamport/d962f45f0a6c65200bf8f74d367dc27a97e586a0/etc/scheme_ios.png
--------------------------------------------------------------------------------
/index.android.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, { Component } from 'react';
4 | import { StyleSheet } from 'react-native';
5 | import { requireNativeComponent, DeviceEventEmitter } from 'react-native';
6 |
7 | const IAmPortViewManager = requireNativeComponent('IAmPortViewManager', null);
8 |
9 | class IAmPort extends Component {
10 |
11 | componentDidMount() {
12 |
13 | DeviceEventEmitter.addListener('paymentEvent', this.paymentEvent.bind(this));
14 | }
15 |
16 | componentWillUnmount() {
17 |
18 | DeviceEventEmitter.removeAllListeners('paymentEvent');
19 | }
20 |
21 | getParameterByName(name, url) {
22 |
23 | if (!url) {
24 | url = window.location.href;
25 | }
26 | name = name.replace(/[\[\]]/g, "\\$&");
27 | var regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)"),
28 | results = regex.exec(url);
29 | if (!results)
30 | return null;
31 | if (!results[2])
32 | return '';
33 | return decodeURIComponent(results[2].replace(/\+/g, " "));
34 | }
35 |
36 | paymentEvent(e) {
37 |
38 | var url = e.result;
39 | var original = e;
40 |
41 | if (e.result == "success" || e.result == "failed") {
42 | this.props.onPaymentResultReceive(e);
43 | }
44 |
45 | var imp_uid = this.getParameterByName("imp_uid", url),
46 | merchant_uid = this.getParameterByName("merchant_uid", url),
47 | result = "";
48 |
49 | if (url.includes('success=false')) { // 취소 버튼을 눌렀거나 결제 실패시
50 | result = "failed"
51 | } else if (url.includes('success=true')) {
52 | result = "success";
53 | } else if (url.includes('payments/vbank')) {
54 | result = "vbank";
55 | }
56 |
57 | if (result) {
58 | this.props.onPaymentResultReceive({result, imp_uid, merchant_uid, original});
59 | }
60 |
61 | return true;
62 | }
63 |
64 | getRequestContent() {
65 |
66 | let params = this.props.params;
67 | const merchant_uid = params.merchant_uid || ('merchant_' + new Date().getTime());
68 | const m_redirect_url = params.m_redirect_url || 'https://service.iamport.kr/payments/success';
69 | let HTML = `
70 |
71 |
72 |
73 | i'mport react native payment module
74 |
75 |
76 |
77 |
78 |
79 |
107 |
108 |
109 | `;
110 | return HTML;
111 | }
112 |
113 | _onPaymentResultReceive(e) {
114 |
115 | if (this.props.onPaymentResultReceive) {
116 |
117 | this.props.onPaymentResultReceive(e);
118 | }
119 | }
120 |
121 | render() {
122 |
123 | return (
124 |
131 | );
132 | }
133 | }
134 |
135 | const style = StyleSheet.create({
136 | flex: 1
137 | });
138 |
139 | module.exports = IAmPort;
140 |
--------------------------------------------------------------------------------
/index.ios.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import { WebView } from 'react-native';
4 |
5 | export default class IAmPort extends Component {
6 |
7 | constructor(props) {
8 |
9 | super(props);
10 | }
11 |
12 | getRequestContent() {
13 |
14 | let params = this.props.params;
15 | const merchant_uid = params.merchant_uid || ('merchant_' + new Date().getTime());
16 | let HTML = `
17 |
18 |
19 |
20 | i'mport react native payment module
21 |
22 |
23 |
24 |
25 |
26 |
58 |
59 |
60 | `;
61 | return HTML;
62 | }
63 |
64 | getParameterByName(name, url) {
65 |
66 | if (!url) {
67 | url = window.location.href;
68 | }
69 | name = name.replace(/[\[\]]/g, "\\$&");
70 | var regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)"),
71 | results = regex.exec(url);
72 | if (!results)
73 | return null;
74 | if (!results[2])
75 | return '';
76 | return decodeURIComponent(results[2].replace(/\+/g, " "));
77 | }
78 |
79 | _onMessage(e) {
80 |
81 | console.log('_onMessage native event', e.nativeEvent);
82 | const { data, action } = e.nativeEvent;
83 | const { params, onPaymentResultReceive } = this.props;
84 |
85 | if(params.pg !== "kakaopay") {
86 |
87 | //iamport 내부적으로 사용되는 다른 action 들이 추가로 더 있기 때문에 done 타입의 action이 아닌 경우 onMessage를 무시해야 함.
88 | if ( action !== "done" ) return;
89 | }
90 |
91 | if (!data) {
92 | return;
93 | }
94 |
95 | const res = JSON.parse(data);
96 | const { success, request_id, imp_uid, merchant_uid, error_msg } = res;
97 | const result = success ? "success" : "cancel";
98 | console.log('_onMessage', result);
99 |
100 | onPaymentResultReceive({ result, imp_uid, merchant_uid });
101 | }
102 |
103 | _onShouldStartLoadWithRequest(e) {
104 |
105 | var url = e.url;
106 | var me = this;
107 |
108 | console.log("onShouldStartLoadWithRequest", e);
109 |
110 | var imp_uid = this.getParameterByName("imp_uid", url),
111 | merchant_uid = this.getParameterByName("merchant_uid", url),
112 | result = "";
113 |
114 | if (url.includes('imp_success=false')) { // 취소 버튼을 눌렀거나 결제 실패시
115 | result = "failed"
116 | } else if (url.indexOf(this.props.params.app_scheme + '://success') == 0) {
117 | result = "success";
118 | } else if (url.indexOf(this.props.params.app_scheme + '://cancel') == 0) {
119 | result = "canceled";
120 | }
121 | console.log("onShouldStartLoadWithRequest result", result);
122 |
123 | if (result) {
124 | this.props.onPaymentResultReceive({result, imp_uid, merchant_uid});
125 | }
126 |
127 | return true;
128 | }
129 |
130 | injectPostMessageFetch() {
131 |
132 | const patchPostMessageFunction = function () {
133 | var originalPostMessage = window.postMessage;
134 |
135 | var patchedPostMessage = function (message, targetOrigin, transfer) {
136 | originalPostMessage(message, targetOrigin, transfer);
137 | };
138 |
139 | patchedPostMessage.toString = function () {
140 | return String(Object.hasOwnProperty).replace('hasOwnProperty', 'postMessage');
141 | };
142 |
143 | window.postMessage = patchedPostMessage;
144 | };
145 |
146 | return '(' + String(patchPostMessageFunction) + ')();';
147 | }
148 |
149 | render() {
150 | return (
151 | {
160 | return null;
161 | }}
162 | style={this.props.style} />
163 | );
164 | }
165 | }
166 |
167 | module.exports = IAmPort;
168 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": {
3 | "name": "Jeong Juwon",
4 | "email": "2jw0718@gmail.com"
5 | },
6 | "bugs": {
7 | "url": "https://github.com/jeongjuwon/react-native-iamport/issues"
8 | },
9 | "dependencies": {},
10 | "description": "Simple react native i'mport module",
11 | "devDependencies": {},
12 | "homepage": "https://github.com/jeongjuwon/react-native-iamport",
13 | "keywords": [
14 | "react",
15 | "react-native",
16 | "react-component",
17 | "iamport",
18 | "import"
19 | ],
20 | "license": "MIT",
21 | "main": "index",
22 | "maintainers": [
23 | {
24 | "name": "Jeong Juwon",
25 | "email": "2jw0718@gmail.com"
26 | },
27 | {
28 | "name": "Jeff Gu Kang",
29 | "email": "jeffgukang@gmail.com"
30 | }
31 | ],
32 | "name": "react-native-iamport",
33 | "optionalDependencies": {},
34 | "peerDependencies": {
35 | "react-native": ">=0.40"
36 | },
37 | "readme": "ERROR: No README data found!",
38 | "repository": {
39 | "type": "git",
40 | "url": "git+https://github.com/jeongjuwon/react-native-iamport.git"
41 | },
42 | "scripts": {
43 | "test": "echo \"Error: no test specified\" && exit 1"
44 | },
45 | "version": "0.4.0"
46 | }
47 |
--------------------------------------------------------------------------------