決済API【Stripe】を使って商品の一覧を取得【Next.js×Laravel連携】

今回は、オンライン決済のAPI<b>Stripe</b>を使って、Stripeのダッシュボードに
登録された商品を取得する方法を載せておきます。

# サンプル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/a4b21bca-e163-4d1b-bd7e-5006b12fe1bd.png)

# 1. Stripeでの商品と価格の関係
Stripeでは、商品は`Product`として定義され、価格はPriceオブジェクトとして管理されています。商品ごとに複数の価格が設定できる場合もありますが、通常、最初に設定された価格（`default_price`）を取得することが多いです。

# 2. default_priceのIDを使って価格情報を取得
商品には`default_price`というフィールドがあり、これを使用して、関連する価格情報を取得する必要があります。`default_price`は`Price`オブジェクトのIDですので、このIDを使って実際の価格情報を取得します。

# 3. 解決方法
現在、`default_price`のみ取得している状態から、実際の価格（例: 20 USD）を取得するには、`default_price`のIDを使用して価格情報を取得する必要があります。

以下のように、Productを取得した後に、Priceオブジェクトを追加で取得することで価格情報を表示することができます。

# フロント側(Next.js)のコード

```frontend/app/products/getListProducts/page.tsx
'use client'
import { useEffect,useState } from "react"
import axios from "axios"

export default function AllListProducts(){
    const [products,setProducts] = useState<any[]>([]);
    const [newProduct,setNewProduct] = useState({
        name:'',
        description:'',
        price:0
    });

    useEffect(()=>{
        //Get List of all products.
        axios.get('http://localhost:8000/api/stripe/products').then((response)=>{
            setProducts(response.data.data);
        });
    },[]);

    const handleCreateProduct = async(e:React.FormEvent)=>{
        e.preventDefault();
        //Register product
        await axios.post('http://localhost:8000/api/stripe/create-product',newProduct);

        //Reget all of products
        const response = await axios.get('/api/stripe/products');
        setProducts(response.data);
        setNewProduct({name:'',description:'',price:0});
    };

    return (
        <div>
            <h1 className="font-bold">Product List</h1>
            <ul>
                {products.map((product)=>(
                    <li key={product.id}>
                        {product.name}-{product.description}-{product.price} USD
                        <img src={product.images[0]} style={{width:100}}></img>
                    </li>
                ))}
            </ul>
            <h2>Register product</h2>
            <form onSubmit={handleCreateProduct}>
                <div>
                    <label>Name</label>
                    <input
                        type="text"
                        value={newProduct.name}
                        onChange={(e)=>setNewProduct({...newProduct,name:e.target.value})}
                    />
                </div>
                <div>
                    <label>Description</label>
                    <input
                        type="text"
                        value={newProduct.description}
                        onChange={(e)=>setNewProduct({...newProduct,description:e.target.value})}
                    />
                </div>
                <div>
                    <label>Price</label>
                    <input
                        type="number"
                        value={newProduct.price}
                        onChange={(e)=>setNewProduct({...newProduct,price:Number(e.target.value)})}
                    />
                </div>
                <button 
                    type="submit"
                    className="bg bg-blue-500 rouded-md text-white px-4 py-4 cursor:text-pointer hover:bg-blue-700"
                    >
                    Create Product
                </button>
            </form>
        </div>
    )
}

```

# バックエンド(Laravel)のコード

```backend/routes/api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\StripeController;//Add
use App\Http\Controllers\AdminRegisterController;//Add

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Route::post('/stripe/create-product',[StripeController::class,'createProduct']);
Route::get('/stripe/products',[StripeController::class,'listProducts']);
Route::delete('/stripe/delete-product/{productId}',[StripeController::class,'deleteProduct']);
Route::put('/stripe/update-product/{productId}',[StripeController::class,'updateProduct']);

Route::post('/adminRegistration',[AdminRegisterController::class,'createAdminUser']);

```
さいごに、

ここでは、
`Price::retrieve($product->default_price) `で、`default_price`のIDを使って価格を取得しています。
取得したPriceオブジェクトから、`unit_amount`（価格）と`currency`（通貨）を取得し、それを商品情報に追加しています。
価格は`unit_amount`がセント単位で返されるため、100で割ってドル（または他の通貨）単位に変換しています。

```backend/app/Http/Controllers/StripeController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Stripe\Stripe;//Add
use Stripe\Product;//Add
use Stripe\Price;//Add

class StripeController extends Controller
{
    //Method to create product
    public function createProduct(Request $request){
        Stripe::setApiKey(env('STRIPE_SECRET_KEY'));

        //Create Product
        $product = Product::create([
            'name'=>$request->name,
            'description'=>$request->description,
        ]);

        //Set price
        $price = Price::create([
            'unit_amount'=>$request->price*100,
            'currency'=>'USD',
            'product'=>$product->id,
        ]);

        return response()->json(['product'=>$product,'price'=>$price]);
    }

    //Methos to list all products
    public function listProducts()
    {
        Stripe::setApiKey(env('STRIPE_SECRET_KEY'));
        try{
            //Get list of all products
            $products = Product::all();
            foreach($products->data as &$product){
                if(isset($product->default_price)){
                    $price = Price::retrieve($product->default_price);
                    $product->price = $price->unit_amount / 100;
                    $product->currency = $price->currency;
                }
            }
            return response()->json($products);
        }catch(\Exception $e){
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }
    //Method to delete product
    public function deleteProduct($productId)
    {
        Stripe::setApiKey(env('STRIPE_SECRET_KEY'));
        //Delete product
        $product = Product::retrieve($productId);
        $product->delete();

        return response()->json(['status'=>'success']);
    }

    //Method to update product
    public function updateProduct($productId,Request $request)
    {
        Stripe::setApiKey(env('STRIPE_SECRET_KEY'));
        //Update product
        $product = Product::retrieve($productId);
        $product->name = $request->name;
        $product->description = $request->description;
        $product->save();
        return response()->json($product);
    }
}

```