決済ページ関連 — ポイント課金システム (Stripe 単発決済)
// PAYMENT — 最終更新: 2026-05-14 / 2026-04-10 ポイント方式に全面移行済
運用中 Stripe PaymentIntent (単発決済) + ポイント1pt=1円 + 月次自動消費
1. 概要 — サブスク廃止 → ポイントプリペイド
従来の Stripe サブスクリプション (自動引き落とし) を廃止し、 ポイントプリペイド方式 に全面移行 (2026-04-10)。 顧客は任意のタイミングでポイントを購入し、 毎月の支払日にポイントから月額分が自動消費される。 カード変更時の決済失敗リスクを解消。
1pt = 1円。 最低購入額: 500pt (継続購入) / 月額分 (初回購入)。 既存契約はすべてテストのため顧客への影響ゼロで移行完了。
2. 決済フロー
// 2-1. 新規申し込み (フォームA / katuocloud.com/plan1/)
顧客がフォーム入力 → Stripe PaymentIntent (単発決済)
→ succeeded 確認 → maguro で契約 + NCアカウント作成
→ ポイント加算 → 課金情報初期化 → thank-you ページ
決済失敗 or 3DS未完了 → アカウント作成しない (エラー返却)
契約作成失敗 → Stripe 自動返金
// 2-2. 継続ポイント購入 (フォームB / katuocloud.com/continuation-contract-points/)
契約ID + パスフレーズで認証
→ 購入額選択 (月額単位 or 500円単位)
→ Stripe PaymentIntent (単発決済)
→ succeeded 確認 → maguro にポイント加算
// 2-3. 月次自動処理 (billing_daily.py / 00:30)
毎日 0:30 実行 (systemd: billing-daily.timer)
1. next_payment_at 到来の契約を検索
2. ポイント残高 ≥ 月額 → ポイント消費、 next_payment_at +30日
3. 残高不足 → billing_status='warning' + Telegram通知 (運営宛)
4. warning 後7日経過 → billing_status='suspended'
→ WireGuard peer 無効化 (wg-clients.conf コメントアウト + wg set wg-clients remove)
→ Nextcloud ユーザー無効化 (occ user:disable)
5. 手動削除が必要な場合は管理画面 /ui/billing から契約解除
顧客への未払い連絡は自動化していない: delivery_method (Telegram/Email/SMS) を確認して運営が手動で連絡する運用。 自動メール送信は誤送信リスクが高いため意図的に止めている。
3. DB 変更 (mikyun_cloud)
// contracts テーブル追加カラム
| カラム | 型 | 用途 |
point_balance | INT DEFAULT 0 | ポイント残高 (1pt=1円) |
monthly_amount | INT DEFAULT 1980 | 月額料金 (自動計算) |
billing_warning_at | DATETIME NULL | 残高不足警告日 |
billing_suspended_at | DATETIME NULL | アクセス停止日 |
// 新規テーブル: point_transactions
| カラム | 型 | 用途 |
id | BIGINT AUTO_INCREMENT PK | ID |
contract_id | VARCHAR(32) | 契約ID |
type | ENUM(‘charge’,’monthly_deduct’,’refund’,’manual_adjust’) | 取引種別 |
amount | INT | 金額 (正=加算、 負=消費) |
balance_after | INT | 取引後残高 |
stripe_payment_intent_id | VARCHAR(128) NULL | Stripe PI ID |
note | TEXT NULL | 備考 |
created_at | DATETIME | 作成日時 |
4. maguro FastAPI 新規エンドポイント (mikyun-portal)
| エンドポイント | 認証 | 用途 |
POST /api/points/verify | なし (passphrase) | 契約認証 + 残高返却 (フォームB用) |
POST /api/points/charge | Basic認証 | ポイント加算 (WordPress → maguro) |
POST /api/points/adjust | Basic認証 | 手動ポイント加減算 (管理者用) |
GET /ui/contracts/{id}/billing | Basic認証 | 課金情報 + 履歴取得 |
POST /api/billing/init | Basic認証 | 課金初期化 (月額自動計算 + 次回支払日設定) |
Basic認証: admin / .env 内 ADMIN_PASS (旧ハードコード 243Katuokun4144! は撤去済)
5. WordPress (R640) 変更 — functions.php
WordPress は R640 /var/www/katuocloud/wp-content/themes/astra-child/functions.php で稼働。 旧 xserver VPS 版の機能は 2026-05-14 R640 移行時にそのまま継承。
// 5-1. 新規ヘルパー関数
| 関数 | 用途 |
katuocloud_stripe_api($endpoint, $data) | Stripe REST API 直接呼出 |
katuocloud_charge_points($contract_id, $amount, $pi_id) | maguro へポイント加算依頼 |
katuocloud_init_billing($contract_id, $monthly_amount) | maguro へ課金初期化依頼 |
// 5-2. 新規 REST API エンドポイント
| エンドポイント | 用途 |
POST /wp-json/katuocloud/v1/verify-contract | 契約認証プロキシ |
POST /wp-json/katuocloud/v1/purchase-points | 継続ポイント購入 |
POST /wp-json/katuocloud/v1/my-billing | マイページ課金情報取得 |
// 5-3. 新規ショートコード
| ショートコード | 設置ページ | 用途 |
[katuocloud_point_purchase] | /continuation-contract-points/ | 継続ポイント購入フォーム |
[katuocloud_mypage] | /point-my-page/ | 顧客マイページ (残高 / 履歴) |
6. 月額料金計算ロジック
基本料金: ¥1,980 (3端末 + 200GB)
端末追加: (max_devices - 3) × ¥500/月
容量追加: (storage_quota_gb - 200) ÷ 100 × ¥500/月
例: 1000GB / 3端末 = 1,980 + 0 + 4,000 = ¥5,980/月
例: 200GB / 5端末 = 1,980 + 1,000 + 0 = ¥2,980/月
maguro 側 calc_monthly_amount() と WordPress JS の updatePricing() で同一ロジック。 /api/billing/init に monthly_amount=0 を渡すと DB から自動計算。
7. Stripe 設定 (変更履歴)
| 項目 | 旧 (廃止) | 現行 |
| 決済方式 | Subscription (自動引き落とし) | PaymentIntent (単発決済) |
| 商品 / Price | 3つの Price ID 使用 (BASE / DEVICE / STORAGE) | 不使用 (金額直接指定) |
| 3D セキュア | 未確認 | status=succeeded 必須 |
| SureCart | インストール済 (未使用) | 無効化推奨 |
| ゲスト招待ビデオ (price_1TIg2jDxP0kEA5q8qeDO28f9) | 未販売のまま提供 | 2026-04-05 完全削除 |
Stripe Dashboard で既存のサブスクリプション商品は単発に変更済。 旧 Price ID (BASE/DEVICE/STORAGE) は maguro mikyun-portal コードから完全除去済。
8. バグ修正 (SSH → ローカル実行)
2026-04-10 移行時、 旧コードで wg0 操作が SSH 経由 (ssh root@10.250.0.1) になっていた箇所をローカル実行に修正。 旧 wg2 バックホール (R640 → VPS 162.43.8.20) の遺物だった。
| ファイル | 関数 | 修正内容 |
client_ui.py | load_wg_status() | ssh wg show → ローカル wg show wg-clients dump |
wg_traffic_collector.py | get_wg_dump() | 同上 |
mikyun_vpn_engine.py | block_device_ip() | ssh wg set remove → ローカル wg set wg-clients remove |
mikyun_vpn_engine.py | unblock_device_ip() | ssh wg set → ローカル + PSKファイル |
mikyun_vpn_engine.py | add_peer_to_vps_wg0() | ssh wg set → ローカル + PSKファイル (関数名は歴史的経緯で残存、 実際は wg-clients 操作) |
maguro Docker 化後 (2026-05-14): wg コマンドは Docker コンテナ内から実行 (NET_ADMIN capability + /etc/wireguard bind mount)。 SSH 経由のリモート WG 操作は完全廃止。
9. systemd タイマー・サービス (maguro)
| 名前 | スケジュール | 用途 |
billing-daily.timer | 毎日 00:30 | ポイント月次消費 + warning + suspended |
mikyun-portal (Docker) | 常駐 :9000 / :9081 | FastAPI 管理ポータル + VPN Engine |
旧 R640 ホスト直 mikyun-cloud.service / mikyun-vpn-engine.service は退役済。
10. 管理画面 — 入金管理 (/ui/billing)
maguro 管理ポータルに /ui/billing を新規追加 (2026-04-10)。 ナビバーの「💳 入金管理」 からアクセス。
表示内容: 全契約の 残高 / 月額 / 残月数 / 次回支払日 / 遅延日数 / 課金状態 / Peer状態 / 削除対象判定。 停止中 / 警告の契約が上部に表示される。 契約解除ボタンから /ui/contracts/{id}/terminate-confirm へ遷移し、 確定で peer削除 + NCデータ完全削除。
11. 顧客向けポータル表示
| ページ | 追加内容 |
クライアントポータル cloud.k2-o.net/client/devices/{id} | 課金カード (残高 / 月額 / 次回支払日 / 状態) + ポイント購入リンク + マイページリンク |
maguro 管理画面 /ui/contracts/{id} | 課金カード (残高 / 月額 / 次回支払日 / 履歴) |
katuocloud.com/point-my-page/ | 顧客マイページ (認証 → 残高・履歴・契約情報) |
katuocloud.com/continuation-contract-points/ | ポイント購入フォーム (月額単位 or 500円単位) |
12. バックアップファイル一覧
| ファイル | バックアップ場所 |
| functions.php (R640) | /var/www/katuocloud/wp-content/themes/astra-child/functions.php.backup-point-system |
| main.py (maguro) | /opt/mikyun-portal/app/main.py.backup-point-system |
| ui_admin.py | ui_admin.py.backup-phase7 / ui_admin.py.backup-billing-page |
| client_ui.py | client_ui.py.backup-phase7 |
| mikyun_vpn_engine.py | mikyun_vpn_engine.py.backup-block-fix |
| wg_traffic_collector.py | wg_traffic_collector.py.backup-ssh |
13. 未テスト / 残課題
本番環境での実テスト未実施:
- 新規申し込みフォーム (Stripe 単発決済 → アカウント作成) — 3DS対応カードでの正常完了
- ポイント購入フォーム (Stripe 単発決済 → ポイント加算)
- 月次バッチ実運用 (ポイント消費 → warning → suspended → peer 無効化)
- 入金管理ページからの契約解除操作
既存契約はすべてテストのため、 本物の顧客でテストできていない状態。 リリース時には1件ずつ慎重に確認すること。
関連