React Native 웹뷰앱에서 토스 페이먼츠 구현하기

React Native 웹뷰앱에서 토스 페이먼츠 구현하기

이번에 회사에서 토스 페이먼츠를 이용하여 웹사이트를 구현했는데, 웹뷰앱에서는 주문 -> 직접 수동으로 토스앱으로 이동 -> 결제 -> 다시 본인 앱으로 돌아와야 하는 프로세스 때문에, 웹뷰앱에서 토스 페이먼츠 앱으로 전환되게 하기 위해 이것저것 알아보면서 코드를 작성했다.

우선, 기존에는 안드로이드 웹뷰로 실행할 때, 애플 웹뷰로 실행할 때, 구글 로그인을 하기 위해 UserAgent를 커스텀으로 넣었는데,
그걸 안드로이드 UserAgent로 넣었던게 문제가 되어서 우선 애플 UserAgent와 안드로이드 UserAgent를 각각 적용했다.

주의: 안드로이드는 토스앱을 깔 수 있는 기기가 없어서 테스트 안해봄!

우선, 앱 전환을 위해 토스 페이먼츠 사이트를 참고하여 @toss-payments/widget-sdk-react-natvie 패키지를 설치했다.

$ yarn add @toss-payments/widget-sdk-react-native

웹뷰가 있는 App.tsx에 urlConverter 함수 생성 후 onShouldStartLoadWithRequest에 사용

const urlConverter = (url: string) => {
  const convertUrl = new ConvertUrl(url); // Intent URL을 앱 스킴 URL로 변환

  if (convertUrl.isAppLink()) {
    convertUrl.launchApp().then((isLaunch) => {
      if (!isLaunch) {
      }
    });
    return false;
  } else {
    return true;
  }
};

export default function App() {
  ...중략...
  const onShouldStartLoadWithRequest = (event: ShouldStartLoadRequest) => {
    if (webViewRef.current) {
      if (event.url.startsWith("intent://")) {
        urlConverter(event.url);
        return false;
      } else {
        return true;
      }
    }

    return true;
  };

ios 폴더의 Info.plist에 결제앱 scheme 추가

<dict>
  <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>
  </array>
  ...중략...
</dict>

android 폴더의 AndroidManifest.xml에 결제앱 package name 추가

<queries>
    <!-- 안드로이드 토스 앱 연결 -->
    <package android:name="com.kakao.talk" /> <!-- 카카오톡 -->
    <package android:name="com.nhn.android.search" /> <!-- 네이버페이 -->
    <package android:name="com.samsung.android.spay" /> <!-- 삼성페이 -->
    <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.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, 현대) -->
</queries>

이렇게까지만 작성하고 빌드 후 실행해주면 앱에서 토스앱으로 잘 넘어가는 것을 볼 수 있다.
토스앱에서 결제 이후에 내 앱으로 돌아오는 것까지 작업하기 위해 appScheme 등록하는 것 까지 알아보았다.

안드로이드의 경우 아래 내용 추가

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="스키마이름" android:host="스키마뒤에들어갈이름" />
</intent-filter>

아이폰의 경우 아래 내용 추가

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLName</key>
    <string>앱식별자</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>스키마명</string>
    </array>
  </dict>
</array>

이후 토스 페이먼츠 코드에서 requestPayment 함수에 appScheme에 스키마명을 넣어주면 된다

tossPayments.requestPayment('CARD', {
  orderId: orderId,
  orderName: orderName,
  successUrl: `${process.env.SUCCESS_URL}`,
  failUrl: `${process.env.FAIL_URL}`,
  amount: amount,
  forceFailure: false,
  windowTarget: 'self',
  appScheme: 'schema://', // 여기 'schema'부분에 스키마명을 넣어준다
});

참고 문서
[https://docs.tosspayments.com/guides/webview#converturl-1]
[https://docs.tosspayments.com/reference/widget-sdk#requestpayment%EA%B2%B0%EC%A0%9C-%EC%A0%95%EB%B3%B4]
[https://velog.io/@mywonhyuni/%EA%B8%B0%EB%8A%A5%EA%B5%AC%ED%98%84RN-Deep-link%EB%A5%BC-%EC%88%98%EC%8B%A0-%ED%9B%84-%EC%95%B1-%ED%8A%B9%EC%A0%95-%ED%8E%98%EC%9D%B4%EC%A7%80%EB%A1%9C-redirect-%ED%95%98%EA%B8%B0]

+ Recent posts