본문으로 건너뛰기

APP WebView 연동하기

1. 설명 (Description)

  • 본 문서는 가맹점 하이브리드 앱 환경에서의 결제 서비스 연동을 돕기 위한 앱 연동 기본 규격을 정의합니다.
  • 하이브리드 APP 연동 전 나이스페이 결제 연동 및 웹 페이지 구현을 필수로 진행해야 합니다.
  • 하이브리드 APP 내에서 인증결제 서비스 사용 시 APP 샘플을 참고해 3rd 앱(카드사·간편결제·백신 등) 호출을 처리합니다.
  • 가맹점 앱을 통해 결제 시 결제창 호출 파라미터 중 WapUrl, IspCancelUrl을 설정합니다. (인증 결제 문서 참고)
  • 테스트 URL https://web.nicepay.co.kr/demo/v3/mobileReq.jsp는 나이스페이 데모 결제 페이지입니다. 운영 전 가맹점 결제 URL로 반드시 변경해야 합니다.

2. 3rd 앱 호출 정보

하이브리드 앱에서 카드사, 간편결제, 계좌이체, 본인인증 앱을 호출하려면 플랫폼별 호출 정보를 사전에 등록해야 합니다.

  • Android 11 이상: AndroidManifest.xmlqueries에 패키지명 등록
  • iOS: Info.plistLSApplicationQueriesSchemes에 Scheme 등록

아래 표는 3rd 앱 호출 시 등록이 필요한 Android 패키지명과 iOS Scheme입니다. 앱사 정책 또는 앱 버전에 따라 호출 정보가 변경될 수 있으므로 운영 반영 전 최신 샘플 기준으로 확인해야 합니다.

구분Android 패키지명iOS Scheme
신용카드삼성 앱카드kr.co.samsungcard.mpocketmpocket.online.ansimclick
신용카드삼성카드 일반결제kr.co.samsungcard.mpocketscardcertiapp
신용카드삼성 monimonet.ib.android.smcardmonimopay, monimopayauth
신용카드신한 앱카드com.shcard.smartpayshinhan-sr-ansimclick
신용카드신한카드 일반결제com.shinhancard.smartshinhansmshinhanansimclick
신용카드신한 슈퍼SOLcom.shinhan.smartcaremgr-
신용카드현대 앱카드com.hyundaicard.appcardhdcardappcardansimclick
신용카드현대카드 일반결제com.hyundaicard.appcardsmhyundaiansimclick
신용카드KB Paycom.kbcard.cxh.appcardkb-acp
신용카드KB스타뱅킹com.kbstar.kbbankkbbank
신용카드KB 리브 NEXTcom.kbstar.rebootnewliiv
신용카드페이북/ISPkvp.jjy.MispAndroid320ispmobile
신용카드하나카드 원큐페이com.hanaskcard.payclacloudpay
신용카드하나카드 일반결제com.hanaskcard.payclahanaskcardmobileportal
신용카드하나멤버스kr.co.hanamembers.hmscustomerhanawalletmembers
신용카드롯데 앱카드com.lcacApplotteappcard
신용카드롯데카드 스마트결제com.lottemembers.androidlottesmartpay
신용카드롯데카드 LPAYcom.lottemembers.androidlpayapp, lmslpay
신용카드NH 올원페이nh.smart.nhallonepaynhappcardansimclick, nhallonepayansimclick
신용카드농협카드 일반결제nh.smart.nhallonepaynonghyupcardansimclick
신용카드우리 WON 카드com.wooricard.smartappwooripay, com.wooricard.wcard
신용카드우리 WON 뱅킹com.wooribank.smart.npibNewSmartPib
신용카드씨티카드kr.co.citibank.citimobilecitispay, citimobileapp
신용카드카카오뱅크 앱카드com.kakaobank.channelkakaobank
공동인증하나카드 공동인증서com.hanaskcard.rocomo.potalqhanamopmoasign
공동인증공동인증서com.lumensoft.touchenappfree-
백신TouchEn mVaccinecom.TouchEn.mVaccine.webs-
백신V3 Mobile Pluscom.ahnlab.v3mobileplus-
백신V-Guardkr.co.shiftworks.vguardweb-
간편결제삼성페이com.samsung.android.spay-
간편결제삼성페이 미니com.samsung.android.spaylite-
간편결제카카오페이com.kakao.talkkakaotalk
간편결제네이버페이com.nhn.android.searchnaversearchthirdlogin
간편결제SSGPaycom.ssg.serviceapp.android.egiftcertificateshinsegaeeasypayment
간편결제페이코com.nhnent.payapppayco
간편결제LG페이com.lge.lgpay-
간편결제위챗페이com.tencent.mm-
간편결제토스viva.republica.tosssupertoss
간편결제쿠팡com.coupang.mobilecoupang
간편결제로켓페이com.coupangpay.rocketpayrocketpay
계좌이체뱅크페이com.kftc.bankpay.androidkftc-bankpay
계좌이체KB 리브페이com.kbstar.liivbankliivbank
계좌이체KB 계좌이체-kb-bankpay
계좌이체케이뱅크페이com.kbankwith.smartbankukbanksmartbanknonloginpay
본인인증SKT PASScom.sktelecom.tauthtauthlink
본인인증KT PASScom.kt.ktauthktauthexternalcall
본인인증LG U+ PASScom.lguplus.smartotpupluscorporation

3. Android Kotlin 연동

3.1. 지원 환경

  • Android 4.4 (KITKAT) 이상

3.2. AndroidManifest.xml

  • Android 11 이상에서는 3rd 앱 호출을 위해 queries에 호출 대상 패키지를 등록해야 합니다.
  • 네트워크 사용을 위해 INTERNET 권한을 추가해야 합니다.
  • Android 9.0 이상에서 일반 텍스트 통신이 필요한 환경이라면 usesCleartextTraffic 또는 별도 네트워크 보안 정책을 설정합니다.
<manifest>
<queries>
<!-- 신용카드 -->
<package android:name="kr.co.samsungcard.mpocket" />
<package android:name="com.shcard.smartpay" />
<package android:name="com.shinhancard.smartshinhan" />
<package android:name="com.kbcard.cxh.appcard" />
<package android:name="com.kbstar.liivbank" />
<package android:name="com.kbstar.kbbank" />
<package android:name="com.kbstar.reboot" />
<package android:name="kvp.jjy.MispAndroid320" />
<package android:name="com.hanaskcard.paycla" />
<package android:name="kr.co.hanamembers.hmscustomer" />
<package android:name="com.lcacApp" />
<package android:name="nh.smart.nhallonepay" />
<package android:name="com.wooricard.smartapp" />
<package android:name="com.wooribank.smart.npib" />
<package android:name="com.hyundaicard.appcard" />
<package android:name="kr.co.citibank.citimobile" />
<package android:name="com.shinhan.smartcaremgr" />
<package android:name="net.ib.android.smcard" />
<package android:name="com.kakaobank.channel" />

<!-- 공동인증 -->
<package android:name="com.hanaskcard.rocomo.potal" />
<package android:name="com.lumensoft.touchenappfree" />

<!-- 백신 -->
<package android:name="com.TouchEn.mVaccine.webs" />
<package android:name="com.ahnlab.v3mobileplus" />
<package android:name="kr.co.shiftworks.vguardweb" />

<!-- 간편결제 -->
<package android:name="com.samsung.android.spay" />
<package android:name="com.samsung.android.spaylite" />
<package android:name="com.kakao.talk" />
<package android:name="com.nhn.android.search" />
<package android:name="com.ssg.serviceapp.android.egiftcertificate" />
<package android:name="com.nhnent.payapp" />
<package android:name="com.lge.lgpay" />
<package android:name="com.lottemembers.android" />
<package android:name="com.tencent.mm" />
<package android:name="viva.republica.toss" />
<package android:name="com.coupang.mobile" />
<package android:name="com.coupangpay.rocketpay" />

<!-- 계좌이체 -->
<package android:name="com.kftc.bankpay.android" />
<package android:name="com.kbankwith.smartbank" />

<!-- 본인인증 -->
<package android:name="com.sktelecom.tauth" />
<package android:name="com.kt.ktauth" />
<package android:name="com.lguplus.smartotp" />
</queries>

<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true">
</application>
</manifest>

3.3. WebView 기본 설정

class WebViewActivity : AppCompatActivity() {
companion object {
const val MERCHANT_URL = "https://{가맹점결제요청페이지URL}"
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_webview)

webview.webViewClient = WebViewClientClass()

val settings = webview.settings
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
settings.cacheMode = WebSettings.LOAD_DEFAULT
settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW

CookieManager.getInstance().setAcceptCookie(true)
CookieManager.getInstance().setAcceptThirdPartyCookies(webview, true)

webview.postUrl(MERCHANT_URL, null)
}
}
캐시 설정 주의

WebSettings.LOAD_CACHE_ELSE_NETWORK 사용 시 일부 카드사 세션 오류가 발생할 수 있습니다. WebView 캐시 모드는 기본값인 WebSettings.LOAD_DEFAULT 사용을 권장합니다.

3.4. URI / Intent 처리

shouldOverrideUrlLoading에서 intent:, market://, 백신·ISP 관련 URL 등을 감지해 Intent.parseUristartActivity 합니다. 앱 미설치 시 Play Store(market://search?q=pname:)로 이동합니다.

Android 구버전 또는 일부 카드사·백신 앱은 intent:// 대신 cloudpay://처럼 scheme만 전달할 수 있으므로 필요한 scheme prefix를 조건에 추가해야 합니다.

private class WebViewClientClass : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?,
): Boolean {
val url = request?.url.toString()

try {
if (
url.startsWith("intent:") ||
url.contains("market://") ||
url.contains("vguard") ||
url.contains("droidxantivirus") ||
url.contains("v3mobile") ||
url.contains(".apk") ||
url.contains("mvaccine") ||
url.contains("smartwall://") ||
url.contains("nidlogin://") ||
url.contains("onestore://") ||
url.contains("http://m.ahnlab.com/kr/site/download")
) {
var intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME)

if (view?.context?.packageManager?.resolveActivity(intent, 0) == null) {
val packageName = intent.`package`
if (packageName != null) {
val marketUri = Uri.parse("market://search?q=pname:$packageName")
intent = Intent(Intent.ACTION_VIEW, marketUri)
view.context.startActivity(intent)
}
} else {
val intentUri = Uri.parse(intent.dataString)
intent = Intent(Intent.ACTION_VIEW, intentUri)
view?.context?.startActivity(intent)
}
} else {
view?.loadUrl(url)
}
} catch (e: Exception) {
e.printStackTrace()
return false
}

return true
}
}

4. Android Java 연동

4.1. 지원 환경

  • Android 4.4 (KITKAT) 이상

4.2. AndroidManifest.xml

AndroidManifest.xml의 queries, INTERNET 권한, 네트워크 보안 정책은 Kotlin 연동의 AndroidManifest.xml 설정과 동일하게 적용합니다.

4.3. WebView 기본 설정

public class WebViewActivity extends Activity {
private static final String MERCHANT_URL = "https://{가맹점결제요청페이지URL}";
private WebView mWebView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_webview);

mWebView = findViewById(R.id.webview);
mWebView.setWebViewClient(new WebViewClientClass());

mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setDomStorageEnabled(true);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
mWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.setAcceptThirdPartyCookies(mWebView, true);

mWebView.postUrl(MERCHANT_URL, null);
}
}
캐시 설정 주의

WebSettings.LOAD_CACHE_ELSE_NETWORK 사용 시 일부 카드사 세션 오류가 발생할 수 있습니다. WebView 캐시 모드는 기본값인 WebSettings.LOAD_DEFAULT 사용을 권장합니다.

4.4. URI / Intent 처리

private class WebViewClientClass extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
String url = request.getUrl().toString();

try {
if (
url.startsWith("intent:") ||
url.contains("market://") ||
url.contains("vguard") ||
url.contains("droidxantivirus") ||
url.contains("v3mobile") ||
url.contains(".apk") ||
url.contains("mvaccine") ||
url.contains("smartwall://") ||
url.contains("nidlogin://") ||
url.contains("onestore://") ||
url.contains("http://m.ahnlab.com/kr/site/download")
) {
Intent intent;

try {
intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
} catch (URISyntaxException e) {
e.printStackTrace();
return false;
}

if (getPackageManager().resolveActivity(intent, 0) == null) {
String packageName = intent.getPackage();
if (packageName != null) {
Uri marketUri = Uri.parse("market://search?q=pname:" + packageName);
intent = new Intent(Intent.ACTION_VIEW, marketUri);
startActivity(intent);
}
} else {
Uri intentUri = Uri.parse(intent.getDataString());
intent = new Intent(Intent.ACTION_VIEW, intentUri);
startActivity(intent);
}
} else {
view.loadUrl(url);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}

return true;
}
}

5. iOS Swift 연동

5.1. 지원 환경

  • iOS 9.0 이상
  • Xcode 7.x 이상
  • Swift 4.0 이상

5.2. URL Scheme 설정

  1. 가맹점 앱 URL SchemeInfo.plistURL Types에 스킴 등록 (결제 요청 WapUrl과 동일, 예: nicepaysample://)
  2. 3rd 앱 URL SchemeInfo.plistLSApplicationQueriesSchemes에 카드사·간편결제 스킴 등록 (미등록 시 canOpenURL 실패)
  3. 네트워크 보안 — HTTP 또는 유효하지 않은 인증서의 HTTPS 접속이 필요한 경우 NSAppTransportSecurity 예외 설정. Apple은 특정 도메인만 예외 처리를 권장합니다.

가맹점 앱 URL Scheme 등록

결제 요청 전문의 WapUrl 필드 값으로 사용할 가맹점 앱 URL Scheme을 등록합니다. 미등록 시 일부 3rd 앱에서 인증 또는 결제 완료 후 가맹점 앱으로 자동 전환되지 않을 수 있습니다.

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>kr.co.nicepay.swift.NicepayAppSample</string>
<key>CFBundleURLSchemes</key>
<array>
<string>nicepaysample</string>
</array>
</dict>
</array>

3rd 앱 URL Scheme 등록

가맹점 앱에서 카드사, 간편결제, 계좌이체, 본인인증 앱을 호출하려면 LSApplicationQueriesSchemes에 3rd 앱 scheme을 등록합니다.

<key>LSApplicationQueriesSchemes</key>
<array>
<string>kftc-bankpay</string>
<string>ispmobile</string>
<string>shinhan-sr-ansimclick</string>
<string>smshinhanansimclick</string>
<string>hdcardappcardansimclick</string>
<string>smhyundaiansimclick</string>
<string>mpocket.online.ansimclick</string>
<string>scardcertiapp</string>
<string>cloudpay</string>
<string>nhappcardansimclick</string>
<string>nonghyupcardansimclick</string>
<string>kb-acp</string>
<string>lotteappcard</string>
<string>lottesmartpay</string>
<string>citispay</string>
<string>shinsegaeeasypayment</string>
<string>kakaotalk</string>
<string>kakaobank</string>
<string>tswansimclick</string>
<string>nhallonepayansimclick</string>
<string>citimobileapp</string>
<string>payco</string>
<string>hanaskcardmobileportal</string>
<string>wooripay</string>
<string>com.wooricard.wcard</string>
<string>lpayapp</string>
<string>hanawalletmembers</string>
<string>tauthlink</string>
<string>ktauthexternalcall</string>
<string>upluscorporation</string>
<string>liivbank</string>
<string>kb-bankpay</string>
<string>naversearchthirdlogin</string>
<string>lmslpay</string>
<string>newliiv</string>
<string>NewSmartPib</string>
<string>kbbank</string>
<string>ukbanksmartbanknonloginpay</string>
<string>monimopay</string>
<string>monimopayauth</string>
<string>qhanamopmoasign</string>
<string>supertoss</string>
<string>coupang</string>
<string>rocketpay</string>
</array>

네트워크 보안 예외 설정

HTTP 또는 유효하지 않은 인증서를 가진 HTTPS 연결이 필요한 경우에만 예외를 설정합니다. Apple은 전체 허용보다 특정 도메인 단위 예외 처리를 권장합니다.

<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

5.3. 결제 페이지 호출 (WKWebView)

override func viewDidLoad() {
super.viewDidLoad()
title = "구매하기"

webView = WKWebView(frame: self.view.frame)
webView?.navigationDelegate = self
webView?.uiDelegate = self
self.view.addSubview(webView!)

let url = URL(string: PAY_URL)! // 가맹점 결제 요청 URL
let request = URLRequest(url: url)
webView?.load(request)
}

5.4. URL Scheme / 3rd 앱 호출

URL에 포함된 App Scheme을 확인해 3rd 앱을 호출합니다. ISP 또는 BANKPAY 앱이 미설치된 경우 App Store로 이동하도록 처리합니다.

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
let request = navigationAction.request
let optUrl = request.url
let optUrlScheme = optUrl?.scheme

guard let url = optUrl, let scheme = optUrlScheme else {
decisionHandler(.cancel)
return
}

debugPrint("url : \(url)")

if scheme != "http" && scheme != "https" {
if scheme == "ispmobile" && !UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(
URL(string: "https://itunes.apple.com/kr/app/id369125087?mt=8")!,
options: [:],
completionHandler: nil
)
} else if scheme == "kftc-bankpay" && !UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(
URL(string: "https://itunes.apple.com/us/app/id398456030?mt=8")!,
options: [:],
completionHandler: nil
)
} else if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
} else {
// 1. App 미설치 여부 확인
// 2. Info.plist 내 scheme 등록 여부 확인
}
}

decisionHandler(.allow)
}

5.5. JavaScript alert

func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String,
initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
let alert = UIAlertController(title: "", message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "확인", style: .default) { _ in
completionHandler()
})
present(alert, animated: true, completion: nil)
}

6. iOS Objective-C 연동

6.1. 지원 환경

  • iOS 9.0 이상
  • Xcode 7.x 이상

6.2. URL Scheme 설정

Objective-C 연동도 Swift 연동과 동일하게 Info.plist에 가맹점 앱 URL Scheme, 3rd 앱 URL Scheme, 네트워크 보안 예외를 설정합니다.

가맹점 앱 URL Scheme 등록

<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>kr.co.testApp.sample</string>
<key>CFBundleURLSchemes</key>
<array>
<string>nicepaysample</string>
</array>
</dict>
</array>

3rd 앱 호출을 위한 LSApplicationQueriesSchemesNSAppTransportSecurity 설정은 Swift 연동의 URL Scheme 설정을 동일하게 적용합니다.

6.3. 결제 페이지 로드

- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"구매하기";

self.webView = [[[WKWebView alloc] init] autorelease];
self.webView.navigationDelegate = self;
self.webView.UIDelegate = self;
[self.view addSubview:self.webView];

[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:PAY_URL]]];
}

6.4. URL Scheme / 3rd 앱 호출

URL에 포함된 App Scheme을 확인해 3rd 앱을 호출합니다. ISP 또는 BANKPAY 앱이 미설치된 경우 App Store로 이동하도록 처리합니다.

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
NSURLRequest *request = navigationAction.request;
NSURL *url = [request URL];
NSString *urlScheme = [url scheme];

NSLog(@"url : %@", url);

if (![urlScheme isEqualToString:@"http"] && ![urlScheme isEqualToString:@"https"]) {
if ([urlScheme isEqualToString:@"ispmobile"] && ![[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://itunes.apple.com/kr/app/id369125087?mt=8"]
options:@{}
completionHandler:nil];
} else if ([urlScheme isEqualToString:@"kftc-bankpay"] && ![[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://itunes.apple.com/us/app/id398456030?mt=8"]
options:@{}
completionHandler:nil];
} else if ([[UIApplication sharedApplication] canOpenURL:url]) {
[[UIApplication sharedApplication] openURL:url
options:@{}
completionHandler:nil];
} else {
// 1. App 미설치 여부 확인
// 2. Info.plist 내 scheme 등록 여부 확인
}
}

decisionHandler(WKNavigationActionPolicyAllow);
}

6.5. JavaScript alert

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message
initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil
message:message
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"확인"
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
completionHandler();
}]];
[self presentViewController:alertController animated:YES completion:^{}];
}

7. 체크리스트

항목AndroidiOS
Web 결제·ReturnURL 구성
JavaScript / DOM Storage 활성화WKWebView 기본
캐시 모드 기본값 유지
3rd 앱 호출 (Intent / openURL)
WapUrl / IspCancelUrl
가맹점·3rd URL Scheme
운영 결제 URL 적용

8. 관련 문서