intelligence_finance_v1_ga-.../intelligence_finance_v1_ga/generate.md

32 KiB
Raw Permalink Blame History

// File: intelligence_finance_v1_ga/go.mod

module intelligence_finance_v1_ga

go 1.21

// File: intelligence_finance_v1_ga/crypto.go

package intelligence_finance_v1_ga

import (
	"crypto/hmac"
	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"math/big"
	"sort"
	"strings"
	"time"
)

// GenerateTimestamp 生成秒级时间戳。
func GenerateTimestamp() string {
	return fmt.Sprintf("%d", time.Now().Unix())
}

// GenerateTimestampMillis 生成毫秒级时间戳。
func GenerateTimestampMillis() string {
	return fmt.Sprintf("%d", time.Now().UnixMilli())
}

// GenerateNonce 生成指定长度的随机字符串(加密安全)。
func GenerateNonce(length int) (string, error) {
	const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
	b := make([]byte, length)
	for i := range b {
		num, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
		if err != nil {
			return "", err
		}
		b[i] = charset[num.Int64()]
	}
	return string(b), nil
}

// BuildSignString 方式1字典序排序拼接。
func BuildSignString(params map[string]string) string {
	keys := make([]string, 0, len(params))
	for k, v := range params {
		if v != "" && k != "sign" && k != "signature" {
			keys = append(keys, k)
		}
	}
	sort.Strings(keys)

	var parts []string
	for _, k := range keys {
		parts = append(parts, fmt.Sprintf("%s=%s", k, params[k]))
	}
	return strings.Join(parts, "&")
}

// BuildSignStringOrdered 方式2固定顺序拼接。
func BuildSignStringOrdered(params map[string]string, orderedKeys []string) string {
	var parts []string
	for _, k := range orderedKeys {
		if v, ok := params[k]; ok && v != "" {
			parts = append(parts, fmt.Sprintf("%s=%s", k, v))
		}
	}
	return strings.Join(parts, "&")
}

// HmacSHA256Base64 使用 HmacSHA256 算法对 data 进行签名,并返回 Base64 编码结果。
// 密钥为 client-secret签名数据为 x-bfl-signature-timestamp + x-bfl-signature-nonce。
func HmacSHA256Base64(secret, data string) string {
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write([]byte(data))
	return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}

// File: intelligence_finance_v1_ga/errors.go

package intelligence_finance_v1_ga

import "fmt"

// APIError 表示 API 调用返回的错误。
type APIError struct {
	// StatusCode HTTP 状态码。
	StatusCode int
	// Code 业务错误码。
	Code int
	// Message 错误信息。
	Message string
}

// Error 实现 error 接口。
func (e *APIError) Error() string {
	if e.Code != 0 {
		return fmt.Sprintf("api error: code=%d, msg=%s", e.Code, e.Message)
	}
	return fmt.Sprintf("api error: http status=%d, body=%s", e.StatusCode, e.Message)
}

// File: intelligence_finance_v1_ga/types.go

package intelligence_finance_v1_ga

import "encoding/json"

// ==================== 枚举常量 ====================

// 发票类型枚举。
const (
	InvoiceTypeSpecial        = 1 // 专用发票
	InvoiceTypeNormal         = 2 // 普通发票
	InvoiceTypeNormalElec     = 3 // 普通发票(电子)
	InvoiceTypeSpecialElec    = 4 // 专用发票(电子)
	InvoiceTypeDigitalSpecial = 8 // 数电专票
	InvoiceTypeDigitalNormal  = 9 // 数电普票
)

// 开票状态枚举。
const (
	InvoiceStatusNotIssued     = 0 // 未开票
	InvoiceStatusIssuing       = 1 // 开票中
	InvoiceStatusPartialFail   = 2 // 部分失败
	InvoiceStatusSuccess       = 3 // 开票成功
	InvoiceStatusFail          = 4 // 开票失败
	InvoiceStatusPartialNot    = 5 // 部分未开
	InvoiceStatusNoDigitalAcct = 6 // 未配置数电账号
	InvoiceStatusNoAutoConfig  = 7 // 未配置自动开票配置
)

// 支付状态枚举。
const (
	PaymentStatusSuccess     = "SUCCESS"      // 支付成功
	PaymentStatusFail        = "FAIL"         // 支付失败
	PaymentStatusTerminate   = "TERMINATE"    // 支付取消
	PaymentStatusWaitPay     = "WAIT_PAY"     // 待支付
	PaymentStatusPaying      = "PAYING"       // 支付中
	PaymentStatusPartSuccess = "PART_SUCCESS" // 部分支付成功
	PaymentStatusRefund      = "REFUND"       // 退款
)

// 来源枚举。
const (
	SourceApproval = "approval" // 审批单
	SourceOpenAPI  = "openapi"  // 开发接口
)

// 账户类型枚举。
const (
	AccountTypeAlipay           = "ALIPAY"            // 支付宝
	AccountTypeBankCard         = "BANKCARD"          // 银行卡
	AccountTypeCorpBankCard     = "CORP_BANK_CARD"    // 对公银行卡
	AccountTypePersonalBankCard = "PERSONAL_BANK_CARD" // 对私银行卡
)

// 通知响应常量。
const (
	NotifyResponseSuccess = "SUCCESS" // 通知处理成功
	NotifyResponseFailed  = "FAILED"  // 通知处理失败
)

// ==================== 通用结构 ====================

// CommonResponse 通用响应结构。
type CommonResponse struct {
	Code int             `json:"code"`
	Msg  string          `json:"msg"`
	Data json.RawMessage `json:"data"`
}

// CommonNotifyData 通用通知数据结构bizType/bizId/datatype CommonNotifyData struct {
	BizType string `json:"bizType"`
	BizID   string `json:"bizId"`
	Data    string `json:"data,omitempty"`
}

// ==================== 接口1订单开票 ====================

// OrderInvoiceRequest 订单开票请求参数。
type OrderInvoiceRequest struct {
	CompanyCode      string    `json:"companyCode,omitempty"`      // 开票的企业主体编码,不传则默认主体开票
	OrderID          string    `json:"orderId"`                    // 订单唯一标识
	InvoiceType      int       `json:"invoiceType"`                // 发票类型枚举
	Products         []Product `json:"products"`                   // 货物/服务明细列表,至少一项
	Remark           string    `json:"remark,omitempty"`           // 订单备注(非发票备注)
	Purchaser        string    `json:"purchaser"`                  // 购方企业名称
	Taxnum           string    `json:"taxnum,omitempty"`           // 购方纳税人识别号
	PurchaserAddress string    `json:"purchaserAddress,omitempty"` // 购方地址
	PurchaserTel     string    `json:"purchaserTel,omitempty"`     // 购方电话
	BankName         string    `json:"bankName,omitempty"`         // 购方开户行名称
	BankAccount      string    `json:"bankAccount,omitempty"`      // 购方银行账号
	Phone            string    `json:"phone,omitempty"`            // 收票人手机号(用于接收电票短信)
	Email            string    `json:"email,omitempty"`            // 收票人邮箱(用于接收电票邮件)
	ApplyPerson      string    `json:"applyPerson,omitempty"`      // 开票申请人名称
	Payee            string    `json:"payee,omitempty"`            // 收款人(发票票面)
	Reviewer         string    `json:"reviewer,omitempty"`         // 复核人(发票票面)
	InvoiceRemark    string    `json:"invoiceRemark,omitempty"`    // 发票备注栏内容
	NaturalPerson    string    `json:"naturalPerson,omitempty"`    // 购买方自然人标识Y-是N-否默认N
	AdditionInfo     string    `json:"additionInfo,omitempty"`     // 附加信息JSON数组字符串
}

// Product 货物/服务明细项。
type Product struct {
	ProductName      string `json:"productName"`        // 货物或服务名称
	RevenueCode      string `json:"revenueCode"`        // 19位税收分类编码
	AmountIncludeTax string `json:"amountIncludeTax"`   // 单条明细含税总金额(单位:元)
	Specs            string `json:"specs,omitempty"`    // 规格型号
	Unit             string `json:"unit,omitempty"`     // 计量单位(如:台、个、次)
	Quantity         string `json:"quantity"`           // 数量
	Discount         string `json:"discount,omitempty"` // 折扣金额无折扣传0
	TaxSign          int    `json:"taxSign,omitempty"`  // 是否含税0-不含税1-含税默认建议传1
	TaxRate          string `json:"taxRate,omitempty"`  // 税率小数形式如0.13表示13%
}

// OrderInvoiceResponse 订单开票响应参数。
type OrderInvoiceResponse struct {
	Status   int           `json:"status"`   // 开票状态
	ErrorMsg string        `json:"errorMsg"` // 错误信息(开票失败时返回原因)
	DataList []InvoiceData `json:"dataList"` // 发票数据列表
}

// InvoiceData 发票数据。
type InvoiceData struct {
	DeviceCode           string   `json:"deviceCode"`                 // 税控设备号
	Drawer               string   `json:"drawer"`                     // 开票人
	Email                string   `json:"email"`                      // 邮箱(购方邮箱)
	InvoiceType          string   `json:"invoiceType"`                // 发票类型
	IssueType            string   `json:"issueType"`                  // 开票类型0-正数票1-负数票(红冲)
	ListFlag             string   `json:"listFlag"`                   // 清单标识0-无清单1-有清单
	Mobile               string   `json:"mobile"`                     // 手机号(购方手机)
	OriginalInvCode      string   `json:"originalInvCode,omitempty"`  // 红冲时对应的原蓝票代码
	OriginalInvNo        string   `json:"originalInvNo,omitempty"`    // 红冲时对应的原蓝票号码
	AdditionInfo         string   `json:"additionInfo,omitempty"`     // 数电发票备注栏的附加信息部分
	Payee                string   `json:"payee"`                      // 收款人
	PurchaserAddress     string   `json:"purchaserAddress"`           // 购方地址
	PurchaserBankAccount string   `json:"purchaserBankAccount"`       // 购方银行账号
	PurchaserBankName    string   `json:"purchaserBankName"`          // 购方开户行
	PurchaserName        string   `json:"purchaserName"`              // 购方名称
	PurchaserTaxNo       string   `json:"purchaserTaxNo"`             // 购方税号
	PurchaserTel         string   `json:"purchaserTel"`               // 购方电话
	NaturalPerson        string   `json:"naturalPerson,omitempty"`    // 购买方自然人标识Y-是N-否
	Remark               string   `json:"remark"`                     // 备注
	Reviewer             string   `json:"reviewer"`                   // 复核人
	SellerAddress        string   `json:"sellerAddress,omitempty"`    // 销方地址
	SellerBankAccount    string   `json:"sellerBankAccount"`          // 销方开户账号
	SellerBankName       string   `json:"sellerBankName"`             // 销方开户行
	SellerName           string   `json:"sellerName"`                 // 销方名称
	CheckCode            string   `json:"checkCode"`                  // 校验码
	CipherText           string   `json:"cipherText"`                 // 密码区
	DrewDate             string   `json:"drewDate,omitempty"`         // 开票日期格式yyyy-MM-dd HH:mm:ss
	InvoiceCode          string   `json:"invoiceCode"`                // 发票代码
	InvoiceNo            string   `json:"invoiceNo"`                  // 发票号码
	InvoiceStatus        string   `json:"invoiceStatus"`              // 发票状态1-正常2-已红冲3-已作废
	LayoutFileURL        string   `json:"layoutFileUrl,omitempty"`    // 电子发票地址PDF/OFD
	PDFURL               string   `json:"pdfUrl,omitempty"`           // 电子发票PDF地址
	OFDURL               string   `json:"ofdUrl,omitempty"`           // 电子发票OFD地址
	XMLURL               string   `json:"xmlUrl,omitempty"`           // 电子发票XML数据地址
	TotalExcludeTax      string   `json:"totalExcludeTax"`            // 合计金额(不含税)
	TotalIncludeTax      string   `json:"totalIncludeTax"`            // 合计金额(含税)
	TotalTaxAmount       string   `json:"totalTaxAmount"`             // 合计税额
	LevyingType          string   `json:"levyingType"`                // 征税方式
	Details              []Detail `json:"details"`                    // 商品明细列表
}

// Detail 商品明细。
type Detail struct {
	Amount             string `json:"amount,omitempty"`             // 金额
	Quantity           string `json:"quantity,omitempty"`           // 数量
	DeductionAmount    string `json:"deductionAmount,omitempty"`    // 扣除金额
	TaxAmount          string `json:"taxAmount,omitempty"`          // 税额
	ItemTitle          string `json:"itemTitle"`                    // 商品合并显示名称
	TaxCode            string `json:"taxCode"`                      // 税收分类编码19位
	ItemType           string `json:"itemType"`                     // 商品行性质0-正常行1-折扣行2-被折扣行
	ItemName           string `json:"itemName"`                     // 商品简称
	Specs              string `json:"specs,omitempty"`              // 商品规格型号
	TaxFreePolicy      string `json:"taxFreePolicy"`                // 免税政策1-免税2-不征税3-普通零税率
	PreferentialPolicy string `json:"preferentialPolicy"`           // 优惠政策类型
	TaxRate            string `json:"taxRate"`                      // 税率小数形式如0.13
	TaxSign            string `json:"taxSign"`                      // 是否含税0-否1-是
	Unit               string `json:"unit,omitempty"`               // 计量单位(如:台、个、次)
	UnitPrice          string `json:"unitPrice,omitempty"`          // 单价
}

// ==================== 接口2开票状态查询 ====================

// QueryInvoiceStatusRequest 开票状态查询请求参数。
type QueryInvoiceStatusRequest struct {
	OrderID string `json:"orderId"` // 订单唯一标识
}

// QueryInvoiceStatusResponse 开票状态查询响应参数。
type QueryInvoiceStatusResponse struct {
	Status  int           `json:"status"`  // 开票状态
	Message string        `json:"message"` // 状态描述(如"开票成功"
	Data    []InvoiceData `json:"data"`    // 发票详细列表
}

// ==================== 接口3创建付款单据 ====================

// CreatePaymentOrderRequest 创建付款单据请求参数。
type CreatePaymentOrderRequest struct {
	Code                     string              `json:"code"`                            // 单据编码(必填)
	YidaAppType              string              `json:"yidaAppType,omitempty"`           // 宜搭应用类型
	EmpAccountUserId         string              `json:"empAccountUserId,omitempty"`      // 员工账号用户ID
	Department               *Department         `json:"department,omitempty"`            // 部门信息
	Usage                    string              `json:"usage,omitempty"`                 // 用途
	PaymentUserId            string              `json:"paymentUserId,omitempty"`         // 付款人用户ID
	Customer                 *Customer           `json:"customer,omitempty"`              // 客户信息
	PrincipalID              string              `json:"principalId,omitempty"`           // 负责人ID
	Remark                   string              `json:"remark,omitempty"`                // 备注
	Supplier                 *Supplier           `json:"supplier,omitempty"`              // 供应商信息
	Title                    string              `json:"title,omitempty"`                 // 标题
	Project                  *Project            `json:"project,omitempty"`               // 项目信息
	PaymentUserIDListStr     string              `json:"paymentUserIdListStr,omitempty"`  // 付款人用户ID列表字符串
	NeedPayment              bool                `json:"needPayment,omitempty"`           // 是否需要付款
	PaymentDetailListJSONStr string              `json:"paymentDetailListJsonStr,omitempty"` // 付款明细列表JSON字符串
	PaymentDetailList        []PaymentDetail     `json:"paymentDetailList,omitempty"`     // 付款明细列表
	Company                  *Company            `json:"company,omitempty"`               // 企业主体信息
	Amount                   string              `json:"amount,omitempty"`                // 金额
	RecipientAccountInfo     *RecipientAccount   `json:"recipientAccountInfo,omitempty"`  // 收款账户信息
	EnterpriseAccount        *EnterpriseAccount  `json:"enterpriseAccount,omitempty"`     // 企业账号信息
	Category                 []Category          `json:"category,omitempty"`              // 收支类别信息
	UserID                   string              `json:"userId"`                          // 用户ID必填
	OccurDate                int64               `json:"occurDate,omitempty"`             // 发生日期(时间戳)
	Product                  *ProductInfo        `json:"product,omitempty"`               // 商品信息
	YidaFormUUID             string              `json:"yidaFormUuid,omitempty"`          // 宜搭表单UUID
	CanEditPaymentInfo       bool                `json:"canEditPaymentInfo,omitempty"`    // 是否可编辑付款信息
	PaymentUserIDList        []string            `json:"paymentUserIdList,omitempty"`     // 付款人用户ID列表
	YidaProcInsID            string              `json:"yidaProcInsId,omitempty"`         // 宜搭流程实例ID
	SyncPaymentOrder         bool                `json:"syncPaymentOrder,omitempty"`      // 是否同步付款单据
}

// Department 部门信息。
type Department struct {
	Code string `json:"code,omitempty"` // 部门编码
	Name string `json:"name"`           // 部门名称
}

// Customer 客户信息。
type Customer struct {
	Code string `json:"code,omitempty"` // 客户编码
	Name string `json:"name"`           // 客户名称
}

// Supplier 供应商信息。
type Supplier struct {
	Code string `json:"code,omitempty"` // 供应商编码
	Name string `json:"name"`           // 供应商名称
}

// Project 项目信息。
type Project struct {
	Code string `json:"code,omitempty"` // 项目编码
	Name string `json:"name"`           // 项目名称
}

// Category 收支类别信息。
type Category struct {
	Code string `json:"code,omitempty"` // 类别编码
	Name string `json:"name"`           // 类别名称
}

// ProductInfo 商品信息。
type ProductInfo struct {
	Code string `json:"code,omitempty"` // 商品编码
	Name string `json:"name"`           // 商品名称
}

// Company 企业主体信息。
type Company struct {
	Code string `json:"code,omitempty"` // 企业编码
	Name string `json:"name"`           // 企业名称
}

// EnterpriseAccount 企业账号信息。
type EnterpriseAccount struct {
	EnterpriseAccountCode string `json:"enterpriseAccountCode,omitempty"` // 企业账号编码
	AccountCategory       string `json:"accountCategory"`                 // 账户类别
	AccountType           string `json:"accountType,omitempty"`           // 账户类型
	CardNo                string `json:"cardNo,omitempty"`                // 卡号
	AccountName           string `json:"accountName,omitempty"`           // 账户名称
	OfficialNumber        string `json:"officialNumber,omitempty"`        // 对公账号
	OfficialName          string `json:"officialName,omitempty"`          // 对公账户名称
	Name                  string `json:"name,omitempty"`                  // 名称
	Code                  string `json:"code,omitempty"`                  // 编码
	City                  string `json:"city,omitempty"`                  // 城市
	Province              string `json:"province,omitempty"`              // 省份
}

// RecipientAccount 收款账户信息。
type RecipientAccount struct {
	AccountCategory string `json:"accountCategory"`       // 账户类别
	AccountType     string `json:"accountType,omitempty"` // 账户类型
	CardNo          string `json:"cardNo,omitempty"`      // 卡号
	AccountName     string `json:"accountName,omitempty"` // 账户名称
}

// PaymentDetail 付款明细。
type PaymentDetail struct {
	Amount      string       `json:"amount,omitempty"`      // 金额
	InvoiceInfo *InvoiceInfo `json:"invoiceInfo,omitempty"` // 发票信息
	ProductCode string       `json:"productCode,omitempty"` // 商品编码
	ProjectCode string       `json:"projectCode,omitempty"` // 项目编码
	Remark      string       `json:"remark,omitempty"`      // 备注
	PrincipalID string       `json:"principalId,omitempty"` // 负责人ID
	Tax         string       `json:"tax,omitempty"`         // 税额
}

// InvoiceInfo 付款明细发票信息。
type InvoiceInfo struct {
	InvoiceNo   string `json:"invoiceNo,omitempty"`   // 发票号码
	InvoiceCode string `json:"invoiceCode,omitempty"` // 发票代码
}

// CreatePaymentOrderResponse 创建付款单据响应参数。
type CreatePaymentOrderResponse struct {
	Code string `json:"code"` // 单据唯一编码
}

// ==================== 接口4支付完成通知 / 接口5支付状态查询 ====================

// PaymentNotifyData 支付完成通知数据接口4通知数据也是接口5的响应数据type PaymentNotifyData struct {
	Code                 string            `json:"code"`                            // 单据编码
	InstanceID           string            `json:"instanceId"`                      // 实例ID
	CorpID               string            `json:"corpId"`                          // 企业ID
	PaymentStatus        string            `json:"paymentStatus"`                   // 支付状态
	PaymentTime          string            `json:"paymentTime"`                     // 支付时间
	UserID               string            `json:"userId"`                          // 用户ID
	FailReason           string            `json:"failReason,omitempty"`            // 失败原因
	PayerAccountInfo     *PayerAccountInfo `json:"payerAccountInfo,omitempty"`      // 付款账户信息
	PayeeAccountInfo     *PayeeAccountInfo `json:"payeeAccountInfo,omitempty"`      // 收款账户信息
	RelatedRowNumberList []string          `json:"relatedRowNumberList,omitempty"`  // 关联行号列表
	Source               string            `json:"source,omitempty"`                // 来源
	Template             string            `json:"template,omitempty"`              // 模板
	Amount               string            `json:"amount,omitempty"`                // 金额
}

// PayerAccountInfo 付款账户信息。
type PayerAccountInfo struct {
	BankOpenDTO          *BankOpenDTO `json:"bankOpenDTO,omitempty"`          // 银行信息
	EnterpriseAccountCode string      `json:"enterpriseAccountCode,omitempty"` // 企业账号编码
	AccountType          string      `json:"accountType,omitempty"`          // 账户类型
}

// PayeeAccountInfo 收款账户信息。
type PayeeAccountInfo struct {
	BankOpenDTO *BankOpenDTO `json:"bankOpenDTO,omitempty"` // 银行信息
}

// BankOpenDTO 银行信息。
type BankOpenDTO struct {
	BankCode       string `json:"bankCode,omitempty"`       // 银行编码
	BankName       string `json:"bankName,omitempty"`       // 银行名称
	BankBranchCode string `json:"bankBranchCode,omitempty"` // 银行支行编码
	BankBranchName string `json:"bankBranchName,omitempty"` // 银行支行名称
	AccountName    string `json:"accountName,omitempty"`    // 账户名称
	BankCardNo     string `json:"bankCardNo,omitempty"`     // 银行卡号
	Type           string `json:"type,omitempty"`           // 账户类型
}

// QueryPaymentStatusRequest 支付状态查询请求参数。
type QueryPaymentStatusRequest struct {
	Code   string `json:"code"`   // 单据编码
	UserID string `json:"userId"` // 用户ID
}

// QueryPaymentStatusResponse 支付状态查询响应参数(与支付通知数据结构一致)。
type QueryPaymentStatusResponse = PaymentNotifyData

// File: intelligence_finance_v1_ga/client.go

package intelligence_finance_v1_ga

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"
)

// 接口路径常量。
// 文档未提供具体路径,接口短码在对接时分配,请根据实际分配结果修改以下常量。
const (
	// PathOrderInvoice 订单开票接口路径。
	PathOrderInvoice = "/invoice/order"
	// PathQueryInvoiceStatus 开票状态查询接口路径。
	PathQueryInvoiceStatus = "/invoice/status"
	// PathCreatePaymentOrder 创建付款单据接口路径。
	PathCreatePaymentOrder = "/payment/order"
	// PathQueryPaymentStatus 支付状态查询接口路径。
	PathQueryPaymentStatus = "/payment/status"
)

// Client 是业财连接接口的 SDK 客户端。
type Client struct {
	baseURL      string
	tenantID     string
	clientID     string
	clientSecret string
	httpClient   *http.Client
}

// ClientOption 定义客户端配置选项。
type ClientOption func(*Client)

// WithHTTPClient 自定义 HTTP 客户端。
func WithHTTPClient(hc *http.Client) ClientOption {
	return func(c *Client) { c.httpClient = hc }
}

// NewClient 创建业财连接接口客户端。
// baseURL 为平台接口根地址tenantID 为平台分配的租户唯一标识;
// clientID 为平台分配的应用标识钉钉AI表格固定为 "dd-ai-table"
// clientSecret 为平台分配的密钥,用于 HmacSHA256 签名。
func NewClient(baseURL, tenantID, clientID, clientSecret string, opts ...ClientOption) *Client {
	c := &Client{
		baseURL:      strings.TrimRight(baseURL, "/"),
		tenantID:     tenantID,
		clientID:     clientID,
		clientSecret: clientSecret,
		httpClient:   &http.Client{Timeout: 30 * time.Second},
	}
	for _, opt := range opts {
		opt(c)
	}
	return c
}

// do 发送 POST 请求,自动生成时间戳、随机数并完成 HmacSHA256 签名。
// 若响应符合通用结构 {code, msg, data},则自动解包 data 到 respBody
// 否则直接将整个响应体解析到 respBody。
func (c *Client) do(ctx context.Context, path string, reqBody, respBody interface{}) error {
	bodyBytes, err := json.Marshal(reqBody)
	if err != nil {
		return fmt.Errorf("marshal request body: %w", err)
	}

	timestamp := GenerateTimestamp()
	nonce, err := GenerateNonce(16)
	if err != nil {
		return fmt.Errorf("generate nonce: %w", err)
	}
	signature := HmacSHA256Base64(c.clientSecret, timestamp+nonce)

	req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL+path, bytes.NewReader(bodyBytes))
	if err != nil {
		return fmt.Errorf("new request: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("tenant-id", c.tenantID)
	req.Header.Set("client-id", c.clientID)
	req.Header.Set("x-bfl-signature-timestamp", timestamp)
	req.Header.Set("x-bfl-signature-nonce", nonce)
	req.Header.Set("x-bfl-signature", signature)

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return fmt.Errorf("do request: %w", err)
	}
	defer resp.Body.Close()

	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("read response body: %w", err)
	}

	if resp.StatusCode != http.StatusOK {
		return &APIError{StatusCode: resp.StatusCode, Message: string(data)}
	}

	// 尝试按通用响应结构 {code, msg, data} 解包
	var common struct {
		Code int             `json:"code"`
		Msg  string          `json:"msg"`
		Data json.RawMessage `json:"data"`
	}
	if err := json.Unmarshal(data, &common); err == nil && len(common.Data) > 0 {
		if err := json.Unmarshal(common.Data, respBody); err == nil {
			return nil
		}
	}

	// 直接解析整个响应体
	if err := json.Unmarshal(data, respBody); err != nil {
		return fmt.Errorf("unmarshal response body: %w", err)
	}
	return nil
}

// OrderInvoice 提交订单开票请求。
func (c *Client) OrderInvoice(ctx context.Context, req *OrderInvoiceRequest) (*OrderInvoiceResponse, error) {
	var resp OrderInvoiceResponse
	if err := c.do(ctx, PathOrderInvoice, req, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// QueryInvoiceStatus 查询订单开票状态。
func (c *Client) QueryInvoiceStatus(ctx context.Context, req *QueryInvoiceStatusRequest) (*QueryInvoiceStatusResponse, error) {
	var resp QueryInvoiceStatusResponse
	if err := c.do(ctx, PathQueryInvoiceStatus, req, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// CreatePaymentOrder 创建付款单据。
func (c *Client) CreatePaymentOrder(ctx context.Context, req *CreatePaymentOrderRequest) (*CreatePaymentOrderResponse, error) {
	var resp CreatePaymentOrderResponse
	if err := c.do(ctx, PathCreatePaymentOrder, req, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// QueryPaymentStatus 查询支付状态。
func (c *Client) QueryPaymentStatus(ctx context.Context, req *QueryPaymentStatusRequest) (*QueryPaymentStatusResponse, error) {
	var resp QueryPaymentStatusResponse
	if err := c.do(ctx, PathQueryPaymentStatus, req, &resp); err != nil {
		return nil, err
	}
	return &resp, nil
}

// ParsePaymentNotify 解析支付完成通知接口4的请求体。
// 客户在回调接口中调用此方法解析通知数据,解析成功后应返回 "SUCCESS",失败返回 "FAILED"。
func ParsePaymentNotify(body []byte) (*PaymentNotifyData, error) {
	var data PaymentNotifyData
	if err := json.Unmarshal(body, &data); err != nil {
		return nil, fmt.Errorf("parse payment notify: %w", err)
	}
	return &data, nil
}

// ParseCommonNotify 解析通用通知bizType/bizId/data的请求体。
func ParseCommonNotify(body []byte) (*CommonNotifyData, error) {
	var data CommonNotifyData
	if err := json.Unmarshal(body, &data); err != nil {
		return nil, fmt.Errorf("parse common notify: %w", err)
	}
	return &data, nil
}

// File: intelligence_finance_v1_ga/example_test.go

package intelligence_finance_v1_ga_test

import (
	"context"
	"fmt"
	"testing"

	sdk "intelligence_finance_v1_ga"
)

// TestOrderInvoice 演示订单开票接口的调用。
func TestOrderInvoice(t *testing.T) {
	client := sdk.NewClient(
		"https://api.example.com",
		"your-tenant-id",
		"dd-ai-table",
		"your-client-secret",
	)

	req := &sdk.OrderInvoiceRequest{
		OrderID:     "ORDER-20240101-001",
		InvoiceType: sdk.InvoiceTypeDigitalSpecial,
		Purchaser:   "示例科技有限公司",
		Taxnum:      "91330100MA27XXXXXX",
		Email:       "finance@example.com",
		Phone:       "13800000000",
		Products: []sdk.Product{
			{
				ProductName:      "软件开发服务",
				RevenueCode:      "3040201000000000000",
				AmountIncludeTax: "10000.00",
				Quantity:         "1",
				TaxSign:          1,
				TaxRate:          "0.06",
			},
		},
	}

	resp, err := client.OrderInvoice(context.Background(), req)
	if err != nil {
		t.Fatalf("OrderInvoice failed: %v", err)
	}
	fmt.Printf("开票状态: %d, 错误信息: %s\n", resp.Status, resp.ErrorMsg)
}

// TestQueryInvoiceStatus 演示开票状态查询接口的调用。
func TestQueryInvoiceStatus(t *testing.T) {
	client := sdk.NewClient(
		"https://api.example.com",
		"your-tenant-id",
		"dd-ai-table",
		"your-client-secret",
	)

	resp, err := client.QueryInvoiceStatus(context.Background(), &sdk.QueryInvoiceStatusRequest{
		OrderID: "ORDER-20240101-001",
	})
	if err != nil {
		t.Fatalf("QueryInvoiceStatus failed: %v", err)
	}
	fmt.Printf("状态: %d, 描述: %s\n", resp.Status, resp.Message)
}

// TestCreatePaymentOrder 演示创建付款单据接口的调用。
func TestCreatePaymentOrder(t *testing.T) {
	client := sdk.NewClient(
		"https://api.example.com",
		"your-tenant-id",
		"dd-ai-table",
		"your-client-secret",
	)

	req := &sdk.CreatePaymentOrderRequest{
		Code:   "PAY-20240101-001",
		UserID: "user-001",
		Title:  "供应商货款",
		Amount: "10000.00",
		Supplier: &sdk.Supplier{
			Name: "示例供应商",
		},
		Company: &sdk.Company{
			Name: "示例企业",
		},
		PaymentDetailList: []sdk.PaymentDetail{
			{
				Amount: "10000.00",
				Remark: "货款",
			},
		},
	}

	resp, err := client.CreatePaymentOrder(context.Background(), req)
	if err != nil {
		t.Fatalf("CreatePaymentOrder failed: %v", err)
	}
	fmt.Printf("单据编码: %s\n", resp.Code)
}

// TestQueryPaymentStatus 演示支付状态查询接口的调用。
func TestQueryPaymentStatus(t *testing.T) {
	client := sdk.NewClient(
		"https://api.example.com",
		"your-tenant-id",
		"dd-ai-table",
		"your-client-secret",
	)

	resp, err := client.QueryPaymentStatus(context.Background(), &sdk.QueryPaymentStatusRequest{
		Code:   "PAY-20240101-001",
		UserID: "user-001",
	})
	if err != nil {
		t.Fatalf("QueryPaymentStatus failed: %v", err)
	}
	fmt.Printf("支付状态: %s, 支付时间: %s\n", resp.PaymentStatus, resp.PaymentTime)
}

// TestParsePaymentNotify 演示支付完成通知的解析(客户回调接口中使用)。
func TestParsePaymentNotify(t *testing.T) {
	body := []byte(`{
		"code": "PAY-20240101-001",
		"instanceId": "inst-001",
		"corpId": "corp-001",
		"paymentStatus": "SUCCESS",
		"paymentTime": "2024-01-01 12:00:00",
		"userId": "user-001",
		"source": "openapi",
		"amount": "10000.00"
	}`)

	data, err := sdk.ParsePaymentNotify(body)
	if err != nil {
		t.Fatalf("ParsePaymentNotify failed: %v", err)
	}
	fmt.Printf("支付状态: %s\n", data.PaymentStatus)
}

=== SDK 生成完成 ===