对于400错误,出现的原因大概有几个。
一:第一步确认postmen中发送的数据类型是json。比如Headers中Content-Type类型是application/json;或是前端代码Ajax中添加:contentType: 'application/json;charset=UTF-8';
二:确认postmen中发送的数据格式是否正确。postmen中经常有人有漏写一对“{}“或是缺少逗号,引号,冒号的小问,好在postmen会自动报错提示; 而在前端中你必须重新包装传入参数为JSON型。使用JSON.stringify(params)将params参数重新包装;
三:检查参数的类型是否一一对应;
四:对接接口时,有可能参数的值不匹配,比如说地址不符合实际要求时,可能返回400错误提示;
本人遇到的属于第四种情况,在检查完预报参数类型和数据格式之后,依然报400错误,后来发现是对方地址有验证,有实际的报错信息,但是我们得到的是400错误,怎么解决呢?
下面贴代码:
1.预报参数

//创建货件,设置请求参数
public ShipmentRequest SetRequest(Package package, PBUSPSConfig Config) { var model = new ShipmentRequest(); string[] address1 = new string[] { package.SenderAddress.Address };//发件地址
string[] address2 = new string[] { !string.IsNullOrWhiteSpace(package.ShippingAddress.Address)? package.ShippingAddress.Address:"", !string.IsNullOrWhiteSpace(package.ShippingAddress.Address2)? package.ShippingAddress.Address2:"" , !string.IsNullOrWhiteSpace(package.ShippingAddress.Address3) ? package.ShippingAddress.Address3:"" };//收件地址
foreach (var packageInfo in package.PackageInfos) { //1磅等于453.59克
double weights = Convert.ToDouble(packageInfo.Weight * 1000); //常衡盎司:重量单位。整体缩写为oz.av。 1盎司 = 28.350克
decimal Weight = Convert.ToDecimal(weights / 28.350);//重量转盎司
model.fromAddress = new Address() { company = package.SenderAddress.CompanyName, name = package.SenderAddress.FirstName, phone = !string.IsNullOrWhiteSpace(package.SenderAddress.PhoneNumber) ? package.SenderAddress.PhoneNumber : package.SenderAddress.Mobile, email = package.SenderAddress.Email, residential = false, addressLines = address1, cityTown = package.SenderAddress.City, stateProvince = package.SenderAddress.Province, postalCode = package.SenderAddress.PostalCode, countryCode = package.SenderAddress.CountryCode, }; model.toAddress = new Address() { company = package.ShippingAddress.CompanyName, name = package.ShippingAddress.FirstName, phone =!string.IsNullOrWhiteSpace(package.ShippingAddress.PhoneNumber)? package.ShippingAddress.PhoneNumber: package.ShippingAddress.Mobile, email = "", residential = false, addressLines = address2, cityTown = package.ShippingAddress.City, stateProvince = !string.IsNullOrWhiteSpace(localityProvincia) ? localityProvincia : package.ShippingAddress.Province, postalCode = package.ShippingAddress.PostalCode, countryCode = package.ShippingAddress.CountryCode, }; model.parcel = new parcel() { weight = new Weight() { unitOfMeasurement = "OZ",//度量单位
weight = Weight,//包裹的重量
}, dimension = new Dimension() { unitOfMeasurement = "IN", length=10, width=4, height=6, irregularParcelGirth = "20"//将此设置为不规则包裹的周长。周长是高度和宽度之和的两倍:
} }; model.rates = new rates[] { new rates() { carrier="NEWGISTICS", serviceId="PRCLSEL", parcelType="PKG", specialServices= new SpecialServices[]{ new SpecialServices() { specialServiceId="DelCon" }, new SpecialServices() { specialServiceId="NOTIFICATIONS", inputParameters=new InputParameters[] { new InputParameters(){ name="RECIPIENT_NOTIFICATION_TYPE", value="ON_DELIVER" }, new InputParameters(){ name="RECIPIENT_NOTIFICATION_EMAIL", value="widgets@example.com" } } } } } }; model.documents = new documents[] { new documents(){ type="SHIPPING_LABEL", contentType="URL", size="DOC_4X6", fileFormat="PDF", } }; model.shipmentOptions = new shipmentOptions[] { new shipmentOptions(){ name="SHIPPER_ID", value=Config.ShipperId, }, new shipmentOptions(){ name="IS_RECTANGULAR", value="false", }, new shipmentOptions(){ name="CLIENT_FACILITY_ID", value=Config.ClientFacilityId, }, new shipmentOptions(){ name="CARRIER_FACILITY_ID", value=Config.CarrierFacilityId, }, new shipmentOptions(){ name="NON_DELIVERY_OPTION", //大于一磅的包裹,就是这样的值ChangeServiceRequested, 小于一磅的,就空着,不填
value=weights > 453.59?"ChangeServiceRequested":"", } }; } return model; }
2.访问接口返回值

1 //创建货件,取返回参数 ShipmentResponse 2 public string GetResponse(ShipmentRequest ShipmentRequest, string access_token, PBUSPSConfig config) 3 { 4 var stopWatch = new Stopwatch(); 5 var Url = config.ForecastUrl + "/shippingservices/v1/shipments?includeDeliveryCommitment=true"; 6 var TransactionId = GenerateStringID(); 7 HttpWebRequest request = null; 8 if (Url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) 9 { 10 request = WebRequest.Create(Url) as HttpWebRequest; 11 request.ProtocolVersion = HttpVersion.Version11; 12 request.KeepAlive = false; 13 } 14 else 15 { 16 request = (HttpWebRequest)WebRequest.Create(Url); 17 } 18 request.Method = "POST"; 19 request.ContentType = "application/json"; 20 request.Accept = "application/json"; 21 request.AllowAutoRedirect = true; 22 request.Headers.Add("Authorization", "Bearer " + access_token); 23 request.Headers.Add("X-PB-TransactionId", TransactionId); 24 Stream myRequestStream = request.GetRequestStream(); 25 StreamWriter myStreamWriter = 26 new StreamWriter(myRequestStream, Encoding.GetEncoding("utf-8")); 27 var Ship = JsonConvert.SerializeObject(ShipmentRequest); 28 byte[] data = Encoding.UTF8.GetBytes(Ship); 29 SetCertificatePolicy(); 30 using (Stream requestStream = request.GetRequestStream()) 31 { 32 requestStream.Write(data, 0, data.Length); 33 } 34 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 35 { 36 Stream myResponseStream = response.GetResponseStream(); 37 StreamWriter myStreamReader = 38 new StreamWriter(myResponseStream, Encoding.GetEncoding("utf-8")); 39 using (StreamReader reader = new StreamReader(response.GetResponseStream())) 40 { 41 return reader.ReadToEnd(); 42 } 43 } 44 }
3.处理400错误

View Code
4.在得到具体的返回值之后,发现返回值是一个以中括号开头和结尾的字符串类型,添加一个实体类,映射返回值

1 public class Errors { 2 [JsonProperty("errorCode")] 3 public string errorCode { get; set; } 4 [JsonProperty("message")] 5 public string message { get; set; } 6 [JsonProperty("parameters")] 7 public string[] parameters { get; set; } 8 }
以上就是处理400参数的解决方案。
5.取Token

1 //获取Token 2 public static string GetToken(PBUSPSConfig Config, Encoding encoding) 3 { 4 if (encoding == null) 5 encoding = Encoding.UTF8; 6 //根据Key获取缓存中的Auth值 7 var cacheKey = "PBUSPSREQUESTTOKEN"; 8 var cacheResult = Cache.Get<string>(cacheKey); 9 10 if (!string.IsNullOrWhiteSpace(cacheResult)) 11 return cacheResult; 12 13 var stopWatch = new Stopwatch(); 14 var Key = Config.Key;//键 15 var Secret = Config.Secret;//值 16 var Token = ForecastHelper.Base64(Key, Secret); 17 var Url = Config.ForecastUrl + "/oauth/token"; 18 string paramStr = "grant_type=client_credentials"; 19 20 WebClient wc = new WebClient(); 21 // 采取POST方式必须加的Header 22 wc.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); 23 wc.Headers.Add("Authorization", "Basic " + Token); 24 byte[] postData = encoding.GetBytes(paramStr); 25 SetCertificatePolicy(); 26 byte[] responseData = wc.UploadData(Url, "POST", postData); // 得到返回字符流 27 string result = encoding.GetString(responseData);// 解码 28 if (result != null) 29 { 30 if (result.Contains("error")) 31 { 32 var OAuthError = SerializeUtil.FromJson<Error>(result); 33 return "服务商:" + OAuthError.errors[0].errorDescription; 34 } 35 else 36 { 37 var OAuthresult = SerializeUtil.FromJson<TokenResponse>(result); 38 var access_token = OAuthresult.access_token;//取Auth值 39 Cache.Add(cacheKey, access_token, 480); // 添加进缓存 有效时间8个小时 40 return access_token; 41 } 42 } 43 return "CMS:服务商返回为空"; 44 }
6.“基础连接已经关闭”的错误

1 private static void SetCertificatePolicy() 2 { 3 ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult); 4 // 这里设置了协议类型。 5 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Ssl3;// SecurityProtocolType.Tls1.2; 6 ServicePointManager.CheckCertificateRevocationList = true; 7 ServicePointManager.DefaultConnectionLimit = 100; 8 ServicePointManager.Expect100Continue = false; 9 } 10 private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) 11 { 12 return true; //总是接受 13 }