Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
473 changes: 224 additions & 249 deletions README.md

Large diffs are not rendered by default.

Empty file modified icon.png
100755 → 100644
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<Copyright>Copyright © AfterShip</Copyright>
<AssemblyTitle>AfterShipTracking</AssemblyTitle>
<NeutralLanguage>en-US</NeutralLanguage>
<VersionPrefix>13.0.0</VersionPrefix>
<VersionPrefix>14.0.0</VersionPrefix>
<VersionSuffix>
</VersionSuffix>
<Authors>AfterShip</Authors>
Expand Down Expand Up @@ -44,8 +44,6 @@
</ItemGroup>

<ItemGroup>
<Folder Include="Adapter\" />
<Folder Include="Adapter\" />
<Folder Include="Exception\" />
<Folder Include="Models\" />
<Folder Include="Properties\" />
Expand Down
18 changes: 9 additions & 9 deletions src/AfterShipTracking/AfterShipTracking/AftershipClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ public class AfterShipClient

public IHttpClient HttpClient { get; }

public TrackingService Tracking { get; set; }
public CourierService Courier { get; set; }
public CourierConnectionService CourierConnection { get; set; }
public EstimatedDeliveryDateService EstimatedDeliveryDate { get; set; }
public TrackingService Tracking { get; set; }
public CourierService Courier { get; set; }
public AfterShipClient(
string domain = null,
string apiKey = null,
Expand Down Expand Up @@ -96,27 +96,27 @@ public AfterShipClient(

HttpClient = httpClient ?? new SystemNetHttpClient(this.ApiBase, authenticator, this.MaxRetry, this.Timeout, this.UserAgent,this.Proxy);

Tracking = new TrackingService(HttpClient);
Courier = new CourierService(HttpClient);
CourierConnection = new CourierConnectionService(HttpClient);
EstimatedDeliveryDate = new EstimatedDeliveryDateService(HttpClient);
Tracking = new TrackingService(HttpClient);
Courier = new CourierService(HttpClient);
}

private void CheckConfig()
{
if (string.IsNullOrEmpty(ApiKey))
{
throw ErrorCode.GenSDKError(ErrorCode.INVALID_API_KEY, "apiKey cannot be empty");
throw ErrorCode.GenSDKError(ErrorCode.INVALID_API_KEY, "Invalid API key");
}

if (this.Timeout < 0 || this.Timeout > 30000)
{
throw ErrorCode.GenSDKError(ErrorCode.INVALID_OPTION, "timeout invalid, timeout must between 0 and 30000 (milliseconds)");
throw ErrorCode.GenSDKError(ErrorCode.INVALID_OPTION, "Invalid option: Timeout");
}

if (this.MaxRetry < 0 || this.MaxRetry > 10)
{
throw ErrorCode.GenSDKError(ErrorCode.INVALID_OPTION, "max retry invalid, max retry must between 0 and 10");
throw ErrorCode.GenSDKError(ErrorCode.INVALID_OPTION, "Invalid option: MaxRetry");
}

string[] array = {
Expand All @@ -127,14 +127,14 @@ private void CheckConfig()
var authenticationType = AuthenticationType;
if (!array.Contains(authenticationType))
{
throw ErrorCode.GenSDKError(ErrorCode.INVALID_OPTION, "Invalid option: authenticationType should be one of API_KEY, AES, RSA");
throw ErrorCode.GenSDKError(ErrorCode.INVALID_OPTION, "Invalid option: AuthenticationType");
}

if (authenticationType == AfterShipConfiguration.AUTHENTICATION_TYPE_AES || authenticationType == AfterShipConfiguration.AUTHENTICATION_TYPE_AES)
{
if (string.IsNullOrEmpty(ApiSecret))
{
throw ErrorCode.GenSDKError(ErrorCode.INVALID_API_KEY, "Invalid option: apiSecret cannot be empty");
throw ErrorCode.GenSDKError(ErrorCode.INVALID_OPTION, "Invalid option: ApiSecret");
}
}
}
Expand Down
47 changes: 7 additions & 40 deletions src/AfterShipTracking/AfterShipTracking/Exception/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ namespace AfterShipTracking
{
public class ErrorCode
{
public const string REQUEST_ERROR = "REQUEST_ERROR";

// Common AfterShipError
public const string INVALID_API_KEY = "INVALID_API_KEY";
public const string INVALID_OPTION = "INVALID_OPTION";
public const string RATE_LIMIT_EXCEEDED = "RATE_LIMIT_EXCEEDED";
public const string BAD_REQUEST = "BAD_REQUEST";
public const string RATE_LIMIT_EXCEED = "RATE_LIMIT_EXCEED";
public const string TIMED_OUT = "TIMED_OUT";

// API error
public const string UNKNOWN_ERROR = "UNKNOWN_ERROR";
public const string INVALID_REQUEST = "INVALID_REQUEST";
public const string INVALID_JSON = "INVALID_JSON";
public const string TRACKING_ALREADY_EXIST = "TRACKING_ALREADY_EXIST";
Expand All @@ -30,7 +27,7 @@ public class ErrorCode
public const string MISSING_OR_INVALID_REQUIRED_FIELD = "MISSING_OR_INVALID_REQUIRED_FIELD";
public const string BAD_COURIER = "BAD_COURIER";
public const string INACTIVE_RETRACK_NOT_ALLOWED = "INACTIVE_RETRACK_NOT_ALLOWED";
public const string NOTIFICATION_REUQIRED = "NOTIFICATION_REUQIRED";
public const string NOTIFICATION_REQUIRED = "NOTIFICATION_REQUIRED";
public const string ID_INVALID = "ID_INVALID";
public const string RETRACK_ONCE_ALLOWED = "RETRACK_ONCE_ALLOWED";
public const string TRACKING_NUMBER_FORMAT_INVALID = "TRACKING_NUMBER_FORMAT_INVALID";
Expand All @@ -55,7 +52,7 @@ public class ErrorCode
{ 4011, MISSING_OR_INVALID_REQUIRED_FIELD },
{ 4012, BAD_COURIER },
{ 4013, INACTIVE_RETRACK_NOT_ALLOWED },
{ 4014, NOTIFICATION_REUQIRED },
{ 4014, NOTIFICATION_REQUIRED },
{ 4015, ID_INVALID },
{ 4016, RETRACK_ONCE_ALLOWED },
{ 4017, TRACKING_NUMBER_FORMAT_INVALID },
Expand All @@ -69,36 +66,6 @@ public class ErrorCode
{ 504, INTERNAL_ERROR },
};

private static Dictionary<string, string> errorMessageMap = new Dictionary<string, string>
{
{ INVALID_API_KEY, "Invalid API key" },
{ INVALID_OPTION, "Invalid option" },
{ RATE_LIMIT_EXCEEDED, "You have exceeded the API call rate limit. The default limit is 10 requests per second." },
{ TIMED_OUT, "Request timed out" },
{ INVALID_REQUEST, "The request was invalid or cannot be otherwise served."},
{ INVALID_JSON, "Invalid JSON data."},
{ TRACKING_ALREADY_EXIST, "Tracking already exists."},
{ TRACKING_DOES_NOT_EXIST, "Tracking does not exist."},
{ TRACKING_NUMBER_INVALID, "The value of tracking_number is invalid."},
{ TRACKING_REQUIRED, "tracking object is required."},
{ TRACKING_NUMBER_REQUIRED, "tracking_number is required."},
{ VALUE_INVALID, "The value of [field_name] is invalid."},
{ VALUE_REQUIRED, "[field_name] is required."},
{ SLUG_INVALID, "The value of slug is invalid."},
{ MISSING_OR_INVALID_REQUIRED_FIELD, "Missing or invalid value of the required fields for this courier. Besides tracking_number, also required: [field_name]"},
{ BAD_COURIER, "The error message will be one of the following:1. Unable to import shipment as the carrier is not on your approved list for carrier auto-detection. Add the carrier here: https://admin.aftership.com/settings/couriers2. Unable to import shipment as we don’t recognize the carrier from this tracking number.3. Unable to import shipment as the tracking number has an invalid format.4. Unable to import shipment as this carrier is no longer supported.5. Unable to import shipment as the tracking number does not belong to a carrier in that group."},
{ INACTIVE_RETRACK_NOT_ALLOWED, "Retrack is not allowed. You can only retrack an inactive tracking."},
{ NOTIFICATION_REUQIRED, "notification object is required."},
{ ID_INVALID, "The value of id is invalid."},
{ RETRACK_ONCE_ALLOWED, "Retrack is not allowed. You can only retrack each shipment once."},
{ TRACKING_NUMBER_FORMAT_INVALID, "The format of tracking_number is invalid."},
{ API_KEY_INVALID, "The API Key is invalid."},
{ REQUEST_NOT_ALLOWED, "The request is understood, but it has been refused or access is not allowed."},
{ NOT_FOUND, "The URI requested is invalid or the resource requested does not exist."},
{ TOO_MANY_REQUEST, "You have exceeded the API call rate limit. The default limit is 10 requests per second."},
{ INTERNAL_ERROR, "Something went wrong on AfterShip's end."},
};

public static AfterShipError GenAPIError(int statusCode, int metaCode, string responseBody = null, string message = null, object responseHeader= null)
{
string errorCode = LocateErrorCode(metaCode);
Expand All @@ -114,7 +81,7 @@ public static AfterShipError GenError(string errorCode, int? statusCode, int? me
{
if (string.IsNullOrEmpty(message))
{
message = errorMessageMap.GetValueOrDefault(errorCode) ?? "Unknown error";
message = "Unknown error";
}
return new AfterShipError(message, errorCode, statusCode, metaCode, responseBody, responseHeader);
}
Expand All @@ -125,7 +92,7 @@ private static string LocateErrorCode(int metaCode)
{
return errorMap[metaCode];
}
return INVALID_REQUEST;
return UNKNOWN_ERROR;
}
}
}
108 changes: 26 additions & 82 deletions src/AfterShipTracking/AfterShipTracking/Models/Checkpoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,146 +16,90 @@ public class Checkpoint
/// <summary>
/// CreatedAt The date and time of the checkpoint event was added to AfterShip. It uses the format `YYYY-MM-DDTHH:mm:ssZ` for the timezone GMT +0.
/// </summary>
[JsonProperty("created_at",NullValueHandling = NullValueHandling.Ignore)]
public string? CreatedAt { get; set; }
[JsonProperty("created_at")]
public string CreatedAt { get; set; }
/// <summary>
/// Slug The unique code of courier for this checkpoint. Get courier slug
/// </summary>
[JsonProperty("slug",NullValueHandling = NullValueHandling.Ignore)]
public string? Slug { get; set; }
[JsonProperty("slug")]
public string Slug { get; set; }
/// <summary>
/// CheckpointTime The date and time of the checkpoint event, provided by the carrier. It uses the timezone of the checkpoint. The format may differ depending on how the carrier provides it:- YYYY-MM-DDTHH:mm:ss- YYYY-MM-DDTHH:mm:ssZ
/// </summary>
[JsonProperty("checkpoint_time",NullValueHandling = NullValueHandling.Ignore)]
public string? CheckpointTime { get; set; }
[JsonProperty("checkpoint_time")]
public string CheckpointTime { get; set; }
/// <summary>
/// Location Location info provided by carrier
/// </summary>
[JsonProperty("location",NullValueHandling = NullValueHandling.Ignore)]
[JsonProperty("location")]
public string? Location { get; set; }
/// <summary>
/// City City info provided by carrier
/// </summary>
[JsonProperty("city",NullValueHandling = NullValueHandling.Ignore)]
[JsonProperty("city")]
public string? City { get; set; }
/// <summary>
/// State State info provided by carrier
/// </summary>
[JsonProperty("state",NullValueHandling = NullValueHandling.Ignore)]
[JsonProperty("state")]
public string? State { get; set; }
/// <summary>
/// Zip Postal code info provided by carrier
/// </summary>
[JsonProperty("zip",NullValueHandling = NullValueHandling.Ignore)]
[JsonProperty("zip")]
public string? Zip { get; set; }
/// <summary>
/// Coordinate The latitude and longitude coordinates indicate the precise location of the shipments that are currently in transit.
/// </summary>
[JsonProperty("coordinate",NullValueHandling = NullValueHandling.Ignore)]
public CoordinateCheckpoint? Coordinate { get; set; }
[JsonProperty("coordinate")]
public CheckpointCoordinate? Coordinate { get; set; }
/// <summary>
/// CountryRegion Country/Region ISO Alpha-3 (three letters) of the checkpoint
/// </summary>
[JsonProperty("country_region",NullValueHandling = NullValueHandling.Ignore)]
[JsonProperty("country_region")]
public string? CountryRegion { get; set; }
/// <summary>
/// CountryRegionName Country/Region name of the checkpoint, may also contain other location info.
/// </summary>
[JsonProperty("country_region_name",NullValueHandling = NullValueHandling.Ignore)]
[JsonProperty("country_region_name")]
public string? CountryRegionName { get; set; }
/// <summary>
/// Message Checkpoint message
/// </summary>
[JsonProperty("message",NullValueHandling = NullValueHandling.Ignore)]
public string? Message { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
/// <summary>
/// Tag Current status of tracking. (
/// </summary>
[JsonProperty("tag",NullValueHandling = NullValueHandling.Ignore)]
[JsonProperty("tag")]
public Tag? Tag { get; set; }
/// <summary>
/// Subtag Current subtag of checkpoint. (
/// </summary>
[JsonProperty("subtag",NullValueHandling = NullValueHandling.Ignore)]
public string? Subtag { get; set; }
[JsonProperty("subtag")]
public string Subtag { get; set; }
/// <summary>
/// SubtagMessage Normalized checkpoint message. (
/// </summary>
[JsonProperty("subtag_message",NullValueHandling = NullValueHandling.Ignore)]
public string? SubtagMessage { get; set; }
[JsonProperty("subtag_message")]
public string SubtagMessage { get; set; }
/// <summary>
/// RawTag Checkpoint raw status provided by courier
/// </summary>
[JsonProperty("raw_tag",NullValueHandling = NullValueHandling.Ignore)]
[JsonProperty("raw_tag")]
public string? RawTag { get; set; }
/// <summary>
/// Events The array provides details about specific event(s) that occurred to a shipment, such as "returned_to_sender". You can find the full list of events and reasons </span>- The events' value for the same checkpoint message is subject to change as we consistently strive to enhance the performance of this feature.
/// </summary>
[JsonProperty("events",NullValueHandling = NullValueHandling.Ignore)]
public EventsCheckpoint? [] Events { get; set; }
[JsonProperty("events")]
public CheckpointEvents [] Events { get; set; }
/// <summary>
/// Source The source of the checkpoint, which can either be from the carrier or when the user marks the tracking as completed.
/// </summary>
[JsonProperty("source",NullValueHandling = NullValueHandling.Ignore)]
public string? Source { get; set; }
[JsonProperty("source")]
public CheckpointSource? Source { get; set; }
public Checkpoint()
{
}
}

/// <summary>
///
/// </summary>
public class CoordinateCheckpoint
{
/// <summary>
/// Latitude Represents the latitude.
/// </summary>
[JsonProperty("latitude",NullValueHandling = NullValueHandling.Ignore)]
public double? Latitude { get; set; }
/// <summary>
/// Longitude Represents the longitude.
/// </summary>
[JsonProperty("longitude",NullValueHandling = NullValueHandling.Ignore)]
public double? Longitude { get; set; }

public CoordinateCheckpoint()
{
}
}
/// <summary>
///
/// </summary>
public class ReasonEventsCheckpoint
{
/// <summary>
/// Code The code of the reason.
/// </summary>
[JsonProperty("code",NullValueHandling = NullValueHandling.Ignore)]
public string? Code { get; set; }

public ReasonEventsCheckpoint()
{
}
}
/// <summary>
///
/// </summary>
public class EventsCheckpoint
{
/// <summary>
/// Code Represents the event code.
/// </summary>
[JsonProperty("code",NullValueHandling = NullValueHandling.Ignore)]
public string? Code { get; set; }
/// <summary>
/// Reason Describes the specific reason that led to the event.
/// </summary>
[JsonProperty("reason",NullValueHandling = NullValueHandling.Ignore)]
public ReasonEventsCheckpoint? Reason { get; set; }

public EventsCheckpoint()
{
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* This code was auto generated by AfterShip SDK Generator.
* Do not edit the class manually.
*/
using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace AfterShipTracking
{
/// <summary>
/// The latitude and longitude coordinates indicate the precise location of the shipments that are currently in transit.
/// </summary>
public class CheckpointCoordinate
{
/// <summary>
/// Latitude Represents the latitude.
/// </summary>
[JsonProperty("latitude")]
public double Latitude { get; set; }
/// <summary>
/// Longitude Represents the longitude.
/// </summary>
[JsonProperty("longitude")]
public double Longitude { get; set; }
public CheckpointCoordinate()
{
}
}
}
Loading