diff --git a/controller/channel-billing.go b/controller/channel-billing.go
index e69cd9c2..9f7ca189 100644
--- a/controller/channel-billing.go
+++ b/controller/channel-billing.go
@@ -112,6 +112,13 @@ type DeepSeekUsageResponse struct {
} `json:"balance_infos"`
}
+type OpenRouterResponse struct {
+ Data struct {
+ TotalCredits float64 `json:"total_credits"`
+ TotalUsage float64 `json:"total_usage"`
+ } `json:"data"`
+}
+
// GetAuthHeader get auth header
func GetAuthHeader(token string) http.Header {
h := http.Header{}
@@ -285,6 +292,22 @@ func updateChannelDeepSeekBalance(channel *model.Channel) (float64, error) {
return balance, nil
}
+func updateChannelOpenRouterBalance(channel *model.Channel) (float64, error) {
+ url := "https://openrouter.ai/api/v1/credits"
+ body, err := GetResponseBody("GET", url, channel, GetAuthHeader(channel.Key))
+ if err != nil {
+ return 0, err
+ }
+ response := OpenRouterResponse{}
+ err = json.Unmarshal(body, &response)
+ if err != nil {
+ return 0, err
+ }
+ balance := response.Data.TotalCredits - response.Data.TotalUsage
+ channel.UpdateBalance(balance)
+ return balance, nil
+}
+
func updateChannelBalance(channel *model.Channel) (float64, error) {
baseURL := channeltype.ChannelBaseURLs[channel.Type]
if channel.GetBaseURL() == "" {
@@ -313,6 +336,8 @@ func updateChannelBalance(channel *model.Channel) (float64, error) {
return updateChannelSiliconFlowBalance(channel)
case channeltype.DeepSeek:
return updateChannelDeepSeekBalance(channel)
+ case channeltype.OpenRouter:
+ return updateChannelOpenRouterBalance(channel)
default:
return 0, errors.New("尚未实现")
}
diff --git a/controller/channel-test.go b/controller/channel-test.go
index c24ad971..3894691c 100644
--- a/controller/channel-test.go
+++ b/controller/channel-test.go
@@ -153,6 +153,7 @@ func testChannel(ctx context.Context, channel *model.Channel, request *relaymode
rawResponse := w.Body.String()
_, responseMessage, err = parseTestResponse(rawResponse)
if err != nil {
+ logger.SysError(fmt.Sprintf("failed to parse error: %s, \nresponse: %s", err.Error(), rawResponse))
return "", err, nil
}
result := w.Result()
diff --git a/web/default/src/components/ChannelsTable.js b/web/default/src/components/ChannelsTable.js
index b9caba6b..f94970c9 100644
--- a/web/default/src/components/ChannelsTable.js
+++ b/web/default/src/components/ChannelsTable.js
@@ -57,6 +57,8 @@ function renderBalance(type, balance, t) {
return ¥{balance.toFixed(2)};
case 13: // AIGC2D
return {renderNumber(balance)};
+ case 20: // OpenRouter
+ return ${balance.toFixed(2)};
case 36: // DeepSeek
return ¥{balance.toFixed(2)};
case 44: // SiliconFlow