How to integrate Softbank payment gateway (日本語)
Table of contents
この間、決済代行サービス(SoftBankペイメント)を案件に導入したので、実際に実装して分かったことをこの記事にまとめてシェアしたいと思います。
バックグラウンド
- 私はこれまで決済代行サービスとの連携を実装したことがありません。
- この案件は、クレジットカード支払いに対応しなければなりません。今後キャリア決済も対応する可能性があります。
- Railsで実装されたWebアプリケーションからの連携となります。
決済代行サービスとは
- 加盟店と各決済会社(カード会社やオンライ決済)の間に入り、多種の決済方法を対応してくれるサービスです。
- 決済代行サービスを使わない場合、どうなるか?
- 各決済会社と個別契約をしないといけない → 審査が大変厳しくなってしまう、工数もかなり掛かってしまう
- 決済会社によって、入金サイクルや手数料率が異なるので、事務処理に大変手間が掛かってしまう
- カード情報保管など、加盟店側が行わなければならない為、セキュリティー面の対応のハドルは高い
- 上のような不便を解決するために、決済代行サービスが存在しています。
SoftBankペイメントについてのまとめ
1. 導入の大きな流れ
- まずは、エントリーシートを記入してSoftBankペイメント(SBペイメント)へ提出する
- SB側が各決済会社への審査を行ってくれる
- 審査が通過したら、私たち(加盟店)の環境が構築される
※ キャリア決済の審査が遅い傾向にある為、各カード会社の審査がOKになったら、途中で環境構築が始められるそうです。急いでる方はSBの営業担当者へ依頼してください。 - 環境構築が終わり次第、試験と本番環境の接続情報がもらえる
- 連携時に必要な情報
- 管理画面のログイン情報
- 審査に時間はかかる為、基本的には「共用試験環境」を使って実装を先に進めてください!と営業担当者から案内される
※ 共用試験環境は、SBペイメントの導入を検討している人々がシェアして使う環境である。実装を確認する為に、使えるテストカード情報なども共有される。
2. システム接続方式
SBペイメントは以下の2つの接続方法を対応しています。
契約する時、どちらかしか選択できないという訳ではありません。API+リンク両方使用することも可能です。
- リンク型:エンドユーザーをSBペイメントの画面に誘導して、決済させるというイメージ
- API型:加盟店の画面がSBペイメントのAPIを呼び出して決済処理を行うというイメージ
2.1 リンク型
SBペイメントが提供する決済手続きの各画面を利用する方式です。 決済処理が終わた後、任意の加盟店側のページに画面遷移されます。
2.2 API型
SBペイメントの画面を使わず、APIでサーバー間の連携を行う方式です。 決済画面全部が自由にカスタマイズできます。
2.3 リンク型とAPI型の比較
項目 | リンク型 | API型 |
---|---|---|
決済画面のカスタマイズ | プラス料金を出せば、デザインのカスタマイズはできるが、 リンク追加など出来ない内容もある | 自由に |
決済処理フロー | 決済代行サービスの仕様に依存 | 自由に |
開発容易度と工数 | 低 | 高 |
利用可能な決済手段の差 | 豊富 | 一部の決済手段はAPI型対応しない |
3. 実装についてのまとめ
3.1 開発者支援サイト
一応あります。こちらdeveloper.sbpayment.jpになります。
しかし残念ですが、仕様書のダウンロード以外は、あまり役に立たないという個人の印象でした。
また、アカウントが必要なのですが、契約しなくても簡単に登録できますので、興味ある方はどうぞ見てみてください。
3.2 リンク型・API型の実装の共通点
加盟店 ⇄ SBペイメント間のリクエストが改ざんされないかバリデーションをする為?だと思いますが、 チェックサムを生成して送ることが必須で要されています。
チェックサムに値が設定されなかった又は正しく生成されなかった場合、リクエストが処理されず、エラーが返ってきます。 このチェックサム生成は実装の最初の壁となり、クリアしないと先に進むことができませんのでかなり重要なところと思います。
チェックサムの生成方法は下記の通りに説明されています。
リクエストの各パラメーターの値を項目定義順に文字列結合し、 最後に当社より払い出されたハッシュキーを結合した値を「UTF-8」へ変換して、 「SHA1」にてハッシュ演算を行ってください。
2ステップに分けて実装すれば良いかと思います。
- ステップ1:文字列結合
- ステップ2:ハッシュ演算
分かりやすい図を作ってみました。
github上の他の方のコードを参考にして、以下のように実際コーティングしました。 Railsで標準のモジュールを使ってかなり短く書けますね!
def generate_sps_hashcode(encoding: 'UTF-8', hashkey: Sbpayment.config.hashkey)
Digest::SHA1.hexdigest((values_for_sps_hashcode.map(&:to_s).map(&:strip).join + hashkey).encode(encoding))
end
def values_for_sps_hashcode
# 各パラメーターの値を項目定義順に返す
end
3.3 今回実装した内容
リンク型とAPI型、両方を利用していました。
- エンドユーザーの支払い情報登録のところは、今後決済方法を増やしたい時に、開発工数を抑えて対応できるように、リンク型を利用すると決まりました。
- 決済処理自体はバッチにも使う予定があった為、API型で実装することになりました。
エンドユーザーの支払い情報(カードの情報など)をSBペイメント側へ登録する時、ユニークな「顧客ID」を設定する必要があります。それ以降、決済などを行いたい時はこの顧客IDを指定すれば処理できるという仕組みです。要は、毎回エンドユーザーにカード情報を入力させなくて良いです。
顧客IDの値は、ユニークになっていれば良いので、一番楽な実装方法はそのままデータベースのインクレメンタルIDを使用するという方法ですね。 しかし、このIDは推測されやすい為、UUID使用をおすすめします。
3.4 支払い情報登録の実装(リンク型)
SBペイメントを呼び出す方法としては、対象の機能(画面)に対してフォームをサブミットすることです。必要なパラメーターはフォームの入力項目に設定するイメージです。
今回、支払い情報登録画面を呼び出す為に生成したフォームを下記共有します。サンプルとして参考してもらえらばと思います。
<form method="post" action="https://stbfep.sps-system.com/f04/FepPayInfoReceive.do">
<input type="hidden" name="pay_method" value="credit3d">
<input type="hidden" name="merchant_id" value="30132">
<input type="hidden" name="service_id" value="103">
<input type="hidden" name="cust_code" value="2bacfeb0...c617862">
<input type="hidden" name="success_url" value="https://example.com/home">
<input type="hidden" name="cancel_url" value="https://example.com/payment-info/require">
<input type="hidden" name="error_url" value="https://example.com/payment-info/error">
<input type="hidden" name="pagecon_url" value="https://example.com/payment-info/cgi-callback">
<input type="hidden" name="request_date" value="20191209152914">
<input type="hidden" name="sps_hashcode" value="7218980...e454f8f">
<input id="submitBtn" type="submit" class="hide">
</form>
この実装をした時に、ハマってしまったところがあります。登録通知先CGIと呼ばれる pagecon_url
パラメーターでした!
最初はこのパラメーターの意味が理解できず、適当のURLを設定して進めました。
そうしたら、カード情報の入力が終わったらSBのエラーページが表示されてしまいました。
仕様書をちゃんと確認できなかったことが原因でしたが、 支払い情報の登録流れの中、SBペイメント → 加盟店サイトという折り返しのリクエストが存在しました。 適当のURLを設定した為、当然このリクエストに対して200ステータスを返却できなかったので、SBペイメント側が怒ってました。 対処法としては、登録通知を受け取って200ステータスを返却するrouteを実装することですね。
ところで、上のエラーが出てしまったが、実は顧客と支払い情報がちゃんとSBペイメント側に登録されました。 あくまで、登録通知先CGIはコールバックとして設けられている感じです。 ローカルで開発する時、SBペイメントからのリクエストを受け取ることが無理なので、逆にこの仕様ではありがたい!助かった!と思いました。
3.5 決済処理の実装(API型)
SBペイメントはこの記事を書いた時点(2019/12)まだxml形式しか対応していません。 かなりレガシーですね。WebAPIの世界でよく用いられるjson形式ではないです。ご注意を!
APIに送らないといけないデータはリンク型とほぼ一緒です。
ここもハマったことがありました。「決済要求」と「確定要求」2つのAPIが存在するのですが、 決済処理を行いたい時は、セットで2リクエストを送信しなければなりません。 この仕様を見落とした私は、「決済要求」APIだけ叩くような処理を実装してしまいました。 APIのレスポンスが正常だったのに、なんで管理画面で確認したら請求エラーになるの?って何時間か悩んでいました。 請求が正常に行えたか判定する時は、必ずこの2リクエストが両方成功したか見なければなりません。ご注意ください。
感想
SBペイメントは開発者に優しくないという印象でした。
理由はいくつかあります。
- APIはレガシーのxmlしか対応しない
- ドキュメントは日本語のみ、PDF形式のみ
- APIリクエストの認証はアクセスキーのようなものではなく、Basic認証
- リクエスト(APIとリンク両方とも)のバリデーションのため、面倒なハッシュ計算が要される
それに対して、海外のStripe決済代行サービルに比べてみると
- APIはjson対応 ⭐️
- ドキュメントは多言語対応、web上見れる(検索やナビは簡単)、各プログラミング言語のサンプルコードもある ⭐️
- リクエストのバリデーションが省略され、安易にAPIが叩ける ⭐️
- さらに、各言語の公式のモジュールも準備されるので、実装がすごく楽になる ⭐️
ただ、どこの決済代行サービスを使うか決める時、実装の優しさだけ見てはいけません。 対応できる支払い方法は代行サービスによって異なりますし、コスト面も考えてフィットするプランがあるかどうか検討しなければなりませんね。