Flutter X Node.js X Stirpeを使用して単発決済をしてみる


## イントロダクション
#### 記事の目的や背景を説明
現在自社で作成しているサービスに決済機能を追加する必要が出てきたので技術検証としてFlutter X Stripeの簡単な調査とプロトタイプの作成をしたので備忘録として残しておきます。

#### 対象読者
今回Flutterそのものについてやコードには深くは言及しないのである程度Flutterを扱うことができる方。
個人アプリ開発や仕事で決済機能をつけたい方向けの記事となっています。
## 目次
1. Flutter_stripeについて
2. Stripeアカウントの作成
3. 開発環境
4. Flutter X Stripeの仕組み
5. 実際のコードとモック画像
6. サーバーサイドコード
7. クライアントサイドコード

## 1. Flutter_stripeについて
今回はFlutterとStripeを簡単に連携できるようにflutter_stripeというパッケージがあるのでそちらを使用します。
https://pub.dev/packages/flutter_stripe
https://pub.dev/documentation/flutter_stripe/latest/
クレジットカード決済意外にもApple PayやGoogle Payなども対応できるようになっていますが、今回は必要ないのでクレジットカード決済の機能のみを実装していいます。
決済機能をFlutterアプリと統合する上でFlutter_stripeから三つの方法が提供されています




今回は一番導入コストも簡単かつ自動でエラーハンドリングやUIも提供してくれているPayment Sheetで実装していきます。




## 2. Stripeアカウントの作成
flutter_stripeを使用するにはStripeのアカウントを作成しシークレットキーと公開キーの両方を取得する必要があります。
[公式サイト](https://stripe.dev/ )からアカウントを作成しシークレットキーと公開キーを控えておいてください
## 3. 開発環境
続いて今回使用する開発環境についてです。
### クライアントサイド
Flutter 3.7.1
Dart 2.19
### サーバーサイド
Node.js 20
Cloud Functions

まずはcloud functionsにデプロイするサーバーサイドのコード        
```
const functions = require('@google-cloud/functions-framework');
const Stripe = require('stripe');

functions.http('helloHttp',  async (req, res) => {
  const stripe = Stripe(process.env.STRIPE_SECRET_KEY);
  const amount = req.body['amount']
  // Use an existing Customer ID if this is a returning customer.
  const customer = await stripe.customers.create();
  const ephemeralKey = await stripe.ephemeralKeys.create(
    {customer: customer.id},
    {apiVersion: '2023-10-16'}
  );
  const paymentIntent = await stripe.paymentIntents.create({
    amount: Number(amount),
    currency: 'jpy',
    customer: customer.id,
    automatic_payment_methods: {
      enabled: true,
    },
  });

  res.json({
    paymentIntent: paymentIntent.client_secret,
    ephemeralKey: ephemeralKey.secret,
    customer: customer.id,
    publishableKey: process.env.STRIPE_PUBLIC_KEY
  });

});

```



クライアントサイドのコード実装
```
flutter pub add flutter_stripe
```
上記コマンドでflutter_stripeをインストールします。
` 'import 'package:flutter_stripe/flutter_stripe.dart';'`
でflutter_stripeをmain.dartにインポートします。

```
 Stripe.publishableKey = stripePublishableKey;
 Stripe.merchantIdentifier = 'merchant.flutter.stripe.test';
 Stripe.urlScheme = 'flutterstripe';
 await Stripe.instance.applySettings();
```
main関数の中に上記コマンドを記載しStripeの初期設定を行います。
続いてPayment sheetの実装と決済周りのコードを記述します。
今回は自動的に決済を完了させるのではなく一度決済を完了させる前に確認できるようにしていきます。
```
  data = 'サーバーサイドの処理の戻り値'
 await Stripe.instance.initPaymentSheet(
    paymentSheetParameters: SetupPaymentSheetParameters(
    // Trueにすることで確認を挟むことができます。
    customFlow: true,
    merchantDisplayName: 'Flutter Stripe Store Demo',
    paymentIntentClientSecret: data['paymentIntent'],
    customerEphemeralKeySecret: data['ephemeralKey'],
    customerId: data['customer'],
     ),
    );
// PaymentSheet を表示
await Stripe.instance.presentPaymentSheet();

```
ここまでの実装ができれば以下の画像のようにpayment sheetが表示されると思います。
![スクリーンショット 2024-01-23 15.50.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3513156/829e5923-be6f-90d2-f1d8-5ffc9bce8e78.png)
この状態で決済を行うと以下の状態になっています。
![スクリーンショット 2024-01-23 16.04.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3513156/0d380b02-a25d-bbe6-aa84-68de239464d4.png)

以下のコードで決済を確定させます。
```
await Stripe.instance.confirmPaymentSheetPayment();
```
決済完了後は以下のように切り替わります。
![スクリーンショット 2024-01-23 16.04.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3513156/75d2e5c9-1ba3-1ed5-0801-a733c078d7f8.png)