Compare commits

...
4 Commits
Author SHA1 Message Date
maguodong 7777630306 修改商户附件字段名称
- 将 FileData 结构体中的 AttField 字段重命名为 AttFileId
- 保持 AttType 字段不变
- 更新相关注释说明文件编号的含义
2025-10-16 16:46:07 +08:00
maguodong de64d7b076 优化JSON日志输出格式
- 将reqJson的日志输出格式从%+v改为%v
- 使用string()方法确保JSON数据以字符串形式输出
- 避免复杂结构体的冗余字段展示
2025-10-16 16:08:31 +08:00
maguodong 02cab5fbde refactor(common):优化JSON清理和签名生成逻辑
- 移除多余的json.Marshal调用,直接传递结构体给签名函数
- 修改CleanJSON函数返回类型从string改为[]byte
- 更新日志输出格式,使用%+v显示完整结构体内容
- 简化请求数据处理流程,提高代码可读性
- 修复潜在的JSON序列化性能问题
2025-10-16 16:05:06 +08:00
maguodong adabb186f0 重构客户端引用以使用公共包
- 将 lklsdk.Client 替换为 common.Client
- 更新所有服务初始化方法参数类型
- 修改配置字段访问方式从 c.config 到 c.Config
- 统一请求方法调用为 DoRequest
- 移除重复的 client.go 文件实现
- 调整 trade.go 中 OutOrgCode 的获取路径
2025-10-16 15:46:09 +08:00
12 changed files with 53 additions and 177 deletions
+5 -4
View File
@@ -2,17 +2,18 @@ package lklsdk
import ( import (
"github.com/black1552/lkl_sdk/consts" "github.com/black1552/lkl_sdk/consts"
"github.com/black1552/lkl_sdk/lklsdk/common"
"github.com/black1552/lkl_sdk/model" "github.com/black1552/lkl_sdk/model"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
) )
// AccountService 账户服务 // AccountService 账户服务
type AccountService[T any] struct { type AccountService[T any] struct {
client *Client[T] client *common.Client[T]
} }
// NewAccountService 创建账户服务实例 // NewAccountService 创建账户服务实例
func NewAccountService[T any](client *Client[T]) *AccountService[T] { func NewAccountService[T any](client *common.Client[T]) *AccountService[T] {
return &AccountService[T]{ return &AccountService[T]{
client: client, client: client,
} }
@@ -30,7 +31,7 @@ func (a *AccountService[T]) BalanceQuery(req *model.BalanceQueryReqData) (*T, er
ReqData: req, ReqData: req,
} }
// 发送请求 // 发送请求
respBody, err := a.client.doRequest(url, baseReq) respBody, err := a.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -51,7 +52,7 @@ func (a *AccountService[T]) Withdraw(req *model.WithdrawReqData) (*T, error) {
} }
// 发送请求 // 发送请求
respBody, err := a.client.doRequest(url, baseReq) respBody, err := a.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
-125
View File
@@ -1,125 +0,0 @@
package lklsdk
import (
"context"
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"fmt"
ran "math/rand"
"time"
"github.com/black1552/base-common/utils"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/util/gconv"
)
// Config 拉卡拉SDK配置
type Config struct {
PublicKey string `json:"public_key" dc:"公钥字符串"`
PrivateKey string `json:"private_key" dc:"私钥字符串"`
AppId string `json:"app_id" dc:"lakala应用ID"`
SerialNo string `json:"serial_no" dc:"序列号"`
SubAppId string `json:"sub_app_id" dc:"子应用ID 微信AppId"`
Version string `json:"version" dc:"lakala版本号"`
AccountType string `json:"account_type" dc:"账户类型"`
TransType string `json:"trans_type" dc:"交易类型"`
NotifyUrl string `json:"notify_url" dc:"回调地址"`
}
// Client 拉卡拉SDK客户端
type Client[T any] struct {
config *Config
response T
ctx context.Context
}
// NewClient 创建拉卡拉SDK客户端
func NewClient[T any](ctx context.Context, cfgJson string) *Client[T] {
var config *Config
err := gconv.Struct(cfgJson, &config)
if err != nil {
return nil
}
return &Client[T]{
config: config,
ctx: ctx,
}
}
func (c *Client[T]) generateNonceStr() string {
const letterBytes = "abcdefghijklmnopqrstuvwxyz0123456789"
nonce := make([]byte, 12)
for i := range nonce {
nonce[i] = letterBytes[ran.Intn(len(letterBytes))]
}
return string(nonce)
}
// generateSign 生成签名
func (c *Client[T]) generateSign(request []byte) (string, error) {
// 生成随机字符串
nonceStr := c.generateNonceStr()
// 获取当前时间戳(秒)
timestamp := fmt.Sprintf("%d", time.Now().Unix())
// 构建待签名报文
signData := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n", c.config.AppId, c.config.SerialNo, timestamp, nonceStr, string(request))
// 计算签名
hashed := sha256.Sum256([]byte(signData))
privateKey, err := c.loadPrivateKey()
if err != nil {
return "", err
}
signature, err := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed[:])
if err != nil {
return "", err
}
signatureBase64 := base64.StdEncoding.EncodeToString(signature)
// 构建Authorization头
authorization := fmt.Sprintf("LKLAPI-SHA256withRSA appid=\"%s\",serial_no=\"%s\",timestamp=\"%s\",nonce_str=\"%s\",signature=\"%s\"",
c.config.AppId, c.config.SerialNo, timestamp, nonceStr, signatureBase64)
return authorization, nil
}
func (c *Client[T]) loadPrivateKey() (*rsa.PrivateKey, error) {
block, _ := pem.Decode(gfile.GetBytes(c.config.PrivateKey))
if block == nil {
return nil, fmt.Errorf("无法解码私钥PEM数据")
}
// 解析PKCS#8格式私钥
privateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return privateKey.(*rsa.PrivateKey), nil
}
// doRequest 发送HTTP请求
func (c *Client[T]) doRequest(url string, reqData interface{}) (*T, error) {
// 序列化为JSON
jsonData, err := json.Marshal(reqData)
if err != nil {
return nil, fmt.Errorf("序列化请求数据失败: %v", err)
}
auth, err := c.generateSign(jsonData)
if err != nil {
return nil, fmt.Errorf("生成签名失败: %v", err)
}
header := map[string]string{
"Authorization": auth,
"Content-Type": "application/json",
"Accept": "application/json",
}
// 设置其他必要的请求头
return utils.NewClient[T](jsonData, url, header).Post(c.ctx)
}
+8 -14
View File
@@ -8,7 +8,6 @@ import (
"crypto/sha256" "crypto/sha256"
"crypto/x509" "crypto/x509"
"encoding/base64" "encoding/base64"
"encoding/json"
"encoding/pem" "encoding/pem"
"fmt" "fmt"
ran "math/rand" ran "math/rand"
@@ -23,7 +22,7 @@ import (
// Client 拉卡拉SDK客户端 // Client 拉卡拉SDK客户端
type Client[T any] struct { type Client[T any] struct {
config *Config Config *Config
response T response T
ctx context.Context ctx context.Context
} }
@@ -36,7 +35,7 @@ func NewClient[T any](ctx context.Context, cfgJson string) *Client[T] {
return nil return nil
} }
return &Client[T]{ return &Client[T]{
config: config, Config: config,
ctx: ctx, ctx: ctx,
} }
} }
@@ -57,7 +56,7 @@ func (c *Client[T]) generateSign(request []byte) (string, error) {
timestamp := fmt.Sprintf("%d", time.Now().Unix()) timestamp := fmt.Sprintf("%d", time.Now().Unix())
// 构建待签名报文 // 构建待签名报文
signData := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n", c.config.AppId, c.config.SerialNo, timestamp, nonceStr, string(request)) signData := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n", c.Config.AppId, c.Config.SerialNo, timestamp, nonceStr, string(request))
// 计算签名 // 计算签名
hashed := sha256.Sum256([]byte(signData)) hashed := sha256.Sum256([]byte(signData))
@@ -74,12 +73,12 @@ func (c *Client[T]) generateSign(request []byte) (string, error) {
// 构建Authorization头 // 构建Authorization头
authorization := fmt.Sprintf("LKLAPI-SHA256withRSA appid=\"%s\",serial_no=\"%s\",timestamp=\"%s\",nonce_str=\"%s\",signature=\"%s\"", authorization := fmt.Sprintf("LKLAPI-SHA256withRSA appid=\"%s\",serial_no=\"%s\",timestamp=\"%s\",nonce_str=\"%s\",signature=\"%s\"",
c.config.AppId, c.config.SerialNo, timestamp, nonceStr, signatureBase64) c.Config.AppId, c.Config.SerialNo, timestamp, nonceStr, signatureBase64)
return authorization, nil return authorization, nil
} }
func (c *Client[T]) loadPrivateKey() (*rsa.PrivateKey, error) { func (c *Client[T]) loadPrivateKey() (*rsa.PrivateKey, error) {
block, _ := pem.Decode(gfile.GetBytes(c.config.PrivateKey)) block, _ := pem.Decode(gfile.GetBytes(c.Config.PrivateKey))
if block == nil { if block == nil {
return nil, fmt.Errorf("无法解码私钥PEM数据") return nil, fmt.Errorf("无法解码私钥PEM数据")
} }
@@ -101,14 +100,9 @@ func (c *Client[T]) DoRequest(url string, reqData interface{}) (*T, error) {
if err != nil { if err != nil {
return nil, fmt.Errorf("清理JSON空值失败: %v", err) return nil, fmt.Errorf("清理JSON空值失败: %v", err)
} }
g.Log().Infof(c.ctx, "清理后的json: %s", reqJson) g.Log().Infof(c.ctx, "清理后的json: %v", string(reqJson))
// 序列化为JSON
jsonData, err := json.Marshal(reqJson)
if err != nil {
return nil, fmt.Errorf("序列化请求数据失败: %v", err)
}
auth, err := c.generateSign(jsonData) auth, err := c.generateSign(reqJson)
if err != nil { if err != nil {
return nil, fmt.Errorf("生成签名失败: %v", err) return nil, fmt.Errorf("生成签名失败: %v", err)
} }
@@ -119,5 +113,5 @@ func (c *Client[T]) DoRequest(url string, reqData interface{}) (*T, error) {
} }
// 设置其他必要的请求头 // 设置其他必要的请求头
return utils.NewClient[T](jsonData, url, header).Post(c.ctx) return utils.NewClient[T](reqJson, url, header).Post(c.ctx)
} }
+4 -4
View File
@@ -6,12 +6,12 @@ import (
) )
// CleanJSON 清理JSON字符串中的空值和0值字段 // CleanJSON 清理JSON字符串中的空值和0值字段
func CleanJSON(jsonStr string) (string, error) { func CleanJSON(jsonStr string) ([]byte, error) {
var data interface{} var data interface{}
// 解析JSON字符串 // 解析JSON字符串
if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { if err := json.Unmarshal([]byte(jsonStr), &data); err != nil {
return "", err return nil, err
} }
// 递归清理数据 // 递归清理数据
@@ -20,10 +20,10 @@ func CleanJSON(jsonStr string) (string, error) {
// 转换回JSON字符串 // 转换回JSON字符串
result, err := json.Marshal(cleaned) result, err := json.Marshal(cleaned)
if err != nil { if err != nil {
return "", err return nil, err
} }
return string(result), nil return result, nil
} }
// cleanData 递归清理map或slice中的空值和0值 // cleanData 递归清理map或slice中的空值和0值
+7 -6
View File
@@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/black1552/lkl_sdk/consts" "github.com/black1552/lkl_sdk/consts"
"github.com/black1552/lkl_sdk/lklsdk/common"
"github.com/black1552/lkl_sdk/model" "github.com/black1552/lkl_sdk/model"
"github.com/gogf/gf/v2/crypto/gmd5" "github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
@@ -12,11 +13,11 @@ import (
// MerService 商户服务 // MerService 商户服务
type MerService[T any] struct { type MerService[T any] struct {
client *Client[T] client *common.Client[T]
} }
// NewMerService 创建交易服务实例 // NewMerService 创建交易服务实例
func NewMerService[T any](client *Client[T]) *MerService[T] { func NewMerService[T any](client *common.Client[T]) *MerService[T] {
return &MerService[T]{ return &MerService[T]{
client: client, client: client,
} }
@@ -39,7 +40,7 @@ func (t *MerService[T]) AddMer(req *model.MerchantApplyReqData) (*T, error) {
} }
// 发送请求 // 发送请求
respBody, err := t.client.doRequest(url, baseReq) respBody, err := t.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -62,7 +63,7 @@ func (t *MerService[T]) QueryMer(req *model.QueryMerRequestData) (*T, error) {
} }
// 发送请求 // 发送请求
respBody, err := t.client.doRequest(url, baseReq) respBody, err := t.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -84,7 +85,7 @@ func (t *MerService[T]) MerValidate(req *model.MerValidateRequestData) (*T, erro
} }
// 发送请求 // 发送请求
respBody, err := t.client.doRequest(url, baseReq) respBody, err := t.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -107,7 +108,7 @@ func (t *MerService[T]) ReconsiderSubmit(req *model.ReConfSubmitRequestData) (*T
} }
// 发送请求 // 发送请求
respBody, err := t.client.doRequest(url, baseReq) respBody, err := t.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+4 -3
View File
@@ -2,16 +2,17 @@ package lklsdk
import ( import (
"github.com/black1552/lkl_sdk/consts" "github.com/black1552/lkl_sdk/consts"
"github.com/black1552/lkl_sdk/lklsdk/common"
"github.com/black1552/lkl_sdk/model" "github.com/black1552/lkl_sdk/model"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
) )
type MergePreService[T any] struct { type MergePreService[T any] struct {
client *Client[T] client *common.Client[T]
} }
// NewMergePreService 创建拉卡拉主扫合单交易 // NewMergePreService 创建拉卡拉主扫合单交易
func NewMergePreService[T any](client *Client[T]) *MergePreService[T] { func NewMergePreService[T any](client *common.Client[T]) *MergePreService[T] {
return &MergePreService[T]{ return &MergePreService[T]{
client: client, client: client,
} }
@@ -29,7 +30,7 @@ func (s *MergePreService[T]) PreOrder(req *model.MergePreorderReqData) (*T, erro
} }
// 发送请求 // 发送请求
respBody, err := s.client.doRequest(url, baseReq) respBody, err := s.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+3 -2
View File
@@ -3,12 +3,13 @@ package lklsdk
import ( import (
"context" "context"
"github.com/black1552/lkl_sdk/lklsdk/common"
"github.com/black1552/lkl_sdk/model" "github.com/black1552/lkl_sdk/model"
) )
// SDK 拉卡拉SDK主入口 // SDK 拉卡拉SDK主入口
type SDK[T any] struct { type SDK[T any] struct {
Client *Client[T] Client *common.Client[T]
SplitLedger *SplitLedgerService[T] SplitLedger *SplitLedgerService[T]
Trade *TradeService[T] Trade *TradeService[T]
Account *AccountService[T] Account *AccountService[T]
@@ -19,7 +20,7 @@ type SDK[T any] struct {
// NewSDK 创建拉卡拉SDK实例 // NewSDK 创建拉卡拉SDK实例
func NewSDK[T any](ctx context.Context, cfgJson string) *SDK[T] { func NewSDK[T any](ctx context.Context, cfgJson string) *SDK[T] {
client := NewClient[T](ctx, cfgJson) client := common.NewClient[T](ctx, cfgJson)
return &SDK[T]{ return &SDK[T]{
Client: client, Client: client,
SplitLedger: NewSplitLedgerService(client), SplitLedger: NewSplitLedgerService(client),
+6 -5
View File
@@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/black1552/lkl_sdk/consts" "github.com/black1552/lkl_sdk/consts"
"github.com/black1552/lkl_sdk/lklsdk/common"
"github.com/black1552/lkl_sdk/model" "github.com/black1552/lkl_sdk/model"
"github.com/gogf/gf/v2/crypto/gmd5" "github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
@@ -13,11 +14,11 @@ import (
// SplitLedgerService 分账服务 // SplitLedgerService 分账服务
type SplitLedgerService[T any] struct { type SplitLedgerService[T any] struct {
client *Client[T] client *common.Client[T]
} }
// NewSplitLedgerService 创建分账服务实例 // NewSplitLedgerService 创建分账服务实例
func NewSplitLedgerService[T any](client *Client[T]) *SplitLedgerService[T] { func NewSplitLedgerService[T any](client *common.Client[T]) *SplitLedgerService[T] {
return &SplitLedgerService[T]{ return &SplitLedgerService[T]{
client: client, client: client,
} }
@@ -41,7 +42,7 @@ func (s *SplitLedgerService[T]) ApplyLedgerMer(req *model.ApplyLedgerMerReqData)
} }
// 发送请求 // 发送请求
respBody, err := s.client.doRequest(url, baseReq) respBody, err := s.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -67,7 +68,7 @@ func (s *SplitLedgerService[T]) ApplyLedgerReceiver(req *model.ApplyLedgerReceiv
} }
// 发送请求 // 发送请求
respBody, err := s.client.doRequest(url, baseReq) respBody, err := s.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -88,7 +89,7 @@ func (s *SplitLedgerService[T]) QueryLedgerMer(req *model.QueryLedgerMerReqData)
} }
// 发送请求 // 发送请求
respBody, err := s.client.doRequest(url, baseReq) respBody, err := s.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+3 -3
View File
@@ -29,7 +29,7 @@ func (s *SplitLedgerService[T]) ApplyBind(req *model.ApplyBindReqData) (*T, erro
} }
// 发送请求 // 发送请求
respBody, err := s.client.doRequest(url, baseReq) respBody, err := s.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -49,7 +49,7 @@ func (s *SplitLedgerService[T]) QuerySplitBalance(req *model.SplitBalanceReqData
} }
// 发送请求 // 发送请求
respBody, err := s.client.doRequest(url, baseReq) respBody, err := s.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -69,7 +69,7 @@ func (s *SplitLedgerService[T]) OrderSplitLedger(req *model.OrderSplitLedgerReqD
} }
// 发送请求 // 发送请求
respBody, err := s.client.doRequest(url, baseReq) respBody, err := s.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+7 -6
View File
@@ -4,16 +4,17 @@ import (
"time" "time"
"github.com/black1552/lkl_sdk/consts" "github.com/black1552/lkl_sdk/consts"
"github.com/black1552/lkl_sdk/lklsdk/common"
"github.com/black1552/lkl_sdk/model" "github.com/black1552/lkl_sdk/model"
) )
// TradeService 交易服务 // TradeService 交易服务
type TradeService[T any] struct { type TradeService[T any] struct {
client *Client[T] client *common.Client[T]
} }
// NewTradeService 创建交易服务实例 // NewTradeService 创建交易服务实例
func NewTradeService[T any](client *Client[T]) *TradeService[T] { func NewTradeService[T any](client *common.Client[T]) *TradeService[T] {
return &TradeService[T]{ return &TradeService[T]{
client: client, client: client,
} }
@@ -28,12 +29,12 @@ func (t *TradeService[T]) TradeQuery(req *model.TradeQueryReqData) (*T, error) {
baseReq := model.TradeQuery{ baseReq := model.TradeQuery{
ReqTime: time.Now().Format("20060102150405"), ReqTime: time.Now().Format("20060102150405"),
Version: "3.0", Version: "3.0",
OutOrgCode: t.client.config.AppId, OutOrgCode: t.client.Config.AppId,
ReqData: req, ReqData: req,
} }
// 发送请求 // 发送请求
respBody, err := t.client.doRequest(url, baseReq) respBody, err := t.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -49,7 +50,7 @@ func (t *TradeService[T]) PreOrder(req *model.PreorderReqData) (*T, error) {
baseReq := model.NewPreorder(req) baseReq := model.NewPreorder(req)
// 发送请求 // 发送请求
respBody, err := t.client.doRequest(url, baseReq) respBody, err := t.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -65,7 +66,7 @@ func (t *TradeService[T]) Refound(req *model.RefundReqData) (*T, error) {
// 构建BaseModel请求 // 构建BaseModel请求
baseReq := model.NewRefund(req) baseReq := model.NewRefund(req)
// 发送请求 // 发送请求
respBody, err := t.client.doRequest(url, baseReq) respBody, err := t.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+4 -3
View File
@@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/black1552/lkl_sdk/consts" "github.com/black1552/lkl_sdk/consts"
"github.com/black1552/lkl_sdk/lklsdk/common"
"github.com/black1552/lkl_sdk/model" "github.com/black1552/lkl_sdk/model"
"github.com/gogf/gf/v2/crypto/gmd5" "github.com/gogf/gf/v2/crypto/gmd5"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
@@ -12,11 +13,11 @@ import (
// UploadFileService 交易服务 // UploadFileService 交易服务
type UploadFileService[T any] struct { type UploadFileService[T any] struct {
client *Client[T] client *common.Client[T]
} }
// NewUploadFileService 创建交易服务实例 // NewUploadFileService 创建交易服务实例
func NewUploadFileService[T any](client *Client[T]) *UploadFileService[T] { func NewUploadFileService[T any](client *common.Client[T]) *UploadFileService[T] {
return &UploadFileService[T]{ return &UploadFileService[T]{
client: client, client: client,
} }
@@ -39,7 +40,7 @@ func (t *UploadFileService[T]) UploadFileQuery(req *model.UploadFileReqData) (*T
} }
// 发送请求 // 发送请求
respBody, err := t.client.doRequest(url, baseReq) respBody, err := t.client.DoRequest(url, baseReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
+2 -2
View File
@@ -81,8 +81,8 @@ type FeeData struct {
// FileData 附件集合结构体 // FileData 附件集合结构体
type FileData struct { type FileData struct {
AttField string `json:"attField"` // 文件编号/附件上传后返回的编号,必填 AttFileId string `json:"attFileId"` // 文件编号/附件上传后返回的编号,必填
AttType string `json:"attType"` // 附件类型,必填 AttType string `json:"attType"` // 附件类型,必填
} }
// MerchantApplyResponse 商户进件响应结构体 // MerchantApplyResponse 商户进件响应结构体