4.0 KiB
4.0 KiB
LongPort HTTP Endpoint Fallback (2026-08-02)
Problem
Cron scripts that use the LongPort Python SDK fail with:
longport.OpenApiException: error sending request for url
(https://openapi.longportapp.cn/v1/socket/token): client error (Connect)
The script set LONGBRIDGE_HTTP_URL, but the SDK silently ignores it and uses the default openapi.longportapp.cn. When the .cn endpoint is down (Aliyun load balancer 502), the cron fails.
Root Cause
The SDK's Config.from_env() reads LONGPORT_HTTP_URL, NOT LONGBRIDGE_HTTP_URL. The CLI uses LONGBRIDGE_*; the Python SDK uses LONGPORT_*. This is a frequent bug because:
- The CLI's documentation uses
LONGBRIDGE_* - The Python wheel's type stubs (
.pyi) documentLONGPORT_* - Scripts often copy bashrc exports (
LONGBRIDGE_*) and assume they work
Fix Pattern
Always set both env vars in cron wrappers (they don't conflict):
# In the wrapper script (e.g. cn_dividend_buy_timing_cron.sh):
export LONGPORT_HTTP_URL=https://openapi.longportapp.cn
export LONGPORT_QUOTE_WS_URL=wss://openapi-quote.longportapp.cn
export LONGPORT_TRADE_WS_URL=wss://openapi-trade.longportapp.cn
export LONGPORT_LANGUAGE=zh-CN
Fallback Pattern (Python init)
When the .cn endpoint is down, try the .com endpoint:
def get_longbridge():
"""带重试的长桥 SDK init - 优先 .cn (国内), fallback .com (海外)"""
import time
load_longbridge_env()
configs = [
{
'http': 'https://openapi.longportapp.cn',
'quote_ws': 'wss://openapi-quote.longportapp.cn',
'trade_ws': 'wss://openapi-trade.longportapp.cn',
},
{
'http': 'https://openapi.longbridge.com',
'quote_ws': 'wss://openapi-quote.longbridge.com/v2',
'trade_ws': 'wss://openapi-trade.longbridge.com/v2',
},
]
from longport import openapi
last_err = None
for i, c in enumerate(configs):
try:
os.environ['LONGPORT_HTTP_URL'] = c['http']
os.environ['LONGPORT_QUOTE_WS_URL'] = c['quote_ws']
os.environ['LONGPORT_TRADE_WS_URL'] = c['trade_ws']
os.environ.setdefault('LONGPORT_LANGUAGE', 'zh-CN')
cfg = openapi.Config.from_env()
ctx = openapi.QuoteContext(config=cfg)
try:
ctx.quote(['600000.SH']) # test connection
except Exception as e:
last_err = e
if i < len(configs) - 1:
print(f"[longbridge] {c['http']} quote 失败: {e}, 重试下一节点", flush=True)
time.sleep(1)
continue
else:
return ctx, openapi.Period
print(f"[longbridge] 使用 {c['http']} ✓", flush=True)
return ctx, openapi.Period
except Exception as e:
last_err = e
print(f"[longbridge] {c['http']} init 失败: {e}", flush=True)
if i < len(configs) - 1:
time.sleep(1)
continue
raise last_err or RuntimeError("长桥 SDK init 全部失败")
Test
2026-08-02: cron 8000d3cfed23 cn-dividend-buy-timing failed at 11:30 with OpenApiException: client error (Connect). After applying the fix:
.cn(Aliyun) endpoint came back online — script ran successfullylongrun_http_url=https://openapi.longportapp.cnprinted ✓
Open Questions
- Are
.cnand.comendpoints actually interchangeable? E.g. do quotes for the same symbol return identical data? The fallback assumes yes; not verified. - Could there be a subtle difference between the SDK's hardcoded
openapi.longportapp.cnand the user-configured one? E.g. token validation, rate limits, etc.?
Files Touched
~/.hermes/scripts/cn_dividend_buy_timing.py— get_longbridge() with fallback~/.hermes/skills/trading/lottery-hk/scripts/lottery_4frame.py— same idempotent init~/.hermes/scripts/cn_dividend_buy_timing_cron.sh— wrapper sets LONGPORT_* env vars