海关179号通知对接C#完整源码
电子口岸抓取实时始数据流程
流程一:
- 电子口岸调用电商企业接口,通知其上传实时数据,接口参数含有订单ID和SessionID
- 电商企业响应请求,返回码为1000,告知电子口岸可以上传数据
流程二:
- 电商企业根据流程一的订单ID和SessionID生成上报数据
- 将数据通过websocket发送给ukey服务器,ukey服务器返回签名
- 将数据和签名url编码
- 上传给电子口岸
C#源码
namespace Admin.Controllers
{
public class PushController : Controller
{
/// <summary>
/// 等待海关请求的接口
/// </summary>
[HttpPost]
public JsonResult OpenRealTimeUpload(string openReq)
{
openReq = HttpUtility.UrlDecode(openReq, Encoding.UTF8);
var reqModel = JsonConvert.DeserializeObject<ServiceStack.Text.JsonObject>(openReq);
var pushPayInfoRecord = new
{
orderNo = reqModel.GetValueOrDefault("orderNo"),
sessionID = reqModel.GetValueOrDefault("sessionID"),
serviceTime = reqModel.GetValueOrDefault("serviceTime"),
};
GetPayInfo(pushPayInfoRecord);
return new JsonResult()
{
Data = new
{
code = 10000,
message = "",
serviceTime = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds
},
};
}
/// <summary>
/// 组装需要上传的数据
/// </summary>
private PushPayInfoModel GetPayInfo(PushPayInfoRecord pushPayInfoRecord)
{
var pushPayInfoModel = new PushPayInfoModel();
pushPayInfoModel.sessionID = pushPayInfoRecord.sessionID;
pushPayInfoModel.serviceTime = ((long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds).ToString();
pushPayInfoModel.certNo = pushSetting.certNo;
var payExchangeInfoHead = new PayExchangeInfoHead();
payExchangeInfoHead.guid = Guid.NewGuid().ToString();
payExchangeInfoHead.initalRequest = "test";
payExchangeInfoHead.initalResponse = "test";
payExchangeInfoHead.ebpCode = pushSetting.ebpCode;
payExchangeInfoHead.payCode = pushSetting.payCode;
payExchangeInfoHead.payTransactionId = "test";
payExchangeInfoHead.totalAmount = 1.0;
payExchangeInfoHead.currency = "142";
payExchangeInfoHead.verDept = pushSetting.verDept;
payExchangeInfoHead.payType = "3";
payExchangeInfoHead.tradingTime = DateTime.Now.ToString("yyyyMMddHHmmss");
payExchangeInfoHead.note = "test";
pushPayInfoModel.payExchangeInfoHead = payExchangeInfoHead;
var payExchangeInfoList = new List<PayExchangeInfoList>();
var orderItems = _orderService.GetOrderItemsByOrderId(long.Parse(pushPayInfoRecord.orderNo));
payExchangeInfoList.Add(new PayExchangeInfoList
{
orderNo = pushPayInfoRecord.orderNo,
recpAccount = pushSetting.recpAccount,
recpCode = pushSetting.recpCode,
recpName = pushSetting.recpName,
goodsInfo = orderItems.Select(item => new GoodsInfo
{
gname = item.ProductName,
itemLink = item.Link
}).ToList()
});
pushPayInfoModel.payExchangeInfoLists = payExchangeInfoList;
SignAndUpload(pushPayInfoModel, pushPayInfoRecord);
return pushPayInfoModel;
}
/// <summary>
/// 签名
/// </summary>
private void SignAndUpload(PushPayInfoModel pushPayInfoModel, PushPayInfoRecord pushPayInfoRecord)
{
string pushPayInfoStr = JsonConvert.SerializeObject(pushPayInfoModel);
// 移除第一个{号
pushPayInfoStr = pushPayInfoStr.Remove(0, 1);
// 移除签名节点
pushPayInfoStr = Regex.Replace(pushPayInfoStr, @",""certNo.+$", "");
// 插入||分隔符
pushPayInfoStr = Regex.Replace(pushPayInfoStr, @",(""payExchangeInfoHead"":)", "||$1\"");
pushPayInfoStr = Regex.Replace(pushPayInfoStr, @",(""payExchangeInfoLists"":)", "\"||$1\"");
pushPayInfoStr = Regex.Replace(pushPayInfoStr, @",(""serviceTime"":)", "\"||$1");
var websocket = new WebSocket("ws://127.0.0.1:61232");
websocket.Error += new EventHandler<SuperSocket.ClientEngine.ErrorEventArgs>((sender, e) =>
{
websocket.Close();
pushPayInfoRecord.signError = e.Exception.Message.Trim();
});
websocket.MessageReceived += new EventHandler<MessageReceivedEventArgs>((sender, e) =>
{
var message = e.Message.Trim();
var errorMessage = Regex.Match(message, @"Error"":\[(\S+)\]").Groups[1].Value;
if (message.Contains("握手成功"))
{
string strSendData = "{\"_method\":\"cus-sec_SpcSignDataAsPEM\",\"_id\":1,\"args\":{\"inData\":\"" + pushPayInfoStr.Replace("\"", "\\\"") + "\",\"passwd\":\"12345678\"}}";
websocket.Send(strSendData);
}
else if (errorMessage.Length > 0)
{
// 加签错误
websocket.Close();
pushPayInfoRecord.signError = errorMessage;
}
else
{
// 加签正确
websocket.Close();
pushPayInfoModel.signValue = Regex.Match(message, @"Data"":\[""(\S+?)""").Groups[1].Value;
UploadRealTimeData(pushPayInfoModel, pushPayInfoRecord);
}
});
websocket.Open();
}
/// <summary>
/// 上传实时数据
/// </summary>
public void UploadRealTimeData(PushPayInfoModel pushPayInfoModel, PushPayInfoRecord pushPayInfoRecord)
{
var dataJson = JsonConvert.SerializeObject(pushPayInfoModel);
var dataInfo = HttpUtility.UrlEncode(dataJson, Encoding.UTF8);
// 需要使用payExInfoStr=UrlEncodeDate的键值组成报文内容
var content = new StringContent("payExInfoStr=" + dataInfo, Encoding.UTF8, "application/x-www-form-urlencoded");
var client = new HttpClient();
var url = "https://customs.chinaport.gov.cn/ceb2grab/grab/realTimeDataUpload";
var response = client.PostAsync(url, content).GetAwaiter().GetResult();
pushPayInfoRecord.uploadRealTimeData = dataJson;
pushPayInfoRecord.uploadResponse = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
pushPayInfoRecord.uploadTime = DateTime.Now;
}
}
}