ここでは、モバイル SDK を利用してトークン作成時に 3Dセキュアを導入する方法について説明します。
3Dセキュアの概要については、下記ドキュメントをご覧ください。
リダイレクト URL を設定する(各 SDK 共通)
まずはじめに、管理画面 > API設定 > 3Dセキュア からリダイレクト URL を設定します。
モバイル SDK では、カード会社が提供する 3Dセキュア認証画面を表示するためにブラウザアプリを利用します。 認証を実施した後、モバイルアプリで再度処理を継続するためにリダイレクト URL とその識別子を登録します(ここで設定した URL と識別子は実装に利用します)。
URL スキームは HTTPS 以外にカスタム URL スキームを利用できます。 HTTPS スキームの URL の場合、iOS では Universal Link、Android では App Links の設定を行ってください。

3Dセキュア開始方法
各 SDK でカードフォーム開始時にオプションを指定することで、トークン作成時に 3Dセキュアを開始できます。
また、管理画面 > API設定 > 3Dセキュア よりトークン 3Dセキュアの実施モードを指定することで、パラメーターを指定することなく全てのトークン作成に 3Dセキュアを必須にすることが可能です。
管理画面でトークン 3Dセキュアを実施するモードが有効になっている場合、たとえ SDK でカードフォーム開始時に 3Dセキュアを実施しないオプションを指定しても、3Dセキュアは実施されます。
管理画面でのモード | SDK でのオプション( useThreeDSecure ) |
トークン作成時の3Dセキュア |
---|---|---|
有効 | true |
実施 |
有効 | false |
実施 |
無効 | true |
実施 |
無効 | false |
実施されない |
ここから先の設定方法は、各 SDK によって異なります。利用する SDK に合わせて設定を追加してください。
payjp-iosの場合
XcodeでURLスキームを設定する
管理画面で追加したリダイレクト URL の設定に合わせて、アプリにも URL スキームの設定をします。
参考: Defining a Custom URL Scheme for Your App | Apple Developer Documentation
Xcode を開き、プロジェクト設定でアプリのターゲットを選択し Info
タブに切り替えます。 URL Types
という項目の +
ボタンからスキーム設定を追加し、管理画面で登録したリダイレクト URL のスキームを設定します。
たとえば、リダイレクト URL が jp.pay.example://tds/finish
の場合、以下のように jp.pay.example
を設定します。

リダイレクトURLを登録する
管理画面で指定したリダイレクト URL と識別子を登録します。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
PAYJPSDK.publicKey = YourPayjpPublicKey
PAYJPSDK.locale = Locale.current
PAYJPSDK.threeDSecureURLConfiguration =
ThreeDSecureURLConfiguration(redirectURL: URL(string: "jp.pay.example://tds/finish")!,
redirectURLKey: "mobileapp")
return true
}
カスタム URL スキームによってアプリが起動された際、 ThreeDSecureProcessHandler
の completeThreeDSecureProcess(url:)
を呼び出すことで、認証フローを完了します。
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return ThreeDSecureProcessHandler.shared.completeThreeDSecureProcess(url: url)
}
カード所有者を 3Dセキュアに誘導する
カードフォーム画面を利用している場合
CardFormViewController.createCardFormViewController()
を利用してカードフォーム画面を呼び出している場合は、SDK が自動的にハンドリングするため、カードフォーム開始時に 3Dセキュアの実施を指定するのみです。
let cardFormViewController = CardFormViewController.createCardFormViewController(
delegate: self,
useThreeDSecure: true
)
それ以外の場合
3Dセキュアの認証を実施するには、 createToken
の引数 useThreeDSecure
に true
を指定します。
createToken
によって取得した Token
の Token.card.threeDSecureStatus
が .unverified
の場合、3Dセキュアの認証を開始してください。
まず、 ThreeDSecureProcessHandler.startThreeDSecureProcess(viewController:delegate:token:)
の第3引数に取得した Token
を渡します。
これにより、SDK はブラウザを開きカード所有者を認証画面へと誘導します。認証が完了、失敗、またはキャンセルによって終了するまで、SDK によるトークン作成処理は中断状態となります。
self.cardFormView.createToken(useThreeDSecure: true) { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let token):
if tdsStatus = token.card.threeDSecureStatus, status == .unverified {
ThreeDSecureProcessHandler.shared.startThreeDSecureProcess(viewController: self,
delegate: self,
token: token)
} else {
// 取得したトークンを扱う
self.onSuccess(token)
}
case .failure(let error):
// エラー処理
}
}
}
認証が終了し、リダイレクト URL によって ThreeDSecureProcessHandler.completeThreeDSecureProcess(url:)
が呼び出されることで、SDK は認証フローの終了を検知します。 ThreeDSecureProcessHandlerDelegate
をアプリの ViewController に適合し、 threeDSecureProcessHandlerDidFinish(_:status:)
で受け取る ThreeDSecureProcessStatus
に応じてトークン作成処理を完了させてください。
public func threeDSecureProcessHandlerDidFinish(_ handler: ThreeDSecureProcessHandler,
status: ThreeDSecureProcessStatus) {
switch status {
case .completed:
// 3DSの処理を完了する
completeTokenTds()
case .canceled:
// UI更新など
default:
break
}
}
ThreeDSecureProcessStatus
が .completed
の場合、先に取得した Token
を利用して認証済みの Token
を取得できます。 APIClient.finishTokenThreeDSecure(tokenId:completion:)
を利用して再取得を行ってください。
let completion: (Result<Token, APIError>) -> Void = { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let token):
self.onSuccess(token)
case .failure(let error):
self.onFailure(error)
}
}
if let token = self.pendingToken {
APIClient.shared.finishTokenThreeDSecure(tokenId: token.identifer, completion: completion)
}
以上でトークン作成時に 3Dセキュアを要求する iOS の実装は完了です。
payjp-androidの場合
リダイレクトURLを登録する
管理画面で指定したリダイレクト URL と識別子を登録します。
Payjp.init(PayjpConfiguration.Builder(YOUR_PUBLIC_KEY)
.setThreeDSecureRedirectName("mobileapp") // URLではなく識別子を登録します
.build())
AndroidManifest.xmlにIntentFilterを追加する
アプリの AndroidManifest.xml
に管理画面で指定したリダイレクト URL を追加します。アクティビティとして jp.pay.android.verifier.ui.PayjpThreeDSecureStepActivity
を追加し、IntentFilter
を設定します。
たとえば、リダイレクト URL が my-app://tds/complete
の場合、以下のように記述します。
<activity android:name="jp.pay.android.verifier.ui.PayjpThreeDSecureStepActivity">
<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="my-app" android:host="tds" android:path="complete" />
</intent-filter>
</activity>
カード所有者を3Dセキュアに誘導する
カードフォーム画面を利用している場合
Payjp.cardForm().start()
を利用してカードフォーム画面を呼び出している場合は、SDK が自動的にハンドリングするため、カードフォーム開始時に 3Dセキュアの実施を指定するのみです。
Payjp.cardForm().start(
activity = this,
face = PayjpCardForm.FACE_MULTI_LINE,
extraAttributes = arrayOf(ExtraAttribute.Email()),
useThreeDSecure = true,
)
それ以外の場合
3Dセキュアの認証を実施するには、 createToken
の引数に useThreeDSecure = true
を指定します。
createToken
によって取得した Token
の Token.card.threeDSecureStatus
が UNVERIFIED
のとき、3Dセキュアの認証を開始してください。
まず、 Token.retrieveId()
で得られる TokenId
を、 Payjp.verifier().startThreeDSecureFlow(TokenId, Activity)
の第1引数に渡します。
これにより、SDK はブラウザを開きカード所有者を認証画面へと誘導します。認証が完了、失敗、またはキャンセルによって終了するまで、SDK によるトークン作成処理は中断状態となります。
以下の例は PayjpCardFormFragment#createToken
を利用した場合です。
cardFormFragment.createToken(useThreeDSecure = true).enqueue(object : Task.Callback<Token> {
override fun onSuccess(data: Token) {
if (data.card.threeDSecureStatus == ThreeDSecureStatus.UNVERIFIED) {
Payjp.verifier()
.startThreeDSecureFlow(data.retrieveId(), this@SampleActivity)
} else {
sendTokenToServer(token: data)
}
}
override fun onError(throwable: Throwable) {
updateUI(throwable)
}
})
認証が終了すると、Payjp.verifier().startThreeDSecureFlow(TokenId, Activity)
の第2引数に渡した呼び出し元の Activity(または Fragment)で onActivityResult
に結果を受け取ります。
Payjp.verifier().handleThreeDSecureResult(requestCode, callback)
を使って認証フローの結果を取り出し、コールバックで渡される PayjpThreeDSecureResult
に応じて処理を再開してください。 PayjpThreeDSecureResult#isSuccess()
が true の場合は認証フローが完了していることを表します。
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Payjp.verifier().handleThreeDSecureResult(requestCode) { result ->
if (result.isSuccess()) {
this.onCompleteTds(result)
} else {
Toast.makeText(this, "3-D Secure canceled.", Toast.LENGTH_SHORT).show()
}
}
}
3Dセキュアの認証に成功した場合、Payjp.verifier().completeTokenThreeDSecure(result)
で認証済みの Token
を取得します。
if (!result.isSuccess()) {
return
}
Payjp.token().completeTokenThreeDSecure(result)
.enqueue(object : Task.Callback<Token> {
override fun onSuccess(data: Token) {
Log.i("PAY.JP", "token => $data")
}
override fun onError(throwable: Throwable) {
Log.e("PAY.JP", "failure getting token", throwable)
}
})
以上でトークン作成時に 3Dセキュアを要求する Android の実装は完了です。
payjp-react-native-pluginの場合
カードフォーム画面を利用する方法以外はサポートしていません。
各プラットフォームごとにリダイレクトの設定をする
iOS では、payjp-ios同様、XcodeでURLスキームを設定します。 Android では、payjp-android同様、AndroidManifest.xmlにIntentFilterを追加します。
リダイレクトURLを登録する
管理画面で設定したリダイレクト URL と識別子を登録します。
PayjpCore#init
の引数となるオブジェクトに threeDSecureRedirect
というキーで下記のように URL と識別子を指定してください。
PayjpCore.init({
publicKey: YOUR_PUBLIC_KEY,
threeDSecureRedirect: {
url: "jp.pay.example://tds/finish",
key: "mobileapp",
},
});
カードフォーム開始時に 3Dセキュアの実施を指定する
PayjpCardForm.startCardForm()
の引数となる CardFormOption
オブジェクトに useThreeDSecure
というキーで true
を指定してください。
PayjpCardForm.startCardForm({
useThreeDSecure: true
});
payjp-flutter-pluginの場合
カードフォーム画面を利用する方法以外はサポートしていません。
各プラットフォームごとにリダイレクトの設定をする
iOS では、payjp-ios同様、XcodeでURLスキームを設定します。 Android では、payjp-android同様、AndroidManifest.xmlにIntentFilterを追加します。
リダイレクトURLを登録する
管理画面で設定したリダイレクト URL と識別子を登録します。
Payjp#init
の引数となるオブジェクトに threeDSecureRedirect
というキーで下記のように URL と識別子を指定してください。
Future<void> _initPayjp() async {
await Payjp.init(
publicKey: YOUR_PUBLIC_KEY,
threeDSecureRedirect: PayjpThreeDSecureRedirect(
url: 'jp.pay.example://tds/finish', key: 'mobileapp'));
}
カードフォーム開始時に 3Dセキュアの実施を指定する
Payjp#startCardForm
の引数 useThreeDSecure
に true
を指定してください。
await Payjp.startCardForm(
onCardFormCanceledCallback: _onCardFormCanceled,
onCardFormCompletedCallback: _onCardFormCompleted,
onCardFormProducedTokenCallback: _onCardFormProducedToken,
useThreeDSecure: true);
まとめ
モバイル SDK を利用して 3Dセキュアを導入する手順は以下のとおりです。
- 管理画面でリダイレクト URL と識別子を設定する
- 各 SDK ごとに必要な設定を行う
- iOS の場合は Xcode で URL スキームを設定
- Android の場合は AndroidManifest.xml に IntentFilter を追加
- SDK の初期化時にリダイレクト URL と識別子を登録する
- カードフォーム画面開始時(またはトークン作成時)に、3Dセキュアの実施を指定する(管理画面の設定によっては不要)
- トークン作成後、3Dセキュアが必要な場合は SDK の機能を使ってカード所有者を認証フローに誘導する
- 認証後のリダイレクトを受け取り、SDK の機能で認証済みのトークンを取得する
これらの手順に沿って実装を行うことで、モバイルアプリでも安全なクレジットカード決済を提供できます。 セキュリティ強化のため、ぜひ 3Dセキュアの導入をご検討ください。