【2025年版】PHPとStripeを用いてサイト内にクレカ決済及びキャンセル機能を実装する方法
2025/06/25
5年ほど前にPHPとStripeを用いたクレカ決済機能をテスト実装したが最近試したところ動作しなかった。調べてみるとStripe Checkoutのバージョンが新しくなったらしく、そちらが原因っぽい。そのため現行のバージョンでのクレカ決済及びキャンセル機能の実装方法をメモ。尚、2025年6月時点で動作確認済み。
目次
やりたいこと
やりたいことは以下の二点になる。
- サブスクは無しで1回限りのクレジットカード決済の実装
- クレジットカード決済後のキャンセル(返金)処理の実装
下準備
Stripeのアカウント作成
Stripe公式サイトでアカウントを作成しておく。
登録するとテスト用の「公開可能キー」「シークレットキー」が発行されるのでメモっておく。
ライブラリのインストール
サーバにSSH接続し適当なディレクトリに移動後、以下でライブラリをインストールする。
composer require stripe/stripe-php
ライブラリの要件はPHP5.6.0以降とのこと。尚、当方の環境はPHP8.3.3になる。
テスト用クレジットカード
テスト用のクレジットカードはこちらのページより確認できる。有効期限は「12 / 34」等の未来日付、セキュリティコードは「123」等の任意の3桁の数値となる。
クレジットカード決済機能の実装方法
基本的には公式サイトのドキュメントと同じソースコードになる。
secrets.php(シークレットキーの保存場所)
シークレットキーはメモったものに書き換えること。
<?php $stripeSecretKey = 'sk_test_xxxxx';
checkout.php(決済処理)
「$domain(サイトのURL)」「name(商品名)」「unit_amount(金額)」部分は適宜変更すること。
決済成功時、MySQLにデータを登録したいような場合はsuccess_urlに遷移後、行う必要あり。そのため何らかのパラメータを送る場合はsession_idの後ろにGETパラメータを付与するか、セッションとして引き回す形になりそう。
<?php
require_once './vendor/autoload.php';
require_once 'secrets.php';
\Stripe\Stripe::setApiKey($stripeSecretKey);
header('Content-Type: application/json');
$domain = 'https://test.com/checkout';
$checkout_session = \Stripe\Checkout\Session::create([
'payment_method_types' => ['card'],
'line_items' => [[
'price_data' => [
'currency' => 'JPY',
'product_data' => [
'name' => '商品名',
],
'unit_amount' => 200,
],
'quantity' => 1,
]],
'mode' => 'payment',
'success_url' => $domain . '/success.php?session_id={CHECKOUT_SESSION_ID}',
'cancel_url' => $domain . '/error.php?session_id={CHECKOUT_SESSION_ID}',
]);
header("HTTP/1.1 303 See Other");
header("Location: " . $checkout_session->url);
index.php(決済用フォームの設置ページ)
form内に「input type="hidden"」を設置し、送信後に上記のcheckout.phpで受け取ることも可能。
<!DOCTYPE html>
<html lang="ja">
<html>
<head>
<script src="https://js.stripe.com/v3/"></script>
</head>
<body>
<section>
<form action="./checkout.php" method="POST">
<button type="submit" id="checkout-button">購入</button>
</form>
</section>
</body>
</html>
error.php(決済失敗時に表示されるページ)
こちらは以下のようなHTMLべた書きでも問題ない。
<!DOCTYPE html> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> </head> <body> エラー </body> </html>
success.php(決済成功時に表示されるページ)
<?php require_once './vendor/autoload.php'; require_once 'secrets.php'; $stripe = new \Stripe\StripeClient($stripeSecretKey); $session = $stripe->checkout->sessions->retrieve($_GET['session_id'], []); var_dump($session->payment_intent);
var_dumpでは以下のような値が出力される筈。
こちらpayment_intentとなり決済キャンセル時に必要なIDになるのでMySQL等に保存した方が良い。
string(27) "pi_xxxxxxxxxx"
決済キャンセル(返金)処理の実装方法
こちらも基本的には公式サイトのドキュメントと同じソースコードになる。
cancel.php
payment_intent(pi_xxxxxxxxxx部分)の部分は前述のsuccess.phpで取得したIDに変更すること。
<?php require_once './vendor/autoload.php'; require_once 'secrets.php'; $stripe = new \Stripe\StripeClient($stripeSecretKey); $refund = $stripe->refunds->create(['payment_intent' => 'pi_xxxxxxxxxx']); var_dump($refund);
var_dumpでは以下のような値が出力される筈。そのため正常に処理されたかのチェックは「$refund->status」が「succeeded」になっているかどうかを見るのが良さそう。
object(Stripe\Refund)#16 (15){
["id"]=> string(27) "re_xxxxxxxxxx"
["object"]=> string(6) "refund"
["amount"]=> int(200)
["balance_transaction"]=> string(28) "txn_xxxxxxxxxx"
["charge"]=> string(27) "ch_xxxxxxxxxx"
["created"]=> int(1749486797)
["currency"]=> string(3) "jpy"
["destination_details"]=> object(Stripe\StripeObject)#21 (2) {
["card"]=> object(Stripe\StripeObject)#26 (3) {
["reference_status"]=> string(7) "pending"
["reference_type"]=> string(25) "acquirer_reference_number"
["type"]=> string(6) "refund"
}
["type"]=> string(4) "card"
}
["metadata"]=> object(Stripe\StripeObject)#22 (0) { }
["payment_intent"]=> string(27) "pi_xxxxxxxxxx"
["reason"]=> NULL
["receipt_number"] => NULL
["source_transfer_reversal"]=> NULL
["status"]=> string(9) "succeeded"
["transfer_reversal"]=> NULL
}
その他
JCBカードが使えない
テスト用JCBクレジットカードで試したところ決済が通らなかった。公式にサイトによると本番環境の利用が可能になるとJCBも受付可能になるとのこと。そのためテスト環境では利用不可。
所感
決済完了後、別ページに遷移してからデータベースに登録する形になるのがセキュリティ的にやや不安。
payment_intent(pi_xxxxxxxxxx部分)はStripe側が発行するsession_idを元に呼び出せるので問題無さそうだが、それ以外のデータを登録する際にGETパラメータで渡す場合はちょっと面倒だが復号可能な形で暗号化して渡す方が良いかも。もしくはセッションとして保持しておいて受け取り側でデータベース登録等、何らかの処理が完了次第セッションを破棄する形になるかと。
参考サイト
https://qiita.com/p_s_m_t/items/e665a3492b80ea7fc7df
https://docs.stripe.com/checkout/quickstart?client=html&lang=php&locale=ja-JP
https://docs.stripe.com/refunds?locale=ja-JP&dashboard-or-api=api
関連記事
-
-
PHPとStripeで定額課金(サブスクリプション)実装する方法
PHPとStripeで1ヶ月ごとに500円でサイト内のサービスを使い放題、といっ ...
-
-
Stripe Checkoutにてクレジットカード決済の際に3Dセキュア対応にする方法
先日Stripe Checkoutを用いたクレジットカード決済機能についてメモし ...
-
-
PHPとStripeを使ってサイト内でクレジットカード決済処理の実装方法
PHPとStripeの組み合わせでWebサービスにクレジットカード決済処理を導入 ...
-
-
PHPにてサイトにPayPay決済システム及び決済キャンセル機能を実装する方法
ここのところクレジットカード決済関連のメモを書いているが、他の決済方法についても ...
-
-
PHPとPAY.JPを用いてサイト内にクレカ決済及びキャンセル機能を実装する方法
先日PHPとStripeを用いてサイト内にクレカ決済及びキャンセル機能を実装する ...