This commit is contained in:
jiangyong 2024-01-21 18:12:39 +08:00
commit 4dba9b162c
17 changed files with 1009 additions and 0 deletions

11
.gitignore vendored Normal file
View File

@ -0,0 +1,11 @@
*.iml
.idea/
output/
dockerfiles/
log
.DS_Store
doc
cmd/test
go.sum
pkg
test.go

249
adapi/sdk.go Normal file
View File

@ -0,0 +1,249 @@
package adapi
import (
"encoding/json"
"fmt"
"github.com/smbrave/gosdk/util"
"github.com/spf13/cast"
"net/url"
"strconv"
"strings"
"time"
)
type Sdk struct {
address string
token string
}
func NewSdk(address string, token string) *Sdk {
if address == "" {
address = "http://127.0.0.1:9281"
}
return &Sdk{
address: address,
token: token,
}
}
func (s *Sdk) httpGet(url string) error {
body, err := util.HttpGet(url, map[string]string{
"x-token": s.token,
})
if err != nil {
return err
}
type rsp_t struct {
Code int `json:"code"`
Message string `json:"message"`
}
var rsp rsp_t
if err := json.Unmarshal(body, &rsp); err != nil {
return err
}
if rsp.Code != 0 {
return fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
return nil
}
func (s *Sdk) httpMatchGet(url string) (*Result, error) {
body, err := util.HttpGet(url, map[string]string{
"x-token": s.token,
})
if err != nil {
return nil, err
}
type rsp_t struct {
Code int `json:"code"`
Message string `json:"message"`
Data *Result `json:"data"`
}
var rsp rsp_t
if err := json.Unmarshal(body, &rsp); err != nil {
return nil, err
}
if rsp.Code != 0 {
return nil, fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
return rsp.Data, nil
}
func (s *Sdk) httpDataGet(url string) (map[string]interface{}, error) {
body, err := util.HttpGet(url, map[string]string{
"x-token": s.token,
})
if err != nil {
return nil, err
}
type rsp_t struct {
Code int `json:"code"`
Message string `json:"message"`
Data map[string]interface{} `json:"data"`
}
var rsp rsp_t
if err := json.Unmarshal(body, &rsp); err != nil {
return nil, err
}
if rsp.Code != 0 {
return nil, fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
return rsp.Data, nil
}
func (s *Sdk) Match(c *Request) (*Result, error) {
if err := c.Check(); err != nil {
return nil, err
}
params := url.Values{}
params.Add("os", strings.ToLower(c.Os))
params.Add("ip", c.Ip)
params.Add("ua", c.Ua)
params.Add("model", c.Model)
params.Add("brand", c.Brand)
params.Add("idfa", c.Idfa)
params.Add("oaid", c.Oaid)
params.Add("imei", c.Imei)
params.Add("channel", c.Channel)
params.Add("version", c.Version)
params.Add("active", strconv.FormatBool(c.Active))
if c.Extra != nil {
extra, _ := json.Marshal(c.Extra)
params.Add("extra", string(extra))
}
u := fmt.Sprintf("%s/api/ad/client/match?%s", s.address, params.Encode())
return s.httpMatchGet(u)
}
func (s *Sdk) Active(adId int64, extra map[string]string) error {
params := url.Values{}
params.Add("adId", strconv.FormatInt(adId, 10))
if extra != nil {
ex, _ := json.Marshal(extra)
params.Add("extra", string(ex))
}
url := fmt.Sprintf("%s/api/ad/client/active?%s",
s.address, params.Encode())
return s.httpGet(url)
}
/*
extra存放扩展数据注册相关信息都填上
unionidphoneopenidnickname
*/
func (s *Sdk) Register(adId int64, extra map[string]string) error {
params := url.Values{}
params.Add("adId", strconv.FormatInt(adId, 10))
if extra != nil {
ex, _ := json.Marshal(extra)
params.Add("extra", string(ex))
}
url := fmt.Sprintf("%s/api/ad/client/register?%s",
s.address, params.Encode())
return s.httpGet(url)
}
/*
extra存放扩展数据支付相关信息都填上
支付金额payFee 单位分
支付方式payTypeweixinalipayapple
支付位置payLocation 内容自定义
支付商品goodsIdgoodsName
*/
func (s *Sdk) Pay(adId int64, extra map[string]string) error {
params := url.Values{}
params.Add("adId", strconv.FormatInt(adId, 10))
if extra != nil {
ex, _ := json.Marshal(extra)
params.Add("extra", string(ex))
}
url := fmt.Sprintf("%s/api/ad/client/pay?%s",
s.address, params.Encode())
return s.httpGet(url)
}
func (s *Sdk) Relation(adId int64) (*AdRelation, error) {
params := url.Values{}
params.Add("adId", strconv.FormatInt(adId, 10))
url := fmt.Sprintf("%s/api/ad/client/relation?%s",
s.address, params.Encode())
var relation AdRelation
data, err := s.httpDataGet(url)
if err != nil {
return nil, err
}
res, _ := json.Marshal(data)
json.Unmarshal(res, &relation)
return &relation, nil
}
func (s *Sdk) GetAccountReport(startDay, endDay string, accountType string) ([]*AccountReport, error) {
if startDay == "" && endDay == "" {
startDay = time.Now().Format("2006-01-02")
endDay = startDay
}
reqUrl := fmt.Sprintf("%s/api/ad/account/report?startDay=%s&endDay=%s&accountType=%s",
s.address, startDay, endDay, accountType)
body, err := util.HttpGet(reqUrl, map[string]string{
"x-token": s.token,
})
if err != nil {
return nil, err
}
type rsp_t struct {
BaseResponse
Data []map[string]interface{} `json:"data"`
}
var rsp rsp_t
if err := json.Unmarshal(body, &rsp); err != nil {
return nil, err
}
if rsp.Code != 0 {
return nil, fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
results := make([]*AccountReport, 0)
for _, data := range rsp.Data {
r := new(AccountReport)
r.Id = cast.ToString(data["accounId"])
r.Name = cast.ToString(data["accounName"])
r.Type = cast.ToString(data["accounType"])
r.Day = cast.ToString(data["day"])
r.Cost = cast.ToFloat64(data["cost"])
r.Show = cast.ToInt64(data["show"])
r.Click = cast.ToInt64(data["click"])
r.Download = cast.ToInt64(data["download"])
r.Active = cast.ToInt64(data["active"])
r.Register = cast.ToInt64(data["register"])
r.Pay = cast.ToInt64(data["pay"])
r.PayAmount = cast.ToFloat64(data["payAmount"])
r.Balance = cast.ToFloat64(data["balance"])
results = append(results, r)
}
return results, nil
}

23
adapi/sdk_test.go Normal file
View File

@ -0,0 +1,23 @@
package adapi
import (
"fmt"
"testing"
)
func TestSdk(t1 *testing.T) {
fmt.Println("ok1")
sdk := NewSdk("http://localhost:9281", "10020", "")
res, err := sdk.GetAccountReport("", "", "")
if err != nil {
panic(err)
}
fmt.Println("ok2")
fmt.Println(len(res))
fmt.Printf("%+v", res)
for i, r := range res {
fmt.Println(i, r.Name)
}
fmt.Println("ok3")
}

89
adapi/type.go Normal file
View File

@ -0,0 +1,89 @@
package adapi
import (
"errors"
"strings"
)
type BaseResponse struct {
Code int `json:"code"`
Message string `json:"message"`
}
type Request struct {
Channel string //安装包的渠道
Version string //安装包版本
Os string //手机系统类别 android、ioss
Ip string //客户端的外网ip
Ua string //客户端的user-agent
Brand string // 客户端手机品牌
Model string //客户端的手机型号NOH-AN00
Idfa string //客户端的广告idios时候有效
Oaid string //客户端的广告idandroid时有效
Imei string //设备唯一识别码
Extra map[string]string //其他额外数据
Active bool // 是否直接激活
}
type Result struct {
AdId int64 `json:"adId"`
Source string `json:"source"`
Extra map[string]string `json:"extra"`
}
func (c *Request) Check() error {
if strings.ToLower(c.Os) != "ios" && c.Channel == "" {
return errors.New("channel must set")
}
if c.Version == "" {
return errors.New("version must set")
}
return nil
}
type AccountReport struct {
Id string `json:"id"`
Type string `json:"type"`
Name string `json:"name"`
Day string `json:"day"`
Cost float64 `json:"cost"`
Show int64 `json:"show"`
Click int64 `json:"click"`
Download int64 `json:"download"`
Active int64 `json:"active"`
Register int64 `json:"register"`
Pay int64 `json:"pay"`
PayAmount float64 `json:"payAmount"`
Balance float64 `json:"balance"`
}
type Relation struct {
MatchType string `json:"matchType"`
CreateTime int64 `json:"createTime"`
ActiveTime int64 `json:"activeTime"`
RegisterTime int64 `json:"registerTime"`
PayTime int64 `json:"payTime"`
Source string `json:"source"`
}
type Click struct {
Action string `json:"action"`
AccountId int64 `json:"accountId"`
AccountName string `json:"accountName"`
PlanId int64 `json:"planId"`
PlanName string `json:"planName"`
GroupId int64 `json:"groupId"`
GroupName string `json:"groupName"`
CreativeId int64 `json:"creativeId"`
CreativeName string `json:"creativeName"`
ClickTime int64 `json:"clickTime"`
Ip string `json:"ip"`
Ua string `json:"ua"`
Idfa string `json:"idfa"`
Oaid string `json:"oaid"`
}
type AdRelation struct {
Relation *Relation `json:"relation"`
Click *Click `json:"click"`
}

46
adminapi/application.go Normal file
View File

@ -0,0 +1,46 @@
package adminapi
import (
"encoding/json"
"fmt"
"github.com/smbrave/gosdk/util"
)
type Application struct {
token string
address string
}
func NewApplication(addreess string, token string) *Application {
if addreess == "" {
addreess = "http://127.0.0.1:9281"
}
return &Application{
address: addreess,
token: token,
}
}
func (m *Application) Login(username, password, appid string) (interface{}, error) {
reqUrl := fmt.Sprintf("%s/admin/app/login", m.address)
params := make(map[string]interface{})
params["username"] = username
params["password"] = password
params["appid"] = appid
reqBody, _ := json.Marshal(params)
body, err := util.HttpPostJson(reqUrl, map[string]string{
"x-token": m.token,
}, reqBody)
if err != nil {
return nil, err
}
var rsp util.DataResponse
if err := json.Unmarshal(body, &rsp); err != nil {
return nil, err
}
if rsp.Code != 0 {
return nil, fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
return rsp.Data, nil
}

43
adminapi/message.go Normal file
View File

@ -0,0 +1,43 @@
package adminapi
import (
"encoding/json"
"fmt"
"github.com/smbrave/gosdk/util"
"net/url"
)
type Message struct {
token string
sender string
address string
}
func NewMessage(addreess string, token string, sender string) *Message {
if addreess == "" {
addreess = "http://127.0.0.1:9281"
}
return &Message{
address: addreess,
token: token,
sender: sender,
}
}
func (m *Message) Send(receiver, content string) error {
reqUrl := fmt.Sprintf("%s/admin/message/send?sender=%s&receiver=%s&content=%s", m.address, m.sender, receiver, url.QueryEscape(content))
body, err := util.HttpGet(reqUrl, map[string]string{
"x-token": m.token,
})
if err != nil {
return err
}
var rsp util.Response
if err := json.Unmarshal(body, &rsp); err != nil {
return err
}
if rsp.Code != 0 {
return fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
return nil
}

19
adminapi/message_test.go Normal file
View File

@ -0,0 +1,19 @@
package adminapi
import (
"fmt"
"strings"
"testing"
)
func TestMessage_Send(t *testing.T) {
s := NewMessage("http://u.batiao8.com", "", "alarm")
mess := make([]string, 0)
mess = append(mess, "加发到")
mess = append(mess, "asdfasdfadfa")
mess = append(mess, "@3q452345~!@@#$$%^&*())")
err := s.Send("jiangyong", strings.Join(mess, "\n"))
fmt.Println(err)
}

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module github.com/smbrave/gosdk
go 1.18
require github.com/spf13/cast v1.5.0

34
metric/config.go Normal file
View File

@ -0,0 +1,34 @@
package metric
import "os"
var (
serv *service
)
type Config struct {
Address string
Interval int
}
func NewConfg() *Config {
return &Config{
Address: "10.0.1.15:17000",
Interval: 10,
}
}
func Init(c *Config) error {
if serv != nil {
return nil
}
hostname, _ := os.Hostname()
serv = &service{
config: c,
hostname: hostname,
metrics: make(chan *metric, 100000),
}
go serv.run()
return nil
}

18
metric/metric.go Normal file
View File

@ -0,0 +1,18 @@
package metric
import (
"time"
)
func Metric(name string, value float64, tag map[string]string) {
if serv == nil {
return
}
serv.add(&metric{
Metric: name,
Value: value,
Tags: tag,
Timestamp: time.Now().Unix(),
})
}

32
metric/metric_test.go Normal file
View File

@ -0,0 +1,32 @@
package metric
import (
"math/rand"
"testing"
"time"
)
func TestName(t *testing.T) {
c := NewConfg()
c.Address = "https://monitor.batiao8.com"
Init(c)
for i := 0; i < 100; i++ {
Metric("test", float64(rand.Int()%100), map[string]string{
"a": "b",
"c": "d",
})
time.Sleep(time.Second)
}
}
func TestMetric(t *testing.T) {
c := NewConfg()
c.Address = "https://monitor.batiao8.com"
Init(c)
Metric("test.test1.test2", 12, map[string]string{
"a": "b",
"c": "d",
})
}

123
metric/service.go Normal file
View File

@ -0,0 +1,123 @@
package metric
import (
"bytes"
"encoding/json"
"fmt"
"github.com/spf13/cast"
"io/ioutil"
"log"
"net/http"
"sort"
"strings"
"time"
)
type metric struct {
Timestamp int64 `json:"timestamp"`
Metric string `json:"metric"`
Value float64 `json:"value"`
Tags map[string]string `json:"tags"`
}
type service struct {
hostname string
metrics chan *metric
megers map[string]*metric
config *Config
}
func (s *service) run() {
timer := time.NewTicker(time.Duration(s.config.Interval) * time.Second)
for {
select {
case m := <-s.metrics:
s.process(m)
case <-timer.C:
s.report()
}
}
}
func (s *service) sortMap(tag map[string]string) string {
arr := make([]string, 0)
for k, v := range tag {
arr = append(arr, fmt.Sprintf("%s=%s", k, v))
}
sort.Strings(arr)
return strings.Join(arr, ":")
}
func (s *service) process(m *metric) {
if s.megers == nil {
s.megers = make(map[string]*metric)
}
key := m.Metric
if m.Tags != nil {
key += "_" + s.sortMap(m.Tags)
}
if v, ok := s.megers[key]; ok {
v.Value += m.Value
v.Timestamp = m.Timestamp
return
}
s.megers[key] = m
}
func (s *service) defaultTags(tags map[string]string) map[string]string {
if tags == nil {
tags = map[string]string{
"hostname": s.hostname,
}
} else {
tags["hostname"] = s.hostname
}
return tags
}
func (s *service) report() {
if s.megers == nil {
return
}
metrics := make([]*metric, 0)
for _, v := range s.megers {
v.Tags = s.defaultTags(v.Tags)
metrics = append(metrics, v)
}
reqUrl := fmt.Sprintf("%s/opentsdb/put", serv.config.Address)
reqBody, _ := json.Marshal(metrics)
resp, err := http.Post(reqUrl, "application/json", bytes.NewBuffer(reqBody))
if err != nil {
log.Printf("http.Post error :%s", err.Error())
return
}
defer resp.Body.Close()
rspBody, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf(" ioutil.ReadAll error :%s", err.Error())
return
}
result := make(map[string]interface{})
if err := json.Unmarshal(rspBody, &result); err != nil {
log.Printf("json result : %s", string(rspBody))
return
}
fail := cast.ToInt(result["fail"])
if fail != 0 {
log.Printf("http result : %s", string(rspBody))
return
}
s.megers = nil
}
func (s *service) add(m *metric) {
select {
case s.metrics <- m:
default:
fmt.Println("chan is full")
}
}

124
payapi/pay.go Normal file
View File

@ -0,0 +1,124 @@
package payapi
import (
"encoding/json"
"errors"
"fmt"
"github.com/smbrave/gosdk/util"
)
var (
PayTypeWeixin = "weixin"
PayTypeAlipay = "alipay"
)
type Pay struct {
address string
token string
}
func NewPay(address string, token string) *Pay {
if address == "" {
address = "http://127.0.0.1:9281"
}
return &Pay{
address: address,
token: token,
}
}
func (p *Pay) CreateOrder(order *CreateOrderReq) (map[string]interface{}, error) {
if order.PayType == "" {
errors.New("payType is nil")
}
if order.PayPrice <= 0 {
return nil, errors.New("payPrice is nil")
}
reqBody, _ := json.Marshal(order)
result, err := util.HttpPostJson(p.address+"/api/pay/order", map[string]string{
"x-token": p.token,
}, reqBody)
if err != nil {
return nil, err
}
var rsp CommonResponse
if err := json.Unmarshal([]byte(result), &rsp); err != nil {
return nil, err
}
if rsp.Code != 0 {
return nil, fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
return rsp.Data, nil
}
func (p *Pay) UpdateOrder(data map[string]interface{}) error {
reqBody, _ := json.Marshal(data)
result, err := util.HttpPutJson(p.address+"/api/pay/order", map[string]string{
"x-token": p.token,
}, reqBody)
if err != nil {
return err
}
var rsp CommonResponse
if err := json.Unmarshal([]byte(result), &rsp); err != nil {
return err
}
if rsp.Code != 0 {
return fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
return nil
}
func (p *Pay) GetOrder(outTradeNo string) (map[string]interface{}, error) {
if outTradeNo == "" {
errors.New("outTradeNo is nil")
}
reqUrl := fmt.Sprintf("%s/api/pay/order?outTradeNo=%s", p.address, outTradeNo)
result, err := util.HttpGet(reqUrl, map[string]string{
"x-token": p.token,
})
if err != nil {
return nil, err
}
var rsp CommonResponse
if err := json.Unmarshal([]byte(result), &rsp); err != nil {
return nil, err
}
if rsp.Code != 0 {
return nil, fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
return rsp.Data, nil
}
func (p *Pay) RefundOrder(outTradeNo, reason string) error {
if outTradeNo == "" {
errors.New("outTradeNo is nil")
}
reqUrl := fmt.Sprintf("%s/api/pay/order?outTradeNo=%s&reason=%s", p.address, outTradeNo, reason)
result, err := util.HttpDelete(reqUrl, map[string]string{
"x-token": p.token,
})
if err != nil {
return err
}
var rsp CommonResponse
if err := json.Unmarshal([]byte(result), &rsp); err != nil {
return err
}
if rsp.Code != 0 {
return fmt.Errorf("%d:%s", rsp.Code, rsp.Message)
}
return nil
}

17
payapi/pay_test.go Normal file
View File

@ -0,0 +1,17 @@
package payapi
import (
"encoding/json"
"fmt"
"testing"
)
func TestNewPay(t *testing.T) {
payApi := NewPay("http://u.batiao8.com", "")
order, err := payApi.GetOrder("ZB_20230826122127_2YAxfg")
if err != nil {
panic(err)
}
res, _ := json.Marshal(order)
fmt.Println(string(res))
}

39
payapi/type.go Normal file
View File

@ -0,0 +1,39 @@
package payapi
type OrderUser struct {
UserId string `json:"userId"`
UserName string `json:"userName"`
CreateTime string `json:"createTime"`
Openid string `json:"openid"`
Source string `json:"source"`
SourceId string `json:"sourceId"`
MobileBrand string `json:"brand"`
MobileModel string `json:"model"`
Platform string `json:"platform"`
Channel string `json:"channel"`
Version string `json:"version"`
}
type OrderGoods struct {
GoodsId string `json:"goodsId"`
GoodsName string `json:"goodsName"`
Source string `json:"source"`
Autopay string `json:"autopay"`
}
type CreateOrderReq struct {
OutTradeNo string `json:"outTradeNo"`
PayType string `json:"payType"`
PayChannel string `json:"payChannel"`
PayPrice int64 `json:"payPrice"`
PaySource string `json:"paySource"`
NotifyUrl string `json:"notifyUrl"`
Extra interface{} `json:"extra"`
User *OrderUser `json:"user,omitempty"`
Goods *OrderGoods `json:"goods,omitempty"`
}
type CommonResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data map[string]interface{} `json:"data"`
}

126
util/http.go Normal file
View File

@ -0,0 +1,126 @@
package util
import (
"bytes"
"crypto/tls"
"fmt"
"io"
"net/http"
"time"
)
// PostJson 请求
func HttpPostJson(link string, header map[string]string, json []byte) ([]byte, error) {
client := &http.Client{Timeout: 20 * time.Second}
//忽略https的证书
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
req, err := http.NewRequest("POST", link, bytes.NewBuffer(json))
if err != nil {
return nil, err
}
if header != nil {
for k, v := range header {
req.Header.Add(k, v)
}
}
req.Header.Add("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%d:%s", resp.StatusCode, resp.Status)
}
return io.ReadAll(resp.Body)
}
// PostJson 请求
func HttpPutJson(link string, header map[string]string, json []byte) ([]byte, error) {
client := &http.Client{Timeout: 20 * time.Second}
//忽略https的证书
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
req, err := http.NewRequest("PUT", link, bytes.NewBuffer(json))
if err != nil {
return nil, err
}
if header != nil {
for k, v := range header {
req.Header.Add(k, v)
}
}
req.Header.Add("Content-Type", "application/json")
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%d:%s", resp.StatusCode, resp.Status)
}
return io.ReadAll(resp.Body)
}
// Get 请求 link请求url
func HttpGet(link string, header map[string]string) ([]byte, error) {
client := &http.Client{Timeout: 20 * time.Second}
//忽略https的证书
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
req, err := http.NewRequest("GET", link, nil)
if err != nil {
return nil, err
}
if header != nil {
for k, v := range header {
req.Header.Add(k, v)
}
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%d:%s", resp.StatusCode, resp.Status)
}
return io.ReadAll(resp.Body)
}
// Get 请求 link请求url
func HttpDelete(link string, header map[string]string) ([]byte, error) {
client := &http.Client{Timeout: 20 * time.Second}
//忽略https的证书
client.Transport = &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
req, err := http.NewRequest("DELETE", link, nil)
if err != nil {
return nil, err
}
if header != nil {
for k, v := range header {
req.Header.Add(k, v)
}
}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%d:%s", resp.StatusCode, resp.Status)
}
return io.ReadAll(resp.Body)
}

11
util/type.go Normal file
View File

@ -0,0 +1,11 @@
package util
type Response struct {
Code int `json:"code"`
Message string `json:"message"`
}
type DataResponse struct {
Response
Data interface{} `json:"data"`
}