ポイント課金システム導入 & Stripe決済変更(2026-04-10)
1. 概要 — サブスク廃止・ポイントプリペイド方式へ移行
従来のStripeサブスクリプション(自動引き落とし)を廃止し、ポイントプリペイド方式に全面移行した。顧客は任意のタイミングでポイントを購入(Stripe単発決済)し、毎月の支払日にポイントから月額分が自動消費される。カード変更時の決済失敗リスクが解消される。
1pt = 1円。最低購入額: 500pt(継続購入)/ 月額分(初回購入)
2. 決済フロー
2-1. 新規申し込み(フォームA)
顧客がフォーム入力 → Stripe PaymentIntent(単発決済) → succeeded確認 → R640で契約+NCアカウント作成 → ポイント加算 → 課金情報初期化 → thank-youページ ※ 決済失敗 or 3DS未完了 → アカウント作成しない(エラー返却) ※ 契約作成失敗 → Stripe自動返金
2-2. 継続ポイント購入(フォームB)
契約ID + パスフレーズで認証 → 購入額選択(月額単位 or 500円単位) → Stripe PaymentIntent(単発決済) → succeeded確認 → R640にポイント加算
2-3. 月次自動処理(billing_daily.py)
毎日 0:30 実行(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無効化(wg0.confコメントアウト + wg set remove) → Nextcloudユーザー無効化(occ user:disable) 5. 手動削除が必要な場合は管理画面の入金管理ページから契約解除
顧客への未払い連絡は自動化していない。delivery_methodを確認して運営が手動で連絡する。
3. DB変更
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 | StripePI ID |
note | TEXT NULL | 備考 |
created_at | DATETIME | 作成日時 |
4. R640 FastAPI新規エンドポイント(main.py追記)
| エンドポイント | 認証 | 用途 |
|---|---|---|
POST /api/points/verify | なし(passphrase) | 契約認証 + 残高返却(フォームB用) |
POST /api/points/charge | Basic認証 | ポイント加算(WordPress→R640) |
POST /api/points/adjust | Basic認証 | 手動ポイント加減算(管理者用) |
GET /ui/contracts/{id}/billing | Basic認証 | 課金情報+履歴取得 |
POST /api/billing/init | Basic認証 | 課金初期化(月額自動計算+次回支払日設定) |
Basic認証:
admin:243Katuokun4144!(既存と同一)5. WordPress(XServer)変更 — functions.php
5-1. 新規ヘルパー関数
| 関数 | 用途 |
|---|---|
katuocloud_stripe_api($endpoint, $data) | Stripe REST API直接呼び出し |
katuocloud_charge_points($contract_id, $amount, $pi_id) | R640にポイント加算依頼 |
katuocloud_init_billing($contract_id, $monthly_amount) | R640に課金初期化依頼 |
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/月
R640の
calc_monthly_amount() と WordPress JS の updatePricing() で同一ロジック。/api/billing/init に monthly_amount=0 を渡すとDBから自動計算。7. Stripe設定変更
| 項目 | 変更前 | 変更後 |
|---|---|---|
| 決済方式 | Subscription(自動引き落とし) | PaymentIntent(単発決済) |
| 商品/Price | 3つのPrice ID使用 | 不使用(金額直接指定) |
| 3Dセキュア | 未確認 | status=succeeded必須 |
| SureCart | インストール済み(未使用) | 無効化推奨 |
重要: Stripe Dashboardで既存のサブスクリプション商品は単発に変更済み。旧Price ID(STRIPE_PRICE_BASE/DEVICE/STORAGE)はR640コードから完全除去済み。
8. バグ修正(SSH→ローカル実行)
以下のファイルでwg0操作がSSH経由(root@10.250.0.1)だった問題を修正し、R640ローカル実行に変更:
| ファイル | 関数/処理 | 修正内容 |
|---|---|---|
client_ui.py | load_wg_status() | ssh wg show → ローカル wg show wg0 dump |
wg_traffic_collector.py | get_wg_dump() | ssh wg show → ローカル wg show wg0 dump |
mikyun_vpn_engine.py | block_device_ip() | ssh wg set remove → ローカル wg set wg0 remove |
mikyun_vpn_engine.py | unblock_device_ip() | ssh wg set → ローカル wg set wg0 + PSKファイル |
mikyun_vpn_engine.py | add_peer_to_vps_wg0() | ssh wg set → ローカル wg set wg0 + PSKファイル |
9. systemdタイマー・サービス一覧
| 名前 | スケジュール | 用途 |
|---|---|---|
billing-daily.timer | 毎日 0:30 | ポイント月次消費 + warning + suspended |
mikyun-cloud.service | 常駐 :9000 | FastAPI管理ポータル |
mikyun-vpn-engine.service | 常駐 :9081 | VPN操作API(localhost only) |
10. 管理画面(入金管理ページ)
R640管理ポータルに/ui/billingを新規追加。ナビバーの「💳 入金管理」からアクセス。
表示内容: 全契約の残高・月額・残月数・次回支払日・遅延日数・課金状態・Peer状態・削除対象判定。停止中/警告の契約が上部に表示される。契約解除ボタンから/ui/contracts/{id}/terminate-confirmへ遷移し、確定でpeer削除+NCデータ完全削除。
11. 顧客向けポータル表示
| ページ | 追加内容 |
|---|---|
| クライアントポータル(cloud.k2-o.net/client/devices/{id}) | 課金カード(残高・月額・次回支払日・状態)+ ポイント購入リンク + マイページリンク |
| R640管理画面(/ui/contracts/{id}) | 課金カード(残高・月額・次回支払日・履歴) |
| katuocloud.com/point-my-page/ | 顧客マイページ(認証→残高・履歴・契約情報) |
| katuocloud.com/continuation-contract-points/ | ポイント購入フォーム(月額単位 or 500円単位) |
12. バックアップファイル一覧
| ファイル | バックアップ |
|---|---|
| functions.php | functions.php.backup-point-system |
| main.py | 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単発決済→アカウント作成)
・ポイント購入フォーム(Stripe単発決済→ポイント加算)— 3DS対応カードでの正常完了
・月次バッチの実運用(ポイント消費→warning→suspended→peer無効化)
・入金管理ページからの契約解除操作
・新規申し込みフォーム(Stripe単発決済→アカウント作成)
・ポイント購入フォーム(Stripe単発決済→ポイント加算)— 3DS対応カードでの正常完了
・月次バッチの実運用(ポイント消費→warning→suspended→peer無効化)
・入金管理ページからの契約解除操作
