306 lines
6.9 KiB
Go
306 lines
6.9 KiB
Go
package main
|
||
|
||
import (
|
||
"bytes"
|
||
"crypto/aes"
|
||
"crypto/cipher"
|
||
"crypto/rand"
|
||
"encoding/base64"
|
||
"encoding/hex"
|
||
"encoding/json"
|
||
"fmt"
|
||
"io"
|
||
"net/http"
|
||
"time"
|
||
)
|
||
|
||
// ==================== 配置区域 ====================
|
||
// 请根据实际情况修改以下配置参数
|
||
|
||
const (
|
||
// API接口配置
|
||
InterfaceName = "XXXXXXXX" // 接口编号
|
||
AccessID = "XXXXXXXXXXX"
|
||
EncryptionKey = "XXXXXXXXXXXXXXXXXXXXX"
|
||
BaseURL = "https://api.tianyuanapi.com"
|
||
|
||
// 测试数据配置
|
||
TestName = "XXXXXXXX"
|
||
TestIDCard = "XXXXXXXXXXXXX"
|
||
TestMobileNo = "XXXXXXXXXXXXXXXXXXXX"
|
||
TestAuthDate = "20250318-20270318"
|
||
|
||
// HTTP请求配置
|
||
RequestTimeout = 30 * time.Second
|
||
)
|
||
|
||
// API响应结构体
|
||
type APIResponse struct {
|
||
Code int `json:"code"`
|
||
Message string `json:"message"`
|
||
Data string `json:"data"`
|
||
}
|
||
|
||
// 请求参数结构体
|
||
type RequestParams struct {
|
||
MobileNo string `json:"mobile_no"`
|
||
IDCard string `json:"id_card"`
|
||
AuthDate string `json:"auth_date"`
|
||
Name string `json:"name"`
|
||
}
|
||
|
||
// 请求载荷结构体
|
||
type RequestPayload struct {
|
||
Data string `json:"data"`
|
||
}
|
||
|
||
// 结果结构体
|
||
type Result struct {
|
||
Code int `json:"code"`
|
||
Success bool `json:"success"`
|
||
Message string `json:"message"`
|
||
EncryptedResponse string `json:"encrypted_response"`
|
||
DecryptedResponse interface{} `json:"decrypted_response"`
|
||
}
|
||
|
||
// ==================== AES加密解密方法 ====================
|
||
|
||
// AES CBC 加密函数,返回 Base64
|
||
func aesEncrypt(plaintext, key string) (string, error) {
|
||
keyBytes, err := hex.DecodeString(key)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
block, err := aes.NewCipher(keyBytes)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
// 生成随机IV
|
||
iv := make([]byte, aes.BlockSize)
|
||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||
return "", err
|
||
}
|
||
|
||
// 填充数据
|
||
paddedData := pkcs7Pad([]byte(plaintext), aes.BlockSize)
|
||
|
||
// 加密
|
||
ciphertext := make([]byte, len(iv)+len(paddedData))
|
||
copy(ciphertext, iv)
|
||
|
||
mode := cipher.NewCBCEncrypter(block, iv)
|
||
mode.CryptBlocks(ciphertext[len(iv):], paddedData)
|
||
|
||
return base64.StdEncoding.EncodeToString(ciphertext), nil
|
||
}
|
||
|
||
// AES CBC 解密函数,返回解密后的明文
|
||
func aesDecrypt(encryptedText, key string) (string, error) {
|
||
keyBytes, err := hex.DecodeString(key)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
ciphertext, err := base64.StdEncoding.DecodeString(encryptedText)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
block, err := aes.NewCipher(keyBytes)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
if len(ciphertext) < aes.BlockSize {
|
||
return "", fmt.Errorf("密文太短")
|
||
}
|
||
|
||
iv := ciphertext[:aes.BlockSize]
|
||
ciphertext = ciphertext[aes.BlockSize:]
|
||
|
||
if len(ciphertext)%aes.BlockSize != 0 {
|
||
return "", fmt.Errorf("密文长度不是块大小的倍数")
|
||
}
|
||
|
||
mode := cipher.NewCBCDecrypter(block, iv)
|
||
mode.CryptBlocks(ciphertext, ciphertext)
|
||
|
||
// 去除填充
|
||
unpaddedData, err := pkcs7Unpad(ciphertext)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
return string(unpaddedData), nil
|
||
}
|
||
|
||
// PKCS7填充
|
||
func pkcs7Pad(data []byte, blockSize int) []byte {
|
||
padding := blockSize - len(data)%blockSize
|
||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||
return append(data, padtext...)
|
||
}
|
||
|
||
// PKCS7去除填充
|
||
func pkcs7Unpad(data []byte) ([]byte, error) {
|
||
length := len(data)
|
||
if length == 0 {
|
||
return nil, fmt.Errorf("数据为空")
|
||
}
|
||
unpadding := int(data[length-1])
|
||
if unpadding > length {
|
||
return nil, fmt.Errorf("无效的填充")
|
||
}
|
||
return data[:length-unpadding], nil
|
||
}
|
||
|
||
// ==================== API调用方法 ====================
|
||
|
||
// 调用API函数
|
||
func callAPI(name, idCard, mobileNo, authDate string) *Result {
|
||
// 构建完整的API URL
|
||
url := fmt.Sprintf("%s/api/v1/%s", BaseURL, InterfaceName)
|
||
|
||
// 构建请求参数
|
||
params := RequestParams{
|
||
MobileNo: mobileNo,
|
||
IDCard: idCard,
|
||
AuthDate: authDate,
|
||
Name: name,
|
||
}
|
||
|
||
// 将参数转换为JSON字符串并加密
|
||
jsonStr, err := json.Marshal(params)
|
||
if err != nil {
|
||
return &Result{
|
||
Success: false,
|
||
Message: fmt.Sprintf("JSON序列化失败: %v", err),
|
||
}
|
||
}
|
||
|
||
fmt.Printf("请求参数: %s\n", string(jsonStr))
|
||
|
||
encryptedData, err := aesEncrypt(string(jsonStr), EncryptionKey)
|
||
if err != nil {
|
||
return &Result{
|
||
Success: false,
|
||
Message: fmt.Sprintf("加密失败: %v", err),
|
||
}
|
||
}
|
||
|
||
fmt.Printf("加密后的数据: %s\n", encryptedData)
|
||
|
||
// 构建请求载荷
|
||
payload := RequestPayload{
|
||
Data: encryptedData,
|
||
}
|
||
|
||
// 序列化请求载荷
|
||
requestBody, err := json.Marshal(payload)
|
||
if err != nil {
|
||
return &Result{
|
||
Success: false,
|
||
Message: fmt.Sprintf("请求载荷序列化失败: %v", err),
|
||
}
|
||
}
|
||
|
||
fmt.Printf("发送请求到: %s\n", url)
|
||
|
||
// 发送HTTP请求
|
||
client := &http.Client{
|
||
Timeout: RequestTimeout,
|
||
}
|
||
|
||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
|
||
if err != nil {
|
||
return &Result{
|
||
Success: false,
|
||
Message: fmt.Sprintf("创建请求失败: %v", err),
|
||
}
|
||
}
|
||
|
||
// 设置请求头
|
||
req.Header.Set("Access-Id", AccessID)
|
||
req.Header.Set("Content-Type", "application/json")
|
||
|
||
resp, err := client.Do(req)
|
||
if err != nil {
|
||
return &Result{
|
||
Success: false,
|
||
Message: fmt.Sprintf("请求失败: %v", err),
|
||
}
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
// 读取响应
|
||
respBody, err := io.ReadAll(resp.Body)
|
||
if err != nil {
|
||
return &Result{
|
||
Success: false,
|
||
Message: fmt.Sprintf("读取响应失败: %v", err),
|
||
}
|
||
}
|
||
|
||
// 解析响应
|
||
var apiResp APIResponse
|
||
if err := json.Unmarshal(respBody, &apiResp); err != nil {
|
||
return &Result{
|
||
Success: false,
|
||
Message: fmt.Sprintf("解析响应失败: %v", err),
|
||
}
|
||
}
|
||
|
||
fmt.Printf("API响应: %s\n", string(respBody))
|
||
|
||
// 处理响应
|
||
result := &Result{
|
||
Code: apiResp.Code,
|
||
Success: apiResp.Code == 0,
|
||
Message: apiResp.Message,
|
||
EncryptedResponse: apiResp.Data,
|
||
}
|
||
|
||
// 如果有返回data,尝试解密
|
||
if apiResp.Data != "" {
|
||
decryptedData, err := aesDecrypt(apiResp.Data, EncryptionKey)
|
||
if err != nil {
|
||
fmt.Printf("解密响应数据失败: %v\n", err)
|
||
result.DecryptedResponse = nil
|
||
} else {
|
||
var decryptedJSON interface{}
|
||
if err := json.Unmarshal([]byte(decryptedData), &decryptedJSON); err != nil {
|
||
fmt.Printf("解析解密后的JSON失败: %v\n", err)
|
||
result.DecryptedResponse = decryptedData
|
||
} else {
|
||
result.DecryptedResponse = decryptedJSON
|
||
}
|
||
}
|
||
}
|
||
|
||
return result
|
||
}
|
||
|
||
// ==================== 主程序 ====================
|
||
|
||
func main() {
|
||
fmt.Println("===== 个人涉诉详版 =====")
|
||
|
||
// 调用API
|
||
result := callAPI(TestName, TestIDCard, TestMobileNo, TestAuthDate)
|
||
|
||
fmt.Println("\n===== 结果 =====")
|
||
if result.Success {
|
||
fmt.Println("请求成功!")
|
||
if result.DecryptedResponse != nil {
|
||
decryptedJSON, _ := json.MarshalIndent(result.DecryptedResponse, "", " ")
|
||
fmt.Printf("解密后的响应: %s\n", string(decryptedJSON))
|
||
} else {
|
||
fmt.Println("未能获取或解密响应数据")
|
||
}
|
||
} else {
|
||
fmt.Printf("请求失败: %s\n", result.Message)
|
||
}
|
||
}
|