katuocloud 顧客視点 E2E 完全検証レポート
テスト購入 完走 ポータル動作確認 切り戻し完了 BUG 2 件発見 UX 課題 5 件 新機能要望 1 件
17:00 Phase 1 結果: BUG #1 / UX 課題 4 件発見、 「サブスクのまま」 を WP DB で確認
17:10 サブスク確認: わんくんが Stripe Dashboard を共有 → 3 商品全部「サブスク」 表記
17:20 真相判明: functions.php に「Phase 4: Stripe単発決済 (サブスク廃止)」 のコメント、 実装は既に PaymentIntent (都度) ✓
17:25 Stripe API で 3 つの Price 確認: すべて
type=one_time ✓ サブスク表記は古い残骸17:30 Phase 2 開始 (test 環境で実購入完走を目指す)
17:45 わんくん test API キー共有 → functions.php に
KATUOCLOUD_TEST_MODE flag 追加17:55 1 回目 test 購入試行 → 「No such paymentmethod: live mode key was used」 エラー
18:00-19:45 cache の謎 + functions.php 修正が反映されない問題で迷走 (深い泥沼)
19:42 一旦 revert: functions.php を元版 (pk_live + sk_live) に戻す
19:45 わんくん新 API キー画像共有 (
51THc 系列) → 別 Stripe アカウント発見19:50 アカウント分析:
51PWJ = わんくん本物アカウント、 51THc = SureCart Sandbox 用別アカウント19:53:30 真因発覚: host nginx access log で POST /wp-json/…/create-subscription が
/var/www/katuocloud/ (host 旧 WP) で処理されている → 私はずっと docker container 内の 使われていない WP を修正していた19:53:50 真の WP
/var/www/katuocloud/wp-content/themes/astra-child/functions.php を sk_test に修正 + php-fpm reload19:55:17 test 購入完全成功 (HTTP 200 / Stripe PI succeeded / 契約 260518-5687 発行 / QR 自動生成 / Telegram 通知)
19:58-20:05 ポータル各機能確認 (デバイス一覧 / QR / WG conf / 容量 全 HTTP 200)
20:06 切り戻し: functions.php を sk_live に復元 + php-fpm reload
20:08 公開サイト復旧確認 (HTTP 200)
20:10 テスト契約 260518-5687 を
/terminate で cleanup → DB / WG / QR / NC user / screenshot 全削除20:15 本レポート作成
| イベント | 記録 |
|---|---|
POST /wp-json/katuocloud/v1/create-subscription |
HTTP 200 |
| Stripe PaymentIntent | pi_3TYOp5DxP0kEA5q80A2JNxfU status: succeeded |
| 契約 ID 発行 | 260518-5687 (mikyun_cloud DB に active) |
| QR 自動生成 (maguro) | /opt/mikyun/output/qr/260518-5687-DEV-001.png |
| WG conf 生成 (maguro) | /opt/mikyun/output/client-configs/260518-5687-DEV-001.conf (Address 10.200.0.5/24, AllowedIPs 10.200/16+192.168.20/24+192.168.30/24+173.0.0/24) |
| Telegram 通知 | 送信成功 |
| Screenshot アップロード | /wp-content/uploads/screenshots/wantest18_1779101699.png (48,910 bytes) |
| サンキュー画面 | 表示成功 (わんくん iPhone で確認) |
顧客ポータル動作確認 (curl ベース、 contract 260518-5687):
| 機能 | endpoint | 結果 |
|---|---|---|
| デバイス一覧 | GET /client/devices/260518-5687 |
HTTP 200 / 20,179 bytes |
| WG conf DL | GET /client/conf/260518-5687-DEV-001 |
HTTP 200 / 366 bytes (text/plain) – 正常な WG config |
| QR 表示 | GET /client/qr/260518-5687/260518-5687-DEV-001 |
HTTP 200 / 15,030 bytes |
| 容量変更 | GET /client/quota/260518-5687/260518-5687-DEV-001 |
HTTP 200 / 16,542 bytes |
🚨 構成発見 #1: 公開 katuocloud.com は host 旧 WP で動作中
memory hosts.md (2026-05-15) には「NPM (id=4) → wp-katuo:80 (docker, wordpress:6-php8.3-apache)」 と書かれていますが、 実態は host nginx + host php8.1-fpm + /var/www/katuocloud/ で処理されている。 docker container wp-katuo は起動しているが 使われていない (ゾンビ状態)。
証拠:
- host nginx access log に
POST /wp-json/katuocloud/v1/create-subscriptionが記録されている (19:55:17) - docker container access log は health check 以外空 (host から経由していない)
- host php-fpm が `/var/www/katuocloud/…/functions.php` を実行している
影響:
- R640 docker 移行が 完了していない。 hosts.md の記載と実態が乖離
- functions.php / WP 設定の修正は host 側
/var/www/katuocloud/で行う必要 - memory
project-bakusoku-hp-r640やhosts.mdの更新が必要
🐛 BUG #1: username 同字繰返し block が英字に効かない
Phase 1 検証で発見:
aaaaaaaa (英字 a x 8) |
「使用可能なユーザー名です」 ← 通る |
11111111 (数字 1 x 8) |
「同じ文字の繰り返しは避けてください」 ✓ |
原因: JS validation regex が /^(\d)\1+$/ の数字限定。 修正案: /^(.)\1+$/ に変更で全文字種カバー。
🐛 BUG #2: customer_email が運営ポータル UI で空表示 → 本日 fix 完了
DB contracts テーブルには wan.pero.chance@gmail.com が保存されているが、 https://cloud.k2-o.net/ui/contracts/260518-5687 ページの「メール」 欄が空表示だった。
原因: maguro:/root/mikyun-cloud/mikyun-portal/mikyun_vpn_engine.py の GET /contracts/{id} endpoint (line 1488 周辺) の SELECT 句に customer_email カラムが含まれていない、 line 1527 の return dict にも含まれない。
修正 (20:17 完了):
- line 1488 SELECT 句:
customer_name, customer_email, customer_phone, storage_quota_gb, ... - line 1527-1528 return dict:
'customer_email': contract.get('customer_email'), 'customer_phone': contract.get('customer_phone') sudo docker restart mikyun-vpn-engine+sudo docker restart mikyun-cloud- API レスポンス確認:
"customer_email": "wan.pero.chance@gmail.com"✓ - UI 表示確認:
<div>wan.pero.chance@gmail.com</div>が表示される ✓ - backup:
mikyun_vpn_engine.py.bak.email-fix-20260518-201732
= 次回新規契約から自動的に正しく表示される
✨ 新機能追加: darkhero (173.0.0.18) から admin として WG 不要で操作可能 → 本日 fix 完了
顧客ポータル (/client/* endpoint) は WG client (10.200.0.x) からのみアクセス可能だったが、 わんくん要望で darkhero (作業端末、 173.0.0.18) からも admin として通過するように変更。
修正 (20:26 完了):
- ファイル:
maguro:/root/mikyun-cloud/mikyun-portal/app/client/client_ui.pyline 748 - 変更:
LOCAL_ADMIN_SUBNETStuple に"173.0.0."を追加 (既存の192.168.x, 127.0.0., 10.25x.0.と並列) - 仕組み: 既存の
is_local_admin(request)関数で IP prefix チェックしており、require_parent_device()内で「ローカル IP は運営モード」 として WG check skip 済 (元から実装されていた、 prefix 追加のみで全 endpoint に反映) sudo docker restart mikyun-cloud- 動作確認:
X-Real-IP: 173.0.0.18ヘッダで GET/client/devices/260518-5687→ HTTP 200 / 「アクセス拒否」 ゼロ / 契約画面表示 ✓ - backup:
client_ui.py.bak.darkheroAdmin-20260518-202648
注意: darkhero から実 cloud.k2-o.net 経由でアクセスする場合は R640 host nginx (SNI passthrough) を通るため、 maguro 側で見える request.client.host が R640 IP になる可能性あり。 その場合は X-Real-IP ヘッダで真の IP を伝える nginx 設定の追加が必要。 まずわんくん実機確認推奨。
| # | 箇所 | 内容 |
|---|---|---|
| U1 | username | 「一般名 user, test」 が partial match (user1234 / test1234) で通る。 help-text は「避けて」 と書いてあるが完全一致のみ block |
| U2 | username | 全角日本語入力時、 minlength エラー先行で「半角のみ」 エラーが見えない |
| U3 | customer_name | maxlength なし、 500 文字でも通る、 XSS payload (<img onerror=...>) フロント素通り |
| U4 | customer_email | 300+ 文字を通す (RFC 5321 上限 320 までは OK だが UX 上 254 cap が親切) |
| U5 | customer_email | iPhone Safari の auto-fill で +alias が消える 可能性大 (frontend で wan.pero.chance+katuotest@gmail.com → backend で wan.pero.chance@gmail.com に届く) |
https://cloud.k2-o.net/ui/contracts/260518-5687/customer-view 画面で 運営側も操作できるようにしてほしい。 現状は表示のみ、 操作しようとすると「WG で接続して」 と表示される。 → 運営 admin auth 経由なら WG 不要で操作可能にしたい (= delegate 機能)。 仕様変更レベル、 別タスク化。
| 項目 | 状態 |
|---|---|
| サブスク廃止 → 都度決済化 | 既に完了済。 functions.php に「Phase 4: Stripe単発決済 (サブスク廃止)」 コメント、 実装は PaymentIntent ベース |
| Stripe Price object | 既に全 type=one_time (4/10 13:47 の更新で one_time 化済) |
| 継続課金 | ポイント制 (/continuation-contract-points/ page + katuocloud_charge_points()) |
WP DB recurring=1 メタ |
残骸 (実装で参照されていない、 SureCart admin 画面表示の名残) |
| frontend「月額」「毎月自動引き落とし」 文言 | 古い表現 (実態は 1 回限り都度決済) |
REST endpoint 名 create-subscription |
古い命名 (実態 PaymentIntent) |
| frontend stripe instance 初期化 | page content の Stripe(window.STRIPE_PUBLIC_KEY || 'pk_test_fallback')、 順序的に pk_test fallback で init → 「mode 不整合」 を意図せず生んでいる |
| 時刻 | 対象 | 修正内容 | 切り戻し |
|---|---|---|---|
| 18:13 | docker container wp-katuo 内 functions.php |
KATUOCLOUD_TEST_MODE flag 追加 (結果: 使われていない WP だった、 影響なし) |
19:42 元版に restore |
| 18:20 | docker container 内 _elementor_data |
「月額」「毎月」 文言を「税込」「初回のみ」 に書換 (結果: 反映前に escape 問題で一時 NULL 化 → backup から復旧) | 19:30 backup から restore |
| 19:53:50 | host 旧 WP /var/www/katuocloud/.../functions.php |
KATUOCLOUD_STRIPE_SK を sk_live_51PWJ... → sk_test_51PWJ... に変更 |
20:06 sk_live に復元 |
| 20:06 | host php-fpm | reload (opcache reset) | — |
| 20:08 | 公開サイト動作確認 | curl https://katuocloud.com/plan1/ → HTTP 200 |
— |
| 20:10 | test 契約 260518-5687 | POST /ui/contracts/260518-5687/terminate で全自動 cleanup |
— |
backup ファイル一覧 (R640 上):
/var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.realFix-20260518-195350(host 旧 WP 修正前 = sk_live)/var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.before-revertToLive-20260518-200638(sk_test 状態のスナップ)/srv/wp-nvme/wp-stacks/katuocloud.com/wordpress/wp-content/themes/astra-child/functions.php.bak.*(docker container 内、 6 ファイル、 影響なし)/srv/wp-nvme/wp-stacks/katuocloud.com/_backups/cleanup_20260518-1800/(Step 1 backup、 functions.php + DB dump)
| 優先 | 項目 | 所要 | 備考 |
|---|---|---|---|
| 🔴 高 | R640 docker 移行完了 or memory 修正 | 2-4h or 30 分 | 「NPM → wp-katuo docker」 を完成させる or memory に「実態は host 旧 WP」 を反映。 後者が現実的 |
| 🔴 高 | BUG #2 fix: customer_email を vpn-engine API で返す | 5-10 分 | maguro mikyun_vpn_engine.py line 1488 + 1527 に customer_email 追加 + service reload |
| 🟠 中 | BUG #1 fix: username 同字繰返し regex を (\d)\1+ → (.)\1+ |
5 分 | host 旧 WP functions.php の inline JS。 影響低 (セキュリティ強化) |
| 🟠 中 | frontend「月額」「毎月」 文言を都度決済表現に | 15 分 | page 1594 を Elementor 編集画面 (WP-admin) で修正が安全 (SQL 直編集は escape リスク) |
| 🟡 低 | WP DB recurring=1 メタ → 0 or 削除 |
2 分 | SureCart 表示整合性のみ。 実害なし |
| 🟡 低 | Stripe Dashboard の「Recurring Price」 表示整理 (旧 Recurring Price archive) | 5 分 | 使われていない old Price object archive。 実害なし |
| 🔵 新機能 | /ui/contracts/{id}/customer-view で運営も操作できるように |
2-4h | delegate 機能。 仕様設計 + 実装 + 認可フロー追加 |
| 🟡 低 | UX U1-U5 検討 (一般名 partial / 全角 / maxlength / +alias) | 1-2h | UX 改善、 各 1 行修正 |
| 🟢 既知 | WG peer (wg-clients.conf) の termiate 時自動削除 | 1h | terminate flow で wg-clients.conf 自動編集していない。 status revoked で機能無効だが clean cleanup には実装が望ましい |
- Stripe 警告メール: 検証中の curl で
card[number]=4242...を直接 Stripe API に POST した結果、 PCI compliance 違反警告メールが届いた。 1 回限り、 実害なし。 今後は Stripe Elements 経由のみ - 2 Stripe アカウント発見:
acct_1PWJMJDxP0kEA5q8(本物) とacct_1THcoq43LxdXmxke(SureCart Sandbox 用) が存在。 katuocloud.com WP の SureCart 接続は51PWJ側 - iPhone Safari の auto-fill で email の
+aliasが抜ける可能性が高い (検証中の入力で発生したと推定) - cache 層が多重: wp-super-cache (active_plugins に残存) + Elementor element_cache + Elementor css cache + opcache + Astra theme の HTML キャッシュ。 plugin folder rename + active_plugins 削除 + WP_CACHE=false + cache dir 削除 + opcache reset + docker recreate + php-fpm reload など多重に cache clear が必要 (revert で全て元に戻した)
すべて D:\コード君\コード君が見るところ\katuocloud_e2e_verify_20260518\ 配下:
playwright/01_recon.mjs,02_boundary.mjs,03_verify_wording.mjs,04_verify_stripe_mode.mjs— Playwright テストスクリプト01_recon_result_*.json,02_boundary_result_*.json,03_verify_wording_*.json,04_stripe_mode_*.json— 結果 JSONhtml_capture/*.html— 公開 URL HTML capturescreenshots/*.png— 検証中スクショfunctions.php(local copy)、update_plan1_content.sql、fix_elementor_wording.py、stripe_archive_prices.py等の作業 scriptportal_verify_*.log,find_fetch_urls.sh,dump_eldata.py等の調査 script
R640 / maguro 上の保管:
- host R640:
/var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.*(修正前 = sk_live、 sk_test スナップショット) - R640 container:
/srv/wp-nvme/wp-stacks/katuocloud.com/_backups/cleanup_20260518-1800/(DB dump + functions.php + page content backup) - maguro:
/tmp/elementor_data_pre_20260518-182024.json(使われていない docker container WP の Elementor data 退避)
katuocloud_E2E検証_Phase1報告_20260518.html— Phase 1 (フォーム境界値テスト 43 シナリオ) の詳細結果。 本レポートと相補的- 本レポート
katuocloud_E2E検証_完全レポート_20260518.html— Phase 1 結果サマリー + Phase 2 (実購入完走) + cleanup + 切り戻しの全記録
| 項目 | 状態 |
|---|---|
host 旧 WP /var/www/katuocloud/.../functions.php |
KATUOCLOUD_STRIPE_SK = sk_live_51PWJ... ✓ (本番モード) |
wp-config.php WP_CACHE |
true ✓ |
公開 https://katuocloud.com/plan1/ |
HTTP 200 / 233,911 bytes ✓ |
window.STRIPE_PUBLIC_KEY = pk_live_... |
set 文 1 件 ✓ |
| test 契約 260518-5687 | terminated + 全 cleanup ✓ |
| wg-clients.conf | 260518-5687 関連 0 件、 残り peer は 260403-865C 系 (本番) のみ ✓ |
| QR / WG conf / NC user / screenshot | すべて削除済 ✓ |
| maguro mikyun-vpn-engine.py | customer_email SELECT + dict 追加 = 本番に残置 (BUG #2 fix) |
| maguro client_ui.py | LOCAL_ADMIN_SUBNETS に 173.0.0. 追加 = 本番に残置 (darkhero admin 機能) |
本番に残した「改良」 2 点 (test mode とは無関係、 本番でも有益):
- customer_email 表示 fix (vpn-engine SELECT + return dict): 次回新規契約から運営ポータル UI に email が正しく表示される
- darkhero admin 機能 (LOCAL_ADMIN_SUBNETS): darkhero (173.0.0.x) から顧客ポータル全画面で WG 不要 admin として通過。 顧客サポート時に運営代行操作可能
切り戻し対象 (test mode 一時化): すべて元版に復元済 ✓
- host 旧 WP
functions.php: sk_live 復元 ✓ - wp-config
WP_CACHE: true 復元 ✓ - docker container 内 functions.php (使われていない方): 元版復元 ✓
- docker container 内の wp-super-cache plugin: folder は削除済 (cleanup 過程で誤削除)、 container 自体使われていないので影響なし
backup ファイル (R640 / maguro 上):
- R640:
/var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.realFix-20260518-195350(sk_live 元版) - R640:
/var/www/katuocloud/wp-content/themes/astra-child/functions.php.bak.before-revertToLive-20260518-200638(sk_test スナップ) - maguro:
/root/mikyun-cloud/mikyun-portal/mikyun_vpn_engine.py.bak.email-fix-20260518-201732 - maguro:
/root/mikyun-cloud/mikyun-portal/app/client/client_ui.py.bak.darkheroAdmin-20260518-202648 - maguro:
/root/wg-clients.conf.bak.final-cleanup-20260518-204529
🚨 真の本物バグ: 本番販売の決済が 4 月 7 日以降ずっと通らなかった
本番モード復帰 (20:48) 後、 わんくんが本物のカードで購入操作 → 「No such paymentmethod: live mode key was used」 エラー。 当初「test 検証の残骸」 と思ったが Stripe Dashboard 確認の結果 4 月 7 日以降 live mode で成功した payment ゼロ = 1.5 ヶ月本番販売壊れていた。
真因:
<!-- page 1594 (Elementor) の content 内、 line 1091 で先に実行 --> const stripe = Stripe(window.STRIPE_PUBLIC_KEY || 'pk_test_51PWJ...'); <!-- functions.php の wp_footer hook、 line 2002 で後で実行 --> window.STRIPE_PUBLIC_KEY = 'pk_live_51PWJ...';
JavaScript 実行順序的に line 1091 が先に実行されるとき window.STRIPE_PUBLIC_KEY は undefined → fallback の pk_test で stripe 初期化 → pm が test mode で作成 → backend (sk_live) で問い合わせ → 「test pm + live key」 不整合エラー。 page 1594 の post_modified = 2026-04-07 で「fallback を pk_live → pk_test に間違って書き換えた」 と推定。
✅ 修正 (22:15 完了): wp_head priority 1 で pk_live を最早期に set
変更: host R640 /var/www/katuocloud/wp-content/themes/astra-child/functions.php の add_action('wp_enqueue_scripts', ...) 直後に追加:
add_action("wp_head", function() {
?>
<script>window.STRIPE_PUBLIC_KEY = "pk_live_51PWJ..."</script>
<?php
}, 1); // priority 1 = 最早期、 page content より先に出力
効果: response 内で <head> 内 line 10 に window.STRIPE_PUBLIC_KEY = pk_live set 文が出力される → page content (line 1091 = body 内) の inline JS より先に実行 → stripe = Stripe(pk_live) で正常初期化 → 本番販売復活。
backup: functions.php.bak.wpHeadFix-20260518-210019
📊 検証用商品 (作成 → 全 archive 済)
検証目的で「カツオくんのスマイル ¥100 one_time」 Stripe Product 作成 (Payment Link 付き)、 ただし「商品が表示されない」 と発覚で諦め (Stripe API 側は正常、 ブラウザ側の問題と推定)。 検証完了後 Product / Price / Payment Link 全 archive 済 (active=false)。
| 項目 | ID | 状態 |
|---|---|---|
| Product | prod_UXWNQIset3wQwx |
archive (active=false) |
| Price | price_1TYRKgDxP0kEA5q8jRIHPPGj |
archive (active=false) |
| Payment Link | plink_1TYRKgDxP0kEA5q8U09SIMmt |
deactivate (active=false) |
- functions.php base_price: 1980 ✓ (本番価格)
- functions.php wp_head pk_live set: 有効 ✓ (1.5 ヶ月壊れていた決済 fix)
- frontend 表示「¥1,980」 ✓
- functions.php sk_live: 本番モード ✓
- カツオくんのスマイル: 全 archive 済 ✓
- = 本番販売 完全復活、 顧客が本物のカードで購入可能
— E2E 完全検証 + 本番販売 fix (1.5 ヶ月の bug 発見) + 本番移行 完了 23:15 JST、 お疲れさまでした 🐟🐕 —
