直连天下,sdk开发

This commit is contained in:
李子铭 2024-11-14 18:33:56 +08:00
parent 307205cdfd
commit c9c91d9146
17 changed files with 1000 additions and 1 deletions

62
dctw/v1/api/card/card.go Normal file
View File

@ -0,0 +1,62 @@
package card
import (
"context"
"encoding/json"
"fmt"
"gitea.cdlsxd.cn/sdk/plugin/dctw/v1/api"
"gitea.cdlsxd.cn/sdk/plugin/dctw/v1/core"
"io/ioutil"
"net/http"
)
type Card api.Service
const (
orderPath = "/internal/v1/card/order"
queryPath = "/internal/v1/card/query"
)
func (c *Card) Order(ctx context.Context, request *Order) (*OrderResp, error) {
result, err := c.Request(ctx, request, orderPath)
if err != nil {
return nil, err
}
fmt.Println("result:", string(result))
var response *OrderResp
if err = json.Unmarshal(result, &response); err != nil {
return nil, err
}
return response, nil
}
func (c *Card) Query(ctx context.Context, request *Query) (*QueryResp, error) {
result, err := c.Request(ctx, request, queryPath)
if err != nil {
return nil, err
}
fmt.Println("result:", string(result))
var response *QueryResp
if err = json.Unmarshal(result, &response); err != nil {
return nil, err
}
return response, nil
}
func (c *Card) Notify(_ context.Context, httpRequest *http.Request) (*Notify, error) {
body, err := ioutil.ReadAll(httpRequest.Body)
if err != nil {
return nil, err
}
if err = c.VerifyDctW(httpRequest.Header.Get(core.SignKeyName), body); err != nil {
return nil, err
}
var response *Notify
if err = json.Unmarshal(body, &response); err != nil {
return nil, err
}
return response, err
}

View File

@ -0,0 +1,89 @@
package card
import (
"bytes"
"context"
"gitea.cdlsxd.cn/sdk/plugin/dctw/v1/core"
"io/ioutil"
"net/http"
"testing"
)
func TestCardOrder(t *testing.T) {
server, err := core.NewDctWServer(&core.DctWConfig{
AppId: "1",
AppKey: "1e2bf7a04b8b1e6be5dc78d04e8639c9",
BaseUri: "http://test.openapi.1688sup.cn",
})
if err != nil {
t.Fatal(err)
}
a := &Card{DctWServer: server}
req := &Order{
Number: 1,
MerchantId: "101",
OutTradeNo: "test_1_zltx_4",
ProductId: "106",
Mobile: "18666666666",
NotifyUrl: "http://test.openapi.1688sup.cn",
Version: "1.0",
}
resp, err := a.Order(context.Background(), req)
if err != nil {
t.Error(err)
return
}
t.Log(resp)
}
func TestCard_Query(t *testing.T) {
server, err := core.NewDctWServer(&core.DctWConfig{
AppId: "1",
AppKey: "1e2bf7a04b8b1e6be5dc78d04e8639c9",
BaseUri: "http://test.openapi.1688sup.cn",
})
if err != nil {
t.Fatal(err)
}
a := &Card{DctWServer: server}
req := &Query{
MerchantId: "101",
OutTradeNo: "test_1_zltx_4",
Version: "1.0",
}
resp, err := a.Query(context.Background(), req)
if err != nil {
t.Error(err)
return
}
t.Log(resp)
}
func TestCard_Notify(t *testing.T) {
server, err := core.NewDctWServer(&core.DctWConfig{
AppId: "1",
AppKey: "1e2bf7a04b8b1e6be5dc78d04e8639c9",
BaseUri: "http://test.openapi.1688sup.cn",
})
if err != nil {
t.Fatal(err)
}
a := &Card{DctWServer: server}
body := []byte(`{"merchantId":23329,"outTradeNo":"202409111714224026320002","rechargeAccount":"18512869479","sign":"474ACB521DEE99551153B6CE108FD06D","status":"01"}`)
headers := make(http.Header)
headers.Set(core.SignKeyName, "MD5 appid=101,sign=292e21f3683219369cf68dede0d45730")
headers.Set("Content-Type", core.ApplicationJSON)
var httpRequest = &http.Request{
Header: http.Header{},
Body: ioutil.NopCloser(bytes.NewBuffer(body)),
}
resp, err := a.Notify(context.Background(), httpRequest)
if err != nil {
t.Error(err)
return
}
t.Log(resp)
}

38
dctw/v1/api/card/code.go Normal file
View File

@ -0,0 +1,38 @@
package card
type Code string
const CodeSuccess Code = "0000"
const RechargeCodeSuccess Code = "2000"
var ResMessageMap = map[Code]string{
"1000": "Ip limit(ip未绑定或绑定失败)",
"1001": "Missing parameters(参数异常)",
"1002": "Invalid merchant(无效商户信息)",
"1003": "Invalid signature(签名校验失败)",
"1004": "Request expiration(请求时间过期)",
"1005": "Order repeat(订单重复)",
"1006": "Invalid item(商品未开通)",
"1007": "Item price invalid(商品价格无效)",
"1008": "Insufficient Balance(余额不足)",
"1009": "Interface adjustment(商品映射无效)",
"1010": "Interface price adjustment(映射价格无效)",
"1011": "Account format matching(充值账号格式不匹配)",
"1012": "no order(无订单信息)",
"1999": "unknown error(异常错误,建议人工处理或查询订单状态)",
}
func (c Code) IsRechargeSuccess() bool {
return c == RechargeCodeSuccess
}
func (c Code) GetMessage() string {
if message, ok := ResMessageMap[c]; ok {
return message
}
return ""
}
func (c Code) IsSuccess() bool {
return c == CodeSuccess
}

View File

@ -0,0 +1,43 @@
package card
import (
"gitea.cdlsxd.cn/sdk/plugin/proto"
)
type OrderStatus string
const (
OrderSuccess OrderStatus = "01" // 充值成功
OrderPending OrderStatus = "02" // 充值处理中
OrderFail OrderStatus = "03" // 充值失败
OrderAbnormal OrderStatus = "04" // 充值异常,处理中
)
var orderStatusMap = map[OrderStatus]proto.Status{
OrderSuccess: proto.Status_SUCCESS,
OrderPending: proto.Status_ING,
OrderFail: proto.Status_FAIL,
}
func (o OrderStatus) IsSuccess() bool {
return o == OrderSuccess
}
func (o OrderStatus) IsPending() bool {
return o == OrderPending
}
func (o OrderStatus) IsFail() bool {
return o == OrderFail
}
func (o OrderStatus) IsAbnormal() bool {
return o == OrderAbnormal
}
func (o OrderStatus) GetOrderStatus() proto.Status {
if resultStatus, ok := orderStatusMap[o]; ok {
return resultStatus
}
return proto.Status_ING
}

99
dctw/v1/api/card/trans.go Normal file
View File

@ -0,0 +1,99 @@
package card
import (
"encoding/json"
"fmt"
"gitea.cdlsxd.cn/sdk/plugin/alipay/vo"
"github.com/go-playground/validator/v10"
)
type Order struct {
Number uint32 `validate:"required" json:"number"`
MerchantId string `validate:"required" json:"merchantId"`
OutTradeNo string `validate:"required" json:"outTradeNo"`
ProductId string `validate:"required" json:"productId"`
Mobile string `json:"mobile"`
NotifyUrl string `validate:"required" json:"notifyUrl"`
Version string `validate:"required" json:"version"`
}
type OrderResp struct {
Code vo.Code `json:"code"`
Message string `json:"message"`
}
type Query struct {
MerchantId string `validate:"required" json:"merchantId"`
OutTradeNo string `validate:"required" json:"outTradeNo"`
Version string `validate:"required" json:"version"`
}
type QueryResp struct {
Code vo.Code `json:"code"`
Status OrderStatus `json:"status"`
Message string `json:"message"`
OutTradeNo string `json:"outTradeNo"`
CardCode string `json:"cardCode"`
}
type Notify struct {
MerchantId int `json:"merchantId"`
OutTradeNo string `json:"outTradeNo"`
RechargeAccount string `json:"rechargeAccount"`
Status OrderStatus `json:"status"`
CardCode string `json:"cardCode"`
}
func (o *Order) Json() ([]byte, error) {
b, err := json.Marshal(o)
if err != nil {
return nil, err
}
return b, nil
}
func (o *Order) Validate() error {
err := validator.New().Struct(o)
if err != nil {
for _, err = range err.(validator.ValidationErrors) {
return fmt.Errorf("参数有误:" + err.Error())
}
}
return nil
}
func (o *Query) Json() ([]byte, error) {
b, err := json.Marshal(o)
if err != nil {
return nil, err
}
return b, nil
}
func (o *Query) Validate() error {
err := validator.New().Struct(o)
if err != nil {
for _, err = range err.(validator.ValidationErrors) {
return fmt.Errorf("参数有误:" + err.Error())
}
}
return nil
}
func (o *Notify) Json() ([]byte, error) {
b, err := json.Marshal(o)
if err != nil {
return nil, err
}
return b, nil
}
func (o *Notify) Validate() error {
err := validator.New().Struct(o)
if err != nil {
for _, err = range err.(validator.ValidationErrors) {
return fmt.Errorf("参数有误:" + err.Error())
}
}
return nil
}

View File

@ -0,0 +1,38 @@
package direct
import "encoding/json"
type Code json.Number
const (
CodeSuccess Code = "2000"
)
var ResMessageMap = map[Code]string{
CodeSuccess: "成功",
"1000": "Ip limit(ip未绑定或绑定失败)",
"1001": "Missing parameters(参数异常)",
"1002": "Invalid merchant(无效商户信息)",
"1003": "Invalid signature(签名校验失败)",
"1004": "Request expiration(请求时间过期)",
"1005": "Order repeat(订单重复)",
"1006": "Invalid item(商品未开通)",
"1007": "Item price invalid(商品价格无效)",
"1008": "Insufficient Balance(余额不足)",
"1009": "Interface adjustment(商品映射无效)",
"1010": "Interface price adjustment(映射价格无效)",
"1011": "Account format matching(充值账号格式不匹配)",
"1012": "no order(无订单信息)",
"1999": "unknown error(异常错误,建议人工处理或查询订单状态)",
}
func (c Code) IsSuccess() bool {
return c == CodeSuccess
}
func (c Code) GetMessage() string {
if message, ok := ResMessageMap[c]; ok {
return message
}
return "未知错误,请联系平台"
}

View File

@ -0,0 +1,61 @@
package direct
import (
"context"
"encoding/json"
"fmt"
"gitea.cdlsxd.cn/sdk/plugin/dctw/v1/api"
"gitea.cdlsxd.cn/sdk/plugin/dctw/v1/core"
"io/ioutil"
"net/http"
)
type Direct api.Service
const (
orderPath = "/internal/v1/recharge/create"
queryPath = "/internal/v1/recharge/query"
)
func (c *Direct) Order(ctx context.Context, request *Order) (*OrderResp, error) {
result, err := c.Request(ctx, request, orderPath)
if err != nil {
return nil, err
}
fmt.Printf("result: %s\n", string(result))
var response *OrderResp
if err = json.Unmarshal(result, &response); err != nil {
return nil, err
}
return response, nil
}
func (c *Direct) Query(ctx context.Context, request *Query) (*QueryResp, error) {
result, err := c.Request(ctx, request, queryPath)
if err != nil {
return nil, err
}
var response *QueryResp
if err = json.Unmarshal(result, &response); err != nil {
return nil, err
}
return response, nil
}
func (c *Direct) Notify(_ context.Context, httpRequest *http.Request) (*Notify, error) {
body, err := ioutil.ReadAll(httpRequest.Body)
if err != nil {
return nil, err
}
if err = c.VerifyDctW(httpRequest.Header.Get(core.SignKeyName), body); err != nil {
return nil, err
}
var response *Notify
if err = json.Unmarshal(body, &response); err != nil {
return nil, err
}
return response, err
}

View File

@ -0,0 +1,97 @@
package direct
import (
"bytes"
"context"
"gitea.cdlsxd.cn/sdk/plugin/dctw/v1/core"
"github.com/stretchr/testify/assert"
"io/ioutil"
"net/http"
"testing"
)
func TestDirect_Order(t *testing.T) {
server, err := core.NewDctWServer(&core.DctWConfig{
AppId: "1",
AppKey: "1e2bf7a04b8b1e6be5dc78d04e8639c9",
BaseUri: "http://test.openapi.1688sup.cn",
})
if err != nil {
t.Fatal(err)
}
a := &Direct{DctWServer: server}
req := &Order{
Number: 1,
MerchantId: "23329",
OutTradeNo: "test_1_zltx_6",
ProductId: "106",
AccountType: 1,
RechargeAccount: "18666666666",
NotifyUrl: "http://test.openapi.1688sup.cn",
Version: "1.0",
}
resp, err := a.Order(context.Background(), req)
if err != nil {
t.Error(err)
return
}
if !resp.Code.IsSuccess() {
t.Error(resp.Message)
return
}
t.Log(resp)
}
func TestDirect_Query(t *testing.T) {
server, err := core.NewDctWServer(&core.DctWConfig{
AppId: "1",
AppKey: "1e2bf7a04b8b1e6be5dc78d04e8639c9",
BaseUri: "http://test.openapi.1688sup.cn",
})
if err != nil {
t.Fatal(err)
}
a := &Direct{DctWServer: server}
req := &Query{
MerchantId: "106",
OutTradeNo: "test_1_zltx_4",
Version: "1.0",
}
resp, err := a.Query(context.Background(), req)
if err != nil {
t.Error(err)
return
}
t.Log(resp)
assert.Equal(t, resp.Status.IsSuccess(), true, "充值是否成功")
}
func TestDirect_Notify(t *testing.T) {
server, err := core.NewDctWServer(&core.DctWConfig{
AppId: "1",
AppKey: "1e2bf7a04b8b1e6be5dc78d04e8639c9",
BaseUri: "http://test.openapi.1688sup.cn",
})
if err != nil {
t.Fatal(err)
}
a := &Direct{DctWServer: server}
body := []byte(`{"merchantId":23329,"outTradeNo":"202409111714224026320002","rechargeAccount":"18512869479","sign":"474ACB521DEE99551153B6CE108FD06D","status":"01"}`)
headers := make(http.Header)
headers.Set(core.SignKeyName, "MD5 appid=101,sign=292e21f3683219369cf68dede0d45730")
headers.Set("Content-Type", core.ApplicationJSON)
var httpRequest = &http.Request{
Header: http.Header{},
Body: ioutil.NopCloser(bytes.NewBuffer(body)),
}
resp, err := a.Notify(context.Background(), httpRequest)
if err != nil {
t.Error(err)
return
}
t.Log(resp)
assert.Equal(t, resp.Status.IsSuccess(), true, "充值是否成功")
}

View File

@ -0,0 +1,43 @@
package direct
import (
"gitea.cdlsxd.cn/sdk/plugin/proto"
)
type OrderStatus string
const (
OrderSuccess OrderStatus = "01" // 充值成功
OrderPending OrderStatus = "02" // 充值处理中
OrderFail OrderStatus = "03" // 充值失败
OrderAbnormal OrderStatus = "04" // 充值异常,处理中
)
var orderStatusMap = map[OrderStatus]proto.Status{
OrderSuccess: proto.Status_SUCCESS,
OrderPending: proto.Status_ING,
OrderFail: proto.Status_FAIL,
}
func (o OrderStatus) IsSuccess() bool {
return o == OrderSuccess
}
func (o OrderStatus) IsPending() bool {
return o == OrderPending
}
func (o OrderStatus) IsFail() bool {
return o == OrderFail
}
func (o OrderStatus) IsAbnormal() bool {
return o == OrderAbnormal
}
func (o OrderStatus) GetOrderStatus() proto.Status {
if resultStatus, ok := orderStatusMap[o]; ok {
return resultStatus
}
return proto.Status_ING
}

View File

@ -0,0 +1,99 @@
package direct
import (
"encoding/json"
"fmt"
"github.com/go-playground/validator/v10"
)
type Order struct {
Number uint32 `validate:"required" json:"number"`
MerchantId string `validate:"required" json:"merchantId"`
OutTradeNo string `validate:"required" json:"outTradeNo"`
ProductId string `validate:"required" json:"productId"`
AccountType AccountType `validate:"required" json:"accountType"` // 账号类型(1:手机号 2:QQ号 其他0)
RechargeAccount string `validate:"required" json:"rechargeAccount"`
NotifyUrl string `validate:"required" json:"notifyUrl"`
Version string `validate:"required" json:"version"`
}
type OrderResp struct {
Code Code `json:"code"`
Message string `json:"message"`
TradeNo string `json:"tradeNo"`
}
type Query struct {
MerchantId string `validate:"required" json:"merchantId"`
OutTradeNo string `validate:"required" json:"outTradeNo"`
Version string `validate:"required" json:"version"`
}
type QueryResp struct {
Code Code `json:"code"`
Status OrderStatus `json:"status"`
Message string `json:"message"`
OutTradeNo string `json:"outTradeNo"`
CardCode string `json:"cardCode"`
}
type Notify struct {
MerchantId int `json:"merchantId"`
OutTradeNo string `json:"outTradeNo"`
RechargeAccount string `json:"rechargeAccount"`
Status OrderStatus `json:"status"`
}
func (o *Order) Json() ([]byte, error) {
b, err := json.Marshal(o)
if err != nil {
return nil, err
}
return b, nil
}
func (o *Order) Validate() error {
err := validator.New().Struct(o)
if err != nil {
for _, err = range err.(validator.ValidationErrors) {
return fmt.Errorf("参数有误:" + err.Error())
}
}
return nil
}
func (o *Query) Json() ([]byte, error) {
b, err := json.Marshal(o)
if err != nil {
return nil, err
}
return b, nil
}
func (o *Query) Validate() error {
err := validator.New().Struct(o)
if err != nil {
for _, err = range err.(validator.ValidationErrors) {
return fmt.Errorf("参数有误:" + err.Error())
}
}
return nil
}
func (o *Notify) Json() ([]byte, error) {
b, err := json.Marshal(o)
if err != nil {
return nil, err
}
return b, nil
}
func (o *Notify) Validate() error {
err := validator.New().Struct(o)
if err != nil {
for _, err = range err.(validator.ValidationErrors) {
return fmt.Errorf("参数有误:" + err.Error())
}
}
return nil
}

28
dctw/v1/api/direct/vo.go Normal file
View File

@ -0,0 +1,28 @@
package direct
import (
"gitea.cdlsxd.cn/sdk/plugin/utils"
)
type AccountType int
const (
AccountTypeDefault AccountType = iota
AccountTypePhone
AccountTypeQQ
)
func (o AccountType) AccountType(account string) AccountType {
if account == "" {
return AccountTypeDefault
} else if utils.IsPhoneNumber(account) {
return AccountTypePhone
} else if utils.IsValidQQ(account) {
return AccountTypeQQ
}
return AccountTypeDefault
}
func (o AccountType) Value() int {
return int(o)
}

7
dctw/v1/api/service.go Normal file
View File

@ -0,0 +1,7 @@
package api
import "gitea.cdlsxd.cn/sdk/plugin/dctw/v1/core"
type Service struct {
*core.DctWServer
}

196
dctw/v1/core/core.go Normal file
View File

@ -0,0 +1,196 @@
package core
import (
"bytes"
"context"
"fmt"
"gitea.cdlsxd.cn/sdk/plugin/utils"
"github.com/go-playground/validator/v10"
"io/ioutil"
"net/http"
"strings"
"time"
)
const (
DeBug = true
SignType = "MD5"
SignKeyName = "Authorization"
ApplicationJSON = "application/json"
)
// DctWRequest 直连天下 Direct connection The world
type DctWRequest interface {
Json() ([]byte, error)
Validate() error
}
type DctWConfig struct {
AppId string `json:"app_id" validate:"required"`
AppKey string `json:"app_key" validate:"required"`
BaseUri string `json:"base_uri" validate:"required"`
}
func (c *DctWConfig) Validate() error {
if err := validator.New().Struct(c); err != nil {
for _, err = range err.(validator.ValidationErrors) {
return err
}
}
return nil
}
type DctWServer struct {
DeBug bool
Config *DctWConfig
HttpClient *http.Client
}
type Option func(*DctWServer)
func WithHttpClient(client *http.Client) Option {
return func(s *DctWServer) {
s.HttpClient = client
}
}
func WithDebug(debug bool) Option {
return func(s *DctWServer) {
s.DeBug = debug
}
}
func NewDctWServer(config *DctWConfig, o ...Option) (*DctWServer, error) {
if err := config.Validate(); err != nil {
return nil, err
}
httpClient := &http.Client{
Timeout: 15 * time.Second,
}
server := &DctWServer{
DeBug: DeBug,
Config: config,
HttpClient: httpClient,
}
for _, f := range o {
f(server)
}
return server, nil
}
func (c *DctWServer) Sign(body, path, timestamp string) string {
str := c.Config.AppId + body + path + timestamp + c.Config.AppKey
return utils.Md5([]byte(str))
}
func (c *DctWServer) BuildAuth(signStr, timestamp string) string {
return fmt.Sprintf("%s appid=%s,timestamp=%s,sign=%s", SignType, c.Config.AppId, timestamp, signStr)
}
func (c *DctWServer) Headers(signStr, timestamp string) http.Header {
h := make(http.Header)
h.Add("Content-type", ApplicationJSON)
h.Add(SignKeyName, c.BuildAuth(signStr, timestamp))
return h
}
func (c *DctWServer) verify(authorization, path string, body []byte) error {
trimmedAuth := strings.TrimPrefix(authorization, "MD5 ")
authData := make(map[string]string)
parts := strings.Split(trimmedAuth, ",")
for _, part := range parts {
keyValue := strings.Split(part, "=")
if len(keyValue) != 2 {
return fmt.Errorf("授权信息格式错误: %s", part)
}
authData[keyValue[0]] = keyValue[1]
}
sign, ok := authData["sign"]
if !ok {
return fmt.Errorf("签名数据获取失败")
}
timestamp, ok := authData["timestamp"]
if !ok {
return fmt.Errorf("时间戳获取失败")
}
calculatedSign := c.Sign(string(body), path, timestamp)
if sign == calculatedSign {
return nil
}
return fmt.Errorf("验签失败")
}
func (c *DctWServer) VerifyDctW(authorization string, body []byte) error {
trimmedAuth := strings.TrimPrefix(authorization, "MD5 ")
authData := make(map[string]string)
parts := strings.Split(trimmedAuth, ",")
for _, part := range parts {
keyValue := strings.Split(part, "=")
if len(keyValue) != 2 {
return fmt.Errorf("授权信息格式错误: %s", part)
}
authData[keyValue[0]] = keyValue[1]
}
sign, ok := authData["sign"]
if !ok {
return fmt.Errorf("签名数据获取失败")
}
signStr := fmt.Sprintf("%s%s%s", c.Config.AppId, string(body), c.Config.AppKey)
calculatedSign := utils.Md5([]byte(signStr))
if sign == calculatedSign {
return nil
}
return fmt.Errorf("验签失败")
}
func (c *DctWServer) Request(_ context.Context, request DctWRequest, path string) ([]byte, error) {
timestamp := fmt.Sprintf("%d", time.Now().Unix())
body, err := request.Json()
if err != nil {
return nil, err
}
signStr := c.Sign(string(body), path, timestamp)
url := fmt.Sprintf("%s%s", c.Config.BaseUri, path)
httpClient := &http.Client{
Timeout: 15 * time.Second,
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(body))
if err != nil {
return nil, err
}
req.Header = c.Headers(signStr, timestamp)
if c.DeBug {
fmt.Printf("url:%s\n", url)
fmt.Printf("body:%s\n", string(body))
fmt.Printf("signStr:%s\n", signStr)
fmt.Printf("Header:%+v\n", req.Header)
}
resp, err := httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if c.DeBug {
fmt.Printf("resp.Status:%s\n", resp.Status)
fmt.Printf("bodyStr:%s\n", string(bodyBytes))
}
return bodyBytes, nil
}

28
dctw/v1/core/core_test.go Normal file
View File

@ -0,0 +1,28 @@
package core
import (
"testing"
)
func TestZc_DctWServer(t *testing.T) {
server, err := NewDctWServer(&DctWConfig{
AppId: "101",
AppKey: "5k8bJV6axIukpkwz5vdte8QCw5etlC+txi+Nu69nIhOMN4VhmcNgf/THdllpt0jO",
BaseUri: "http://openapi.1688sup.cn",
})
if err != nil {
t.Fatal(err)
}
timestamp := "1731566046566"
body := "xx=1"
path := "/xx/xx"
str := server.Sign(body, path, timestamp)
authorization := server.BuildAuth(str, timestamp)
if err = server.verify(authorization, path, []byte(body)); err != nil {
t.Fatal(err)
}
t.Log("验签成功")
}

32
utils/aes.go Normal file
View File

@ -0,0 +1,32 @@
package utils
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"fmt"
)
func AesDecode(data string, key []byte) (string, error) {
decoded, err := base64.StdEncoding.DecodeString(data)
if err != nil {
return "", fmt.Errorf("base64 decode error: %v", err)
}
block, err := aes.NewCipher(key)
if err != nil {
return "", fmt.Errorf("aes new cipher error: %v", err)
}
if len(decoded) < aes.BlockSize {
return "", fmt.Errorf("ciphertext too short")
}
decrypted := make([]byte, len(decoded))
mode := cipher.NewCBCDecrypter(block, make([]byte, aes.BlockSize))
mode.CryptBlocks(decrypted, decoded)
padding := decrypted[len(decrypted)-1]
decrypted = decrypted[:len(decrypted)-int(padding)]
return string(decrypted), nil
}

View File

@ -1,8 +1,12 @@
package utils
import (
"crypto/md5"
"encoding/hex"
"fmt"
"os"
"regexp"
"strings"
)
// Load 获取插件目录中的文件信息
@ -24,3 +28,27 @@ func Load(dir string) ([]string, error) {
return files, nil
}
func Md5(values []byte) string {
hash := md5.Sum(values)
return strings.ToUpper(hex.EncodeToString(hash[:]))
}
// IsPhoneNumber 检查给定的字符串是否为有效的手机号码
func IsPhoneNumber(phoneNumber string) bool {
phoneRegex := `^1[34578]\d{9}$`
return regexp.MustCompile(phoneRegex).MatchString(phoneNumber)
}
// IsEmail 检查给定的字符串是否为有效的电子邮箱地址
func IsEmail(email string) bool {
var emailRegex = regexp.MustCompile(`[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
return emailRegex.MatchString(email)
}
// IsValidQQ 检查给定的字符串是否为有效的 QQ 号
func IsValidQQ(qq string) bool {
// QQ号正则表达式5到11位数字且开头不为0的情况
re := regexp.MustCompile(`^(?!0)[0-9]{5,11}$`)
return re.MatchString(qq)
}

View File

@ -5,7 +5,7 @@ import (
"testing"
)
func Test_load(t *testing.T) {
func Test_Load(t *testing.T) {
got, err := Load("../../pkg")
if err != nil {
t.Errorf("load() error = %v", err)
@ -28,3 +28,14 @@ func Test_BuildPem(t *testing.T) {
puk2 := NewPublic()
t.Logf("\n%s", puk2.Build("puk key"))
}
func Test_AesDecode(t *testing.T) {
key := "837c7a898810160ce5aab4c42bf22bc4"
encStr := ""
str, err := AesDecode(encStr, []byte(key))
if err != nil {
t.Errorf("AesDecode() error = %v", err)
return
}
t.Logf("encStr: %s, str: %s", encStr, str)
}