update
This commit is contained in:
389
internal/api/client.go
Normal file
389
internal/api/client.go
Normal file
@@ -0,0 +1,389 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user