虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

決済サービスStripeの超入門実装

はじめに

皆さんこんにちは、虎の穴ラボの片岡です。

虎の穴ラボ #アドベントカレンダー 22日目の記事です!

Stirpeについて皆さんは一度聞いたことがあると思います。Stripeについての超入門内容です。

Stripeについて

Stripeとは決済代行サービスです。 f:id:toranoana-lab:20211203113312p:plain

APIとStripeのサービ管理フォームを使うことで、自身のサービスの決済処理を担ってくれます! ややこしい実装もいらない、かつ管理フォームまで用意してくれます。

自身のサイトに取り込む、もしくは一切コードを使わない決済を実装することが魅力なところと思います。

この記事は、Stripeをはじめて触る人がStripeプロジェクトを取り込むに必要な手順とサンプルコードの説明になります。

開発環境

  • macOS Catalina(10.15.7)
  • Homebrew
  • rbenv (ruby 2.7.5)
  • stripe開発環境のアカウント(作成ページはこちら)

導入手順

1.Stripe CLIをインストールします。

brew install stripe/stripe-cli/stripe

2.Stripe cliでをログインする、ブラウザが開きます。

stripe login

3.カスタムの支払いフローのサンプルプロジェクトを作成します。

使うコマンドはこちら: stripe samples create (プロジェクト名)

例:

stripe samples create stripe-sample

4.gemをインストールします。

cd stripe-sample/ #(プロジェクト名)
bundle install --clean --path vendor/bundle 

5.APIキーをセットアップします。

サンプルプロジェクトはdotenvを使っているので、 フォルダ内に.env.sampleをコピーし.env内の下記の2つAPIキーを設定しましょう。

STRIPE_PUBLISHABLE_KEY=pk_test...
STRIPE_SECRET_KEY=sk_test...

APIキーの場所はこちらです: https://stripe.com/docs/development/quickstart#api-keys

 6.サービス起動します。

下記のコマンドでサービスを起動させます。

ruby /server/server.rb

サービス起動正常時のログはこんな感じです。

Checking that `.env` exists...
Checking that valid API keys are set...
No previous payments found. Unable to confirm if publishable and secret key pair is for the same account.
[2021-11-28 21:09:25] INFO  WEBrick 1.6.1
[2021-11-28 21:09:25] INFO  ruby 2.7.4 (2021-07-07) [x86_64-darwin19]
== Sinatra (v2.1.0) has taken the stage on 4242 for development with backup from WEBrick

ローカルの下記のページを開くと、サンプルプロジェクトのトップページが表示されます。

http://localhost:4242

サンプルプロジェクト説明

 1.トップページには、いろいろリンクが表示されますが、今回はカード支払を説明します。

Cardのリンクをクリックし、クレジットカードの支払ページを開きます。

f:id:toranoana-lab:20211129190408p:plain

 2.クレジットカードの支払ページはクレジットカードを決済する際に、カード情報の入力フォームと決済ボタンなど、最低限のUIとなっています。

f:id:toranoana-lab:20211129190437p:plain

また、画面上部が表示している3つのクレジットカード番号ですが、それぞれ

4242424242424242 Visaカード
5555555555554444 Mastercardカード
4000002500003155 Visaカード、3DSecureの認証が必要、こちらもテストで失敗・成功設定できますので、どちらも試すことができます。

 3.テストカード使って、決済テストを実行します。

カード番号の入力欄に上記の3つの番号から任意のカード番号を入力し、名前、年・月とCVCコードと郵便番号は任意で大丈夫です。

※年・月は過去の期限を入力すると、「カードの有効期限が過ぎています」というエラーが表示されます。 ※適当なカード番号を入力すると、「カード番号が無効です。」というエラーが表示されます。

 4.支払成功後、下記のメッセージが表示されます。

> Client secret returned.
> Payment succeeded: [決済IDが発行されます]

Payment succeeded最後のIDの文字列がリンクになっています。クリックしたらStripeの管理画面に遷移します。

https://dashboard.stripe.com/test/payments/ [上記で発行された決済ID]

f:id:toranoana-lab:20211217155523p:plain

支払いデータの情報や、アクティビティ、JSONデータなどを見ることができます。

{
  "id": " [上記で発行された決済ID]",  <-- 決済ID
  "object": "payment_intent",
  "last_payment_error": null,
  "livemode": false,
  "next_action": null,
  "status": "succeeded",  <-- 決済ステータス
  "amount": 1999,   <-- 決済金額
  "amount_capturable": 0,
  .....

コード説明

card.jsとserver.rb

「Pay」ボタンをクリックすると、javascript側で下記のコードを実行されます。

 client/card.js
const {error: backendError, clientSecret} = await fetch(
 '/create-payment-intent',
   {
     method: 'POST',
     headers: {
      'Content-Type': 'application/json',
     },
     body: JSON.stringify({
       currency: 'usd',
       paymentMethodType: 'card',
     }),
   }
).then((r) => r.json());

javascript側呼んだのAPIエンドポイント/create-payment-intentの処理はこちらになります。

 /server/server.rb
post '/create-payment-intent' do
  payment_method_type = data['paymentMethodType']
  currency = data['currency']
  params = {
    payment_method_types: [payment_method_type], <--- 支払い方法
    amount: 1999, <--- 支払い金額
    currency: currency <--- 通貨(usd, jpyなど)
  }

サンプル上、クレジットカードの支払いを選ぶ際はcurrency(通貨)は('usd'), 支払い方法(payment_method_types)はカード('card')

 /client/card.js
   body: JSON.stringify({
      currency: 'usd',
      paymentMethodType: 'card',
   }),

上記のデータで支払いparamsを作成し、支払いインテントに引数として渡しします。 支払いインテント(PaymentIntent)を作成します。支払いの試行失敗があった場合にはその記録を残して顧客への請求に重複が発生しないようにします。

 /server/server.rb
  begin
    payment_intent = Stripe::PaymentIntent.create(params)
  rescue Stripe::StripeError => e
    halt 400,
      { 'Content-Type' => 'application/json' },
      { error: { message: e.error.message }}.to_json
  rescue => e
    halt 500,
      { 'Content-Type' => 'application/json' },
      { error: { message: e.error.message }}.to_json
  end

  {
    clientSecret: payment_intent.client_secret,
  }.to_json

支払いインテントのpayment_intent.client_secretをレスポンスで返して、クライアントで支払いを完了します。

クライアント側でawaitでサーバ側帰ってきたレスポンスを待つ処理です。

/client/card.js
const {error: stripeError, paymentIntent} = await stripe.confirmCardPayment(
   clientSecret,
   {
     payment_method: {
       card: card,
       billing_details: {
         name: nameInput.value,
       },
     },
   }
);

最後は支払い成功時。UI上「Payment .....」の部分を表示するメッセージはこちらのコードで制御しています。

  addMessage(`Payment ${paymentIntent.status}: ${paymentIntent.id}`);

実際画面上はこのように表示されます。

f:id:toranoana-lab:20211217155531p:plain

少量のコードで必要最低限の支払いフォローを構築でき、充実な決済管理機能も使えるのはStripeの強みと思います。

おまけ

vscodeを使っている場合は、Stripeのプラグインを利用して、vscode上でサンプルコード作成したり、決済をテストすることができます。こちら公式の説明ドキュメントです。

https://stripe.com/docs/stripe-vscode

明日の担当は虎の穴ラボ・インフラ担当のSKさんです。 楽しみです!

P.S. エンジニア絶賛募集中!!

採用情報

■募集職種
yumenosora.co.jp

カジュアル面談も随時開催中です
■お申し込みはこちら!
news.toranoana.jp