// File: go.mod ``` module intelligence_finance go 1.21 ``` // File: crypto.go ```go package intelligence_finance import ( "crypto/hmac" "crypto/rand" "crypto/sha256" "encoding/base64" "fmt" "math/big" "sort" "strings" "time" ) // GenerateTimestamp generates a Unix timestamp in seconds as a string. func GenerateTimestamp() string { return fmt.Sprintf("%d", time.Now().Unix()) } // GenerateTimestampMillis generates a Unix timestamp in milliseconds as a string. func GenerateTimestampMillis() string { return fmt.Sprintf("%d", time.Now().UnixMilli()) } // GenerateNonce generates a cryptographically secure random string of the given length. 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 "", fmt.Errorf("generate nonce: %w", err) } b[i] = charset[num.Int64()] } return string(b), nil } // HmacSHA256Base64 computes HmacSHA256 of the given data using the secret key, // and returns the result as a Base64-encoded string. 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 sorts parameters by key in dictionary order and concatenates // them as key=value&key2=value2, excluding empty values and the sign/signature fields. 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 concatenates parameters in the specified key order, // excluding empty values. 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: types.go ```go package intelligence_finance // ============================================================ // General API Response // ============================================================ // APIResponse is the general response wrapper returned by the platform APIs. type APIResponse struct { Code int `json:"code"` Msg string `json:"msg,omitempty"` Data map[string]interface{} `json:"data,omitempty"` } // ============================================================ // Interface 1: 订单开票接口 (Invoice Create) // ============================================================ // InvoiceCreateRequest is the request for creating an invoice order. type InvoiceCreateRequest 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 represents a single product/service line item in an invoice. 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"` } // InvoiceCreateResponse is the response for creating an invoice order. type InvoiceCreateResponse struct { Status int `json:"status"` ErrorMsg string `json:"errorMsg,omitempty"` DataList []InvoiceData `json:"dataList"` } // InvoiceData contains detailed information about a single invoice. 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"` PurchaserBankAcct 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"` SellerBankAcct 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 represents a product detail line within an invoice. 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"` } // ============================================================ // Interface 2: 开票状态查询 (Invoice Status Query) // ============================================================ // InvoiceStatusQueryRequest is the request for querying invoice status. type InvoiceStatusQueryRequest struct { OrderID string `json:"orderId"` } // InvoiceStatusQueryResponse is the response for querying invoice status. type InvoiceStatusQueryResponse struct { Status int `json:"status"` Message string `json:"message,omitempty"` Data []InvoiceData `json:"data"` } // ============================================================ // Interface 3: 创建付款单据 (Create Payment Order) // ============================================================ // CreatePaymentOrderRequest is the request for creating a payment order. type CreatePaymentOrderRequest 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 represents department information. type Department struct { Code string `json:"code,omitempty"` Name string `json:"name"` } // Customer represents customer information. type Customer struct { Code string `json:"code,omitempty"` Name string `json:"name"` } // Supplier represents supplier information. type Supplier struct { Code string `json:"code,omitempty"` Name string `json:"name"` } // Project represents project information. type Project struct { Code string `json:"code,omitempty"` Name string `json:"name"` } // Category represents income/expense category information. type Category struct { Code string `json:"code,omitempty"` Name string `json:"name"` } // Product represents product information. type Product struct { Code string `json:"code,omitempty"` Name string `json:"name"` } // Company represents enterprise entity information. type Company struct { Code string `json:"code,omitempty"` Name string `json:"name"` } // EnterpriseAccount represents enterprise account information. 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 represents recipient account information. type RecipientAccount struct { AccountCategory string `json:"accountCategory"` AccountType string `json:"accountType,omitempty"` CardNo string `json:"cardNo,omitempty"` AccountName string `json:"accountName,omitempty"` } // PaymentDetail represents a payment detail line item. 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 represents invoice information within a payment detail. type InvoiceInfo struct { InvoiceNo string `json:"invoiceNo,omitempty"` InvoiceCode string `json:"invoiceCode,omitempty"` } // CreatePaymentOrderResponse is the response for creating a payment order. type CreatePaymentOrderResponse struct { Code string `json:"code"` } // ============================================================ // Interface 4: 支付完成通知 (Payment Notification - Callback) // ============================================================ // PaymentNotificationData represents the payment notification data sent by the platform. type PaymentNotificationData 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 represents the payer's account information. type PayerAccountInfo struct { BankOpenDTO *BankOpenDTO `json:"bankOpenDTO,omitempty"` EnterpriseAccountCode string `json:"enterpriseAccountCode,omitempty"` AccountType string `json:"accountType,omitempty"` } // PayeeAccountInfo represents the payee's account information. type PayeeAccountInfo struct { BankOpenDTO *BankOpenDTO `json:"bankOpenDTO,omitempty"` } // BankOpenDTO represents bank account information. 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"` } // PaymentStatus constants. const ( PaymentStatusSuccess = "SUCCESS" PaymentStatusFail = "FAIL" PaymentStatusTerminate = "TERMINATE" PaymentStatusWaitPay = "WAIT_PAY" PaymentStatusPaying = "PAYING" PaymentStatusPartSucc = "PART_SUCCESS" PaymentStatusRefund = "REFUND" ) // Source constants for payment notifications. const ( SourceApproval = "approval" SourceOpenAPI = "openapi" ) // AccountType constants. const ( AccountTypeAlipay = "ALIPAY" AccountTypeBankCard = "BANKCARD" AccountTypeCorpBankCard = "CORP_BANK_CARD" AccountTypePersonalBankCard = "PERSONAL_BANK_CARD" ) // ============================================================ // Interface 5: 支付状态查询 (Payment Status Query) // ============================================================ // PaymentStatusQueryRequest is the request for querying payment status. type PaymentStatusQueryRequest struct { Code string `json:"code"` UserID string `json:"userId"` } // PaymentStatusQueryResponse is the response for querying payment status, // which has the same structure as PaymentNotificationData. type PaymentStatusQueryResponse struct { PaymentNotificationData } // ============================================================ // Generic Notification (Business Notification) // ============================================================ // NotificationRequest represents a generic notification request from the platform. type NotificationRequest struct { BizType string `json:"bizType"` BizID string `json:"bizId"` Data string `json:"data,omitempty"` } ``` // File: errors.go ```go package intelligence_finance import "fmt" // ErrorCode represents a numeric error code from the API. type ErrorCode int // Predefined error codes. const ( CodeSuccess ErrorCode = 0 ) // APIError represents an error returned by the platform API. type APIError struct { Code ErrorCode `json:"code"` Message string `json:"msg,omitempty"` } // Error implements the error interface. func (e *APIError) Error() string { return fmt.Sprintf("api error: code=%d, msg=%s", e.Code, e.Message) } // ErrInvalidResponse is returned when the API response cannot be parsed. type ErrInvalidResponse struct { Message string } // Error implements the error interface. func (e *ErrInvalidResponse) Error() string { return fmt.Sprintf("invalid response: %s", e.Message) } // ErrNetwork is returned when a network error occurs. type ErrNetwork struct { Err error } // Error implements the error interface. func (e *ErrNetwork) Error() string { return fmt.Sprintf("network error: %v", e.Err) } // Unwrap returns the underlying error. func (e *ErrNetwork) Unwrap() error { return e.Err } // ErrSigning is returned when a signing error occurs. type ErrSigning struct { Message string Err error } // Error implements the error interface. func (e *ErrSigning) Error() string { if e.Err != nil { return fmt.Sprintf("signing error: %s: %v", e.Message, e.Err) } return fmt.Sprintf("signing error: %s", e.Message) } // Unwrap returns the underlying error. func (e *ErrSigning) Unwrap() error { return e.Err } ``` // File: client.go ```go package intelligence_finance import ( "bytes" "context" "encoding/json" "fmt" "io" "net/http" "strings" ) // Default API paths - these can be customized after receiving the actual short codes. const ( defaultPathInvoiceCreate = "/api/invoice/create" defaultPathInvoiceStatusQuery = "/api/invoice/status" defaultPathPaymentCreate = "/api/payment/create" defaultPathPaymentStatusQuery = "/api/payment/status" ) // Client is the intelligence finance API client. type Client struct { baseURL string tenantID string clientID string clientSecret string httpClient *http.Client // Paths for each API endpoint (configurable after onboarding). pathInvoiceCreate string pathInvoiceStatusQuery string pathPaymentCreate string pathPaymentStatusQuery string } // ClientOption is a functional option for configuring the Client. type ClientOption func(*Client) // WithHTTPClient sets a custom HTTP client. func WithHTTPClient(httpClient *http.Client) ClientOption { return func(c *Client) { c.httpClient = httpClient } } // WithInvoiceCreatePath sets a custom path for the invoice create API. func WithInvoiceCreatePath(path string) ClientOption { return func(c *Client) { c.pathInvoiceCreate = path } } // WithInvoiceStatusQueryPath sets a custom path for the invoice status query API. func WithInvoiceStatusQueryPath(path string) ClientOption { return func(c *Client) { c.pathInvoiceStatusQuery = path } } // WithPaymentCreatePath sets a custom path for the payment create API. func WithPaymentCreatePath(path string) ClientOption { return func(c *Client) { c.pathPaymentCreate = path } } // WithPaymentStatusQueryPath sets a custom path for the payment status query API. func WithPaymentStatusQueryPath(path string) ClientOption { return func(c *Client) { c.pathPaymentStatusQuery = path } } // NewClient creates a new intelligence finance API client. // - baseURL: the base URL of the platform API (e.g., "https://api.example.com") // - tenantID: the tenant ID assigned by the platform // - clientID: the application client ID assigned by the platform // - clientSecret: the application client secret assigned by the platform 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{}, pathInvoiceCreate: defaultPathInvoiceCreate, pathInvoiceStatusQuery: defaultPathInvoiceStatusQuery, pathPaymentCreate: defaultPathPaymentCreate, pathPaymentStatusQuery: defaultPathPaymentStatusQuery, } for _, opt := range opts { opt(c) } return c } // doRequest sends an HTTP request with authentication headers and returns the raw response body. func (c *Client) doRequest(ctx context.Context, path string, request interface{}) ([]byte, error) { bodyBytes, err := json.Marshal(request) if err != nil { return nil, &ErrSigning{Message: "marshal request body", Err: err} } req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.baseURL+path, bytes.NewReader(bodyBytes)) if err != nil { return nil, &ErrNetwork{Err: fmt.Errorf("create request: %w", err)} } // Set standard headers req.Header.Set("Content-Type", "application/json") req.Header.Set("tenant-id", c.tenantID) req.Header.Set("client-id", c.clientID) // Generate and set signature headers timestamp := GenerateTimestamp() nonce, err := GenerateNonce(16) if err != nil { return nil, &ErrSigning{Message: "generate nonce", Err: err} } signature := HmacSHA256Base64(c.clientSecret, timestamp+nonce) 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 nil, &ErrNetwork{Err: fmt.Errorf("send request: %w", err)} } defer resp.Body.Close() respBody, err := io.ReadAll(resp.Body) if err != nil { return nil, &ErrNetwork{Err: fmt.Errorf("read response body: %w", err)} } if resp.StatusCode != http.StatusOK { return nil, &ErrInvalidResponse{ Message: fmt.Sprintf("unexpected status code %d: %s", resp.StatusCode, string(respBody)), } } return respBody, nil } // parseResponse parses the API response and extracts the data field. func parseResponse(body []byte, target interface{}) error { var apiResp APIResponse if err := json.Unmarshal(body, &apiResp); err != nil { return &ErrInvalidResponse{Message: fmt.Sprintf("unmarshal response: %v", err)} } if apiResp.Code != 0 { return &APIError{Code: ErrorCode(apiResp.Code), Message: apiResp.Msg} } if target != nil && apiResp.Data != nil { // Convert map to JSON then unmarshal into target dataBytes, err := json.Marshal(apiResp.Data) if err != nil { return &ErrInvalidResponse{Message: fmt.Sprintf("marshal data: %v", err)} } if err := json.Unmarshal(dataBytes, target); err != nil { return &ErrInvalidResponse{Message: fmt.Sprintf("unmarshal data: %v", err)} } } return nil } // parseResponseRaw parses the API response and returns the raw data field. func parseResponseRaw(body []byte) (map[string]interface{}, error) { var apiResp APIResponse if err := json.Unmarshal(body, &apiResp); err != nil { return nil, &ErrInvalidResponse{Message: fmt.Sprintf("unmarshal response: %v", err)} } if apiResp.Code != 0 { return nil, &APIError{Code: ErrorCode(apiResp.Code), Message: apiResp.Msg} } return apiResp.Data, nil } // ============================================================ // Interface 1: CreateInvoice - 订单开票接口 // ============================================================ // CreateInvoice submits an invoice creation request for an order. // It returns the invoice creation response containing status and invoice data. func (c *Client) CreateInvoice(ctx context.Context, req *InvoiceCreateRequest) (*InvoiceCreateResponse, error) { body, err := c.doRequest(ctx, c.pathInvoiceCreate, req) if err != nil { return nil, err } var result InvoiceCreateResponse if err := parseResponse(body, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // Interface 2: QueryInvoiceStatus - 开票状态查询接口 // ============================================================ // QueryInvoiceStatus queries the invoice status for a given order. // It returns the invoice status response containing the current status and invoice data. func (c *Client) QueryInvoiceStatus(ctx context.Context, req *InvoiceStatusQueryRequest) (*InvoiceStatusQueryResponse, error) { body, err := c.doRequest(ctx, c.pathInvoiceStatusQuery, req) if err != nil { return nil, err } var result InvoiceStatusQueryResponse if err := parseResponse(body, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // Interface 3: CreatePaymentOrder - 创建付款单据接口 // ============================================================ // CreatePaymentOrder creates a payment order. // It returns the response containing the unique payment order code. func (c *Client) CreatePaymentOrder(ctx context.Context, req *CreatePaymentOrderRequest) (*CreatePaymentOrderResponse, error) { body, err := c.doRequest(ctx, c.pathPaymentCreate, req) if err != nil { return nil, err } var result CreatePaymentOrderResponse if err := parseResponse(body, &result); err != nil { return nil, err } return &result, nil } // ============================================================ // Interface 4: Payment Notification Handler (平台回调客户接口) // ============================================================ // ParsePaymentNotification parses a payment notification request body // sent by the platform. This is used when the platform calls back to // the customer's system after a payment is completed. // // Usage example in an HTTP handler: // // func handler(w http.ResponseWriter, r *http.Request) { // body, _ := io.ReadAll(r.Body) // notification, err := ParsePaymentNotification(body) // if err != nil { // http.Error(w, "FAILED", http.StatusBadRequest) // return // } // // Process the notification... // w.Write([]byte("SUCCESS")) // } func ParsePaymentNotification(body []byte) (*PaymentNotificationData, error) { var notification PaymentNotificationData if err := json.Unmarshal(body, ¬ification); err != nil { return nil, &ErrInvalidResponse{Message: fmt.Sprintf("parse payment notification: %v", err)} } return ¬ification, nil } // ParseGenericNotification parses a generic notification request body // sent by the platform. The generic notification contains bizType, bizId, and data. func ParseGenericNotification(body []byte) (*NotificationRequest, error) { var notification NotificationRequest if err := json.Unmarshal(body, ¬ification); err != nil { return nil, &ErrInvalidResponse{Message: fmt.Sprintf("parse notification: %v", err)} } return ¬ification, nil } // ============================================================ // Interface 5: QueryPaymentStatus - 支付状态查询接口 // ============================================================ // QueryPaymentStatus queries the payment status for a given payment order. // The response has the same structure as PaymentNotificationData. func (c *Client) QueryPaymentStatus(ctx context.Context, req *PaymentStatusQueryRequest) (*PaymentStatusQueryResponse, error) { body, err := c.doRequest(ctx, c.pathPaymentStatusQuery, req) if err != nil { return nil, err } var result PaymentStatusQueryResponse if err := parseResponse(body, &result); err != nil { return nil, err } return &result, nil } ``` // File: example_test.go ```go package intelligence_finance_test import ( "context" "fmt" "log" "intelligence_finance" ) // ExampleClient_CreateInvoice demonstrates how to create an invoice. func ExampleClient_CreateInvoice() { // Create a new client client := intelligence_finance.NewClient( "https://api.example.com", "your-tenant-id", "your-client-id", "your-client-secret", ) ctx := context.Background() // Build the invoice create request req := &intelligence_finance.InvoiceCreateRequest{ OrderID: "ORD-2024-001", InvoiceType: 9, // 数电普票 Purchaser: "某某科技有限公司", TaxNum: "91110108MA01XXXXX", Phone: "13800138000", Email: "finance@example.com", ApplyPerson: "张三", Payee: "李四", Reviewer: "王五", Products: []intelligence_finance.InvoiceProduct{ { ProductName: "云服务器ECS", RevenueCode: "1010101010101010101", AmountIncludeTax: 1180.00, Unit: "台", Quantity: 1, TaxRate: 0.06, TaxSign: 1, }, }, } resp, err := client.CreateInvoice(ctx, req) if err != nil { log.Fatalf("CreateInvoice failed: %v", err) } fmt.Printf("Invoice status: %d\n", resp.Status) for _, inv := range resp.DataList { fmt.Printf("Invoice No: %s, Amount: %s\n", inv.InvoiceNo, inv.TotalIncludeTax) } } // ExampleClient_QueryInvoiceStatus demonstrates how to query invoice status. func ExampleClient_QueryInvoiceStatus() { client := intelligence_finance.NewClient( "https://api.example.com", "your-tenant-id", "your-client-id", "your-client-secret", ) ctx := context.Background() req := &intelligence_finance.InvoiceStatusQueryRequest{ OrderID: "ORD-2024-001", } resp, err := client.QueryInvoiceStatus(ctx, req) if err != nil { log.Fatalf("QueryInvoiceStatus failed: %v", err) } fmt.Printf("Status: %d, Message: %s\n", resp.Status, resp.Message) for _, inv := range resp.Data { fmt.Printf("Invoice No: %s\n", inv.InvoiceNo) } } // ExampleClient_CreatePaymentOrder demonstrates how to create a payment order. func ExampleClient_CreatePaymentOrder() { client := intelligence_finance.NewClient( "https://api.example.com", "your-tenant-id", "your-client-id", "your-client-secret", ) ctx := context.Background() req := &intelligence_finance.CreatePaymentOrderRequest{ Code: "PAY-2024-001", UserID: "user-001", Title: "采购付款-云服务器", Amount: "1180.00", Department: &intelligence_finance.Department{ Name: "技术部", }, Supplier: &intelligence_finance.Supplier{ Name: "某某云服务商", }, PaymentDetailList: []intelligence_finance.PaymentDetail{ { Amount: "1180.00", }, }, } resp, err := client.CreatePaymentOrder(ctx, req) if err != nil { log.Fatalf("CreatePaymentOrder failed: %v", err) } fmt.Printf("Payment order code: %s\n", resp.Code) } // ExampleClient_QueryPaymentStatus demonstrates how to query payment status. func ExampleClient_QueryPaymentStatus() { client := intelligence_finance.NewClient( "https://api.example.com", "your-tenant-id", "your-client-id", "your-client-secret", ) ctx := context.Background() req := &intelligence_finance.PaymentStatusQueryRequest{ Code: "PAY-2024-001", UserID: "user-001", } resp, err := client.QueryPaymentStatus(ctx, req) if err != nil { log.Fatalf("QueryPaymentStatus failed: %v", err) } fmt.Printf("Payment status: %s\n", resp.PaymentStatus) fmt.Printf("Payment time: %s\n", resp.PaymentTime) } // ExampleParsePaymentNotification demonstrates how to handle a payment notification // callback from the platform. func ExampleParsePaymentNotification() { // This is the body received from the platform's callback body := []byte(`{ "code": "PAY-2024-001", "instanceId": "inst-001", "corpId": "corp-123", "paymentStatus": "SUCCESS", "paymentTime": "2024-01-15 10:30:00", "userId": "user-001", "amount": "1180.00" }`) notification, err := intelligence_finance.ParsePaymentNotification(body) if err != nil { log.Fatalf("ParsePaymentNotification failed: %v", err) } fmt.Printf("Payment code: %s, Status: %s\n", notification.Code, notification.PaymentStatus) // In a real HTTP handler, respond with "SUCCESS" or "FAILED" // w.Write([]byte("SUCCESS")) } // ExampleClient_WithCustomOptions demonstrates how to create a client with custom options. func ExampleClient_WithCustomOptions() { client := intelligence_finance.NewClient( "https://api.example.com", "your-tenant-id", "your-client-id", "your-client-secret", intelligence_finance.WithInvoiceCreatePath("/custom/path/invoice/create"), intelligence_finance.WithInvoiceStatusQueryPath("/custom/path/invoice/status"), intelligence_finance.WithPaymentCreatePath("/custom/path/payment/create"), intelligence_finance.WithPaymentStatusQueryPath("/custom/path/payment/status"), ) _ = client // use the client as needed } ```