#ちょっとした決済機能
クレジットカードを使った決済機能の実装はハードルが高いイメージがあったのですが、StripeとLambdaを使えばとても簡単にできました。
#決済フローのイメージ
Stripeでは、クレジットカード情報を自分達が預かること無く決済処理を行えます。
#APIGatewayとLambdaのセットアップ
予め、APIGatewayからLambdaを実行できるようにしておきます。
- CROSを有効化しておく
- 統合リクエストの本文マッピングテンプレートに「メソッドのパススルー」を設定しておく
その上で、JavaScirptのSDKをコンソール上で生成してダウンロードしておきます。今回はonetime-paymentというリソースのPOSTメソッドでLambdaを実行します。
#フロント側
ディレクトリ構造
- 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);
}
});
};