バック：SpringBoot RestApiに決済機能実装 　Stripeの支払いインテントを作るまで 1/4

# 概要
B2C向けECショップのクローンサイトを作っています。
今回は決済システムを実装するため、サードパーティのStripeを導入します。
記事の内容としては、バックエンド側のみとなります。
フロントエンド側では、React、TypeScriptで実装する予定です。フロントエンドの実装は次の記事で書きます。

# ユースケース
以下画像はStripeを使った決済の流れです。今回の記事は赤枠部分を実装します。

フロントエンド側はReactの代わりにPostmanを使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/bdb983f6-a78b-3f09-398a-db479c9aa759.png)



# 開発環境
OS:windows10

バックエンド側：
IDE:IntelliJ Community
spring-boot-starter-parent 2.75
java　：　11


# 手順
## stripeの会員登録を行う。
Stripeの開発者画面からAPIキーを取得します。（下画像参照）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/967329a8-be8f-e97b-cd5d-51b276cdb86a.png)


APIキーはapplication.propertyにコピペします
XXXにシークレットキーを入れる。

```properties:application.properties

stripe.key.secret=XXXXXXXXXXXXXXXXXXX

```



## mavenにstripeのライブラリを追加する

```xml:pom.xml
		<dependency>
			<groupId>com.stripe</groupId>
			<artifactId>stripe-java</artifactId>
			<version>10.1.0</version>
		</dependency>

```



## SpringBootの実装

### 作成したファイル一覧
ファイル名|説明
---------|----
PaymentInfoRequest| Apiに入っているリクエストボディを定義しているクラス
PaymentService|サービスレイヤー。
PaymentContoller|コントローラーを使用。Restを使用
application.property|Stripeのシークレットキーの値を追加


### 実装の方針
シンプルにするため、自前のデータベース（MySQL）には一切アクセスしません。
支払い情報のデータはstripe側で確認することを前提とします。

本当は自前のMySQL側にもstripe側の処理を記録する必要があると思います。（バックアップとかStripeから別のサードパーティに乗り換えする時など）


### コード部分（長いです。先にファイル一覧を追加してください）





#### PaymentInfoRequest.java

```java:PaymentInfoRequest.java
package com.example.restapi.implement.payment;

import lombok.Data;

@Data
public class PaymentInfoRequest {

    // 金額の量 50以上の値を入力する
    // 単位はcurrency になる
    //例えば　amount=50 currency="jpy"とすると　50円になる
    private int amount;
    //通貨の種類　日本円なので"jpy"と入力する
    private String currency;

    private String receiptEmail;
}

```

#### PaymentService.java

```java:PaymentService.java
package com.example.restapi.implement.payment;

import com.stripe.Stripe;
import com.stripe.exception.StripeException;
import com.stripe.model.PaymentIntent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class PaymentService {

    @Autowired
    public PaymentService(@Value("${stripe.key.secret}") String secretKey) {
        Stripe.apiKey = secretKey;
    }

    public PaymentIntent createPaymentIntent(PaymentInfoRequest paymentInfoRequest) throws StripeException {
        List<String> paymentMethodTypes = new ArrayList<>();
        paymentMethodTypes.add("card");

        Map<String, Object> params = new HashMap<>();
        params.put("amount", paymentInfoRequest.getAmount());
        params.put("currency", paymentInfoRequest.getCurrency());
        params.put("payment_method_types", paymentMethodTypes);

        return PaymentIntent.create(params);
    }

}

```

#### PaymentController.java

```java:PaymentController.java

package com.example.restapi.implement.payment;

import com.stripe.exception.StripeException;
import com.stripe.model.PaymentIntent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
public class PaymentController {

    private PaymentService paymentService;

    @Autowired
    public PaymentController(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    @PostMapping("/api/pay/payment-intent")
    public ResponseEntity<String> createPaymentIntent(@RequestBody PaymentInfoRequest paymentInfoRequest)
            throws StripeException {

        PaymentIntent paymentIntent = paymentService.createPaymentIntent(paymentInfoRequest);
        String paymentStr = paymentIntent.toJson();

        return new ResponseEntity<>(paymentStr, HttpStatus.OK);
    }
}

```

#### application.property
漏洩したら困る情報なのでぼかしています。
```application.properties
stripe.key.secret=XXXXXXXXXXXXXXXXXXX
```





# 実装後の確認
PostmanでSpringBootのRestApiを叩いて支払情報を作成します。
以下gifアニメはその時の画像です。
左側はPostman　右側はブラウザで開いたStripeの画面です。
支払い情報が新規に作成されたことを確認できます。支払いの状態は未完了です。Postmanのレスポンスからクライアントシークレットが入っていることを確認できます。
クライアントシークレットは決済を完了させる必要な値で実装上必須な値です。
![Stripe実装完了１１.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/8eaa752c-9c56-54d0-c96e-0601eca2df8e.gif)







# 他にやったこと
## 公式を参照するとJavaとReactの例がある！しかし…

公式サイトを参照すると、JavaとReactのサンプルコードが書かれています。
しかしSparkFrameWorkの例が書かれており、SpringBootの場合ではありません。

https://stripe.com/docs/checkout/quickstart?client=react&lang=java

スクショ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/d76a2a66-1ab6-92ba-2672-a37b72efb182.png)


# 参考
Section34 Stripe Payment Processing 

https://www.udemy.com/course/full-stack-react-and-java-spring-boot-the-developer-guide/learn/lecture/33402204#content

https://github.com/darbyluv2code/fullstack-react-and-springboot/tree/main/source-code/fullstack-library-app-https/02-backend/spring-boot-library/spring-boot-library/src/main/java/com/luv2code/springbootlibrary