Commit Graph
15 Commits
Author SHA1 Message Date
erio 1455ade5cd fix(payment): use selected instance config for CreatePayment
Root cause: invokeProvider used the registry's provider (created once
at startup from an arbitrary instance) instead of the selected
instance's config. This meant payments always used one instance's
credentials regardless of which instance was selected.

Fix: create a fresh provider from the selected instance's decrypted
config for each payment call, ensuring correct credentials (PID, PKey,
CID, Stripe keys, etc.).

Also fix SelectInstance for Stripe: when paymentType equals providerKey
(e.g. "stripe"), all instances of that provider are candidates. The
DB stores sub-types (card,alipay,wxpay,link) not "stripe" itself.
2026-04-07 11:45:49 +08:00
erio 011ca6da93 fix(payment): parse money field in EasyPay webhook, cancel button text
- EasyPay VerifyNotification was not parsing the 'money' field, causing
  Amount=0 in PaymentNotification → amount mismatch error on callback
- Cancel button on QR page now shows "取消订单" instead of generic "取消"
2026-04-07 11:01:32 +08:00
erio 0cca4524c9 fix(payment): webhook GET support, Stripe as single method, QR page improvements
- EasyPay webhook: add GET route + read params from URL query (fix 404)
- Stripe: expose as single "stripe" method to users, sub-types (card/link/
  alipay/wxpay) passed to PaymentIntent internally via instance config
- QR code page: use order expiresAt for countdown, add cancel button
- InstanceSelection carries SupportedTypes for provider-specific routing
2026-04-07 10:38:21 +08:00
erio f906b5f1f3 feat(payment): add Link payment method for Stripe
- Add TypeLink payment type
- Stripe provider now supports card/alipay/wxpay/link
- Add Link i18n labels and PaymentMethodSelector styles
2026-04-07 00:32:25 +08:00
erio 55b526582b feat(payment): Stripe multi-method support + card type + hide single-type selector
- Add TypeCard payment type for bank card payments
- Stripe provider now supports card/alipay/wxpay payment methods
- Map payment types to Stripe payment_method_types (card, alipay, wechat_pay)
- Hide supported types selector for single-type providers (alipay/wxpay official)
- Add card i18n labels and PaymentMethodSelector styles
2026-04-07 00:23:54 +08:00
erio 29c3670c62 fix(payment): remove paymentMode config, rename easypay to 跳转, add validation
Backend:
- Remove paymentMode config; determine mode by req.PaymentType directly
  (easypay=redirect/submit.php, alipay/wxpay=API/mapi.php)
- EasyPay.SupportedTypes() always returns [easypay, alipay, wxpay]
- Add validateProviderRequest() for create: name, providerKey, supportedTypes required

Frontend:
- Remove paymentMode dropdown from EasyPay config fields
- Show "跳转" label for easypay type in provider supported types toggle
- Add red * to required fields: provider name, provider key, supported types
- Add strict validation in handleSaveProvider before API call
- Add validation i18n keys for zh/en
2026-04-06 21:17:53 +08:00
erio bfcc487a6b feat(payment): add EasyPay dual-mode support (redirect + API)
- Backend: EasyPay provider supports paymentMode config (redirect/api)
  - redirect: builds submit.php signed URL, browser redirects to hosted page
  - api: calls mapi.php, returns payurl/qrcode (existing behavior)
- Add TypeEasyPay payment type constant
- Fix notify/return URL fallback to instance config
- Handle empty TradeNo for redirect mode (SetNillable)
- Frontend: add paymentMode dropdown in EasyPay provider config
- Auto-update supported_types when paymentMode changes
- Add easypay icon/color in PaymentMethodSelector
- Add i18n for easypay, paymentMode labels
- Rename "启用的支付方式" to "服务商"
- Migration 098: clean easypay from ENABLED_PAYMENT_TYPES
2026-04-06 20:57:45 +08:00
erio 225e8aaa97 fix: resolve golangci-lint errors — errcheck, gofmt, deprecated stripe API, unused func 2026-04-06 02:30:14 +08:00
erio 96b1a96cf9 refactor(payment): code quality improvements per project conventions
- payment_service: split GetDashboardStats (131→35 lines) into 4 sub-functions,
  extract applyPagination helper, replace bubble sort with sort.Slice,
  use sync.Once for EnsureProviders, define magic number constants
- providers: merge duplicate PC/Mobile functions in alipay/wxpay,
  extract loadKeyPair/queryOrderTotalFen in wxpay, add centsToYuan in stripe,
  define constants for success codes, currencies, event types
- handlers: extract requireAuth and parseIDParam helpers to eliminate
  repeated auth/ID-parsing boilerplate
- registry: remove dead seen map in GetProviderByKey
- types: centralize order status constants in payment package
- load_balancer+config_service: unify duplicated containsType into
  exported InstanceSupportsType function
2026-04-06 01:13:30 +08:00
erio 5d63dfb0d1 style: minor formatting in registry.go 2026-04-05 22:30:22 +08:00
erio 9af4a53fe9 fix: structured errors, slog logging, snake_case JSON tags
- Registry uses infraerrors.NotFound instead of fmt.Errorf
- Webhook handler uses slog instead of log.Printf
- PaymentConfigService JSON tags unified to snake_case
- PaymentOrderExpiryService uses slog
- Remove duplicate declarations in registry.go
2026-04-05 22:25:51 +08:00
erio 5cde1bcc59 fix: code quality audit — critical bugs + convention compliance
Critical:
- Refund idempotency keys now include UnixNano timestamp (alipay/wxpay)
- PaymentView passes qr/pay_url params to QR code page
- Fix dead code branch in order result handling

Quality:
- Currency symbol $ → ¥ in admin stats and refund dialog
- StripePaymentView setTimeout cleanup on unmount
- Webhook body size limited to 1MB (io.LimitReader)
- SubscriptionPlan features type documented
2026-04-05 22:17:56 +08:00
erio 1b215c88b5 test: add payment system unit tests (69 test cases)
- fee_test.go: 14 cases for CalculatePayAmount precision/rounding
- crypto_test.go: 9 cases for AES-256-GCM encrypt/decrypt round-trip
- registry_test.go: 10 cases including concurrent thread safety
- easypay_sign_test.go: 9 cases for MD5 signing/verification
- load_balancer_test.go: 10 cases for containsType utility
- payment_config_service_test.go: 17 cases for config parsing
2026-04-05 18:48:51 +08:00
erio aa151ef0e1 fix: resolve all audit findings — registry init, expiry task, dashboard, i18n, stripe
C1: Add EnsureProviders() lazy initialization to populate Registry
    from PaymentProviderInstance DB rows at first use
C2: Delete stale payment/provider_factory.go dead code
C3: Add PaymentOrderExpiryService background ticker (60s interval)
C4: Expand DashboardStats with daily_series, payment_methods, top_users
C5+C6: Add 152 payment i18n keys (en + zh) for admin and settings pages
C7: Fix Stripe global key race — use per-instance client.API
I1: Remove old purchase_subscription_enabled/url from settings form
I2: Add MigrateLegacyPurchaseURL to auto-convert old URL to custom menu
I3: Add migration 092 no-op placeholder for numbering continuity
2026-04-05 18:32:24 +08:00
erio 64c4495ae5 feat: integrate payment system (EasyPay, Alipay, WxPay, Stripe)
Replace iframe-based external payment with native implementation:

Backend (Go):
- 5 new Ent schemas: PaymentOrder, PaymentAuditLog, PaymentChannel,
  SubscriptionPlan, PaymentProviderInstance
- 5 SQL migrations (090-094)
- Payment provider interface + registry + load balancer
- 4 provider implementations (EasyPay, Alipay, WxPay, Stripe)
- PaymentService (order lifecycle, fulfillment, refund 3-phase)
- PaymentConfigService (settings, instance/channel/plan CRUD)
- 31 API endpoints (9 user + 4 webhook + 18 admin)
- Wire DI integration

Frontend (Vue3):
- Payment types, API modules, store, router changes
- Sidebar: payment_enabled controls visibility, new menu items
- User pages: PaymentView (replace iframe), QR payment, Stripe,
  result page, order list
- Admin pages: Order management (4 tabs), provider instance mgmt
- Settings: new payment tab, removed old purchase iframe config
- i18n: full payment namespace (en + zh)

Docs:
- PAYMENT_FRONTEND_MIGRATION_PLAN.md
- PAYMENT_BACKEND_MIGRATION_PLAN.md
- PAYMENT_IMPLEMENTATION_ROADMAP.md
2026-04-05 15:06:05 +08:00