请教个问题,我们需要上传数据表内容,以json格式,传到指定的接口,具体要求如图,但在运行时总提示签名不正确,我问一下平台服务人员,告知是:在发送请求时候的 param参数 后面应该是一个 string类型的串,和 paramJson的值一致;


我的代码如下,方便时请指导一下
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OfficeOpenXml; // 注意安装 EPPLUS 时,选择低于 8.0 版本;
using OfficeOpenXml.FormulaParsing.Excel;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System.Globalization;
using System.Data.SqlClient;
namespace Interfacetest
{
public partial class Form1 : Form
{
private static readonly string ak = "d551";
private static readonly string sk = "fdafe";
private static string connectionString = "Data Source=192.168.1.2;Initial Catalog=WHOrganize;User ID=sa;Password=whyy@2021";
private static readonly HttpClient _httpClient = new HttpClient();
public Form1()
{
// 初始化 EPPlus
ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{ }
public class UploadRequest
{
public bool DEL_FLAG { get; set; }
public List<DrugInfo> DATA { get; set; }
}
public class DrugInfo
{
public string TRAC_CODG_SN { get; set; }
public string MED_LIST_CODG { get; set; }
public string NAT_DRUG_CODG { get; set; }
public string DRUG_GENNAME { get; set; }
public string DOSFORM { get; set; }
public string PREP_SPEC { get; set; }
public string PACSPEC { get; set; }
public decimal PAC_CONVRAT { get; set; }
public string PAC_CONVRAT_EMP { get; set; }
public string DRUG_MANU_LOTNUM { get; set; }
public string DRUG_MANU_DATE { get; set; }
public string DRUG_EXPY_ENDDATE { get; set; }
public string DRUG_APRVNO { get; set; }
public string DRUG_APRVNO_DATE { get; set; }
public string RX_FLAG { get; set; }
public string NAT_BAS_MEDN_FLAG { get; set; }
public decimal MANU_CNT { get; set; }
public string PRODENTP_NAME { get; set; }
public string PRODENTP_USCC { get; set; }
public string MANU_ADDR { get; set; }
public string DRUG_LV { get; set; }
public string PROD_CODE { get; set; }
}
private List<DrugInfo> ReadProductInfoFromDatabase()
{
var drugList = new List<DrugInfo>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string query = "SELECT batchNo as TRAC_CODG_SN,ICD as MED_LIST_CODG,NDC as NAT_DRUG_CODG" +
",productName as DRUG_GENNAME,type as DOSFORM ,spec as PREP_SPEC,packageSpec as PACSPEC" +
",packConvert as PAC_CONVRAT,packConUnit as PAC_CONVRAT_EMP,batchNo1 as DRUG_MANU_LOTNUM" +
",madeDate as DRUG_MANU_DATE,validateDate as DRUG_EXPY_ENDDATE,authorizedNo as DRUG_APRVNO" +
",dpndate as DRUG_APRVNO_DATE,drugFlag as RX_FLAG,NdrugFlag as NAT_BAS_MEDN_FLAG,amount as MANU_CNT" +
",company as PRODENTP_NAME, uscc as PRODENTP_USCC ,address as MANU_ADDR ,drugLevel as DRUG_LV,bcode as PROD_CODE" +
" FROM w_NdrugUpload";
using (SqlCommand command = new SqlCommand(query, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
var drug = new DrugInfo
{
TRAC_CODG_SN = reader["TRAC_CODG_SN"].ToString(),
MED_LIST_CODG = reader["MED_LIST_CODG"].ToString(),
NAT_DRUG_CODG = reader["NAT_DRUG_CODG"].ToString(),
DRUG_GENNAME = reader["DRUG_GENNAME"].ToString(),
DOSFORM = reader["DOSFORM"].ToString(),
PREP_SPEC = reader["PREP_SPEC"].ToString(),
PACSPEC = reader["PACSPEC"].ToString(),
PAC_CONVRAT = Convert.ToDecimal(reader["PAC_CONVRAT"]),
PAC_CONVRAT_EMP = reader["PAC_CONVRAT_EMP"].ToString(),
DRUG_MANU_LOTNUM = reader["DRUG_MANU_LOTNUM"].ToString(),
DRUG_MANU_DATE = ConvertToDateString(reader["DRUG_MANU_DATE"].ToString()),
DRUG_EXPY_ENDDATE = ConvertToDateString(reader["DRUG_EXPY_ENDDATE"].ToString()),
DRUG_APRVNO = reader["DRUG_APRVNO"].ToString(),
DRUG_APRVNO_DATE = ConvertToDateString(reader["DRUG_APRVNO_DATE"].ToString()),
RX_FLAG = reader["RX_FLAG"].ToString(),
NAT_BAS_MEDN_FLAG = reader["NAT_BAS_MEDN_FLAG"].ToString(),
MANU_CNT = Convert.ToDecimal(reader["MANU_CNT"]),
PRODENTP_NAME = reader["PRODENTP_NAME"].ToString(),
PRODENTP_USCC = reader["PRODENTP_USCC"].ToString(),
MANU_ADDR = reader["MANU_ADDR"].ToString(),
DRUG_LV = reader["DRUG_LV"].ToString(),
PROD_CODE = reader["PROD_CODE"].ToString()
};
drugList.Add(drug);
}
}
}
connection.Close();
}
return drugList;
}
private string ConvertToDateString(string input) // 解决日期问题
{
if (DateTime.TryParseExact(input, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
{
return date.ToString("yyyyMMdd");
}
return string.Empty;
}
private static async Task UploadProductsAsync(List<DrugInfo> products, bool delFlag = false)
{
try
{
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
var param = new { data = products };
string sign = GenerateSignature(ak, timestamp.ToString(), sk, param);
var uploadRequest = new UploadRequest
{
DEL_FLAG = delFlag,
DATA = products
};
var payload = new
{
ak,
timestamp,
sign,
param = uploadRequest
};
string jsonPayload = JsonConvert.SerializeObject(payload, new JsonSerializerSettings
{
DateFormatString = "yyyyMMdd"
});
StringContent content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");
// 打印请求日志
Console.WriteLine($"Request payload: {JsonConvert.SerializeObject(payload, Formatting.Indented)}");
var response = await _httpClient.PostAsync(
"https://drugtrac ed.nhsa.gov.cn/tb/traceability/micDrugInfo",
content);
var responseString = await response.Content.ReadAsStringAsync();
// 打印响应日志
Console.WriteLine($"Response: {responseString}");
// 增强响应处理
if (!response.IsSuccessStatusCode)
{
throw new Exception($"HTTP 错误: {response.StatusCode}\n响应内容: {responseString}");
}
// 解析业务响应
var result = JObject.Parse(responseString);
if (result["code"]?.ToString() != "0") // 根据实际成功码调整
{
throw new Exception($"业务错误: {result["message"]?.ToString()}");
}
}
catch (Exception ex)
{
// 记录详细错误日志
File.AppendAllText("error.log", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 错误: {ex}\n");
throw;
}
}
private static string GenerateSignature(string ak, string timestamp, string sk, object param)
{
string paramJson = JsonConvert.SerializeObject(param, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
// 确保签名拼接顺序正确
string rawString = $"{ak}{timestamp}{sk}{paramJson}";
using (SHA256 sha256 = SHA256.Create())
{
byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(rawString));
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
// 获取 Unix 时间戳(秒)
//long timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
//private static string GenerateSignature(string ak, string timestamp , string sk, object param)
//{
// // 序列化参数为 JSON 字符串
// string paramJson = JsonConvert.SerializeObject(param, new JsonSerializerSettings
// {
// Formatting = Formatting.None // 确保 JSON 字符串紧凑
// });
// Console.WriteLine("paramJson: " + paramJson); // 调试输出
// // 拼接签名字符串
// string rawString = $"{ak}{timestamp}{sk}{paramJson}";
// Console.WriteLine("rawString: " + rawString); // 调试输出
// // 生成 SHA256 签名
// using (SHA256 sha256 = SHA256.Create())
// {
// byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(rawString));
// string sign = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
// Console.WriteLine("sign: " + sign); // 调试输出
// return sign;
// }
//}
private async void button1_Click(object sender, EventArgs e)
{
try
{
var products = ReadProductInfoFromDatabase();
this.Cursor = Cursors.WaitCursor;
btnUp.Enabled = false;
await UploadProductsAsync(products);
MessageBox.Show("上传成功!请到平台验证数据",
"成功",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"上传失败:{ex.Message}",
"错误",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
finally
{
this.Cursor = Cursors.Default;
btnUp.Enabled = true;
}
}
private void btnquery_Click(object sender, EventArgs e)
{
}
}
}