From 2dc89e17bcbdfbe83f179841180b54fd17b974e1 Mon Sep 17 00:00:00 2001 From: yanfan <1406317364@qq.com> Date: Tue, 10 Jun 2025 22:42:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=9A=E5=B9=B3=E5=B9=B3?= =?UTF-8?q?=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.go | 9 +++++ platform/yapingtech/api.go | 54 ++++++++++++++++++++++++++++++ platform/yapingtech/api_test.go | 46 ++++++++++++++++++++++++++ platform/yapingtech/client.go | 36 ++++++++++++++++++++ platform/yapingtech/consts.go | 8 +++++ platform/yapingtech/encrypt.go | 58 +++++++++++++++++++++++++++++++++ platform/yapingtech/types.go | 50 ++++++++++++++++++++++++++++ 7 files changed, 261 insertions(+) create mode 100644 platform/yapingtech/api.go create mode 100644 platform/yapingtech/api_test.go create mode 100644 platform/yapingtech/client.go create mode 100644 platform/yapingtech/consts.go create mode 100644 platform/yapingtech/encrypt.go create mode 100644 platform/yapingtech/types.go diff --git a/index.go b/index.go index dc0faa6..e212f72 100644 --- a/index.go +++ b/index.go @@ -3,6 +3,7 @@ package third_platform_sdk import ( "github.com/zeromicro/go-zero/core/logx" jd_union "repository.lenntc.com/lenntc/third-platform-sdk/platform/jd-union" + "repository.lenntc.com/lenntc/third-platform-sdk/platform/yapingtech" "repository.lenntc.com/lenntc/third-platform-sdk/platform/zhetaoke" "repository.lenntc.com/lenntc/third-platform-sdk/platform/zjdg" @@ -53,6 +54,8 @@ const ( PlatformJdUnion = "jd_union" // PlatformZheTaoKe 折淘客 PlatformZheTaoKe = "zhetaoke" + // PlatformYaPingTech 亚平 + PlatformYaPingTech = "yapingtech" ) // PlatformNameMap 平台名称 @@ -72,6 +75,7 @@ var PlatformNameMap = map[string]string{ PlatformZdjg: "中捷乐淘-淘宝一分购", PlatformJdUnion: "京东联盟", PlatformZheTaoKe: "折淘客", + PlatformYaPingTech: "亚平", } // GetPlatformName 获取平台名称 @@ -153,3 +157,8 @@ func NewJdUnion(log logx.Logger, conf jd_union.AuthConfig) jd_union.JdUnionApi { func NewZheTaoKe(log logx.Logger, conf zhetaoke.AuthConfig) zhetaoke.ZheTaoKeApi { return zhetaoke.NewApiClient(log, conf) } + +// NewYaPingTech 亚平 +func NewYaPingTech(log logx.Logger, conf yapingtech.AuthConfig) yapingtech.YaPingTechApi { + return yapingtech.NewApiClient(log, conf) +} diff --git a/platform/yapingtech/api.go b/platform/yapingtech/api.go new file mode 100644 index 0000000..a3a13d1 --- /dev/null +++ b/platform/yapingtech/api.go @@ -0,0 +1,54 @@ +package yapingtech + +import ( + "context" + "encoding/json" + "fmt" + "github.com/zeromicro/go-zero/core/logx" + "repository.lenntc.com/lenntc/third-platform-sdk/client" +) + +// YaPingTechApi 亚平平台 +type YaPingTechApi interface { + QueryOrderList(ctx context.Context, req QueryOrderListRequest) ([]*QueryOrderListItem, error) +} +type yaPingTechApiImpl struct { + log logx.Logger + client *Client +} + +func newYaPingTechApiImpl(log logx.Logger, client *Client) YaPingTechApi { + return &yaPingTechApiImpl{ + log: log, + client: client, + } +} + +func (s *yaPingTechApiImpl) QueryOrderList(ctx context.Context, req QueryOrderListRequest) ([]*QueryOrderListItem, error) { + params := map[string]any{ + "page": req.Page, + "out_order_sn": req.OutOrderSn, + } + if req.Type != "" { + params["type"] = req.Type + } + //加密参数 + paramsStr, _ := json.Marshal(params) + jsonData, err := Encrypt(string(paramsStr), s.client.authConfig.AppSecret) + if err != nil { + return nil, fmt.Errorf("yapingtech encrypt failed: %v", err) + } + args := map[string]any{ + "app_id": s.client.authConfig.AppId, + "json_data": jsonData, + } + request := &client.HttpRequest{Headers: s.client.headers, BodyArgs: args} + response := new(QueryOrderListResponse) + if err := s.client.HttpPost(GetOrderListUrl, request, &client.HttpResponse{Result: response}); err != nil { + return nil, fmt.Errorf("yapingtech http post failed: %v", err) + } + if response.Code != 200 { + return nil, fmt.Errorf(response.Message) + } + return response.Data.Items, nil +} diff --git a/platform/yapingtech/api_test.go b/platform/yapingtech/api_test.go new file mode 100644 index 0000000..c77e721 --- /dev/null +++ b/platform/yapingtech/api_test.go @@ -0,0 +1,46 @@ +package yapingtech + +import ( + "context" + "encoding/json" + "github.com/stretchr/testify/suite" + "github.com/zeromicro/go-zero/core/logx" + "testing" +) + +// api-单元测试 +type apiClientSuite struct { + suite.Suite + api YaPingTechApi +} + +func TestApiClient(t *testing.T) { + suite.Run(t, new(apiClientSuite)) +} + +func (a *apiClientSuite) SetupSuite() { + log := logx.WithContext(context.Background()) + apiClient := NewApiClient(log, AuthConfig{ + AppId: "ov595MzFifkk1usgIx3+3Q==", + AppSecret: "8/3eQzZbj9ymbC80MHm1EgcMZ1wUI2wOrxjwx4dfiekG/u+wvW3lqz6PKnzYQ0Hs", + }) + a.api = apiClient +} + +func (a *apiClientSuite) Test_QueryOrderList() { + req := QueryOrderListRequest{ + Page: 1, + OutOrderSn: "Y02141445536174133", + } + result, err := a.api.QueryOrderList(context.Background(), req) + if !a.NoError(err) { + a.T().Errorf("========[Test_QueryOrderList] response error:%s", err) + return + } + resultByte, err := json.Marshal(result) + if err != nil { + a.T().Errorf("========[Test_QueryOrderList] json_marshal error:%s", err) + return + } + a.T().Logf("================[Test_QueryOrderList] result: %s", string(resultByte)) +} diff --git a/platform/yapingtech/client.go b/platform/yapingtech/client.go new file mode 100644 index 0000000..43e17a0 --- /dev/null +++ b/platform/yapingtech/client.go @@ -0,0 +1,36 @@ +package yapingtech + +import ( + "github.com/zeromicro/go-zero/core/logx" + "repository.lenntc.com/lenntc/third-platform-sdk/client" +) + +// AuthConfig api鉴权参数 +type AuthConfig struct { + AppId string // api id + AppSecret string // api secret +} + +// Client 连接第三方平台的client +type Client struct { + log logx.Logger + authConfig AuthConfig + client.HttpClient + headers map[string]string +} + +func NewApiClient(log logx.Logger, conf AuthConfig) YaPingTechApi { + clt := newClient(log, conf) + return newYaPingTechApiImpl(log, clt) +} + +func newClient(log logx.Logger, conf AuthConfig) *Client { + return &Client{ + log: log, + authConfig: conf, + HttpClient: client.NewHttpClient(log), + headers: map[string]string{ + "Content-Type": "application/json", + }, + } +} diff --git a/platform/yapingtech/consts.go b/platform/yapingtech/consts.go new file mode 100644 index 0000000..cf54bd0 --- /dev/null +++ b/platform/yapingtech/consts.go @@ -0,0 +1,8 @@ +package yapingtech + +const ( + ApiDomain = "https://api.haokavip.com" // 正式接口域名 + ApiTestDomain = "https://mp-api.66-six.com" // 测试接口域名 + + GetOrderListUrl = ApiDomain + "/open/api/list_order" +) diff --git a/platform/yapingtech/encrypt.go b/platform/yapingtech/encrypt.go new file mode 100644 index 0000000..fe8a92b --- /dev/null +++ b/platform/yapingtech/encrypt.go @@ -0,0 +1,58 @@ +package yapingtech + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "encoding/base64" +) + +// PKCS7Padding pads the input text according to the PKCS7 standard. +func PKCS7Padding(data []byte, blockSize int) []byte { + padding := blockSize - len(data)%blockSize + padText := bytes.Repeat([]byte{byte(padding)}, padding) + return append(data, padText...) +} + +// Encrypt encrypts the given plaintext using AES-256-ECB. +func Encrypt(plaintext, key string) (string, error) { + // Truncate the key to 32 bytes + truncatedKey := []byte(key)[:32] + block, err := aes.NewCipher(truncatedKey) + if err != nil { + return "", err + } + paddedText := PKCS7Padding([]byte(plaintext), aes.BlockSize) + cipherText := make([]byte, len(paddedText)) + mode := NewECBEncrypter(block) + mode.CryptBlocks(cipherText, paddedText) + return base64.StdEncoding.EncodeToString(cipherText), nil +} + +// ecbEncrypter is a custom implementation of ECB encryption mode. +type ecbEncrypter struct { + b cipher.Block + blockSize int +} + +func NewECBEncrypter(b cipher.Block) cipher.BlockMode { + return &ecbEncrypter{ + b: b, + blockSize: b.BlockSize(), + } +} +func (x *ecbEncrypter) BlockSize() int { return x.blockSize } + +func (x *ecbEncrypter) CryptBlocks(dst, src []byte) { + if len(src)%x.blockSize != 0 { + panic("crypto/cipher: input not full blocks") + } + if len(dst) < len(src) { + panic("crypto/cipher: output smaller than input") + } + for len(src) > 0 { + x.b.Encrypt(dst, src[:x.blockSize]) + src = src[x.blockSize:] + dst = dst[x.blockSize:] + } +} diff --git a/platform/yapingtech/types.go b/platform/yapingtech/types.go new file mode 100644 index 0000000..bfd3b90 --- /dev/null +++ b/platform/yapingtech/types.go @@ -0,0 +1,50 @@ +package yapingtech + +type QueryOrderListRequest struct { + Page int64 `json:"page"` // 分页 + OutOrderSn string `json:"out_order_sn"` //传入亚平科技的订单ID,多个订单号可以使用逗号【,】最大20个订单号。请求会有频次限制,每1秒最多5次,超过之后会禁止访问1小时 + Type string `json:"type"` //查询下级合伙人订单,proxy +} + +type QueryOrderListResponse struct { + Success bool `json:"success"` + Message string `json:"message"` + Code int64 `json:"code"` + Data struct { + Items []*QueryOrderListItem `json:"items"` + PageInfo struct { + Total int64 `json:"total"` + CurrentPage int64 `json:"currentPage"` + TotalPage int64 `json:"totalPage"` + } `json:"pageInfo"` + } `json:"data"` +} + +type QueryOrderListItem struct { + OrderSn string `json:"order_sn"` //自己的ID + OutOrderSn string `json:"out_order_sn"` //亚平科技订单ID + Number string `json:"number"` //开卡号码 + Status int64 `json:"status"` //订单状态,1为开卡中,2为已发货,3为已充值,4为失败 + StatusText string `json:"status_text"` //订单状态描述 + IsActivated int64 `json:"is_activated"` //是否激活 1为激活,0为未激活 + ActivatedAt string `json:"activated_at"` //激活时间 + IsRecharged int64 `json:"is_recharged"` //是否首充 1为首充,0为未首充 + RechargedAt string `json:"recharged_at"` //首充时间 yyyy-mm-dd hh-mm-ss + RechargedAmount int64 `json:"recharged_amount"` //充值金额 + ExpressName string `json:"express_name"` //物流公司 + ExpressSn string `json:"express_sn"` //物流单号 + Reason string `json:"reason"` //失败原因/生产备注 + ProductName string `json:"product_name"` //产品名称 + ProductId int64 `json:"product_id"` //产品ID + UpdateTime string `json:"update_time"` //订单更新时间 + CreateTime string `json:"create_time"` //订单创建时间 + Name string `json:"name"` //开卡人姓名 + IdCard string `json:"id_card"` //开发人身份证号 + Phone string `json:"phone"` //开卡人电话 + Province string `json:"province"` //省 + City string `json:"city"` //市 + District string `json:"district"` //区 + Address string `json:"address"` //完整地址 + Channel string `json:"channel"` //渠道 sid + ShortUrl string `json:"short_url"` //上传三证链接 +}