Flutter × Laravel × Stripe で単発決済

#はじめに
約半年振りの投稿です。
最近はWeb開発から少し離れFlutterの開発を行なっております。

巷で流行っている言語&AndroidとIOSの開発を同一言語でできるというのが大変魅力で学習をはじめました。

KBOYのFlutter大学
https://www.youtube.com/channel/UCReuARgZI-BFjioA8KBpjsw

自分はこのチャンネルから学習を始めました。
超丁寧に説明していただけるので、初学者に大変オススメです！

##経緯
もともと決済処理はWebViewで決済処理を行う予定でした。
しかし、調べているうちに

https://digiryte.com/blog/posts/online-payments-made-easier-by-digiryte-by-flutter-and-ruby-on-rails

こちらの記事を発見しRailsでもできるならLaravelでもできるんじゃね？
と思ったのが事の発端です。

言語違いではありますが、実装例があるのに自分で実装できないのはちょっと悔しいと思い試行錯誤の末実装できました。


##Stripeとは
こちらの記事が大変参考になります。
https://qiita.com/t-kuni/items/bfbec1dcc695c0f18282

## Flutterで画面の作成
画面作成の前にStripeを導入するにあたって必要なパッケージを導入します。

```pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
...
# この辺は自分の環境にあったものを導入してください。
stripe_payment: ^1.0.6
stripe_sdk: ^3.0.1+1
```

```main.dart
import 'package:flutter/material.dart';
import 'package:stripe_payment/stripe_payment.dart';
import 'package:stripe_sdk/stripe_sdk_ui.dart';


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey();
  final formKey = new GlobalKey<FormState>();
  final card = new StripeCard();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            CardForm(card: card, formKey: formKey), // クレジットカード入力欄を表示します。
            FlatButton(
              child: Text("決済する"),
              onPressed: () async {
                if (formKey.currentState.validate()) {
                  formKey.currentState.save();

                  final CreditCard _creditCard = CreditCard(
                      number: card.number,
                      expMonth: card.expMonth,
                      expYear: card.expYear,
                     );
                      StripePayment.createTokenWithCard(
                      _creditCard,
                    ).then((token) async {
                      // apiに処理を渡します。              
                      final url = 'http://127.0.0.1/api/sample_stripe';
                      await http.post(
                       url,
                       body: {
                         'stripeToken': token,
                       }
                     );
                    } else {
                    print('処理が通りませんでした。');
                  }
               },
            ),
          ],
        ),
      ),
    );
  }
}
```
![スクリーンショット 2020-10-11 4.44.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240422/9a8ab5f2-47f2-ad74-8042-15afd6c89b10.png)
上記の画像のようなページが作成されます。

処理の流れとしては下記のような流れになります。
1.CardFormクラスを作成し、クレジットカード情報を入力
2.「決済する」ボタンをタップ
3.CreditCardクラスを作成し入力した値を渡す。
4.stripeTokenを作成
5.Laravel側にstripeTokenを渡す。

作成できない場合は下記のURLを参考に作成してみてください。
https://pub.dev/packages/stripe_sdk


##Laravel側でAPIの作成

```api.php
Route::post('/sample_stripe', 'SampleStripeController@stripe');
```
```SampleStripeController.php
function stirpe(Request $request)
    {
        //  Stripeシークレットキーの取得
        Stripe::setApiKey(config('app.stripe_secret_key'));
        // 顧客の作成
        $customer = Customer::create(array(
            'email' => 'text@example.com',
            'source' => $request->stripeToken //tokenを受け取る
        ));

        $charge = Charge::create(array(
            'description' => 'ストライプ決済',
            'amount' => 500,
            'currency' => 'jpy',
            'customer' => $customer->id,
        ));
    }
```

## Stripe管理画面
![スクリーンショット 2020-10-11 5.36.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240422/ba9283f2-bc85-9d0a-0d00-08e216a81d14.png)
画像のように決済処理が完了しました。
Flutter側だけで処理しようとするとどうしてもわからない部分が多かったので重要な処理はLaravel側に投げて解決させました。

最初はstripeTokenが取得できずStripeの顧客にデータが登録できませんでしたが、「createTokenWithCard」を利用することで顧客データの登録ができるようになりました！

本記事では実装していませんが、決済が終了した後メールを送信してあげたりするともっといいかもしれませんね！

####本システムを作成するにあたって苦戦したところ
Flutter × Laravel × Stripe の記事が存在しなかったことが苦戦しました。
APIに処理を渡すということが理解できていてもstripeTokenが取得できなかったりRailsの記事の内容をLaravelに置き換えて実装してもエラー続きでした。
理解はできていても実装できないという大変歯がゆい思いをしながら開発しました（笑）

指摘等がございましたら是非お願いします。

決済処理やAPIを利用できると実装の幅が増えると思うのでぜひ参考にしてみてください！

#####参考URL
https://medium.com/flutterdevs/stripe-payment-in-flutter-d7f87f9a193c
https://digiryte.com/blog/posts/online-payments-made-easier-by-digiryte-by-flutter-and-ruby-on-rails
https://pub.dev/packages/stripe_sdk