使用Golang拉取阿里云昨天费用发送到钉钉
初始化go项目
- 初始化项目,如果是简单的脚本,怎么方便怎么来
- 直接进入项目目录初始化也行
cd /apps/app/QueryAccount/
go mod init QueryAccount
- 但是如果是项目,或者复杂一点点就,建议使用
go mod init gitee.com/xxx/skills/
- Golang代理推荐
# 下包报错换一下试试吧,不行再换一个
go env -w GOPROXY=https://goproxy.cn,direct
阿里云文档
- 使用的阿里云的
QueryBillOverview
- 具体使用到什么参数我都写到脚本的结构体中了,有一些我没用我就注释了
https://help.aliyun.com/document_detail/472990.html?spm=a2c4g.472986.0.0.6441a859jhnwCv
https://api.aliyun.com/api/BssOpenApi/2017-12-14/QueryAccountTransactions?spm=a2c4g.472990.0.0.29e65bbfBsxOkp&RegionId=
脚本
- 具体不解释了,里面有注释,
BillItem
结构体我只取了我想要的,如果你觉得不够,可以到上面阿里云文档中拿 - 具体情况可以将
Print大法
注释去掉,排错 - 我这里直接借用了SkyWalking机器人,也很简单,具体创建和使用钉钉机器人流程可以看我之前的文章《使用Golang编写Webhook向钉钉告警》
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"strconv"
"time"
bssopenapi20171214 "github.com/alibabacloud-go/bssopenapi-20171214/v5/client"
openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
util "github.com/alibabacloud-go/tea-utils/v2/service"
"github.com/alibabacloud-go/tea/tea"
)
// 定义QueryBillOverview账单结构体来映射响应中的Item
type BillItem struct {
BillingCycle string `json:"BillingCycle"` // 账单日期
Amount string `json:"Amount"` // 消费金额
TransactionTime string `json:"TransactionTime"` // 交易时间
Remarks string `json:"Remarks"` // 交易产品
Balance string `json:"Balance"` // 当前剩余余额
}
// 钉钉消息结构
type DingTalkMessage struct {
Msgtype string `json:"msgtype"`
Markdown struct {
Title string `json:"title"`
Text string `json:"text"`
} `json:"markdown"`
}
func CreateClient() (_result *bssopenapi20171214.Client, _err error) {
config := &openapi.Config{
AccessKeyId: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID")),
AccessKeySecret: tea.String(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")),
}
config.Endpoint = tea.String("business.aliyuncs.com")
client, err := bssopenapi20171214.NewClient(config)
return client, err
}
func foo(startTime, endTime string) (map[string]string, error) {
client, err := CreateClient()
if err != nil {
return nil, err
}
// 阿里云skd
queryAccountTransactionsRequest := &bssopenapi20171214.QueryAccountTransactionsRequest{
PageNum: tea.Int32(1),
PageSize: tea.Int32(300),
CreateTimeStart: tea.String(startTime),
CreateTimeEnd: tea.String(endTime),
}
// 获取数据
runtime := &util.RuntimeOptions{}
response, err := client.QueryAccountTransactionsWithOptions(queryAccountTransactionsRequest, runtime)
if err != nil {
var sdkErr *tea.SDKError
if errors.As(err, &sdkErr) {
fmt.Println(sdkErr.Message)
} else {
fmt.Println(err.Error())
}
return nil, err
}
// fmt.Println("Test1.Print大法.赋值前查看数据结构:", response.Body.Data.AccountTransactionsList.AccountTransactionsList)
// 使用map来存储交易产品和对应的总金额
totalAmounts := make(map[string]string)
for _, item := range response.Body.Data.AccountTransactionsList.AccountTransactionsList {
remarks := *item.Remarks // 交易产品
amountStr := *item.Amount // 消费金额
amount, _ := strconv.ParseFloat(amountStr, 64) // 假设金额是浮点数
// 如果map中已存在该交易产品,则累加金额
if currentAmount, ok := totalAmounts[remarks]; ok {
currentAmountFloat, _ := strconv.ParseFloat(currentAmount, 64)
totalAmounts[remarks] = fmt.Sprintf("%.2f", currentAmountFloat+amount) // 保留两位小数
} else {
totalAmounts[remarks] = fmt.Sprintf("%.2f", amount) // 初始化为当前金额
}
}
return totalAmounts, nil
}
// 发送钉钉消息
func sendToDingTalk(webhookURL string, message DingTalkMessage) error {
jsonData, err := json.Marshal(message)
if err != nil {
return err
}
req, err := http.NewRequest("POST", webhookURL, bytes.NewBuffer(jsonData))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// 可选:检查响应状态码等
return nil
}
func main() {
// 获取当前时间
now := time.Now().UTC() // 使用UTC时间以确保时区一致性
// fmt.Println("当前时间:", now.Format(time.RFC3339))
// 计算昨天的日期
yesterday := now.AddDate(0, 0, -1)
startTime := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 0, 0, 0, 0, time.UTC) // 构造昨天的开始时间(凌晨00:00:00)
endTime := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 23, 59, 59, 0, time.UTC) // 构造昨天的结束时间(23:59:59)
// 将 time.Time 转换为字符串
startTimeStr := startTime.Format(time.RFC3339)
endTimeStr := endTime.Format(time.RFC3339)
sheetNameStr := yesterday.Format("2006-01-02")
totalAmounts, err := foo(startTimeStr, endTimeStr)
if err != nil {
panic(err)
}
// 初始化钉钉消息的文本部分
var buffer bytes.Buffer
buffer.WriteString("<font color='#FF7D00'>SkyWalking 告警通知汇总</font>\n\n")
// 遍历totalAmounts,将每个交易产品的信息添加到钉钉消息的文本中
var totalConsumption float64 = 0
buffer.WriteString("<hr>\n")
buffer.WriteString(fmt.Sprintf("<font color=' #008000 '> 汇报%s阿里云消费情况 </font>", sheetNameStr))
for remarks, amount := range totalAmounts {
buffer.WriteString("<hr>\n")
buffer.WriteString(fmt.Sprintf("<font color='#FF7D00'> 交易产品 </font>: %s <br> \n <font color='#FF7D00'>消费总金额</font>:%s <br>\n", remarks, amount))
amountFloat, _ := strconv.ParseFloat(amount, 64)
totalConsumption += amountFloat
}
totalConsumptionStr := fmt.Sprintf("%.2f", totalConsumption)
buffer.WriteString("<hr>\n")
buffer.WriteString(fmt.Sprintf("<font color=' #008000 '> %s当天所有交易产品总消费为:%s </font> \n", sheetNameStr, totalConsumptionStr))
// 构造钉钉消息
dingTalkMessage := DingTalkMessage{
Msgtype: "markdown",
Markdown: struct {
Title string `json:"title"`
Text string `json:"text"`
}{
Title: "SkyWalking 告警通知汇总",
Text: buffer.String(),
},
}
// 发送钉钉消息
if err := sendToDingTalk("https://oaxxxxxx----你的钉钉webhook----xxxxxxxx", dingTalkMessage); err != nil {
return
}
// for remarks, amount := range totalAmounts {
// fmt.Printf("交易产品: %s\n 消费总金额: %s\n", remarks, amount)
// }
}
-
结果大概是这样
-
这里我将所有后付费产品(按量计费)相同产品价格合并了