intelligence_finance_v1-202.../intelligence_finance_v1/generate.md

1307 lines
44 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// File: intelligence_finance_v1/go.mod
```
module intelligence_finance_v1
go 1.21
```
// File: intelligence_finance_v1/crypto.go
```go
package intelligence_finance_v1
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())
}
// 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算法对数据进行签名返回Base64编码结果
func HmacSHA256Base64(secret, data string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(data))
return base64.StdEncoding.EncodeToString(mac.Sum(nil))
}
// BuildSignString 按字典序排序拼接参数(排除空值和签名字段)
func BuildSignString(params map[string]string) string {
keys := make([]string, 0, len(params))
for k, v := range params {
if v != "" && k != "sign" && k != "signature" && k != "x-bfl-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 按固定顺序拼接参数
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, "&")
}
```
// File: intelligence_finance_v1/types.go
```go
package intelligence_finance_v1
// ============================================================
// 通用请求/响应结构
// ============================================================
// CommonResponse 通用API响应结构
type CommonResponse struct {
Code int `json:"code"`
Msg string `json:"msg,omitempty"`
Data interface{} `json:"data,omitempty"`
}
// NotificationRequest 回调通知请求结构
type NotificationRequest struct {
BizType string `json:"bizType"`
BizID string `json:"bizId"`
Data string `json:"data,omitempty"`
}
// ============================================================
// 接口1订单开票请求/响应
// ============================================================
// CreateInvoiceRequest 提交订单开票申请请求
type CreateInvoiceRequest struct {
CompanyCode string `json:"companyCode,omitempty"`
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"`
}
// InvoiceProduct 货物/服务明细
type InvoiceProduct struct {
ProductName string `json:"productName"`
RevenueCode string `json:"revenueCode"`
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"`
TaxRate float64 `json:"taxRate,omitempty"`
}
// CreateInvoiceResponse 提交订单开票申请响应
type CreateInvoiceResponse struct {
Status int `json:"status"`
ErrorMsg string `json:"errorMsg,omitempty"`
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"`
OfdURL string `json:"ofdUrl,omitempty"`
XmlURL string `json:"xmlUrl,omitempty"`
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"`
}
// ============================================================
// 接口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创建付款单据请求/响应
// ============================================================
// CreatePaymentRequest 创建付款单据请求
type CreatePaymentRequest struct {
Code string `json:"code"`
YidaAppType string `json:"yidaAppType,omitempty"`
EmpAccountUserID string `json:"empAccountUserId,omitempty"`
Department *Department `json:"department,omitempty"`
Usage string `json:"usage,omitempty"`
PaymentUserID string `json:"paymentUserId,omitempty"`
Customer *Customer `json:"customer,omitempty"`
PrincipalID string `json:"principalId,omitempty"`
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"`
NeedPayment bool `json:"needPayment,omitempty"`
PaymentDetailListJsonStr string `json:"paymentDetailListJsonStr,omitempty"`
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"`
OccurDate int64 `json:"occurDate,omitempty"`
Product *Product `json:"product,omitempty"`
YidaFormUUID string `json:"yidaFormUuid,omitempty"`
CanEditPaymentInfo bool `json:"canEditPaymentInfo,omitempty"`
PaymentUserIDList []string `json:"paymentUserIdList,omitempty"`
YidaProcInsID string `json:"yidaProcInsId,omitempty"`
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"`
Tax string `json:"tax,omitempty"`
}
// InvoiceInfo 付款明细发票信息
type InvoiceInfo struct {
InvoiceNo string `json:"invoiceNo,omitempty"`
InvoiceCode string `json:"invoiceCode,omitempty"`
}
// CreatePaymentResponse 创建付款单据响应
type CreatePaymentResponse struct {
Code string `json:"code"`
}
// ============================================================
// 接口4支付完成通知平台回调
// ============================================================
// PaymentNotification 支付完成通知数据结构
type PaymentNotification struct {
Code string `json:"code"`
InstanceID string `json:"instanceId"`
CorpID string `json:"corpId"`
PaymentStatus string `json:"paymentStatus"`
PaymentTime string `json:"paymentTime"`
UserID string `json:"userId"`
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"`
}
// ============================================================
// 接口5支付状态查询请求/响应
// ============================================================
// QueryPaymentStatusRequest 查询支付状态请求
type QueryPaymentStatusRequest struct {
Code string `json:"code"`
UserID string `json:"userId"`
}
// QueryPaymentStatusResponse 查询支付状态响应与PaymentNotification结构一致
type QueryPaymentStatusResponse struct {
PaymentNotification
}
// ============================================================
// 接口6创建供应商请求/响应
// ============================================================
// CreateSupplierRequest 创建供应商请求
type CreateSupplierRequest struct {
InvokeID string `json:"invokeId,omitempty"`
UserID string `json:"userId"`
Data string `json:"data,omitempty"`
BizType string `json:"bizType"`
}
// CreateSupplierBizData 创建供应商业务数据
type CreateSupplierBizData struct {
CorpID string `json:"corpId"`
Creator string `json:"creator"`
SupplierInfo *SupplierInfo `json:"supplierInfo,omitempty"`
}
// SupplierInfo 供应商数据
type SupplierInfo struct {
Name string `json:"name"`
CorpID string `json:"corpId"`
UserDefineCode string `json:"userDefineCode,omitempty"`
Description string `json:"description,omitempty"`
ContactAddress string `json:"contactAddress,omitempty"`
ContactCompanyTelephone string `json:"contactCompanyTelephone,omitempty"`
ContactEmail string `json:"contactEmail,omitempty"`
ContactName string `json:"contactName,omitempty"`
ContactTelephone string `json:"contactTelephone,omitempty"`
Creator string `json:"creator"`
InvoiceAccount string `json:"invoiceAccount,omitempty"`
InvoiceAddress string `json:"invoiceAddress,omitempty"`
InvoiceBankName string `json:"invoiceBankName,omitempty"`
InvoiceName string `json:"invoiceName,omitempty"`
InvoiceTaxNo string `json:"invoiceTaxNo,omitempty"`
PurchaserTel string `json:"purchaserTel,omitempty"`
BankName string `json:"bankName,omitempty"`
InvoiceTelephone string `json:"invoiceTelephone,omitempty"`
AccountName string `json:"accountName,omitempty"`
AccountType string `json:"accountType,omitempty"`
}
// CreateSupplierResponse 创建供应商响应
type CreateSupplierResponse struct {
InvokeID string `json:"invokeId,omitempty"`
BizType string `json:"bizType"`
Data string `json:"data,omitempty"`
}
// CreateSupplierResponseData 创建供应商响应数据
type CreateSupplierResponseData struct {
Result string `json:"result,omitempty"`
Success bool `json:"success"`
}
// SupplierInfoResponse 供应商信息(响应)
type SupplierInfoResponse struct {
SupplierID string `json:"supplierId"`
SupplierName string `json:"supplierName"`
Name string `json:"name"`
CorpID string `json:"corpId"`
UserDefineCode string `json:"userDefineCode,omitempty"`
Description string `json:"description,omitempty"`
ContactAddress string `json:"contactAddress,omitempty"`
ContactCompanyTelephone string `json:"contactCompanyTelephone,omitempty"`
ContactEmail string `json:"contactEmail,omitempty"`
ContactName string `json:"contactName,omitempty"`
ContactTelephone string `json:"contactTelephone,omitempty"`
Creator string `json:"creator"`
InvoiceAccount string `json:"invoiceAccount,omitempty"`
InvoiceAddress string `json:"invoiceAddress,omitempty"`
InvoiceBankName string `json:"invoiceBankName,omitempty"`
}
// ============================================================
// 接口7根据名称查询供应商请求/响应
// ============================================================
// QuerySupplierByNameRequest 根据名称查询供应商请求
type QuerySupplierByNameRequest struct {
InvokeID string `json:"invokeId,omitempty"`
UserID string `json:"userId"`
Data string `json:"data,omitempty"`
BizType string `json:"bizType"`
}
// QuerySupplierByNameBizData 根据名称查询供应商业务数据
type QuerySupplierByNameBizData struct {
CorpID string `json:"corpId"`
Name string `json:"name"`
}
// QuerySupplierByNameResponse 根据名称查询供应商响应
type QuerySupplierByNameResponse struct {
InvokeID string `json:"invokeId,omitempty"`
BizType string `json:"bizType"`
Data string `json:"data,omitempty"`
Result string `json:"result,omitempty"`
Success bool `json:"success"`
}
// QuerySupplierByNameResult 供应商查询结果重要字段
type QuerySupplierByNameResult struct {
SupplierName string `json:"supplierName"`
UserDefineCode string `json:"userDefineCode,omitempty"`
InvoiceName string `json:"invoiceName,omitempty"`
SupplierID string `json:"supplierId"`
CorpID string `json:"corpId"`
ContactTelephone string `json:"contactTelephone,omitempty"`
ContactEmail string `json:"contactEmail,omitempty"`
ContactName string `json:"contactName,omitempty"`
InvoiceBankName string `json:"invoiceBankName,omitempty"`
InvoiceAccount string `json:"invoiceAccount,omitempty"`
Description string `json:"description,omitempty"`
InvoiceAddress string `json:"invoiceAddress,omitempty"`
InvoiceTaxNo string `json:"invoiceTaxNo,omitempty"`
ContactCompanyTelephone string `json:"contactCompanyTelephone,omitempty"`
CreateTime int64 `json:"createTime,omitempty"`
InvoiceTelephone string `json:"invoiceTelephone,omitempty"`
ContactAddress string `json:"contactAddress,omitempty"`
}
// ============================================================
// 接口8更新供应商请求/响应
// ============================================================
// UpdateSupplierRequest 更新供应商请求
type UpdateSupplierRequest struct {
InvokeID string `json:"invokeId,omitempty"`
UserID string `json:"userId"`
Data string `json:"data,omitempty"`
BizType string `json:"bizType"`
}
// UpdateSupplierBizData 更新供应商业务数据
type UpdateSupplierBizData struct {
SupplierID string `json:"supplierId"`
Name string `json:"name"`
CorpID string `json:"corpId"`
UserDefineCode string `json:"userDefineCode,omitempty"`
Description string `json:"description,omitempty"`
ContactAddress string `json:"contactAddress,omitempty"`
ContactCompanyTelephone string `json:"contactCompanyTelephone,omitempty"`
ContactEmail string `json:"contactEmail,omitempty"`
ContactName string `json:"contactName,omitempty"`
ContactTelephone string `json:"contactTelephone,omitempty"`
UserID string `json:"userId"`
InvoiceAccount string `json:"invoiceAccount,omitempty"`
InvoiceAddress string `json:"invoiceAddress,omitempty"`
InvoiceBankName string `json:"invoiceBankName,omitempty"`
InvoiceName string `json:"invoiceName,omitempty"`
InvoiceTaxNo string `json:"invoiceTaxNo,omitempty"`
PurchaserTel string `json:"purchaserTel,omitempty"`
BankName string `json:"bankName,omitempty"`
InvoiceTelephone string `json:"invoiceTelephone,omitempty"`
AccountName string `json:"accountName,omitempty"`
AccountType string `json:"accountType,omitempty"`
BankBranchCode string `json:"bankBranchCode,omitempty"`
BankCode string `json:"bankCode,omitempty"`
BankCity string `json:"bankCity,omitempty"`
BankProvince string `json:"bankProvince,omitempty"`
}
// UpdateSupplierResponse 更新供应商响应
type UpdateSupplierResponse struct {
InvokeID string `json:"invokeId,omitempty"`
BizType string `json:"bizType"`
Data string `json:"data,omitempty"`
}
// UpdateSupplierResponseData 更新供应商响应数据
type UpdateSupplierResponseData struct {
Result string `json:"result,omitempty"`
Success bool `json:"success"`
}
// ============================================================
// 接口9根据用户自定义编码查询供应商请求/响应
// ============================================================
// QuerySupplierByUserDefineCodeRequest 根据用户自定义编码查询供应商请求
type QuerySupplierByUserDefineCodeRequest struct {
InvokeID string `json:"invokeId,omitempty"`
UserID string `json:"userId"`
Data string `json:"data,omitempty"`
BizType string `json:"bizType"`
}
// QuerySupplierByUserDefineCodeBizData 根据自定义编码查询供应商业务数据
type QuerySupplierByUserDefineCodeBizData struct {
CorpID string `json:"corpId"`
UserDefineCode string `json:"userDefineCode"`
}
// QuerySupplierByUserDefineCodeResponse 根据自定义编码查询供应商响应
type QuerySupplierByUserDefineCodeResponse struct {
InvokeID string `json:"invokeId,omitempty"`
BizType string `json:"bizType"`
Data string `json:"data,omitempty"`
}
// QuerySupplierByUserDefineCodeResponseData 响应数据
type QuerySupplierByUserDefineCodeResponseData struct {
Success bool `json:"success"`
}
// QuerySupplierByUserDefineCodeResult 供应商查询结果重要字段
type QuerySupplierByUserDefineCodeResult struct {
UserDefineCode string `json:"userDefineCode"`
SupplierName string `json:"supplierName"`
ModifiedTime int64 `json:"modifiedTime,omitempty"`
Creator string `json:"creator,omitempty"`
SupplierID string `json:"supplierId"`
Code string `json:"code,omitempty"`
CorpID string `json:"corpId"`
CreateTime int64 `json:"createTime,omitempty"`
Name string `json:"name"`
ID int64 `json:"id,omitempty"`
Status string `json:"status,omitempty"`
}
```
// File: intelligence_finance_v1/errors.go
```go
package intelligence_finance_v1
import "fmt"
// SDKError SDK通用错误类型
type SDKError struct {
Code int `json:"code"`
Message string `json:"message"`
Err error `json:"-"`
}
// Error 实现error接口
func (e *SDKError) Error() string {
if e.Err != nil {
return fmt.Sprintf("code=%d, message=%s, err=%v", e.Code, e.Message, e.Err)
}
return fmt.Sprintf("code=%d, message=%s", e.Code, e.Message)
}
// Unwrap 返回包装的错误
func (e *SDKError) Unwrap() error {
return e.Err
}
// NewSDKError 创建SDK错误
func NewSDKError(code int, message string, err error) *SDKError {
return &SDKError{
Code: code,
Message: message,
Err: err,
}
}
// 预定义错误码
const (
ErrCodeSuccess = 0
ErrCodeUnknown = -1
ErrCodeInvalidParam = 1001
ErrCodeSignatureFailed = 1002
ErrCodeNetworkError = 1003
ErrCodeRequestTimeout = 1004
ErrCodeServerError = 2001
ErrCodeUnauthorized = 2002
ErrCodeNotFound = 2003
ErrCodeRateLimit = 2004
)
// 预定义错误
var (
ErrUnknown = NewSDKError(ErrCodeUnknown, "未知错误", nil)
ErrInvalidParam = NewSDKError(ErrCodeInvalidParam, "参数无效", nil)
ErrSignatureFailed = NewSDKError(ErrCodeSignatureFailed, "签名失败", nil)
ErrNetworkError = NewSDKError(ErrCodeNetworkError, "网络错误", nil)
ErrRequestTimeout = NewSDKError(ErrCodeRequestTimeout, "请求超时", nil)
ErrServerError = NewSDKError(ErrCodeServerError, "服务端错误", nil)
ErrUnauthorized = NewSDKError(ErrCodeUnauthorized, "未授权", nil)
ErrNotFound = NewSDKError(ErrCodeNotFound, "未找到", nil)
ErrRateLimit = NewSDKError(ErrCodeRateLimit, "请求频率限制", nil)
)
```
// 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 string
tenantID string
clientID string
clientSecret string
httpClient *http.Client
debug bool
}
// ClientOption 客户端配置选项
type ClientOption func(*Client)
// WithHTTPClient 设置自定义HTTP客户端
func WithHTTPClient(httpClient *http.Client) ClientOption {
return func(c *Client) {
c.httpClient = httpClient
}
}
// WithDebug 开启调试模式
func WithDebug(debug bool) ClientOption {
return func(c *Client) {
c.debug = debug
}
}
// WithTimeout 设置请求超时时间
func WithTimeout(timeout time.Duration) ClientOption {
return func(c *Client) {
c.httpClient.Timeout = timeout
}
}
// NewClient 创建新的SDK客户端
// - baseURL: API基础地址
// - tenantID: 平台分配的租户唯一标识
// - clientID: 平台分配的应用标识
// - clientSecret: 平台分配的客户端密钥
// - opts: 可选配置项
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,
},
}
for _, opt := range opts {
opt(c)
}
return c
}
// doRequest 发送HTTP请求自动添加签名和认证头
func (c *Client) doRequest(ctx context.Context, path string, request interface{}, response interface{}) error {
bodyBytes, err := json.Marshal(request)
if err != nil {
return NewSDKError(ErrCodeInvalidParam, "请求序列化失败", err)
}
if c.debug {
fmt.Printf("[DEBUG] Request URL: %s%s\n", c.baseURL, path)
fmt.Printf("[DEBUG] Request Body: %s\n", string(bodyBytes))
}
// 生成时间戳和随机数
timestamp := GenerateTimestamp()
nonce, err := GenerateNonce(16)
if err != nil {
return NewSDKError(ErrCodeSignatureFailed, "生成随机数失败", err)
}
// 签名数据timestamp + nonce
signData := timestamp + nonce
signature := HmacSHA256Base64(c.clientSecret, signData)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL+path, bytes.NewReader(bodyBytes))
if err != nil {
return NewSDKError(ErrCodeNetworkError, "创建请求失败", 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)
if c.debug {
fmt.Printf("[DEBUG] Headers: tenant-id=%s, client-id=%s, x-bfl-signature=%s\n", c.tenantID, c.clientID, signature)
}
resp, err := c.httpClient.Do(req)
if err != nil {
return NewSDKError(ErrCodeNetworkError, "请求发送失败", err)
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return NewSDKError(ErrCodeNetworkError, "读取响应失败", err)
}
if c.debug {
fmt.Printf("[DEBUG] Response Status: %s\n", resp.Status)
fmt.Printf("[DEBUG] Response Body: %s\n", string(respBody))
}
// 解析通用响应
var commonResp CommonResponse
if err := json.Unmarshal(respBody, &commonResp); err != nil {
return NewSDKError(ErrCodeUnknown, "响应解析失败", err)
}
if commonResp.Code != 0 {
return NewSDKError(commonResp.Code, commonResp.Msg, nil)
}
// 如果有data字段且response不为nil反序列化data到response
if commonResp.Data != nil && response != nil {
dataBytes, err := json.Marshal(commonResp.Data)
if err != nil {
return NewSDKError(ErrCodeUnknown, "响应数据序列化失败", err)
}
if err := json.Unmarshal(dataBytes, response); err != nil {
return NewSDKError(ErrCodeUnknown, "响应数据解析失败", err)
}
}
return nil
}
// ============================================================
// 接口1订单开票
// ============================================================
// CreateInvoice 提交订单开票申请
// 文档接口1 - 提交订单开票申请
func (c *Client) CreateInvoice(ctx context.Context, req *CreateInvoiceRequest) (*CreateInvoiceResponse, error) {
path := "/api/v1/invoice/create"
var resp CreateInvoiceResponse
if err := c.doRequest(ctx, path, req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// ============================================================
// 接口2开票状态查询
// ============================================================
// QueryInvoiceStatus 查询订单开票状态
// 文档接口2 - 查询订单开票状态
func (c *Client) QueryInvoiceStatus(ctx context.Context, req *QueryInvoiceStatusRequest) (*QueryInvoiceStatusResponse, error) {
path := "/api/v1/invoice/query"
var resp QueryInvoiceStatusResponse
if err := c.doRequest(ctx, path, req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// ============================================================
// 接口3创建付款单据
// ============================================================
// CreatePayment 创建付款单据
// 文档接口3 - 创建付款单据
func (c *Client) CreatePayment(ctx context.Context, req *CreatePaymentRequest) (*CreatePaymentResponse, error) {
path := "/api/v1/payment/create"
var resp CreatePaymentResponse
if err := c.doRequest(ctx, path, req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// ============================================================
// 接口4支付完成通知平台回调客户
// 此接口由客户提供平台调用。客户需实现HTTP Handler处理回调。
// ============================================================
// HandlePaymentNotification 处理支付完成通知
// 文档接口4 - 支付完成通知回调处理
// 该函数用于解析平台发起的支付完成通知请求返回SUCCESS或FAILED
func HandlePaymentNotification(body []byte) (string, error) {
var notification PaymentNotification
if err := json.Unmarshal(body, &notification); err != nil {
return "FAILED", NewSDKError(ErrCodeInvalidParam, "解析通知数据失败", err)
}
// 业务处理由调用方自行实现,此处仅返回成功
// 调用方应在此函数基础上扩展业务逻辑
return "SUCCESS", nil
}
// ============================================================
// 接口5支付状态查询
// ============================================================
// QueryPaymentStatus 查询支付状态
// 文档接口5 - 查询支付状态
func (c *Client) QueryPaymentStatus(ctx context.Context, req *QueryPaymentStatusRequest) (*QueryPaymentStatusResponse, error) {
path := "/api/v1/payment/query"
var resp QueryPaymentStatusResponse
if err := c.doRequest(ctx, path, req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// ============================================================
// 接口6创建供应商
// ============================================================
// CreateSupplier 创建供应商
// 文档接口6 - 创建供应商
func (c *Client) CreateSupplier(ctx context.Context, req *CreateSupplierRequest) (*CreateSupplierResponse, error) {
path := "/api/v1/supplier/create"
var resp CreateSupplierResponse
if err := c.doRequest(ctx, path, req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// ============================================================
// 接口7根据名称查询供应商
// ============================================================
// QuerySupplierByName 根据供应商名称查询供应商
// 文档接口7 - 根据名称查询供应商
func (c *Client) QuerySupplierByName(ctx context.Context, req *QuerySupplierByNameRequest) (*QuerySupplierByNameResponse, error) {
path := "/api/v1/supplier/queryByName"
var resp QuerySupplierByNameResponse
if err := c.doRequest(ctx, path, req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// ============================================================
// 接口8更新供应商
// ============================================================
// UpdateSupplier 更新供应商信息
// 文档接口8 - 更新供应商
func (c *Client) UpdateSupplier(ctx context.Context, req *UpdateSupplierRequest) (*UpdateSupplierResponse, error) {
path := "/api/v1/supplier/update"
var resp UpdateSupplierResponse
if err := c.doRequest(ctx, path, req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// ============================================================
// 接口9根据用户自定义编码查询供应商
// ============================================================
// QuerySupplierByUserDefineCode 根据用户自定义编码查询供应商
// 文档接口9 - 根据用户自定义编码查询供应商
func (c *Client) QuerySupplierByUserDefineCode(ctx context.Context, req *QuerySupplierByUserDefineCodeRequest) (*QuerySupplierByUserDefineCodeResponse, error) {
path := "/api/v1/supplier/queryByCode"
var resp QuerySupplierByUserDefineCodeResponse
if err := c.doRequest(ctx, path, req, &resp); err != nil {
return nil, err
}
return &resp, nil
}
```
// File: intelligence_finance_v1/example_test.go
```go
package intelligence_finance_v1
import (
"context"
"encoding/json"
"fmt"
"log"
"time"
)
// ExampleNewClient 展示了如何创建SDK客户端
func ExampleNewClient() {
// 创建客户端
client := NewClient(
"https://api.example.com",
"your-tenant-id",
"dd-ai-table",
"your-client-secret",
WithTimeout(30*time.Second),
WithDebug(true),
)
_ = client
fmt.Println("Client created successfully")
}
// ExampleClient_CreateInvoice 展示了如何提交订单开票申请
func ExampleClient_CreateInvoice() {
client := NewClient(
"https://api.example.com",
"your-tenant-id",
"dd-ai-table",
"your-client-secret",
)
req := &CreateInvoiceRequest{
OrderID: "ORDER20240101001",
InvoiceType: 9, // 数电普票
Purchaser: "测试购买方有限公司",
TaxNum: "91110108MA12345678",
Phone: "13800138000",
Email: "test@example.com",
Products: []InvoiceProduct{
{
ProductName: "办公用品",
RevenueCode: "1090515010000000000",
AmountIncludeTax: 1130.00,
Quantity: 10,
Unit: "个",
TaxRate: 0.13,
TaxSign: 1,
Discount: 0,
},
},
ApplyPerson: "张三",
Payee: "李四",
Reviewer: "王五",
}
resp, err := client.CreateInvoice(context.Background(), req)
if err != nil {
log.Fatalf("创建开票申请失败: %v", err)
}
fmt.Printf("开票状态: %d, 错误信息: %s\n", resp.Status, resp.ErrorMsg)
for i, inv := range resp.DataList {
fmt.Printf("发票%d: 代码=%s, 号码=%s, 金额(含税)=%s\n", i+1, inv.InvoiceCode, inv.InvoiceNo, inv.TotalIncludeTax)
}
}
// ExampleClient_QueryInvoiceStatus 展示了如何查询开票状态
func ExampleClient_QueryInvoiceStatus() {
client := NewClient(
"https://api.example.com",
"your-tenant-id",
"dd-ai-table",
"your-client-secret",
)
req := &QueryInvoiceStatusRequest{
OrderID: "ORDER20240101001",
}
resp, err := client.QueryInvoiceStatus(context.Background(), req)
if err != nil {
log.Fatalf("查询开票状态失败: %v", err)
}
fmt.Printf("开票状态: %d, 描述: %s\n", resp.Status, resp.Message)
}
// ExampleClient_CreatePayment 展示了如何创建付款单据
func ExampleClient_CreatePayment() {
client := NewClient(
"https://api.example.com",
"your-tenant-id",
"dd-ai-table",
"your-client-secret",
)
req := &CreatePaymentRequest{
Code: "PAY20240101001",
UserID: "user123",
Title: "采购付款-2024年1月",
Amount: "50000.00",
Supplier: &Supplier{
Name: "供应商A",
},
Department: &Department{
Name: "财务部",
},
Company: &Company{
Name: "XX科技有限公司",
},
PaymentDetailList: []PaymentDetail{
{
Amount: "50000.00",
Remark: "1月采购货款",
},
},
}
resp, err := client.CreatePayment(context.Background(), req)
if err != nil {
log.Fatalf("创建付款单据失败: %v", err)
}
fmt.Printf("付款单据编码: %s\n", resp.Code)
}
// ExampleHandlePaymentNotification 展示了如何处理支付完成通知
func ExampleHandlePaymentNotification() {
// 模拟平台回调的请求体
notificationBody := `{
"code": "PAY20240101001",
"instanceId": "instance_001",
"corpId": "dingXXXXXX",
"paymentStatus": "SUCCESS",
"paymentTime": "2024-01-15 10:30:00",
"userId": "user123",
"amount": "50000.00",
"source": "openapi"
}`
result, err := HandlePaymentNotification([]byte(notificationBody))
if err != nil {
log.Printf("处理通知失败: %v", err)
}
fmt.Printf("通知处理结果: %s\n", result)
// 实际业务中,可以在此处解析通知数据并执行后续操作
var notification PaymentNotification
if err := json.Unmarshal([]byte(notificationBody), &notification); err == nil {
fmt.Printf("收到支付通知: 单据编码=%s, 支付状态=%s\n", notification.Code, notification.PaymentStatus)
}
}
// ExampleClient_QueryPaymentStatus 展示了如何查询支付状态
func ExampleClient_QueryPaymentStatus() {
client := NewClient(
"https://api.example.com",
"your-tenant-id",
"dd-ai-table",
"your-client-secret",
)
req := &QueryPaymentStatusRequest{
Code: "PAY20240101001",
UserID: "user123",
}
resp, err := client.QueryPaymentStatus(context.Background(), req)
if err != nil {
log.Fatalf("查询支付状态失败: %v", err)
}
fmt.Printf("支付状态: %s, 支付时间: %s\n", resp.PaymentStatus, resp.PaymentTime)
}
// ExampleClient_CreateSupplier 展示了如何创建供应商
func ExampleClient_CreateSupplier() {
client := NewClient(
"https://api.example.com",
"your-tenant-id",
"dd-ai-table",
"your-client-secret",
)
bizData := CreateSupplierBizData{
CorpID: "dingXXXXXX",
Creator: "user123",
SupplierInfo: &SupplierInfo{
Name: "测试供应商有限公司",
CorpID: "dingXXXXXX",
Creator: "user123",
UserDefineCode: "SUP-001",
ContactName: "张三",
ContactTelephone: "13800138000",
ContactEmail: "contact@supplier.com",
ContactAddress: "北京市朝阳区XX路XX号",
},
}
bizDataBytes, _ := json.Marshal(bizData)
req := &CreateSupplierRequest{
InvokeID: "invoke_001",
UserID: "user123",
Data: string(bizDataBytes),
BizType: "create_supplier",
}
resp, err := client.CreateSupplier(context.Background(), req)
if err != nil {
log.Fatalf("创建供应商失败: %v", err)
}
fmt.Printf("创建供应商响应: invokeId=%s, bizType=%s\n", resp.InvokeID, resp.BizType)
}
// ExampleClient_QuerySupplierByName 展示了如何根据名称查询供应商
func ExampleClient_QuerySupplierByName() {
client := NewClient(
"https://api.example.com",
"your-tenant-id",
"dd-ai-table",
"your-client-secret",
)
bizData := []QuerySupplierByNameBizData{
{
CorpID: "dingXXXXXX",
Name: "测试供应商有限公司",
},
}
bizDataBytes, _ := json.Marshal(bizData)
req := &QuerySupplierByNameRequest{
InvokeID: "invoke_002",
UserID: "user123",
Data: string(bizDataBytes),
BizType: "query_supplier_by_name",
}
resp, err := client.QuerySupplierByName(context.Background(), req)
if err != nil {
log.Fatalf("查询供应商失败: %v", err)
}
fmt.Printf("查询结果: success=%v, result=%s\n", resp.Success, resp.Result)
}
// ExampleClient_UpdateSupplier 展示了如何更新供应商
func ExampleClient_UpdateSupplier() {
client := NewClient(
"https://api.example.com",
"your-tenant-id",
"dd-ai-table",
"your-client-secret",
)
bizData := UpdateSupplierBizData{
SupplierID: "SUP_XXXXX",
Name: "更新后的供应商名称",
CorpID: "dingXXXXXX",
UserID: "user123",
ContactName: "李四",
ContactTelephone: "13900139000",
ContactEmail: "new@supplier.com",
Description: "长期合作供应商",
}
bizDataBytes, _ := json.Marshal(bizData)
req := &UpdateSupplierRequest{
InvokeID: "invoke_003",
UserID: "user123",
Data: string(bizDataBytes),
BizType: "update_supplier",
}
resp, err := client.UpdateSupplier(context.Background(), req)
if err != nil {
log.Fatalf("更新供应商失败: %v", err)
}
fmt.Printf("更新供应商响应: invokeId=%s, bizType=%s\n", resp.InvokeID, resp.BizType)
}
// ExampleClient_QuerySupplierByUserDefineCode 展示了如何根据自定义编码查询供应商
func ExampleClient_QuerySupplierByUserDefineCode() {
client := NewClient(
"https://api.example.com",
"your-tenant-id",
"dd-ai-table",
"your-client-secret",
)
bizData := QuerySupplierByUserDefineCodeBizData{
CorpID: "dingXXXXXX",
UserDefineCode: "SUP-001",
}
bizDataBytes, _ := json.Marshal(bizData)
req := &QuerySupplierByUserDefineCodeRequest{
InvokeID: "invoke_004",
UserID: "user123",
Data: string(bizDataBytes),
BizType: "query_supplier_by_userDefineCode",
}
resp, err := client.QuerySupplierByUserDefineCode(context.Background(), req)
if err != nil {
log.Fatalf("查询供应商失败: %v", err)
}
fmt.Printf("查询供应商响应: invokeId=%s, bizType=%s\n", resp.InvokeID, resp.BizType)
}
```
=== SDK 生成完成 ===