。 现在我将根据文档生成完整的 Go SDK 代码工程。 ## 分析 **认证机制**:客户应用使用 `HmacSHA256` 算法,密钥为 `client-secret`,签名数据为 `timestamp + nonce`,结果 Base64 编码。需要生成 timestamp 和 nonce。 **接口列表**: 1. 订单开票(POST) 2. 开票状态查询(POST) 3. 创建付款单据(POST) 4. 支付完成通知(回调,客户提供接口) 5. 支付状态查询(POST) **通知机制**:客户提供接口,平台调用,响应直接返回字符串 `SUCCESS` 或 `FAILED`。 现在开始生成所有文件: --- // File: intelligence_finance_v1/go.mod ```go module intelligence_finance_v1 go 1.21 ``` --- // File: intelligence_finance_v1/errors.go ```go package intelligence_finance_v1 import "fmt" // Error 表示 SDK 返回的错误类型。 type Error struct { // Code 错误码 Code int // Msg 错误信息 Msg string // Err 底层错误 Err error } // Error 实现 error 接口。 func (e *Error) Error() string { if e.Err != nil { return fmt.Sprintf("code=%d, msg=%s, err=%v", e.Code, e.Msg, e.Err) } return fmt.Sprintf("code=%d, msg=%s", e.Code, e.Msg) } // Unwrap 返回底层错误,支持 errors.Is/As。 func (e *Error) Unwrap() error { return e.Err } // NewError 创建一个新的 Error。 func NewError(code int, msg string) *Error { return &Error{Code: code, Msg: msg} } // WrapError 包装底层错误。 func WrapError(code int, msg string, err error) *Error { return &Error{Code: code, Msg: msg, Err: err} } // 预定义错误 var ( // ErrInvalidConfig 配置无效 ErrInvalidConfig = NewError(1001, "invalid config") // ErrNetwork 网络请求失败 ErrNetwork = NewError(1002, "network error") // ErrSignature 签名失败 ErrSignature = NewError(1003, "signature error") // ErrResponse 响应解析失败 ErrResponse = NewError(1004, "response error") // ErrBusiness 业务错误(code != 0) ErrBusiness = NewError(1005, "business error") ) ``` --- // File: intelligence_finance_v1/crypto.go ```go package intelligence_finance_v1 import ( "crypto/hmac" "crypto/rand" "crypto/sha256" "encoding/base64" "fmt" "math/big" "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 } // HmacSHA256Base64 使用 HmacSHA256 算法对 data 进行签名,密钥为 secret,结果以 Base64 编码返回。 // // 对应文档认证机制:客户应用使用 client-secret 对 (timestamp + 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)) } // BuildSignature 根据文档认证机制生成签名。 // // 签名算法:HmacSHA256 // 密钥:client-secret // 签名数据:x-bfl-signature-timestamp + x-bfl-signature-nonce // 结果编码:Base64 func BuildSignature(clientSecret, timestamp, nonce string) string { return HmacSHA256Base64(clientSecret, timestamp+nonce) } ``` --- // File: intelligence_finance_v1/types.go ```go package intelligence_finance_v1 // 发票类型枚举 const ( InvoiceTypeSpecial = 1 // 专用发票 InvoiceTypeNormal = 2 // 普通发票 InvoiceTypeNormalElectronic = 3 // 普通发票(电子) InvoiceTypeSpecialElec = 4 // 专用发票(电子) InvoiceTypeDigitalSpecial = 8 // 数电专票 InvoiceTypeDigitalNormal = 9 // 数电普票 ) // 开票状态枚举 const ( InvoiceStatusNotInvoiced = 0 // 未开票 InvoiceStatusInvoicing = 1 // 开票中 InvoiceStatusPartialFailed = 2 // 部分失败 InvoiceStatusSuccess = 3 // 开票成功 InvoiceStatusFailed = 4 // 开票失败 InvoiceStatusPartialNotDone = 5 // 部分未开 InvoiceStatusNoDigitalAccount = 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" // 对私银行卡 ) // CommonResponse 通用响应结构。 type CommonResponse struct { Code int `json:"code"` // 响应码 Msg string `json:"msg"` // 响应信息 Data any `json:"data"` // 响应数据 } // InvoiceRequest 订单开票请求参数。 type InvoiceRequest struct { CompanyCode string `json:"companyCode"` // 开票的企业主体编码 OrderID string `json:"orderId"` // 订单唯一标识 InvoiceType int `json:"invoiceType"` // 发票类型枚举 Products []InvoiceProduct `json:"products"` // 货物/服务明细列表 Remark string `json:"remark,omitempty"` // 订单备注 Purchaser string `json:"purchaser"` // 购方企业名称 TaxNum string `json:"taxnum,omitempty"` // 购方纳税人识别号 PurchaserAddr 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"` // 购买方自然人标识 AdditionInfo string `json:"additionInfo,omitempty"` // 附加信息(JSON数组字符串) } // InvoiceProduct 订单开票货物/服务明细项。 type InvoiceProduct struct { ProductName string `json:"productName"` // 货物或服务名称 RevenueCode string `json:"revenueCode"` // 19位税收分类编码 AmountIncludeTax float64 `json:"amountIncludeTax"` // 单条明细含税总金额(元) Specs string `json:"specs,omitempty"` // 规格型号 Unit string `json:"unit,omitempty"` // 计量单位 Quantity float64 `json:"quantity"` // 数量 Discount float64 `json:"discount,omitempty"` // 折扣金额 TaxSign int `json:"taxSign,omitempty"` // 是否含税:0-不含税;1-含税 TaxRate float64 `json:"taxRate,omitempty"` // 税率(小数形式) } // InvoiceResponse 订单开票响应参数。 type InvoiceResponse 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"` // 开票类型 ListFlag string `json:"listFlag"` // 清单标识 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"` // 自然人标识 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"` // 开票日期 InvoiceCode string `json:"invoiceCode"` // 发票代码 InvoiceNo string `json:"invoiceNo"` // 发票号码 InvoiceStatus string `json:"invoiceStatus"` // 发票状态 LayoutFileURL string `json:"layoutFileUrl,omitempty"` // 电子发票地址 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 []InvoiceDetail `json:"details"` // 商品明细列表 } // InvoiceDetail 发票商品明细。 type InvoiceDetail 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"` // 税收分类编码 ItemType string `json:"itemType"` // 商品行性质 ItemName string `json:"itemName"` // 商品简称 Specs string `json:"specs,omitempty"` // 商品规格型号 TaxFreePolicy string `json:"taxFreePolicy"` // 免税政策 PreferentialPolicy string `json:"preferentialPolicy"` // 优惠政策类型 TaxRate string `json:"taxRate"` // 税率 TaxSign string `json:"taxSign"` // 是否含税 Unit string `json:"unit,omitempty"` // 计量单位 UnitPrice string `json:"unitPrice,omitempty"` // 单价 } // InvoiceStatusQueryRequest 开票状态查询请求参数。 type InvoiceStatusQueryRequest struct { OrderID string `json:"orderId"` // 订单唯一标识 } // InvoiceStatusQueryResponse 开票状态查询响应参数。 type InvoiceStatusQueryResponse struct { Status int `json:"status"` // 开票状态 Message string `json:"message"` // 状态描述 Data []InvoiceData `json:"data"` // 发票详细列表 } // PaymentOrderRequest 创建付款单据请求参数。 type PaymentOrderRequest 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 *Product `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"` // 类别名称 } // Product 商品信息。 type Product 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"` // 发票代码 } // PaymentOrderResponse 创建付款单据响应参数。 type PaymentOrderResponse struct { Code string `json:"code"` // 单据唯一编码 } // PaymentNotifyRequest 支付完成通知数据(接口4)。 type PaymentNotifyRequest 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"` // 账户类型 } // PaymentStatusQueryRequest 支付状态查询请求参数。 type PaymentStatusQueryRequest struct { Code string `json:"code"` // 单据编码 UserID string `json:"userId"` // 用户ID } // PaymentStatusQueryResponse 支付状态查询响应参数(与支付通知数据结构一致)。 type PaymentStatusQueryResponse 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"` // 金额 } // Notification 通用通知数据(bizType/bizId/data)。 type Notification struct { BizType string `json:"bizType"` // 业务类型 BizID string `json:"bizId"` // 业务ID Data string `json:"data"` // 业务数据 } ``` --- // File: intelligence_finance_v1/client.go ```go package intelligence_finance_v1 import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "time" ) // Client 是智能财务业财连接 SDK 的客户端。 type Client struct { // baseURL 平台接口基础地址 baseURL string // tenantID 平台分配的租户唯一标识 tenantID string // clientID 平台分配的应用标识 clientID string // clientSecret 平台分配的密钥 clientSecret string // httpClient HTTP 客户端 httpClient *http.Client // signEnabled 是否启用签名(钉钉AI表格无需配置签名,可关闭) signEnabled bool } // ClientOption 客户端配置选项。 type ClientOption func(*Client) // WithHTTPClient 自定义 HTTP 客户端。 func WithHTTPClient(hc *http.Client) ClientOption { return func(c *Client) { c.httpClient = hc } } // WithSignEnabled 设置是否启用签名(默认启用)。 func WithSignEnabled(enabled bool) ClientOption { return func(c *Client) { c.signEnabled = enabled } } // NewClient 创建一个新的智能财务业财连接客户端。 // // 参数: // - baseURL:平台接口基础地址 // - tenantID:平台分配的租户唯一标识 // - clientID:平台分配的应用标识(钉钉AI表格固定为 dd-ai-table) // - clientSecret:平台分配的密钥 func NewClient(baseURL, tenantID, clientID, clientSecret string, opts ...ClientOption) *Client { c := &Client{ baseURL: baseURL, tenantID: tenantID, clientID: clientID, clientSecret: clientSecret, httpClient: &http.Client{Timeout: 30 * time.Second}, signEnabled: true, } for _, opt := range opts { opt(c) } return c } // doRequest 发送 HTTP 请求并解析响应。 func (c *Client) doRequest(ctx context.Context, path string, reqBody any, respBody any) error { bodyBytes, err := json.Marshal(reqBody) if err != nil { return WrapError(ErrSignature.Code, "marshal request body failed", err) } req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL+path, bytes.NewReader(bodyBytes)) if err != nil { return WrapError(ErrNetwork.Code, "create request failed", err) } // 设置公共请求头 req.Header.Set("Content-Type", "application/json") req.Header.Set("tenant-id", c.tenantID) req.Header.Set("client-id", c.clientID) // 签名(钉钉AI表格无需配置,可通过 WithSignEnabled(false) 关闭) if c.signEnabled { timestamp := GenerateTimestamp() nonce, err := GenerateNonce(16) if err != nil { return WrapError(ErrSignature.Code, "generate nonce failed", err) } req.Header.Set("x-bfl-signature-timestamp", timestamp) req.Header.Set("x-bfl-signature-nonce", nonce) req.Header.Set("x-bfl-signature", BuildSignature(c.clientSecret, timestamp, nonce)) } resp, err := c.httpClient.Do(req) if err != nil { return WrapError(ErrNetwork.Code, "do request failed", err) } defer resp.Body.Close() respBytes, err := io.ReadAll(resp.Body) if err != nil { return WrapError(ErrResponse.Code, "read response body failed", err) } if resp.StatusCode != http.StatusOK { return WrapError(ErrResponse.Code, fmt.Sprintf("unexpected http status: %d", resp.StatusCode), nil) } if err := json.Unmarshal(respBytes, respBody); err != nil { return WrapError(ErrResponse.Code, "unmarshal response body failed", err) } return nil } // doRequestCommon 发送请求并解析通用响应结构(code/msg/data)。 func (c *Client) doRequestCommon(ctx context.Context, path string, reqBody any, data any) error { var common CommonResponse if err := c.doRequest(ctx, path, reqBody, &common); err != nil { return err } if common.Code != 0 { return WrapError(common.Code, common.Msg, nil) } if data != nil && common.Data != nil { // 将 data 重新序列化后反序列化到目标结构 dataBytes, err := json.Marshal(common.Data) if err != nil { return WrapError(ErrResponse.Code, "marshal data failed", err) } if err := json.Unmarshal(dataBytes, data); err != nil { return WrapError(ErrResponse.Code, "unmarshal data failed", err) } } return nil } // CreateInvoice 提交订单开票请求(接口1)。 // // 请求方法:POST // 描述:提交订单开票请求。 func (c *Client) CreateInvoice(ctx context.Context, req *InvoiceRequest) (*InvoiceResponse, error) { var resp InvoiceResponse if err := c.doRequestCommon(ctx, "/invoice/create", req, &resp); err != nil { return nil, err } return &resp, nil } // QueryInvoiceStatus 查询订单开票状态(接口2)。 // // 请求方法:POST // 描述:查询订单开票状态。 func (c *Client) QueryInvoiceStatus(ctx context.Context, req *InvoiceStatusQueryRequest) (*InvoiceStatusQueryResponse, error) { var resp InvoiceStatusQueryResponse if err := c.doRequestCommon(ctx, "/invoice/status", req, &resp); err != nil { return nil, err } return &resp, nil } // CreatePaymentOrder 创建付款单据(接口3)。 // // 请求方法:POST // 描述:创建付款单据。 func (c *Client) CreatePaymentOrder(ctx context.Context, req *PaymentOrderRequest) (*PaymentOrderResponse, error) { var resp PaymentOrderResponse if err := c.doRequestCommon(ctx, "/payment/order/create", req, &resp); err != nil { return nil, err } return &resp, nil } // QueryPaymentStatus 查询支付状态(接口5)。 // // 请求方法:POST // 描述:查询支付状态,响应数据与支付通知一致。 func (c *Client) QueryPaymentStatus(ctx context.Context, req *PaymentStatusQueryRequest) (*PaymentStatusQueryResponse, error) { var resp PaymentStatusQueryResponse if err := c.doRequestCommon(ctx, "/payment/status", req, &resp); err != nil { return nil, err } return &resp, nil } // HandlePaymentNotify 处理支付完成通知(接口4,平台回调客户接口)。 // // 该方法用于客户服务端接收平台回调,解析通知数据并返回响应字符串。 // 响应 BODY 直接返回字符串:SUCCESS 表示成功,FAILED 表示失败。 func HandlePaymentNotify(body []byte) (*PaymentNotifyRequest, error) { var req PaymentNotifyRequest if err := json.Unmarshal(body, &req); err != nil { return nil, WrapError(ErrResponse.Code, "unmarshal payment notify failed", err) } return &req, nil } // HandleNotification 处理通用通知(bizType/bizId/data)。 // // 该方法用于客户服务端接收平台通用通知,解析通知数据。 func HandleNotification(body []byte) (*Notification, error) { var n Notification if err := json.Unmarshal(body, &n); err != nil { return nil, WrapError(ErrResponse.Code, "unmarshal notification failed", err) } return &n, nil } ``` --- // File: intelligence_finance_v1/example_test.go ```go package intelligence_finance_v1 import ( "context" "encoding/json" "fmt" "net/http" "testing" ) // ExampleNewClient 展示如何创建客户端并提交订单开票请求。 func ExampleNewClient() { // 创建客户端 client := NewClient( "https://api.example.com", "your-tenant-id", "dd-ai-table", "your-client-secret", ) // 构建订单开票请求 req := &InvoiceRequest{ OrderID: "ORDER20240101001", InvoiceType: InvoiceTypeDigitalSpecial, // 数电专票 Purchaser: "示例科技有限公司", TaxNum: "91110000XXXXXXXXXX", Email: "finance@example.com", Phone: "13800000000", Products: []InvoiceProduct{ { ProductName: "软件开发服务", RevenueCode: "1090101000000000000", AmountIncludeTax: 11300, Quantity: 1, TaxSign: 1, TaxRate: 0.13, }, }, } resp, err := client.CreateInvoice(context.Background(), req) if err != nil { fmt.Printf("create invoice failed: %v\n", err) return } fmt.Printf("invoice status: %d\n", resp.Status) } // ExampleClient_QueryInvoiceStatus 展示如何查询开票状态。 func ExampleClient_QueryInvoiceStatus() { client := NewClient( "https://api.example.com", "your-tenant-id", "dd-ai-table", "your-client-secret", ) resp, err := client.QueryInvoiceStatus(context.Background(), &InvoiceStatusQueryRequest{ OrderID: "ORDER20240101001", }) if err != nil { fmt.Printf("query invoice status failed: %v\n", err) return } fmt.Printf("status: %d, message: %s\n", resp.Status, resp.Message) } // ExampleClient_CreatePaymentOrder 展示如何创建付款单据。 func ExampleClient_CreatePaymentOrder() { client := NewClient( "https://api.example.com", "your-tenant-id", "dd-ai-table", "your-client-secret", ) req := &PaymentOrderRequest{ Code: "PAY20240101001", UserID: "user-001", Title: "供应商货款", Amount: "11300.00", Supplier: &Supplier{ Name: "示例供应商有限公司", }, Company: &Company{ Name: "示例科技有限公司", }, PaymentDetailList: []PaymentDetail{ { Amount: "11300.00", InvoiceInfo: &InvoiceInfo{ InvoiceNo: "12345678", InvoiceCode: "011002000111", }, }, }, } resp, err := client.CreatePaymentOrder(context.Background(), req) if err != nil { fmt.Printf("create payment order failed: %v\n", err) return } fmt.Printf("payment order code: %s\n", resp.Code) } // ExampleClient_QueryPaymentStatus 展示如何查询支付状态。 func ExampleClient_QueryPaymentStatus() { client := NewClient( "https://api.example.com", "your-tenant-id", "dd-ai-table", "your-client-secret", ) resp, err := client.QueryPaymentStatus(context.Background(), &PaymentStatusQueryRequest{ Code: "PAY20240101001", UserID: "user-001", }) if err != nil { fmt.Printf("query payment status failed: %v\n", err) return } fmt.Printf("payment status: %s\n", resp.PaymentStatus) } // ExampleHandlePaymentNotify 展示如何在客户服务端处理支付完成通知。 func ExampleHandlePaymentNotify() { // 模拟平台回调的请求体 body := []byte(`{ "code": "PAY20240101001", "instanceId": "inst-001", "corpId": "corp-001", "paymentStatus": "SUCCESS", "paymentTime": "2024-01-01 12:00:00", "userId": "user-001", "amount": "11300.00", "source": "openapi" }`) notify, err := HandlePaymentNotify(body) if err != nil { fmt.Printf("handle payment notify failed: %v\n", err) return } // 处理业务逻辑... // 返回响应字符串 if notify.PaymentStatus == PaymentStatusSuccess { fmt.Println("SUCCESS") } else { fmt.Println("FAILED") } } // TestSignature 验证签名算法。 func TestSignature(t *testing.T) { secret := "test-secret" timestamp := "1700000000" nonce := "abc123" sig := BuildSignature(secret, timestamp, nonce) if sig == "" { t.Fatal("signature should not be empty") } t.Logf("signature: %s", sig) } // TestHandlePaymentNotify 测试支付通知解析。 func TestHandlePaymentNotify(t *testing.T) { body := []byte(`{"code":"PAY001","instanceId":"i1","corpId":"c1","paymentStatus":"SUCCESS","paymentTime":"2024-01-01 12:00:00","userId":"u1"}`) n, err := HandlePaymentNotify(body) if err != nil { t.Fatalf("handle payment notify failed: %v", err) } if n.Code != "PAY001" { t.Fatalf("unexpected code: %s", n.Code) } } // TestHandleNotification 测试通用通知解析。 func TestHandleNotification(t *testing.T) { body := []byte(`{"bizType":"invoice","bizId":"ORDER001","data":"{\"status\":3}"}`) n, err := HandleNotification(body) if err != nil { t.Fatalf("handle notification failed: %v", err) } if n.BizType != "invoice" { t.Fatalf("unexpected bizType: %s", n.BizType) } } // TestJSONMarshal 测试请求体 JSON 序列化。 func TestJSONMarshal(t *testing.T) { req := &InvoiceRequest{ OrderID: "ORDER001", InvoiceType: 9, Purchaser: "测试公司", Products: []InvoiceProduct{ {ProductName: "服务", RevenueCode: "1090101000000000000", AmountIncludeTax: 100, Quantity: 1}, }, } b, err := json.Marshal(req) if err != nil { t.Fatalf("marshal failed: %v", err) } t.Logf("request json: %s", string(b)) } // TestHTTPHandler 展示如何将通知处理接入 HTTP 服务。 func TestHTTPHandler(t *testing.T) { handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var body []byte _, _ = r.Body.Read(body) notify, err := HandlePaymentNotify(body) if err != nil { w.Write([]byte("FAILED")) return } _ = notify w.Write([]byte("SUCCESS")) }) _ = handler } ``` --- === SDK 生成完成 === ## 加密实现 以下是从加密工具获取的完整实现: ### 加密实现 1 { "success": true, "data": "\n### 参数拼接规范\n\n**常见拼接方式**:\n\n1. **字典序排序**:按key字典序排序后拼接 `key=value\u0026key2=value2`\n2. **固定顺序**:按文档指定顺序拼接\n3. **JSON字符串**:整个请求体作为签名串\n\n**代码模板**:\n\n```go\npackage crypto\n\nimport (\n \"fmt\"\n \"sort\"\n \"strings\"\n)\n\n// BuildSignString 方式1:字典序排序拼接\nfunc BuildSignString(params map[string]string) string {\n keys := make([]string, 0, len(params))\n for k, v := range params {\n if v != \"\" \u0026\u0026 k != \"sign\" \u0026\u0026 k != \"signature\" {\n keys = append(keys, k)\n }\n }\n sort.Strings(keys)\n \n var parts []string\n for _, k := range keys {\n parts = append(parts, fmt.Sprintf(\"%s=%s\", k, params[k]))\n }\n return strings.Join(parts, \"\u0026\")\n}\n\n// BuildSignStringOrdered 方式2:固定顺序拼接\nfunc BuildSignStringOrdered(params map[string]string, orderedKeys []string) string {\n var parts []string\n for _, k := range orderedKeys {\n if v, ok := params[k]; ok \u0026\u0026 v != \"\" {\n parts = append(parts, fmt.Sprintf(\"%s=%s\", k, v))\n }\n }\n return strings.Join(parts, \"\u0026\")\n}\n```\n\n**注意事项**:\n- 确认文档指定的排序规则(字典序/固定顺序)\n- 确认空值是否要包含(通常排除空值)\n- 确认是否需要URL编码\n- 注意排除签名字段本身\n", "tool": "param_concat" } ### 加密实现 2 { "success": true, "data": "\n### 时间戳和随机数生成规范\n\n**代码模板**:\n\n```go\npackage crypto\n\nimport (\n \"crypto/rand\"\n \"fmt\"\n \"math/big\"\n \"time\"\n)\n\n// GenerateTimestamp 生成秒级时间戳\nfunc GenerateTimestamp() string {\n return fmt.Sprintf(\"%d\", time.Now().Unix())\n}\n\n// GenerateTimestampMillis 生成毫秒级时间戳\nfunc GenerateTimestampMillis() string {\n return fmt.Sprintf(\"%d\", time.Now().UnixMilli())\n}\n\n// GenerateNonce 生成指定长度的随机字符串(加密安全)\nfunc GenerateNonce(length int) (string, error) {\n const charset = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\"\n b := make([]byte, length)\n for i := range b {\n num, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))\n if err != nil {\n return \"\", err\n }\n b[i] = charset[num.Int64()]\n }\n return string(b), nil\n}\n```\n\n**注意事项**:\n- 确认文档要求的是秒级还是毫秒级时间戳\n- 确认nonce的长度要求(通常16-32位)\n- 生产环境建议使用加密安全的随机数生成器\n", "tool": "nonce_timestamp" }