[iOS] クレジットカード決済機能 Stripe を Swift × Lambdaでアプリに導入してみる

Stripeという決済サービスをiOSアプリに入れてみた手順になります。今回はサーバー側をAWS LambdaとAPI Gatewayで作成しています。テスト環境も整っていてすぐに試すことが出来ました。
2018.07.07

Stripeはモバイルアプリなどにクレジットカード決済機能を入れることの出来るサービスです。
今回はテスト環境でアプリに組み込む所までを試した健忘録を公開します。

Stripe 公式サイト

https://stripe.com/jp

試した環境

サーバーサイド

  • AWS Lambda (Node.js)
  • AWS API Gateway

クライアント

  • iOS (Swift 4.1.2)
  • XCode9.4

Stripeアカウントの登録

Stripeを利用するにはアカウントを作成する必要があります。

アカウントの作成

Stripeのウェブサイトをブラウザで開き、アカウント登録ボタンをクリックします。

登録フォームが表示されるので、メールアドレス、名前、パスワードを入力します。

作成するとダッシュボードな画面に遷移します。

これでアカウントが作成されました。
このままテスト環境として使うことができます。

APIキーを確認する

アカウントが作成されたら、ダッシュボードの開発者ボタンをクリックし、その下に表示されたAPIキーボタンをクリックます。 すると、APIの公開キーとシークレットキーが表示されるのでメモしておきます。

APIGateway+LambdaでStripeの決済呼び出しAPIを作成する

APIGateway+Lambda 環境構築

APIGateway + Lambda の環境構築では、全体的な流れは以下の記事を参考にしました。
今回は記事でPythonで作成しているところをNode.jsに置き換えて作成し、APIGateway から呼び出せるようにしました。

ゼロから作りながら覚えるAPI Gateway環境構築 | Developers.IO

LambdaのStripe関数を用意する

関数を作るにあたって、apexというAWS Lambdaファンクションをビルド、デプロイ、管理するためのツールを利用しました。
インストール手順や使い方については以下の記事が参考になります。

ApexでAWS Lambdaファンクションを管理する | Developers.IO

記事を参考にインストールからプロジェクトディレクトリ(project.json)の作成までやっておきます。

.
├── functions
└── project.json

functions 以下に stripe ディレクトリを作成し、その直下にindex.jsとfunction.jsonという名称の空ファイルを作成します。 ※ このディレクトリ名が Lambdaの関数名になるみたいです。

.
├── functions
│   └── stripe
│       └── index.js
│       └── function.json
└── project.json

function.jsonに以下を記載します。(内容は適宜、書き換えてください)

{
  "description": "Stripe Sample",
  "timeout": 10
}

stripeディレクトリで以下のコマンドを実行し、stripeのライブラリをインストールします。

npm install stripe

インストールが完了したらindex.jsを記載します。

index.js

const stripe = require('stripe')('sk_test_XXXXXXXXXXXXXXXXXX'); // ←シークレットAPIキーを入れます

exports.handler = function(event, context, callback) {
  const token = event.token;
  const amount = event.amount;
  const currency = event.currency;

  stripe.charges.create({
    amount,
    currency,
    description: 'Stripe Test charge',
    source: token,
  })
    .then((charge) => {
      callback(null, charge);
    })
    .catch((err) => {
      callback(err);
    })
};

上記コードを入力したらapexでデプロイします。ルートに戻り下記コマンドを実行します。

apex deploy stripe

Lambdaにアップロードされていれば成功です。APIGatewayの方でこのLambdaを呼び出すメソッドを作って、アプリから呼び出せるようにしておきます。

アプリ側

ライブラリを入れる

まず、iOS用のStripeのSDKを入れます。 CocoaPod か Carthage のうち使い慣れている方で入れると良いと思います。

CocoaPod

Podfileに記載し、

Podfile

pod 'Stripe'

下記コマンドを実行します。

pod install
Carthage

Cartfileに記載し、

Cartfile

github "stripe/stripe-ios"

下記コマンドを実行します。

carthage update stripe-ios --platform ios

コード

ライブラリをインストールしたら、次はクレジットカード番号を入力する画面をコードに入れます。
Stripeではカード入力用のViewControllerが用意されているので呼び出すだけで使えるようになります。
下のコードではボタンをタップした時にカード入力画面のSTPAddCardViewControllerを呼び出しています。

ViewController.swift

import UIKit
import Stripe

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
	
    @IBAction func didTapButton(_ sender: Any) {
        let addCardViewController = STPAddCardViewController()
        addCardViewController.delegate = self
        let navigationController = UINavigationController(rootViewController: addCardViewController)
        present(navigationController, animated: true)
    }
}

extension ViewController: STPAddCardViewControllerDelegate {

    func addCardViewControllerDidCancel(_ addCardViewController: STPAddCardViewController) {
        dismiss(animated: true)
    }

    func addCardViewController(_ addCardViewController: STPAddCardViewController, didCreateToken token: STPToken, completion: @escaping STPErrorBlock) {
        print(token.tokenId)
        dismiss(animated: true)
        // token.tokenId と 価格をパラメーターとして先程作成したAPIを呼び出す
    }
}

一番簡単な使い方は上記コードのように呼び出したあとdelegateでカードトークンを受け取り、 先程Lambda+APIGatewayで作った決済するAPIにtoken.tokenId価格をパラメータとして呼び出せばOKです。

動かしてみる

実際に動かして成功すると、Stripeのダッシュボードに購入履歴が入ります。

テストで使えるカードは決まっており、対応していないカード番号を入力すると、失敗になります。(↑の画像で失敗となっているのはテストに使えないカード番号を入れた為です)
テスト用のカード番号は下記URLからご確認ください。

https://stripe.com/docs/testing

さいごに

今回の手順では、生成したStripeのトークンは1度限り有効なので、同じトークンで再度支払いをしようとすると失敗します。
カード情報を登録したい場合はStripeでCustomer情報を生成する必要があるようです。  

また、今回は試してみませんでしたが、StripeではApple Payに対応しているみたいなので、いつか試してみたいと思いました。

参考