Help us understand the problem. What is going on with this article?

Stripe ✕ Lambdaでサーバーレスな決済機能を作る

More than 1 year has passed since last update.

ちょっとした決済機能

クレジットカードを使った決済機能の実装はハードルが高いイメージがあったのですが、StripeとLambdaを使えばとても簡単にできました。

決済フローのイメージ

Stripeでは、クレジットカード情報を自分達が預かること無く決済処理を行えます。
リソース構成図(縦長).001.png

APIGatewayとLambdaのセットアップ

予め、APIGatewayからLambdaを実行できるようにしておきます。

  • CROSを有効化しておく
  • 統合リクエストの本文マッピングテンプレートに「メソッドのパススルー」を設定しておく

その上で、JavaScirptのSDKをコンソール上で生成してダウンロードしておきます。今回はonetime-paymentというリソースのPOSTメソッドでLambdaを実行します。
スクリーンショット 2018-03-06 16.43.08.png

フロント側

ディレクトリ構造

  • index.html
  • js
    • apigClient.js :APIGatewayで生成したもの
    • lib :APIGatewayで生成したもの
index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Stripe Sample</title>
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
    <style type="text/css">
        #payment-form {
            padding: 30px;
            background-color: #f7f8f9;
        }
        #card-errors {
            margin-top: 16px;
        }
        .StripeElement {
            background-color: white;
            padding: 10px 12px;
            border-radius: 4px;
            border: 1px solid #ced4da;
            -webkit-transition: box-shadow 150ms ease;
            transition: box-shadow 150ms ease;
        }
        .StripeElement--focus {
            border-color: #80bdff;
        }
        .StripeElement--invalid {
            border-color: #fa755a;
        }
        .StripeElement--webkit-autofill {
            background-color: #fefde5 !important;
        }
    </style>

</head>
<body>

    <div class="container">

        <form id="payment-form">
            <div class="row">
                <div class="col-sm-8">
                    <div id="card-element"></div>
                    <div id="card-errors" class="alert alert-warning" role="alert" style="display: none;"></div>
                </div>
                <div class="col-sm-4">
                    <button class="btn btn-primary btn-block">支払いを実行する</button>
                </div>
            </div>
        </form>

    </div>

    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>

    <!-- Bootstrap -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>

    <!-- API Gateway SDK -->
    <script type="text/javascript" src="js/lib/axios/dist/axios.standalone.js"></script>
    <script type="text/javascript" src="js/lib/CryptoJS/rollups/hmac-sha256.js"></script>
    <script type="text/javascript" src="js/lib/CryptoJS/rollups/sha256.js"></script>
    <script type="text/javascript" src="js/lib/CryptoJS/components/hmac.js"></script>
    <script type="text/javascript" src="js/lib/CryptoJS/components/enc-base64.js"></script>
    <script type="text/javascript" src="js/lib/url-template/url-template.js"></script>
    <script type="text/javascript" src="js/lib/apiGatewayCore/sigV4Client.js"></script>
    <script type="text/javascript" src="js/lib/apiGatewayCore/apiGatewayClient.js"></script>
    <script type="text/javascript" src="js/lib/apiGatewayCore/simpleHttpClient.js"></script>
    <script type="text/javascript" src="js/lib/apiGatewayCore/utils.js"></script>
    <script type="text/javascript" src="js/apigClient.js"></script>

    <!-- stripe.js -->
    <script src="https://js.stripe.com/v3/"></script>

    <script type="text/javascript">
        'use strict';

        // Create a Stripe client.
        const stripe = Stripe('公開可能な方のAPIキー');
        // Create an instance of Elements.
        const elements = stripe.elements();
        // Create an instance of the card Element.
        const card = elements.create('card');

        $(function(){

            // Add an instance of the card Element into the `card-element` <div>.
            card.mount('#card-element');

            // Handle real-time validation errors from the card Element.
            card.addEventListener('change', function(event) {
                const displayError = $('#card-errors');
                if (event.error) {
                    displayError.text(event.error.message);
                    displayError.show();
                } else {
                    displayError.hide();
                }
            });
        });

        // Handle form submission.
        $('#payment-form').submit(function(event){
            event.preventDefault();

            stripe.createToken(card).then(function(result) {
                if (result.error) {
                    // Inform the user if there was an error.
                    const errorElement = $('#card-errors');
                    errorElement.text(result.error.message);
                    errorElement.show();
                } else {
                    // Send the token to your server.
                    errorElement.hide();
                    stripeTokenHandler(result.token);
                }
            });

        });

        function stripeTokenHandler(token){
            const apigClient = apigClientFactory.newClient({region: 'ap-northeast-1'});
            apigClient.onetimePaymentPost({}, {token: token.id}, {})
            .then(function(data){
                console.log(data);
                //決済成功時の処理
            })
            .catch(function(err){
                console.log(err);
                //決済失敗時の処理
            });
        }

    </script>
</body>
</html>

Lambda側

npm install stripeでライブラリを導入し、index.jsを下記のようにしてZIPファイルにしてアップロード

index.js
'use strict';
const stripe = require("stripe")("シークレットAPIキー");//シークレットキーでインスタンス生成

exports.handler = (event, context, callback) => {

    const token = event['body-json'].token;

    stripe.charges.create({
        amount: 999,//999円で決済
        currency: "jpy",
        description: "Example charge",
        source: token,
    }, function(err, charge) {
        if(err){
            callback(err);
        }else{
            callback(null, charge);
        }
    });

};

Fujimon_fn
サーバーもいじったことないエンジニア超初心者ですが、いきなりAWSでサーバーレスアーキテクチャに挑戦中です。GUIでポチポチしながら「落ちないシステム」を作れるようになります。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした