React Native を利用したモバイルアプリケーションで PAY.JP を利用する場合は、 PAY.JP SDK React Nativeプラグイン をご利用ください。 これは PAY.JP Mobile SDK を React Native アプリケーションから呼び出すためのプラグインで、以下の機能が利用できます。
ライブラリの追加
プロジェクト構成
まず、React Native プロジェクトにプラグインを導入する手順について説明します。 npx react-native init AwesomeProject
で作成される、以下のような構成の React Native プロジェクトを前提にしています。
.
├── App.js
├── __tests__
├── android
├── app.json
├── babel.config.js
├── index.js
├── ios
├── metro.config.js
├── node_modules
├── package.json
└── yarn.lock
なお、プラグインにはネイティブモジュールが含まれているため、現時点では Expo のManaged workflowには対応していません。
インストール
npm または yarn で最新のパッケージを追加します。
npm install --save payjp-react-native
ネイティブモジュールのセットアップ
次にネイティブモジュールのセットアップを行います。
React Native 0.60 以降のバージョンでは、Autolinking という機能により、パッケージのインストール時に自動でリンクされます。そのため、 ios
ディレクトリに移動して pod install
するだけでネイティブモジュールのセットアップが完了します。
cd ios
pod install
React Native 0.60 未満のバージョンの場合は、以下のように手動で react-native link
を実行したのち、 pod install
を行います。
npx react-native link payjp-react-native
cd ios
pod install
Swiftファイルとヘッダーの追加
iOS SDK は Swift で記述されているため、アプリのプロジェクトで Swift コードが呼び出せるように以下の作業を行います。
まず ios/AwesomeProject.xcodeproj
を開きます。
左側のナビゲーターのアプリの AppDelegate.h
などがある階層で右クリックし New File...
を選択します。
新規で作成するファイルの種類を確認されるので、Swift ファイルを選択します。名前は何でもよく、ここでは Empty.swift
とします(特に何も記述する必要はなく、作成したままで問題ありません)。
作成すると、Objective-C と Swift が混在するプロジェクトに必要なヘッダーファイルの作成を確認されます。 ここで Create Bridging Header を選択すると、Xcode がヘッダーファイルの設定を自動的に行います。
これでライブラリのセットアップは完了です。
SDKの初期化
カードフォームを利用する場合も、Apple Pay を利用する場合も、SDK の初期設定を行います。PAY.JP ダッシュボードのAPIページから取得した公開鍵を設定します。
以下のサンプルコードではテスト公開鍵を利用しています。
import { PayjpCore } from "payjp-react-native";
PayjpCore.init({ publicKey: 'pk_test_0383a1b8f91e8a6e3ea0e2a9' })
.then(() => console.log('payjp init ok'))
.catch(e => console.warn('payjp init error', e));
クレジットカード決済のためのカードフォームを利用する
ここでは、React Native アプリケーションからカードフォームを呼び出し、カード情報から支払いなどに必要なトークンを作成する方法を説明します(トークン化することでカード情報を直接扱うことなく安全に支払い処理を行うことができます)。
カードフォームイメージ
iOS | Android |
---|---|
iOSの事前準備
カードフォームでは、クレジットカードをカメラで読み取る機能を提供しています。 この機能はデバイスのカメラを利用するため、iOS アプリの場合、なぜカメラ利用が必要なのかをユーザーに明示する必要があります(Android ではこの設定は不要です)。
Xcode で iOS のプロジェクト(ios/AwesomeProject.xcodeproj
)を開きます。
Info.plist
に NSCameraUsageDescription というキーで説明を追加します。
これで、ユーザーがアプリで初めてカメラを利用する際に、ここで設定した文言が表示されるようになります。
カードフォームを呼び出す
PayjpCardForm.startCardForm(CardFormOption)
を呼び出して PAY.JP のカードフォームを起動します。
import React from "react";
import { View, Button } from "react-native";
import { PayjpCardForm } from "payjp-react-native";
const SampleScreen = () => {
return (
<>
<Button
title="カードを追加する"
onPress={(): void => { PayjpCardForm.startCardForm({ cardFormType: "cardDisplay" }); }}
/>
</>
);
};
このとき PayjpCardForm.startCardForm(CardFormOption)
の引数 CardFormOption
は以下のオプショナルなプロパティを持ちます。
プロパティの名称 | 説明 |
---|---|
tenantId |
PAY.JP Platform の Marketplace 型を利用している場合にテナント ID を指定できます。( トークン作成時のテナント ID について ) |
cardFormType |
カードフォームの表示タイプを切り替えます。 |
extraAttributes |
カードフォームに追加の属性項目を設定できます。デフォルトはメールアドレスと電話番号が表示されます。( 追加の属性項目を設定する ) |
cardFormType
ではカードフォームを 2 種類の表示タイプから指定できます。何も指定しない場合は multiLine
が適用されます。
CardFormType | iOS(CardFormViewType) | Android(CardFormFace) |
---|---|---|
multiLine |
.labelStyled | FACE_MULTI_LINE |
cardDisplay |
.displayStyled | FACE_CARD_DISPLAY |
表示タイプについては iOS SDKの導入ガイド、Android SDKの導入ガイド をご確認ください。
カードフォームの操作結果を受け取る
次に、ユーザーの操作によってカードフォームが更新されたときの処理を実装します。
PayjpCardForm.onCardFormUpdate()
の引数にリスナー関数を含むオブジェクトを渡すことで、更新を受け取ることができます。
たとえば、ユーザーが入力を完了すると、カード情報からトークンが生成されます。 このトークンを使って支払いを作成したり顧客を作成したりといった処理を行います。
onCardFormUpdate()
に渡すオブジェクトの onCardFormProducedToken
にトークンをサーバーに送信する処理を記述します。
PayjpCardForm.onCardFormUpdate({
onCardFormCanceled: () => {
console.log("PAY.JP card form canceled");
},
onCardFormCompleted: () => {
console.log("PAY.JP card form completed");
},
onCardFormProducedToken: token => {
console.log("PAY.JP token => ", token);
// トークンをサーバーに送信する
sendTokenToServer(token);
}
});
onCardFormProducedToken
の他にも、カードフォームがキャンセルされたとき実行する onCardFormCanceled
、カードフォームが完了したとき実行する onCardFormCompleted
があります。
コンポーネント内でリスナーを追加・削除する
PayjpCardForm.onCardFormUpdate()
は追加したリスナーを解除する関数オブジェクトを返します。
React コンポーネント内で呼び出す場合、React Hooks や componentDidMount/componentWillUnmount
などのライフサイクルメソッド内で、返却された関数を呼び出してメモリーリークを防ぐようにしてください。
以下は React Hooks の Effects を利用した例です。
useEffect
の返すクリーンアップ関数内で登録したリスナーを削除します。
import React, { useEffect } from "react";
import { View, Button } from "react-native";
import { PayjpCardForm } from "payjp-react-native";
const SampleScreen = () => {
useEffect(() => {
const unsubscribeCardForm = PayjpCardForm.onCardFormUpdate(/** 省略 */);
return () => {
// クリーンアップ関数内で登録したリスナーを削除
unsubscribeCardForm();
};
}, []);
return (
<>
<Button
title="カードを追加する"
onPress={(): void => { PayjpCardForm.startCardForm(); }}
/>
</>
);
};
カードフォームを完了する
onCardFormProducedToken
が呼び出されるとき、カードフォームは終了せずに待機している状態です。そのため、このまま完了するか、エラーを表示して再度ユーザーに入力してもらうかを指定する必要があります。
トークンをサーバーに送信しカードフォームを終了するには、 PayjpCardForm.completeCardForm()
を呼び出します。
もし、何らかの問題(たとえば通信エラーなど)によってトークンの送信に失敗した場合は、 PayjpCardForm.showTokenProcessingError(message)
を呼び出しカードフォームにエラーメッセージを表示します。
PayjpCardForm.onCardFormUpdate({
onCardFormCanceled: () => {},
onCardFormCompleted: () => {},
onCardFormProducedToken: token => {
sendTokenToServer(token)
.then(() => {
// トークンの送信に成功したらカードフォームを完了する
return PayjpCardForm.completeCardForm();
})
.catch(e => {
// エラーメッセージを表示する
return PayjpCardForm.showTokenProcessingError(convertMessage(e))
});
}
});
カードフォームの見た目を変更する
iOS
iOS でカードフォームのスタイルを変更するには、 PayjpCardForm.setIOSCardFormStyle(style)
を呼び出します。
import { Platform, PlatformColor } from "react-native";
const style = {
labelTextColor: PlatformColor("label"),
inputTextColor: "rgba(255, 0, 255, 1.0)",
submitButtonColor: "#0055ff",
};
if (Platform.OS === "ios") {
await PayjpCardForm.setIOSCardFormStyle(style);
}
各カラーは、React Native がサポートするカラー表現を用いて指定できます。指定できる形式については公式のリファレンスを参照してください。
スタイル属性と反映されるコンポーネントの対応については、iOS SDKの導入ガイドをご確認ください。
Android
Android では、カードフォームのスタイルは Theme によって制御されています。カードフォームが参照する Theme を上書きすることでカスタマイズできます。
カードフォームの色を変更する場合は、まず android/app/src/main/res/values/colors.xml
に使用するカラーの宣言を追加します。カラーの指定については Android の公式リファレンスもあわせてご確認ください。
<resources>
<color name="primaryColor">#ff5252</color>
<color name="primaryLightColor">#ff867f</color>
<color name="primaryDarkColor">#c50e29</color>
<color name="secondaryColor">#ffc400</color>
<color name="secondaryLightColor">#fff64f</color>
<color name="secondaryDarkColor">#c79400</color>
<color name="primaryTextColor">#424242</color>
<color name="secondaryTextColor">#37474f</color>
</resources>
その他のリソースタイプ | Android デベロッパー | Android Developers
次に、 android/app/src/main/res/values/styles.xml
でカードフォームの Theme を上書きする宣言を追加します。先に追加したカラーはここで参照します。
<resources>
<!-- 省略 -->
<!-- 以下を追加 -->
<style name="Payjp.Theme.CardForm" parent="Payjp.Theme.BaseCardForm">
<!-- 例 -->
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryDark">@color/primaryDarkColor</item>
<item name="colorSecondary">@color/secondaryColor</item>
</style>
</resources>
スタイル属性と反映されるコンポーネントの対応については、Android SDKの導入ガイドをご確認ください。
追加の属性項目を変更する
ExtraAttribute
で入力された情報は3Dセキュアの認証情報として使用されます。
3Dセキュアは2025年3月末までの運用開始が義務化されており、その一つとしてこの追加項目が求められます。
詳細は3Dセキュア認証 - 導入の義務化およびPAY.JPにおける3D セキュア - 3Dセキュア認証における追加項目をご覧ください。
カードフォームに表示される追加の属性項目は、カードフォーム開始時に呼び出す PayjpCardForm.startCardForm(CardFormOption)
の引数 CardFormOption
のプロパティ extraAttributes
によって変更できます。
属性の種類はメールアドレスと電話番号の2種類があり、入力した内容はカードオブジェクトにセットされ、 3Dセキュア認証実施時に送信されます。
- メールアドレスと電話番号両方を表示する場合は、いずれかの入力が必須となります。
- メールアドレスか、電話番号どちらかのみ表示する場合は、表示した項目の入力が必須となります。
- 初期値を設定した場合はフォームに入力された状態で表示され、ユーザーは入力内容を編集して送信できます。
- いずれの項目も表示しない場合は、空の配列を渡すようにしてください。
たとえば、メールアドレスのみを初期値を設定して表示する場合は、以下のサンプルコードのように指定します。
// アプリを利用しているユーザーのメールアドレスを初期値として表示する
PayjpCardForm.startCardForm({
extraAttributes: [
{ type: 'email', preset: user.email },
// { type: 'phone' } // 電話番号の入力は要求しない
],
});
サンプルコードは GitHub リポジトリ でも公開していますのでご参照ください。
Apple Payのアプリ内決済に利用する
Apple Pay をアプリに組み込むにあたって、はじめにApple Pay の利用の準備をご確認ください。
また、ボタンの表示や UI については、Apple のガイドラインを必ず確認するようにしてください。
Introduction - Apple Pay - Human Interface Guidelines - Apple Developer
ここでは、SDK の初期設定をした後に、Apple Pay を利用して支払いに必要なトークンを作成する処理の実装手順について説明します。
Apple Payが利用可能かチェックする
実際に Apple Pay のペイメントシートをリクエストする前に、端末が Apple Pay を利用可能な状況かどうかを確認します。端末が Apple Pay をサポートしていない、ペアレンタルコントロールによって制限されているなどの場合、 PayjpApplePay.isApplePayAvailable()
は Promise で false を返します。
PayjpApplePay.isApplePayAvailable()
.then(available => {
// trueならApple Payの支払いが可能
});
Apple Payのペイメントシートを表示する
PayjpApplePay.makeApplePayToken()
に商品の名称など支払いに必要な情報を渡して、ペイメントシートをリクエストします。
appleMerchantId
には Xcode の設定で有効化したマーチャント ID を設定してください。
PayjpApplePay.makeApplePayToken({
appleMerchantId: "merchant.com.example",
currencyCode: "JPY",
countryCode: "JP",
summaryItemLabel: "PAY.JP T-shirt",
summaryItemAmount: "100",
requiredBillingAddress: false
});
Apple Payの操作結果を受け取る
PayjpApplePay.onApplePayUpdate()
の引数にリスナー関数を含むオブジェクトを渡し、操作結果を受け取ります。
PayjpApplePay.onApplePayUpdate({
onApplePayCompleted: () => console.log("PAY.JP ApplePay completed.") },
onApplePayFailedRequestToken: error => {
console.warn("error => ", error);
PayjpApplePay.completeApplePay(false, error.errorMessage);
},
onApplePayProducedToken: token => {
console.log("PAY.JP token => ", token);
sendTokenToServer(token)
.then(() => {
return PayjpApplePay.completeApplePay(true);
})
.catch(e => {
return PayjpApplePay.completeApplePay(false, convertMessage(e))
});
}
});
ユーザーが必要な情報を入力し Apple Pay による支払いが承認されると、Apple Pay のペイメントトークンが発行されます。PAY.JP SDK はこのペイメントトークンから PAY.JP での支払いなどに利用する PAY.JP トークンを作成します。
onApplePayProducedToken
はこのトークンの作成に成功したとき呼び出されるリスナーで、引数にトークンが渡されます。このトークンは支払い処理に利用するため、リスナー内でサーバーに送信する処理を実装してください。
トークンの送信処理に成功した場合は PayjpCardForm.completeApplePay(isSuccess, errorMessage)
の第1引数に true
を、送信処理に失敗した場合は false
を指定して呼び出します。
onApplePayFailedRequestToken
は、Apple Pay のペイメントトークンから PAY.JP のトークンを生成する際に問題があったとき呼び出されるリスナーです。この場合も PayjpCardForm.completeApplePay(isSuccess, errorMessage)
の第1引数に false
を指定して呼び出すようにしてください。
onApplePayCompleted
は、Apple Pay による支払いが完了したとき呼び出されるリスナーです。
onApplePayProducedToken
あるいは onApplePayFailedRequestToken
が呼び出されるとき、 Apple Payのペイメントシートは終了せずに待機している状態です。完了するには必ず PayjpCardForm.completeApplePay(isSuccess, errorMessage)
を呼び出す必要があります。
注: iOSシミュレーターで実行時には、ペイメントトークンは空の値になりますので、実機で実行してください。
コンポーネント内でApple Payのリスナーの取り扱い
PayjpCardForm.onApplePayUpdate()
は追加したリスナーを解除する関数オブジェクトを返します。
React コンポーネント内で呼び出す場合、カードフォームのリスナー同様、返却された関数を呼び出してリスナーを削除するようにしてください。
ソースコード・サンプルコード
ソースコード・サンプルアプリケーションは GitHub 上で公開されています。