Stripeを使ったクレジットカード自動引き落としシステムの実装
- LOGZA WEB
- ホームページ制作の技術的な取り組み
- Stripeを使ったクレジットカード自動引き落としシステムの実装
クレジットカードによる自動引き落とし(サブスクリプション決済)は、会員制サービスや月額課金ビジネスにおいて重要な機能のひとつです。
ここでは、LOGZA WEB(ログザウェブ)が実際の制作現場で導入しているStripeを利用したクレジットカード自動引き落としシステムの実装方法をもとに、決済処理の構成や設計ポイントを解説します。
ファイル構成
本システムでは、Stripeによるクレジットカード自動引き落とし処理を中心に、会員申込から決済完了までの一連の流れを複数ファイルで構成しています。
決済処理はStripe Checkoutを利用し、入力ページ → 決済処理 → 完了処理の構成で実装しています。
なお、会員申込開始ページおよび会員規約同意ページについては、本記事の主旨から外れるため詳細説明は省略しています。
index.php ← トップページ
├─ join/
│ ├─ index.php ← 会員申込を始めるページ
│ ├─ step2.php ← 会員規約同意書の合意ページ
│ ├─ step3.php ← 会員申込入力ページ
│ ├─ stripe.php ← Stripe Checkout生成・決済遷移処理
│ ├─ success.php ← 決済完了ページ(DB更新・メール送信)
│
└─ phps/
└─ step3.php ← 入力処理(会員登録・Stripe顧客作成・セッション管理)
入力フォーム送信後からStripe決済画面表示までの処理
まずクレジットカードでの自動引き落とし条件を設定する為、会員登録フォームなどで、プラン内容に応じた支払いサイクルや料金情報を入力します。
入力された内容をもとに決済条件を判定し、Stripeのクレジットカード入力画面へ進みます。
- 入会金の有無
- 支払いサイクル(月額・年額・単発など)
- 支払い料金
- オプション追加の有無
- 利用者情報(氏名・メールアドレスなど)
- join/step3.php:入力フォーム(画面)
- phps/step3.php:送信処理(DB登録・Stripe Customer作成・セッション保存)
① Stripeライブラリの読み込みとAPIキー設定
下記コードを「phps/step3.php」に記載します。
require '../admin/vendor/autoload.php';
\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY);
Stripeと通信して決済処理を行うためには、Stripeが提供している公式PHPライブラリを読み込む必要があります。
そのため、Composerでインストールされたオートロードファイル(vendor/autoload.php)を読み込みます。
STRIPE_SECRET_KEY には、Stripe管理画面で取得したシークレットAPIキーを設定します。
このキーを設定することで、サーバー側からStripeへ顧客作成や決済処理などの操作を実行できるようになります。
② Stripe顧客(Customer)の作成
下記コードを「phps/step3.php」に記載します。
$customer = \Stripe\Customer::create([
'email' => $_POST['email'],
'name' => $_POST['name'],
'metadata' => [
'member_id' => $member_id
]
]);
$_SESSION['stripeCustomerId'] = $customer->id;
Stripe側に顧客情報を作成し、会員IDをmetadataとして保存することで、決済完了後の会員管理システムとの連携を容易にしています。
なお、email や name の設定は必須ではありませんが、Stripe管理画面で顧客情報を確認しやすくするため登録しています。
③ セッション保存と決済ページへの遷移
下記コードを「phps/step3.php」に記載します。
$_SESSION['member_id'] = $member_id;
$_SESSION['user_plan'] = $_POST['plan'];
$_SESSION['user_name'] = $_POST['name'];
$_SESSION['user_email'] = $_POST['email'];
header("Location: /join/stripe.php");
exit;
会員情報や申込内容をセッションへ保存し、 Stripe Checkout(クレジットカード入力画面)を生成する処理へ遷移します。
Stripeの決済画面は自社サーバー上ではなく外部サービス(Stripe)側に表示されるため、 決済に必要な情報を一時的にセッションへ保持し、 次の処理でCheckoutセッションを作成する構成としています。
④ 実装例(全体コード)
上記で説明した3つが入力フォーム送信後からStripe決済画面表示までの処理で最低限必要な処理となります。
実際には会員情報の登録や更新処理が入りますが、ここではStripe連携部分を中心に「phps/step3.php」に記載する内容をまとめております。
<?php
session_start();
require_once $_SERVER['DOCUMENT_ROOT'] . '/db/db.php';
require '../admin/vendor/autoload.php';
\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY);
// =============================
// 入力送信時処理
// =============================
if (isset($_POST['confirmbtn'])) {
// --------------------------------------------------
// 会員情報をDBへ登録処理を記載(割愛)
// --------------------------------------------------
// サンプル用(登録済み想定)
$member_id = $_POST['member_id'] ?? 1;
// =============================
// Stripe Customer作成
// =============================
$customer = \Stripe\Customer::create([
'email' => $_POST['email'],
'name' => $_POST['name'],
'metadata' => [
'member_id' => $member_id
]
]);
$_SESSION['stripeCustomerId'] = $customer->id;
// =============================
// セッション保存
// =============================
$_SESSION['member_id'] = $member_id;
$_SESSION['user_plan'] = $_POST['plan'];
$_SESSION['user_name'] = $_POST['name'];
$_SESSION['user_email'] = $_POST['email'];
// =============================
// 決済ページへ遷移
// =============================
header("Location: /join/stripe.php");
exit;
}
なお、申込時点ではStripeの顧客IDや決済情報はデータベースへ保存せず、決済完了後の処理で登録する構成としています。これにより未決済状態の顧客データ登録を防止しています。
また、クレジットカード情報はStripe側で安全に管理されるため、サーバー側でカード番号などの機密情報を保持することはありません。
Stripe決済画面(Checkout)を生成して表示する処理
前の処理で保存した申込内容やプラン情報をもとに、Stripeのクレジットカード入力画面(Checkout)を生成します。
この処理では決済金額や支払いサイクル、オプション料金などを設定し、Stripeが提供する安全な決済ページへ自動的にリダイレクトします。
① Stripeライブラリの読み込みとAPIキー設定
下記コードを「join/stripe.php」に記載します。
require("../admin/vendor/autoload.php");
\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY);
こちらのページにもStripeと通信して決済処理を行うため、Stripeが提供している公式PHPライブラリを読み込む必要があります。
② キャンペーンがある場合の処理
キャンペーン期間中のみ料金を変更したい場合は、条件を判定して入会金や割引内容を設定します。
下記コードを「join/stripe.php」に記載します。
// 年単位判定
$isYearly = ($course_cycle === '年単位');
// =============================
// キャンペーン判定
// =============================
$campaign_end = new DateTime('2026-06-01');
$campaign = (new DateTime() < $campaign_end);
// 入会金計算
$entryPrice = $Sprice_course;
if ($campaign) {
$entryPrice = 0;
}
// 初月割引
if ($campaign && !$isYearly) {
$params['discounts'] = [
['coupon' => 'クーポンコード']
];
}
入会金無料などの金額変更はPHP側で計算し、月額料金の割引はStripeで作成したクーポンコードを適用することで実現できます。
また、年額プランには割引を適用しないなど、支払いサイクルに応じた条件分岐も簡単に実装可能です。
③ 決済内容(Line Items)の生成
Stripeで決済を行うためには、請求対象となる料金情報を配列(line_items)として作成する必要があります。
本システムでは、入会金・月額料金・オプション料金などを条件に応じて追加し、決済内容を構成しています。
下記コードを「join/stripe.php」に記載します。
// =============================
// Line Items生成
// =============================
$lineItems = [];
// 入会金(0円の場合は追加しない)
if ($entryPrice > 0) {
$lineItems[] = [
'price_data' => [
'currency' => 'jpy',
'product_data' => [
'name' => '入会金',
'description' => '入会時費用'
],
'unit_amount' => $entryPrice,
],
'quantity' => 1,
];
}
// 月額・年額プラン
if ($stripe_price_id_course) {
$lineItems[] = [
'price' => $stripe_price_id_course,
'quantity' => 1,
];
}
// オプション料金
if (!empty($stripe_price_id_cs) && $user_cs === '追加') {
$lineItems[] = [
'price' => $stripe_price_id_cs,
'quantity' => 1,
];
}
Stripeでは0円の料金を送信するとエラーになるため、入会金が無料の場合はline_itemsへ追加しない処理を行っています。
月額料金や年額料金については、Stripe側で作成したPrice IDを指定することで、サブスクリプション決済として自動引き落としが行われます。
④ Checkoutセッションの作成と決済画面への遷移
決済内容(line_items)が作成できたら、 Stripe Checkoutセッションを生成し、 クレジットカード入力画面へリダイレクトします。
下記コードを「join/stripe.php」に記載します。
// =============================
// Checkout作成パラメータ
// =============================
$params = [
'payment_method_types' => ['card'],
'line_items' => $lineItems,
'mode' => 'subscription',
'customer' => $customerId,
'success_url' =>
'https://example.com/join/success.php?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' =>
'https://example.com/join/step3.php?error=cancelled',
];
// =============================
// Checkoutセッション生成
// =============================
$session = \Stripe\Checkout\Session::create($params);
// =============================
// Stripe画面へリダイレクト
// =============================
echo "<script src='https://js.stripe.com/v3/'></script>
<script>
var stripe = Stripe('YOUR_PUBLIC_KEY');
stripe.redirectToCheckout({ sessionId: '" . $session->id . "' });
</script>";
payment_method_types は利用可能な決済方法を指定します。ここではクレジットカード決済のみを許可しています。
line_items には請求対象となる料金情報(入会金・月額料金・オプションなど)を設定します。
mode は決済種別を指定する項目で、サブスクリプション(自動引き落とし)の場合は subscription を指定します。
customer には事前に作成したStripe Customer IDを指定し、 どの顧客の決済かを紐付けます。
success_url は決済成功時の遷移先URL、 cancel_url は決済途中キャンセル時の戻り先URLを設定します。
最後にCheckoutセッションIDをJavaScriptへ渡し、 Stripeの決済画面へ自動的にリダイレクトします。
⑤ 実装例(全体コード)
上記で説明した4つがStripe決済画面(Checkout)を生成して表示する処理で最低限必要な処理となります。
ここではStripe連携部分を中心に「join/stripe.php」に記載する内容をまとめております。
<?php
session_start();
require("../db/db.php");
require("../admin/vendor/autoload.php");
\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY);
// =============================
// セッション取得
// =============================
$user_plan = $_SESSION['user_plan'] ?? '';
$user_cs = $_SESSION['user_cs'] ?? '';
$customerId = $_SESSION['stripeCustomerId'] ?? null;
// =============================
// コース情報取得(DB管理)
// =============================
$sql = "
SELECT id, course_name, shoki_price, course_price, course_cycle, stripe_price_id
FROM courseinfo
WHERE id = :user_plan
OR course_name LIKE :course_name
";
$params = [
':user_plan' => $user_plan,
':course_name' => '%オプション%'
];
$result = execPrep($sql, $params);
// 初期化
$course_cycle = '';
$entryPrice = 0;
$stripe_price_id_course = null;
$stripe_price_id_cs = null;
// コース判定
foreach ($result as $row) {
if ($row['id'] == $user_plan) {
$entryPrice = $row['shoki_price'];
$stripe_price_id_course = $row['stripe_price_id'];
$course_cycle = $row['course_cycle'];
}
if (strpos($row['course_name'], 'オプション') !== false) {
if ($row['course_cycle'] === $course_cycle) {
$stripe_price_id_cs = $row['stripe_price_id'];
}
}
}
// =============================
// 年単位判定
// =============================
$isYearly = ($course_cycle === '年単位');
// =============================
// キャンペーン判定
// =============================
$campaign_end = new DateTime('2026-06-01');
$campaign = (new DateTime() < $campaign_end);
// 入会金無料処理
if ($campaign) {
$entryPrice = 0;
}
// =============================
// Line Items生成
// =============================
$lineItems = [];
// 入会金(0円なら追加しない)
if ($entryPrice > 0) {
$lineItems[] = [
'price_data' => [
'currency' => 'jpy',
'product_data' => [
'name' => '入会金',
],
'unit_amount' => $entryPrice,
],
'quantity' => 1,
];
}
// 月額・年額プラン
if ($stripe_price_id_course) {
$lineItems[] = [
'price' => $stripe_price_id_course,
'quantity' => 1,
];
}
// オプション料金
if (!empty($stripe_price_id_cs) && $user_cs === '追加') {
$lineItems[] = [
'price' => $stripe_price_id_cs,
'quantity' => 1,
];
}
// =============================
// Checkout作成
// =============================
$params = [
'payment_method_types' => ['card'],
'line_items' => $lineItems,
'mode' => 'subscription',
'customer' => $customerId,
'success_url' =>
'https://example.com/join/success.php?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' =>
'https://example.com/join/step3.php?error=cancelled',
];
// 初月割引クーポン(月額のみ)
if ($campaign && !$isYearly) {
$params['discounts'] = [
['coupon' => 'クーポンID']
];
}
// =============================
// Checkoutセッション生成
// =============================
$session = \Stripe\Checkout\Session::create($params);
// =============================
// Stripe画面へリダイレクト
// =============================
echo "<script src='https://js.stripe.com/v3/'></script>
<script>
var stripe = Stripe('YOUR_PUBLIC_KEY');
stripe.redirectToCheckout({ sessionId: '" . $session->id . "' });
</script>";
?>
上記コードでは、セッションに保存された申込内容をもとに 決済金額・支払いサイクル・オプション料金などを設定し、 Stripe Checkoutセッションを生成しています。
また、StripeのPrice IDをデータベースで管理することで、 プラン変更や料金改定にも柔軟に対応できる構成としています。
決済完了後の会員登録確定処理(success.php)
Stripe決済完了後は success_url に指定したページへ遷移します。 このページではStripeのCheckoutセッションを取得し、決済結果を確認したうえで 会員情報へStripeの顧客ID・サブスクリプション情報を保存します。
本システムでは、決済成功(paid)が確認できた場合のみ 登録を確定し、実行する構成としています。
① session_id を受け取り、Checkoutセッションを取得
下記コードを「success.php」に記載します。
<?php
session_start();
require_once $_SERVER['DOCUMENT_ROOT'] . '/db/db.php';
require_once $_SERVER['DOCUMENT_ROOT'] . '/admin/vendor/autoload.php';
\Stripe\Stripe::setApiKey(STRIPE_SECRET_KEY);
// session_id取得(success_url から渡される)
if (empty($_GET['session_id'])) {
die('invalid access');
}
$session_id = $_GET['session_id'];
// Checkoutセッション取得
$session = \Stripe\Checkout\Session::retrieve($session_id);
$customer_id = $session->customer;
$subscription_id = $session->subscription;
$payment_status = $session->payment_status;
success_url に付与された session_id を利用して、Stripeから 決済結果(payment_status)と顧客ID・サブスクリプションIDを取得します。
② サブスクリプション情報を取得して「契約アイテムID」を特定
下記コードを「success.php」に記載します。
// サブスクリプション取得(契約内容の詳細)
$subscription = \Stripe\Subscription::retrieve($subscription_id);
$subscriptionItemId = null;
// 契約アイテムID取得
foreach ($subscription->items->data as $item) {
$subscriptionItemId = $item->id;
}
Stripeのサブスクリプションには複数の契約項目(items)が含まれる場合があります。 後からプラン変更や解約を行う際にはこの item id が必要になるため、 サブスクリプションIDとあわせて保存しておきます。
③ 決済成功(paid)のときだけDBへ保存して登録を確定
下記コードを「success.php」に記載します。
if ($payment_status === 'paid') {
$sql = "
UPDATE members SET
stripe_customer_id = :customer,
stripe_subscription_id = :subscription,
stripe_subscription_item = :item
WHERE member_id = :id
";
execPrep($sql, [
':customer' => $customer_id,
':subscription' => $subscription_id,
':item' => $subscriptionItemId,
':id' => $_SESSION['member_id']
]);
}
「未決済・失敗」の状態でDBを確定させないため、 決済成功(paid)の場合のみStripe情報を保存する構成にしています。
動作確認・テスト手順
以上でStripeを使ったクレジットカード自動引き落としシステムの実装は完了となります。
決済処理が正常に動作するか、下記の手順で確認します。
- ① 入力フォームから会員情報とプランを選択して送信する
- ② Stripeのクレジットカード入力画面へ遷移するか確認する
- ③ テスト用カード番号を入力して決済を実行する
- ④ success_url に設定した完了ページへ遷移するか確認する
- ⑤ Stripe管理画面に顧客(Customer)とサブスクリプションが作成されているか確認する
- ⑥ 会員情報にStripe顧客ID・サブスクリプションIDが保存されているか確認する
Stripe管理画面およびデータベースの両方に情報が登録されていることを確認し完了となります。