Files
wasm-go/internal/api/client.go
lychang 7f5350db62 update
2026-05-20 03:25:35 +08:00

390 lines
10 KiB
Go

package api
import (
"crypto/rand"
"crypto/tls"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"math/big"
"net/http"
"net/url"
"strconv"
"time"
"github.com/tjfoc/gmsm/sm2"
"github.com/tjfoc/gmsm/sm3"
)
// CompanyInfoService 公司信息查询服务
type CompanyInfoService struct {
httpClient *HTTPClient
userID string
privateKey string
}
// TaxHealthService 税务健康测评服务
type TaxHealthService struct {
httpClient *HTTPClient
userID string
privateKey string
}
// CompanyInfoRequest 公司信息查询请求
type CompanyInfoRequest struct {
Name string `json:"name"`
Apis []string `json:"apis"`
}
// CompanyInfoResponse 公司信息查询响应
type CompanyInfoResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data map[string]interface{} `json:"data"`
}
// TaxEvalRequest 税务测评请求
type TaxEvalRequest struct {
ReqNo string `json:"req_no"`
Callback string `json:"callback,omitempty"`
Detail TaxEvalDetail `json:"detail"`
}
// TaxEvalDetail 税务测评详情
type TaxEvalDetail struct {
FileURL string `json:"file_url,omitempty"`
Data map[string]interface{} `json:"data,omitempty"`
CompanyName string `json:"company_name"`
Period string `json:"period"`
Year string `json:"year"`
IsVerify bool `json:"is_verify,omitempty"`
CIT float64 `json:"cit"`
VAT float64 `json:"vat"`
InputVAT float64 `json:"input_vat"`
OutputVAT float64 `json:"output_vat"`
PreCIT float64 `json:"pre_cit"`
PreVAT float64 `json:"pre_vat"`
PreInputVAT float64 `json:"pre_input_vat"`
PreOutputVAT float64 `json:"pre_output_vat"`
}
// TaxEvalResponse 税务测评响应
type TaxEvalResponse struct {
Code int `json:"code"`
Message string `json:"msg"`
Data struct {
ReqNo string `json:"req_no"`
OrderNo string `json:"order_no"`
} `json:"data"`
}
// TaxEvalQueryResponse 查询税务测评结果响应
type TaxEvalQueryResponse struct {
Code int `json:"code"`
Message string `json:"msg"`
Data struct {
Status int `json:"status"`
Detail struct {
Files []string `json:"files"`
Error string `json:"error"`
} `json:"detail"`
} `json:"data"`
}
// NewCompanyInfoService 创建公司信息查询服务
func NewCompanyInfoService(userID, privateKey string) *CompanyInfoService {
tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
client := &http.Client{
Transport: tr,
Timeout: 30 * time.Second,
}
httpClient := &HTTPClient{Client: client}
return &CompanyInfoService{
httpClient: httpClient,
userID: userID,
privateKey: privateKey,
}
}
// NewTaxHealthService 创建税务健康测评服务
func NewTaxHealthService(userID, privateKey string) *TaxHealthService {
tr := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
client := &http.Client{
Transport: tr,
Timeout: 30 * time.Second,
}
httpClient := &HTTPClient{Client: client}
return &TaxHealthService{
httpClient: httpClient,
userID: userID,
privateKey: privateKey,
}
}
// GetCompanyInfo 查询公司信息
func (s *CompanyInfoService) GetCompanyInfo(companyName string, apis []string) (*CompanyInfoResponse, error) {
// 生成随机数和时间戳
r, _ := rand.Int(rand.Reader, big.NewInt(10000))
nonce := strconv.FormatInt(time.Now().UnixNano(), 36) + strconv.FormatInt(r.Int64(), 10)
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
// 构建查询参数
params := url.Values{}
params.Set("name", companyName)
params.Set("api", joinAPIParams(apis))
apiURL := "https://a.cmdp.cn/cmds/v1/company/info-rest/custom?" + params.Encode()
// 生成签名
signData := s.userID + timestamp + nonce + apiURL
signature, err := s.generateSignature([]byte(signData))
if err != nil {
return nil, fmt.Errorf("生成签名失败: %v", err)
}
// 设置请求头
headers := map[string]string{
"Accept": "application/json",
"x-gi-user-id": s.userID,
"x-gi-user-sig": signature,
"x-gi-nonce": nonce,
"x-gi-timestamp": timestamp,
}
// 发送GET请求
response, err := s.httpClient.Get(apiURL, headers)
if err != nil {
return nil, fmt.Errorf("发送请求失败: %v", err)
}
var result CompanyInfoResponse
err = json.Unmarshal(response, &result)
if err != nil {
return nil, fmt.Errorf("解析响应失败: %v", err)
}
return &result, nil
}
// EvaluateTaxHealth 执行税务健康测评
func (s *TaxHealthService) EvaluateTaxHealth(request TaxEvalRequest) (*TaxEvalResponse, error) {
// 生成随机数和时间戳
r, _ := rand.Int(rand.Reader, big.NewInt(10000))
nonce := strconv.FormatInt(time.Now().UnixNano(), 36) + strconv.FormatInt(r.Int64(), 10)
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
apiURL := "https://api.cmdp.cn/v1/eval/tax-risk"
// 序列化请求体
jsonData, err := json.Marshal(request)
fmt.Println(string(jsonData))
if err != nil {
return nil, fmt.Errorf("序列化请求体失败: %v", err)
}
// 生成签名
signData := s.userID + timestamp + nonce + apiURL + string(jsonData)
signature, err := s.generateSignature([]byte(signData))
if err != nil {
return nil, fmt.Errorf("生成签名失败: %v", err)
}
// 设置请求头
headers := map[string]string{
"Content-Type": "application/json",
"Accept": "application/json",
"x-gi-user-id": s.userID,
"x-gi-user-sig": signature,
"x-gi-nonce": nonce,
"x-gi-timestamp": timestamp,
}
// 发送POST请求
response, err := s.httpClient.Post(apiURL, jsonData, "application/json", headers)
fmt.Println(string(response))
if err != nil {
return nil, fmt.Errorf("发送请求失败: %v", err)
}
var result TaxEvalResponse
err = json.Unmarshal(response, &result)
if err != nil {
return nil, fmt.Errorf("解析响应失败: %v", err)
}
return &result, nil
}
// QueryTaxEvalResult 查询税务测评结果
func (s *TaxHealthService) QueryTaxEvalResult(orderNo string) (*TaxEvalQueryResponse, error) {
// 生成随机数和时间戳
r, _ := rand.Int(rand.Reader, big.NewInt(10000))
nonce := strconv.FormatInt(time.Now().UnixNano(), 36) + strconv.FormatInt(r.Int64(), 10)
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
apiURL := fmt.Sprintf("https://api.cmdp.cn/v1/eval/order/%s", orderNo)
// 生成签名
signData := s.userID + timestamp + nonce + apiURL
signature, err := s.generateSignature([]byte(signData))
if err != nil {
return nil, fmt.Errorf("生成签名失败: %v", err)
}
// 设置请求头
headers := map[string]string{
"Accept": "application/json",
"x-gi-user-id": s.userID,
"x-gi-user-sig": signature,
"x-gi-nonce": nonce,
"x-gi-timestamp": timestamp,
}
// 发送GET请求
response, err := s.httpClient.Get(apiURL, headers)
if err != nil {
return nil, fmt.Errorf("发送请求失败: %v", err)
}
var result TaxEvalQueryResponse
err = json.Unmarshal(response, &result)
if err != nil {
return nil, fmt.Errorf("解析响应失败: %v", err)
}
return &result, nil
}
// generateSignature 生成签名
func (s *CompanyInfoService) generateSignature(plainText []byte) (string, error) {
privateKey, err := parsePrivateKeyFromHex(s.privateKey)
if err != nil {
return "", fmt.Errorf("解析私钥失败: %v", err)
}
digest := sm3.Sm3Sum(plainText)
signature, err := privateKey.Sign(rand.Reader, digest, nil)
if err != nil {
return "", fmt.Errorf("签名失败: %v", err)
}
return base64.StdEncoding.EncodeToString(signature), nil
}
// generateSignature 生成签名
func (s *TaxHealthService) generateSignature(plainText []byte) (string, error) {
privateKey, err := parsePrivateKeyFromHex(s.privateKey)
if err != nil {
return "", fmt.Errorf("解析私钥失败: %v", err)
}
digest := sm3.Sm3Sum(plainText)
signature, err := privateKey.Sign(rand.Reader, digest, nil)
if err != nil {
return "", fmt.Errorf("签名失败: %v", err)
}
return base64.StdEncoding.EncodeToString(signature), nil
}
// parsePrivateKeyFromHex 从十六进制字符串解析私钥
func parsePrivateKeyFromHex(privateKeyHex string) (*sm2.PrivateKey, error) {
privateKeyBytes, err := hex.DecodeString(privateKeyHex)
if err != nil {
return nil, fmt.Errorf("解码私钥失败: %v", err)
}
d := new(big.Int).SetBytes(privateKeyBytes)
privateKey := &sm2.PrivateKey{
PublicKey: sm2.PublicKey{
Curve: sm2.P256Sm2(),
},
D: d,
}
privateKey.PublicKey.X, privateKey.PublicKey.Y = privateKey.PublicKey.Curve.ScalarBaseMult(d.Bytes())
return privateKey, nil
}
// joinAPIParams 连接API参数
func joinAPIParams(params []string) string {
result := ""
for i, param := range params {
if i > 0 {
result += ","
}
result += param
}
return result
}
// 使用示例
func ExampleUsage() {
// 替换为实际的用户ID和私钥
userID := "your_user_id"
privateKey := "your_private_key_hex"
// 创建公司信息查询服务
companyService := NewCompanyInfoService(userID, privateKey)
// 查询公司信息
companyInfo, err := companyService.GetCompanyInfo("深圳市致远速联信息技术有限公司", []string{"p_info", "p_biddings_all"})
if err != nil {
fmt.Printf("查询公司信息失败: %v\n", err)
} else {
fmt.Printf("公司信息查询结果: %+v\n", companyInfo)
}
// 创建税务健康测评服务
taxService := NewTaxHealthService(userID, privateKey)
// 准备税务测评请求数据
request := TaxEvalRequest{
ReqNo: "REQ001",
Detail: TaxEvalDetail{
CompanyName: "深圳市致远速联信息技术有限公司",
Period: "年度",
Year: "2024",
CIT: 100.0,
VAT: 50.0,
InputVAT: 30.0,
OutputVAT: 80.0,
PreCIT: 90.0,
PreVAT: 45.0,
PreInputVAT: 25.0,
PreOutputVAT: 70.0,
},
}
// 执行税务测评
evalResult, err := taxService.EvaluateTaxHealth(request)
if err != nil {
fmt.Printf("税务测评失败: %v\n", err)
} else {
fmt.Printf("税务测评提交结果: %+v\n", evalResult)
// 查询测评结果
if evalResult.Data.OrderNo != "" {
result, err := taxService.QueryTaxEvalResult(evalResult.Data.OrderNo)
if err != nil {
fmt.Printf("查询测评结果失败: %v\n", err)
} else {
fmt.Printf("测评结果: %+v\n", result)
}
}
}
}