feat(business): split Kingdee token body config
Allow Kingdee token requests to be built from app key, app secret, configurable field names, optional timestamp fields, and extra JSON. Keep raw KINGDEE_TOKEN_BODY_JSON as an advanced override with current-time placeholders. Validation: python3 -m unittest discover -v; python3 -m compileall obsidian_wiki tests; git diff --check.
This commit is contained in:
@@ -67,6 +67,9 @@ class KingdeeApiTests(unittest.TestCase):
|
||||
self.assertIn("用途:销售订单 API 要求的 x-acgw-identity 请求头。", text)
|
||||
self.assertIn("是否必填:可选,手动测试用;长期定时同步建议使用自动登录配置。", text)
|
||||
self.assertIn("是否必填:可选,默认从 data.access_token 读取。", text)
|
||||
self.assertIn("变量:KINGDEE_APP_KEY", text)
|
||||
self.assertIn("变量:KINGDEE_TOKEN_TIMESTAMP_FIELD", text)
|
||||
self.assertIn("支持占位符:{now_ms}", text)
|
||||
|
||||
def test_default_config_path_accepts_none(self):
|
||||
cwd = Path.cwd()
|
||||
@@ -126,6 +129,45 @@ class KingdeeApiTests(unittest.TestCase):
|
||||
self.assertEqual(request.get_header("X-app"), "demo")
|
||||
self.assertEqual(stat.S_IMODE(cache_path.stat().st_mode), 0o600)
|
||||
|
||||
def test_access_token_body_can_be_built_from_split_fields_with_current_time(self):
|
||||
cache_path = self.root / ".runtime" / "kingdee-token.json"
|
||||
config = {
|
||||
"KINGDEE_TOKEN_URL": "https://token.example/access",
|
||||
"KINGDEE_APP_KEY": "abc",
|
||||
"KINGDEE_APP_SECRET": "secret",
|
||||
"KINGDEE_TOKEN_APP_KEY_FIELD": "client_id",
|
||||
"KINGDEE_TOKEN_APP_SECRET_FIELD": "client_secret",
|
||||
"KINGDEE_TOKEN_TIMESTAMP_FIELD": "timestamp",
|
||||
"KINGDEE_TOKEN_TIMESTAMP_FORMAT": "epoch_ms",
|
||||
"KINGDEE_TOKEN_BODY_EXTRA_JSON": '{"tenant":"demo"}',
|
||||
"KINGDEE_TOKEN_FIELD": "data.access_token",
|
||||
}
|
||||
http = RecordingUrlopen([{"data": {"access_token": "access-1"}}])
|
||||
|
||||
token = get_kingdee_access_token(config, cache_path=cache_path, urlopen=http, now_epoch=1000.5)
|
||||
|
||||
self.assertEqual(token, "access-1")
|
||||
body = json.loads(http.calls[0]["request"].data.decode("utf-8"))
|
||||
self.assertEqual(body["client_id"], "abc")
|
||||
self.assertEqual(body["client_secret"], "secret")
|
||||
self.assertEqual(body["timestamp"], 1000500)
|
||||
self.assertEqual(body["tenant"], "demo")
|
||||
|
||||
def test_token_body_json_supports_current_time_placeholders(self):
|
||||
cache_path = self.root / ".runtime" / "kingdee-token.json"
|
||||
config = {
|
||||
"KINGDEE_TOKEN_URL": "https://token.example/access",
|
||||
"KINGDEE_TOKEN_BODY_JSON": '{"app_key":"abc","timestamp":{now_ms},"requested_at":"{now_datetime_utc}"}',
|
||||
"KINGDEE_TOKEN_FIELD": "data.access_token",
|
||||
}
|
||||
http = RecordingUrlopen([{"data": {"access_token": "access-1"}}])
|
||||
|
||||
get_kingdee_access_token(config, cache_path=cache_path, urlopen=http, now_epoch=1000)
|
||||
|
||||
body = json.loads(http.calls[0]["request"].data.decode("utf-8"))
|
||||
self.assertEqual(body["timestamp"], 1000000)
|
||||
self.assertEqual(body["requested_at"], "1970-01-01 00:16:40")
|
||||
|
||||
def test_expired_token_uses_refresh_endpoint(self):
|
||||
cache_path = self.root / ".runtime" / "kingdee-token.json"
|
||||
cache_path.parent.mkdir(parents=True)
|
||||
|
||||
Reference in New Issue
Block a user