LoginSignup
34

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-03-06

ちょっとした決済機能

クレジットカードを使った決済機能の実装はハードルが高いイメージがあったのですが、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);
        }
    });

};

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
34