Version 1
SDK v1은 더 이상 업데이트되지 않습니다. 토스페이먼츠 SDK v2 연동을 추천합니다.
✅ 모바일 웹뷰에서 카드 결제창으로 이동할 때 필요한 외부 앱(3rd-party 앱)을 연동하는 과정을 알 수 있어요.
✅ 연동에 필요한 외부 앱 스킴(App URL Scheme) 목록과 로직을 이해할 수 있어요.
웹뷰는 다음과 같이 사용할 수 있습니다.
- 주문 정보를 작성하고 결제창을 호출합니다.
- 카드사를 선택하고 다음 단계로 이동합니다.
- 선택한 카드사·은행의 결제 앱이 열립니다. 외부 앱이 실행되는 시점입니다.
- 결제 정보를 입력하고 결제를 완료합니다.
- 상점의 결제 페이지로 돌아옵니다.
- 앱 스킴(
appScheme
) 파라미터를 추가하면 별도의 처리 없이도 외부 앱에서 상점 앱으로 돌아올 수 있습니다. 결제 요청 파라미터를 참고하세요.
여기서는 3번 단계에서 외부 앱을 여는 방법을 다룹니다. 웹뷰에서 각 은행의 결제 앱을 실행시키면서 앱 간 일어나는 이동(App to App)입니다.
내 상점 앱에서 인증을 위해 이동하게 되는 3rd-party 앱에는 ISP 앱, 카드사별 앱카드 등이 있습니다. 필요한 앱스킴을 추가해보세요.
카드사·본인확인기관 | 앱스킴 |
---|---|
토스페이 | supertoss:// |
국민카드 | kb-acp:// , liivbank:/ , newliiv:// , kbbank:// |
농협카드 | nhappcardansimclick:// , nhallonepayansimclick:// , nonghyupcardansimclick:// |
롯데카드 | lottesmartpay:// , lotteappcard:// |
삼성카드 | mpocket.online.ansimclick:// , vguardstart:// , samsungpay:// ,monimopay:// , monimopayauth:// |
신한카드 | shinhan-sr-ansimclick:// , smshinhanansimclick:// |
우리카드 | com.wooricard.wcard:// , newsmartpib:// |
씨티카드 | citispay:// , citicardappkr:// , citimobileapp:// |
하나카드 | cloudpay:// , hanawalletmembers:// |
현대카드 | hdcardappcardansimclick:// , smhyundaiansimclick:// |
간편결제 | shinsegaeeasypayment:// , payco:// , lpayapp:// |
ISP(BC/국민) | ispmobile:// |
카카오뱅크 | kakaobank:// |
먼저 AndroidManifest.xml
파일에 카드앱·은행앱 패키지를 등록합니다. 패키지를 등록하지 않으면 앱이 설치되어 있어도 스토어로 이동하고, Google 정책을 위반하게 됩니다.
// AndroidManifest.xml
<queries>
<package android:name="com.kakao.talk" /> <!-- 카카오톡 -->
<package android:name="com.nhn.android.search" /> <!-- 네이버페이 -->
<package android:name="com.samsung.android.spay" /> <!-- 삼성페이 -->
<package android:name="net.ib.android.smcard" /> <!-- 모니모페이 -->
<package android:name="com.mobiletoong.travelwallet" /> <!-- 신한카드 트레블월렛 -->
<package android:name="com.samsung.android.spaylite" /> <!-- 삼성페이 -->
<package android:name="com.ssg.serviceapp.android.egiftcertificate" /> <!-- SSGPAY -->
<package android:name="com.nhnent.payapp" /> <!-- PAYCO -->
<package android:name="com.lottemembers.android" /> <!-- L.POINT -->
<package android:name="viva.republica.toss" /> <!-- 토스-->
<package android:name="com.shinhan.smartcaremgr" /> <!-- 신한 슈퍼SOL -->
<package android:name="com.shinhan.sbanking" /> <!-- 신한 SOL뱅크 -->
<package android:name="com.shcard.smartpay" /> <!-- 신한페이판 -->
<package android:name="com.shinhancard.smartshinhan" /> <!-- 신한페이판-공동인증서 -->
<package android:name="com.hyundaicard.appcard" /> <!-- 현대카드 -->
<package android:name="com.lumensoft.touchenappfree" /> <!-- 현대카드-공동인증서 -->
<package android:name="kr.co.samsungcard.mpocket" /> <!-- 삼성카드 -->
<package android:name="nh.smart.nhallonepay" /> <!-- 올원페이 -->
<package android:name="com.kbcard.cxh.appcard" /> <!-- KB Pay -->
<package android:name="com.kbstar.liivbank" /> <!-- Liiv(KB국민은행) -->
<package android:name="com.kbstar.reboot" /> <!-- Liiv Reboot(KB국민은행) -->
<package android:name="com.kbstar.kbbank" /> <!-- 스타뱅킹(KB국민은행) -->
<package android:name="kvp.jjy.MispAndroid320" /> <!-- ISP/페이북 -->
<package android:name="com.lcacApp" /> <!-- 롯데카드 -->
<package android:name="com.hanaskcard.paycla" /> <!-- 하나카드 -->
<package android:name="com.hanaskcard.rocomo.potal" /> <!--하나카드-->
<package android:name="kr.co.hanamembers.hmscustomer" /> <!-- 하나멤버스 -->
<package android:name="kr.co.citibank.citimobile" /> <!-- 씨티모바일 -->
<package android:name="com.wooricard.wpay" /> <!-- 우리페이 -->
<package android:name="com.wooricard.smartapp" /> <!-- 우리카드 -->
<package android:name="com.wooribank.smart.npib" /> <!-- 우리WON뱅킹 -->
<package android:name="com.lguplus.paynow" /> <!-- 페이나우 -->
<package android:name="com.kftc.bankpay.android" /> <!-- 뱅크페이 -->
<package android:name="com.TouchEn.mVaccine.webs" /> <!-- TouchEn mVaccine (신한) -->
<package android:name="kr.co.shiftworks.vguardweb" /> <!-- V-Guard (삼성) -->
<package android:name="com.ahnlab.v3mobileplus" /> <!-- V3 (NH, 현대) -->
<package android:name="com.kakaobank.channel" /> <!-- 카카오뱅크 -->
</queries>
AndroidManifest.xml
파일에 필요한 앱스킴을 추가했다면, 앱 간 이동에 필요한 아래 코드를 살펴보세요.
WebViewClient의 shouldOverrideUrlLoading
함수에 오버라이딩 로직을 추가하세요.
추가하지 않으면 웹뷰에서 외부 앱을 호출하거나 마켓(market://
)으로 연결할 때 net::ERR_UNKNOWN_URL_SCHEME
에러가 발생합니다.
// API 수준 24 이상을 위한 메서드
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
val url = request.url.toString()
return handleUrl(url)
}
// (선택) API 수준 24 미만을 타게팅 하려면 다음 코드를 추가해 주세요
@Deprecated("Deprecated in Java")
@Suppress("DEPRECATION")
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
return handleUrl(url)
}
return super.shouldOverrideUrlLoading(view, url)
}
// 공통 URL 처리 로직
private fun handleUrl(url: String): Boolean {
if (!URLUtil.isNetworkUrl(url) && !URLUtil.isJavaScriptUrl(url)) {
val uri = try {
Uri.parse(url)
} catch (e: Exception) {
return false
}
return when (uri.scheme) {
"intent" -> {
startSchemeIntent(url)
}
else -> {
return try {
startActivity(Intent(Intent.ACTION_VIEW, uri))
true
} catch (e: Exception) {
false
}
}
}
} else {
return false
}
}
private fun startSchemeIntent(url: String): Boolean {
val schemeIntent: Intent = try {
Intent.parseUri(url, Intent.URI_INTENT_SCHEME)
} catch (e: URISyntaxException) {
return false
}
try {
startActivity(schemeIntent)
return true
} catch (e: ActivityNotFoundException) {
val packageName = schemeIntent.getPackage()
if (!packageName.isNullOrBlank()) {
startActivity(
Intent(
Intent.ACTION_VIEW,
Uri.parse("market://details?id=$packageName")
)
)
return true
}
}
return false
}
위와 같이 구현하기 어려우면 패키지 공개 상태 관리 대응을 확인해보세요.
먼저 Info.plist
에 LSApplicationQueriesSchemes 를 추가하고 카드사, 은행의 앱스킴을 배열에 넣어 주세요. 설정하지 않으면, 앱이 열리지 않고 콘솔 쪽에 canOpenURL : failed for URL
에러가 발생합니다.
//Info.plist
<key>LSApplicationQueriesSchemes</key>
<array>
<string>supertoss</string>
<string>kb-acp</string>
<string>liivbank</string>
<string>newliiv</string>
<string>kbbank</string>
<string>nhappcardansimclick</string>
<string>nhallonepayansimclick</string>
<string>nonghyupcardansimclick</string>
<string>lottesmartpay</string>
<string>lotteappcard</string>
<string>mpocket.online.ansimclick</string>
<string>ansimclickscard</string>
<string>tswansimclick</string>
<string>ansimclickipcollect</string>
<string>vguardstart</string>
<string>samsungpay</string>
<string>scardcertiapp</string>
<string>shinhan-sr-ansimclick</string>
<string>smshinhanansimclick</string>
<string>com.wooricard.wcard</string>
<string>newsmartpib</string>
<string>citispay</string>
<string>citicardappkr</string>
<string>citimobileapp</string>
<string>cloudpay</string>
<string>hanawalletmembers</string>
<string>hdcardappcardansimclick</string>
<string>smhyundaiansimclick</string>
<string>shinsegaeeasypayment</string>
<string>payco</string>
<string>lpayapp</string>
<string>ispmobile</string>
<string>tauthlink</string>
<string>ktauthexternalcall</string>
<string>upluscorporation</string>
<string>kftc-bankpay</string>
<string>kakaotalk</string>
<string>wooripay</string>
<string>lmslpay</string>
<string>naversearchthirdlogin</string>
<string>hanaskcardmobileportal</string>
<string>kb-bankpay</string>
<string>kakaobank</string>
</array>
XCode에 필요한 앱스킴을 추가했다면, 앱 간(App to App) 이동에 필요한 아래 코드를 살펴보세요.
웹뷰에서 URL이 변경될 때 페이지 전환 대신 내 상점의 앱스킴을 실행시키려면 WKNavigationDelegate protocol 중 아래 코드에 해당하는 메서드를 구현해야 합니다.
func webView(
_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void
) {
if let url = navigationAction.request.url,
url.scheme != "http" && url.scheme != "https" {
UIApplication.shared.open(url, options: [:], completionHandler:{ (success) in
if !(success){
/*앱이 설치되어 있지 않을 때*/
}
})
decisionHandler(.cancel)
} else {
decisionHandler(.allow)
}
}
pubspec.yaml
파일에 가장 최신 버전의 토스페이먼츠 플러그인을 추가해주세요.
dependencies:
tosspayments_widget_sdk_flutter: ^0.X.X
webview_flutter
를 사용하고 있다면 webview_flutter_android
는 3.16.0 이하 버전만 사용해주세요. 이후 버전부터는 안드로이드 환경에서 특정 카드앱이 호출되지 않는 문제가 발생합니다.
Flutter 웹뷰에서는 Intent URL을 앱스킴 URL로 변환해야 카드사 앱으로 이동합니다. 아래 예시와 같이 tossPaymentsWebview()
함수를 정의해서 사용하세요.
import 'package:tosspayments_widget_sdk_flutter/model/tosspayments_url.dart';
tossPaymentsWebview(url) {
final appScheme = ConvertUrl(url); // Intent URL을 앱스킴 URL로 변환
if (appScheme.isAppLink()) { // 앱스킴 URL인지 확인
appScheme.launchApp(mode: LaunchMode.externalApplication); // 앱 설치 상태에 따라 앱 실행 또는 마켓으로 이동
return NavigationDecision.prevent;
}
}
ConvertUrl (url : String)
- url
앱스킴 형태로 변환하고 싶은 Intent 스킴 URL입니다. 예를 들어
intent:appScheme://...#Intent;...;end;
형태의 Intent URL이appScheme://...
형태의 앱스킴 URL로 바뀝니다.
npm 또는 yarn으로 토스페이먼츠 결제위젯 React Native SDK를 설치하세요.
# npm
npm install @tosspayments/widget-sdk-react-native
# yarn
yarn add @tosspayments/widget-sdk-react-native
React Native 웹뷰에서는 Intent URL을 앱스킴 URL로 변환해야 카드사 앱으로 이동합니다. 아래 예시와 같이 urlConverter()
함수를 정의해서 사용하세요.
import { ConvertUrl } from "@tosspayments/widget-sdk-react-native/src/utils/convertUrl";
const urlConverter = (url: string) => {
const convertUrl = new ConvertUrl(url); // Intent URL을 앱스킴 URL로 변환
if (convertUrl.isAppLink()) {
// 앱스킴 URL인지 확인
convertUrl.launchApp().then((isLaunch) => {
// 앱 설치 상태에 따라 카드사 앱 실행 또는 앱마켓으로 이동
if (isLaunch === false) {
// 앱 실행 실패 시 처리 로직
}
});
} else {
return true;
}
};
class ConvertUrl {
url: string;
appScheme?: string;
appLink?: string;
package?: string;
}
- url
앱스킴 형태로 변환하고 싶은 Intent 스킴 URL입니다. 예를 들어
intent:appScheme://...#Intent;...;end;
형태입니다. - appScheme
url
의 앱스킴입니다. - appLink
url
의 앱스킴 링크입니다. 예를 들어appScheme://...
형태입니다. - package
url
의 앱 패키지 정보입니다.