- Batch-query daily usage in one SQL (GroupBy) instead of N queries
- Include PENDING orders in daily usage to prevent over-committing
- Check remaining capacity (used + orderAmount > limit) not just used >= limit
- Check SingleMin/SingleMax per-channel limits
- Pre-attach usage to candidates, reuse across filter and strategy pick
- Fallback to full list with warn log when all instances exhausted
chore: bump version to 0.1.108.139
- Replace all ¥ / ¥ with $ across all payment views and components
- Add out_trade_no column to admin order list table
- Add order number field to admin order detail dialog
chore: bump version to 0.1.108.138
Check used + orderAmount > dailyLimit (not just used >= limit) and
also filter by SingleMin/SingleMax per-channel limits.
chore: bump version to 0.1.108.137
Previously SelectInstance always used round-robin regardless of the
configured strategy. Now it reads the strategy from payment config
and selects the instance with the lowest daily transaction amount
when "least-amount" is configured.
chore: bump version to 0.1.108.136
- Call EnsureProviders before webhook provider lookup to fix
"provider not registered" error after restart or config changes
- Display out_trade_no instead of numeric ID in payment result pages
- Remove "at least one payment type required" validation, allow
saving providers with no payment types selected
- Auto-fill current domain for empty notify/return URL on save
(trim whitespace, fall back to window.location.origin)
- Add type="button" to all buttons inside the settings form that
are not submit buttons (edit, delete, refresh, create provider)
to prevent accidental form submission triggering main settings save
All Stripe methods now use confirmPayment({redirect: 'if_required'}):
- Card: confirms inline, shows success page
- WeChat: Stripe shows QR modal overlay on same page, no popup
- Alipay: Stripe redirects to Alipay page, returns to result page
Removes POPUP_METHODS, StripePopupView postMessage handshake, and
onStripeRedirect handler. Eliminates double-popup issue for WeChat
(3 windows → 1) and simplifies Alipay (2 windows → 1 redirect).
Stripe card payment now shows a success page with order details and a
manual confirm button, matching the QR code payment success flow.
Previously it auto-returned to the recharge page after 1.5 seconds.
EasyPay popup mode relies on notify_url (webhook) to update order status,
but if the callback is missed, orders stay PENDING forever. This adds:
- POST /api/v1/payment/orders/verify endpoint that actively queries
the upstream provider to check payment status
- Frontend PaymentResultView calls verify when receiving EasyPay
return_url params (out_trade_no)
- Fix checkPaid to fall back to OutTradeNo when PaymentTradeNo is empty
(popup mode doesn't have trade_no until the notify callback)
Order ID format changed from sub2_5 to sub2_20250409aB3kX9mQ
(prefix + date + 8-char random, no DB ID embedded).
- Add out_trade_no column to payment_orders table
- Store generated external ID on order creation
- Webhook handler looks up order by out_trade_no instead of parsing DB ID
- Fallback to legacy sub2_N format for existing orders
- Remove saveSettings() call from handleSaveProvider - editing a
provider should not save the entire settings form
- Change order ID format from sub2_5 to sub2_20250409_5_aB3kX9mQ
(prefix + date + dbID + 8-char alphanumeric random) to avoid
collisions with external payment providers
- parseOrderID supports both legacy and new format
Backend returns null for unconfigured fields. Object.assign overwrites
form defaults (e.g. payment_enabled_types: []) with null, causing
"Cannot read properties of null" errors. Now only non-null values
are applied, preserving safe defaults for unconfigured environments.
Add alipay_direct and wxpay_direct to METHOD_ORDER so they appear
in the correct position when enabled. The checkout API already returns
these types from direct provider instances; the method selector's
icon/style matching (includes('alipay')) already handles them.
Create StripePopupView.vue - a standalone minimal page (no AppLayout)
that receives clientSecret/publishableKey via postMessage from parent:
- Alipay: auto-calls confirmAlipayPayment(), shows "正在跳转..."
- WeChat: calls confirmWechatPayPayment(), shows QR code inline
- Much faster than loading full StripePaymentView (no API calls needed)
- Add easypay back to enabled provider toggles (alongside alipay, wxpay, stripe)
- Disabling a provider toggle now also disables all matching provider instances
- Simplify enabledProviderKeyOptions - direct mapping instead of special cases
- Label: "启用的服务商" with hint about instance auto-disable