py-canada-post 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- py_canada_post/__init__.py +6 -0
- py_canada_post/__main__.py +4 -0
- py_canada_post/cli/__init__.py +0 -0
- py_canada_post/cli/app.py +32 -0
- py_canada_post/cli/rating/__init__.py +1 -0
- py_canada_post/cli/rating/commands/__init__.py +0 -0
- py_canada_post/cli/rating/commands/discover_services.py +54 -0
- py_canada_post/cli/rating/commands/get_rates.py +154 -0
- py_canada_post/cli/rating/rating_app.py +12 -0
- py_canada_post/client.py +113 -0
- py_canada_post/exceptions/__init__.py +37 -0
- py_canada_post/exceptions/exception_map.py +138 -0
- py_canada_post/exceptions/exceptions.py +150 -0
- py_canada_post/services/__init__.py +0 -0
- py_canada_post/services/rating/__init__.py +31 -0
- py_canada_post/services/rating/operations/__init__.py +0 -0
- py_canada_post/services/rating/operations/discover_services.py +131 -0
- py_canada_post/services/rating/operations/get_rates.py +259 -0
- py_canada_post/services/rating/rating.py +51 -0
- py_canada_post/services/rating/types.py +364 -0
- py_canada_post/utils/__init__.py +0 -0
- py_canada_post/utils/construct_xml_element.py +160 -0
- py_canada_post/utils/error_handler.py +43 -0
- py_canada_post/utils/response_to_object/__init__.py +0 -0
- py_canada_post/utils/response_to_object/response_to_object.py +222 -0
- py_canada_post/utils/response_to_object/serialization/__init__.py +0 -0
- py_canada_post/utils/response_to_object/serialization/rate_to_object.py +212 -0
- py_canada_post/utils/response_to_object/serialization/service_to_object.py +58 -0
- py_canada_post-1.0.0.dist-info/METADATA +261 -0
- py_canada_post-1.0.0.dist-info/RECORD +33 -0
- py_canada_post-1.0.0.dist-info/WHEEL +4 -0
- py_canada_post-1.0.0.dist-info/entry_points.txt +2 -0
- py_canada_post-1.0.0.dist-info/licenses/LICENSE +21 -0
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from importlib.metadata import version
|
|
2
|
+
|
|
3
|
+
from cyclopts import App
|
|
4
|
+
|
|
5
|
+
from .rating import rating_app
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def version_callback() -> str:
|
|
9
|
+
"""
|
|
10
|
+
Function to get a version of the wrapper.
|
|
11
|
+
|
|
12
|
+
Returns
|
|
13
|
+
-------
|
|
14
|
+
str
|
|
15
|
+
Version of the wrapper.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
return version('py_canada_post')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
app = App(
|
|
22
|
+
name="py-canada-post",
|
|
23
|
+
help="Python wrapper to interact with Canada Post API.",
|
|
24
|
+
version_format="rich",
|
|
25
|
+
version_flags=["--version", "-v"],
|
|
26
|
+
version=version_callback,
|
|
27
|
+
help_format="rich",
|
|
28
|
+
)
|
|
29
|
+
app.command(rating_app)
|
|
30
|
+
|
|
31
|
+
if __name__ == "__main__":
|
|
32
|
+
app()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .rating_app import rating_app
|
|
File without changes
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
from typing import Annotated
|
|
2
|
+
|
|
3
|
+
from cyclopts import Parameter, App
|
|
4
|
+
|
|
5
|
+
from py_canada_post.client import PyCanadaPost
|
|
6
|
+
from py_canada_post.services.rating.types import Service
|
|
7
|
+
|
|
8
|
+
client = PyCanadaPost.from_env()
|
|
9
|
+
|
|
10
|
+
discover_services = App(
|
|
11
|
+
name="discover-services",
|
|
12
|
+
help="Command to get available services."
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@discover_services.command
|
|
17
|
+
def discover_services(
|
|
18
|
+
country_code: Annotated[
|
|
19
|
+
str,
|
|
20
|
+
Parameter(name=["country-code", "-c"], required=True)
|
|
21
|
+
],
|
|
22
|
+
origin_postal_code: Annotated[
|
|
23
|
+
str,
|
|
24
|
+
Parameter(name=["origin-postal-code", "-o"], required=False)
|
|
25
|
+
] = None,
|
|
26
|
+
destination_postal_code: Annotated[
|
|
27
|
+
str,
|
|
28
|
+
Parameter(name=["destination-postal-code", "-d"], required=False)
|
|
29
|
+
] = None
|
|
30
|
+
) -> list[Service] | None:
|
|
31
|
+
"""
|
|
32
|
+
Command to get available services.
|
|
33
|
+
|
|
34
|
+
Parameters
|
|
35
|
+
----------
|
|
36
|
+
country_code : str
|
|
37
|
+
Country code in a 2-letter format (e.g. JP, CA, US).
|
|
38
|
+
origin_postal_code : str, optional
|
|
39
|
+
Origin postal code where the package will be sent from.
|
|
40
|
+
destination_postal_code : str, optional
|
|
41
|
+
Destination postal code where the package will be delivered to.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
list[Service] | None
|
|
46
|
+
List of services or None.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
services = client.rating.services.discover_services(
|
|
50
|
+
country_code,
|
|
51
|
+
origin_postal_code,
|
|
52
|
+
destination_postal_code
|
|
53
|
+
)
|
|
54
|
+
return services
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Annotated, Literal
|
|
3
|
+
|
|
4
|
+
from cyclopts import Parameter, App
|
|
5
|
+
|
|
6
|
+
from py_canada_post.client import PyCanadaPost
|
|
7
|
+
from py_canada_post.services.rating.types import Destination, Option, ParcelCharacteristics, Rate
|
|
8
|
+
|
|
9
|
+
client = PyCanadaPost.from_env()
|
|
10
|
+
|
|
11
|
+
get_rates = App(
|
|
12
|
+
name="get-rates",
|
|
13
|
+
help="Command to get rates."
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@get_rates.command
|
|
18
|
+
def get_rates(
|
|
19
|
+
origin_postal_code: Annotated[
|
|
20
|
+
str,
|
|
21
|
+
Parameter(name=["origin-postal-code", "-o"], required=True)
|
|
22
|
+
],
|
|
23
|
+
destination: Annotated[
|
|
24
|
+
Destination,
|
|
25
|
+
Parameter(name=["destination", "-d"], required=True)
|
|
26
|
+
],
|
|
27
|
+
promo_code: Annotated[
|
|
28
|
+
str,
|
|
29
|
+
Parameter(name=["promo-code", "-p"], required=False)
|
|
30
|
+
] = None,
|
|
31
|
+
quote_type: Annotated[
|
|
32
|
+
Literal["commercial", "counter"],
|
|
33
|
+
Parameter(name=["quote-type", "-q"], required=False)
|
|
34
|
+
] = "commercial",
|
|
35
|
+
expected_mailing_date: Annotated[
|
|
36
|
+
datetime,
|
|
37
|
+
Parameter(name=["expected-mailing-date", "-m"], required=False)
|
|
38
|
+
] = None,
|
|
39
|
+
options: Annotated[
|
|
40
|
+
list[Option],
|
|
41
|
+
Parameter(name=["options", "-O"], required=False, consume_multiple=True)
|
|
42
|
+
] = None,
|
|
43
|
+
parcel_characteristics: Annotated[
|
|
44
|
+
ParcelCharacteristics,
|
|
45
|
+
Parameter(name=["parcel-characteristics", "-c"], required=False)
|
|
46
|
+
] = None,
|
|
47
|
+
unpackaged: Annotated[
|
|
48
|
+
bool,
|
|
49
|
+
Parameter(name=["unpackaged", "-u"], required=False)
|
|
50
|
+
] = False,
|
|
51
|
+
mailing_tube: Annotated[
|
|
52
|
+
bool,
|
|
53
|
+
Parameter(name=["mailing-tube", "-t"], required=False)
|
|
54
|
+
] = False,
|
|
55
|
+
oversized: Annotated[
|
|
56
|
+
bool,
|
|
57
|
+
Parameter(name=["oversized", "-z"], required=False)
|
|
58
|
+
] = False,
|
|
59
|
+
services: Annotated[
|
|
60
|
+
list[Literal[
|
|
61
|
+
"DOM.RP",
|
|
62
|
+
"DOM.EP",
|
|
63
|
+
"DOM.XP",
|
|
64
|
+
"DOM.XP.CERT",
|
|
65
|
+
"DOM.PC",
|
|
66
|
+
"DOM.LIB",
|
|
67
|
+
"USA.EP",
|
|
68
|
+
"USA.SP.AIR",
|
|
69
|
+
"USA.TP",
|
|
70
|
+
"USA.TP.LVM",
|
|
71
|
+
"USA.XP",
|
|
72
|
+
"INT.XP",
|
|
73
|
+
"INT.IP.AIR",
|
|
74
|
+
"INT.IP.SURF",
|
|
75
|
+
"INT.SP.AIR",
|
|
76
|
+
"INT.SP.SURF",
|
|
77
|
+
"INT.TP"
|
|
78
|
+
]],
|
|
79
|
+
Parameter(name=["services", "-s"], required=False, consume_multiple=True)
|
|
80
|
+
] = None
|
|
81
|
+
) -> list[Rate] | None:
|
|
82
|
+
"""
|
|
83
|
+
Command to get rates.
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
origin_postal_code : str
|
|
88
|
+
Postal Code from which the parcel will be sent.
|
|
89
|
+
Format ANANAN (only accepted with uppercase)
|
|
90
|
+
destination : Destination
|
|
91
|
+
Defines the destination of the parcel.
|
|
92
|
+
promo_code : str, optional
|
|
93
|
+
If you have a promotional discount code, enter it here. The discount amount will be returned in the response under the adjustment structure.
|
|
94
|
+
quote_type : Literal["commercial", "counter"], default "commercial"
|
|
95
|
+
Either commercial or counter.
|
|
96
|
+
|
|
97
|
+
- "commercial" will return the discounted price for the commercial customer or Solutions for Small Business member.
|
|
98
|
+
- "counter" will return the regular price paid by consumers.
|
|
99
|
+
Defaults to "commercial" if not specified.
|
|
100
|
+
expected_mailing_date : datetime, optional
|
|
101
|
+
The expected mailing date for the parcel.
|
|
102
|
+
|
|
103
|
+
This date is used in calculations of the expected delivery date, however all rate quotes are based on the current system date.
|
|
104
|
+
options : list[Option], optional
|
|
105
|
+
Structure containing the list of options desired for the shipment.
|
|
106
|
+
parcel_characteristics : ParcelCharacteristics, optional
|
|
107
|
+
Details of the parcel such as weight and dimensions.
|
|
108
|
+
unpackaged : bool, default False
|
|
109
|
+
Indicates that the parcel will be unpackaged (e.g. tires)
|
|
110
|
+
mailing_tube : bool, default False
|
|
111
|
+
Indicates that the object will be shipped in a mailing tube
|
|
112
|
+
oversized : bool, default False
|
|
113
|
+
Indicates that the object has oversized dimensions. Automatically set correctly if dimensions are provided.
|
|
114
|
+
services : list[Literal[
|
|
115
|
+
"DOM.RP",
|
|
116
|
+
"DOM.EP",
|
|
117
|
+
"DOM.XP",
|
|
118
|
+
"DOM.XP.CERT",
|
|
119
|
+
"DOM.PC",
|
|
120
|
+
"DOM.LIB",
|
|
121
|
+
"USA.EP",
|
|
122
|
+
"USA.SP.AIR",
|
|
123
|
+
"USA.TP",
|
|
124
|
+
"USA.TP.LVM",
|
|
125
|
+
"USA.XP",
|
|
126
|
+
"INT.XP",
|
|
127
|
+
"INT.IP.AIR",
|
|
128
|
+
"INT.IP.SURF",
|
|
129
|
+
"INT.SP.AIR",
|
|
130
|
+
"INT.SP.SURF",
|
|
131
|
+
"INT.TP"
|
|
132
|
+
]], optional
|
|
133
|
+
List of services to be used for the shipment.
|
|
134
|
+
|
|
135
|
+
Returns
|
|
136
|
+
-------
|
|
137
|
+
list[Rate] or None
|
|
138
|
+
List of rates or None.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
rates = client.rating.rates.get_rates(
|
|
142
|
+
origin_postal_code,
|
|
143
|
+
destination,
|
|
144
|
+
promo_code,
|
|
145
|
+
quote_type,
|
|
146
|
+
expected_mailing_date,
|
|
147
|
+
options,
|
|
148
|
+
parcel_characteristics,
|
|
149
|
+
unpackaged,
|
|
150
|
+
mailing_tube,
|
|
151
|
+
oversized,
|
|
152
|
+
services
|
|
153
|
+
)
|
|
154
|
+
return rates
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from cyclopts import App
|
|
2
|
+
|
|
3
|
+
from .commands.discover_services import discover_services
|
|
4
|
+
from .commands.get_rates import get_rates
|
|
5
|
+
|
|
6
|
+
rating_app = App(
|
|
7
|
+
name="rating",
|
|
8
|
+
help="Command to contain all rating-related commands (e.g. get_rates, discover_services etc.)."
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
rating_app.command(get_rates)
|
|
12
|
+
rating_app.command(discover_services)
|
py_canada_post/client.py
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from base64 import b64encode
|
|
3
|
+
from typing import Literal
|
|
4
|
+
from typing import Self
|
|
5
|
+
|
|
6
|
+
from dotenv import load_dotenv
|
|
7
|
+
from requests.auth import to_native_string
|
|
8
|
+
|
|
9
|
+
from py_canada_post.services.rating.rating import Rating
|
|
10
|
+
|
|
11
|
+
load_dotenv()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PyCanadaPost:
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
customer_number: int,
|
|
18
|
+
api_key: str,
|
|
19
|
+
environment: Literal["SANDBOX", "PRODUCTION"] = "SANDBOX",
|
|
20
|
+
contract_id: int = None,
|
|
21
|
+
language: Literal["en-CA", "fr-CA"] = "en-CA"
|
|
22
|
+
) -> None:
|
|
23
|
+
"""
|
|
24
|
+
Initialize class variables.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
customer_number : int
|
|
29
|
+
Customer number that was obtained from Canada Post Developer Portal.
|
|
30
|
+
api_key : str
|
|
31
|
+
Api key that was obtained from Canada Post Developer Porta
|
|
32
|
+
environment : Literal["SANDBOX", "PRODUCTION"], default "SANDBOX"
|
|
33
|
+
Environment of the app.
|
|
34
|
+
contract_id : int, optional
|
|
35
|
+
Contract id that was obtained from Canada Post Developer Portal.
|
|
36
|
+
language : Literal["en-CA", "fr-CA"], default "en-CA"
|
|
37
|
+
Language to use.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
self.customer_number = customer_number
|
|
41
|
+
self.contract_id = contract_id
|
|
42
|
+
self.environment = environment
|
|
43
|
+
self.language = language
|
|
44
|
+
self._api_key = api_key
|
|
45
|
+
|
|
46
|
+
self.endpoint = self._get_endpoint()
|
|
47
|
+
self.headers = self._get_headers()
|
|
48
|
+
|
|
49
|
+
self.rating = Rating(self.headers, self.endpoint, self.customer_number, self.contract_id)
|
|
50
|
+
|
|
51
|
+
def _get_endpoint(self) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Function to get an endpoint based on the environment.
|
|
54
|
+
|
|
55
|
+
Returns
|
|
56
|
+
-------
|
|
57
|
+
str
|
|
58
|
+
Endpoint.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
endpoints = {
|
|
62
|
+
"SANDBOX": "https://ct.soa-gw.canadapost.ca",
|
|
63
|
+
"PRODUCTION": "https://soa-gw.canadapost.ca"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return endpoints[self.environment]
|
|
67
|
+
|
|
68
|
+
def _get_headers(self) -> dict:
|
|
69
|
+
"""
|
|
70
|
+
Function to get essential headers.
|
|
71
|
+
|
|
72
|
+
Returns
|
|
73
|
+
-------
|
|
74
|
+
dict
|
|
75
|
+
Headers.
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
username, password = self._api_key.split(":")
|
|
79
|
+
|
|
80
|
+
username = username.encode("latin1")
|
|
81
|
+
password = password.encode("latin1")
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
"Accept-Language": self.language,
|
|
85
|
+
"Authorization": "Basic " + to_native_string(b64encode(b":".join((username, password))).strip())
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def from_env(cls) -> Self:
|
|
90
|
+
"""
|
|
91
|
+
Function to initialize PyCanadaPost client object based on the .env variables.
|
|
92
|
+
Function raises an error if .env variables don't exist.
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
Self@PyCanadaPost
|
|
97
|
+
PyCanadaPost client object.
|
|
98
|
+
"""
|
|
99
|
+
customer_number = os.getenv("CUSTOMER_NUMBER", None)
|
|
100
|
+
api_key = os.getenv("API_KEY", None)
|
|
101
|
+
contract_id = os.getenv("CONTRACT_ID", None)
|
|
102
|
+
|
|
103
|
+
if not customer_number or not api_key or not contract_id:
|
|
104
|
+
raise AssertionError(
|
|
105
|
+
"Missing .env variables. "
|
|
106
|
+
"Please make sure you have CUSTOMER_NUMBER, API_KEY and CONTRACT_ID set up in your .env"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
return cls(
|
|
110
|
+
customer_number=int(customer_number),
|
|
111
|
+
api_key=api_key,
|
|
112
|
+
contract_id=int(contract_id),
|
|
113
|
+
)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from py_canada_post.exceptions.exceptions import (
|
|
2
|
+
CanadaPostError,
|
|
3
|
+
ServerError,
|
|
4
|
+
UserIdDeactivated,
|
|
5
|
+
EndpointMissmatch,
|
|
6
|
+
APIMissmatch,
|
|
7
|
+
InvalidCustomer,
|
|
8
|
+
UnspecifiedPlatform,
|
|
9
|
+
PlatformNotAuthorized,
|
|
10
|
+
InactivePlatform,
|
|
11
|
+
UnauthorizedPlatform,
|
|
12
|
+
InvalidPlatformKeyType,
|
|
13
|
+
IncorrectPlatformRequest,
|
|
14
|
+
PostOfficesNotFound,
|
|
15
|
+
InvalidContractNumber,
|
|
16
|
+
InvalidPostalCode,
|
|
17
|
+
MissingOriginPostalCode
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"CanadaPostError",
|
|
22
|
+
"ServerError",
|
|
23
|
+
"UserIdDeactivated",
|
|
24
|
+
"EndpointMissmatch",
|
|
25
|
+
"APIMissmatch",
|
|
26
|
+
"InvalidCustomer",
|
|
27
|
+
"UnspecifiedPlatform",
|
|
28
|
+
"PlatformNotAuthorized",
|
|
29
|
+
"InactivePlatform",
|
|
30
|
+
"UnauthorizedPlatform",
|
|
31
|
+
"InvalidPlatformKeyType",
|
|
32
|
+
"IncorrectPlatformRequest",
|
|
33
|
+
"PostOfficesNotFound",
|
|
34
|
+
"InvalidContractNumber",
|
|
35
|
+
"InvalidPostalCode",
|
|
36
|
+
"MissingOriginPostalCode"
|
|
37
|
+
]
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from .exceptions import (
|
|
2
|
+
ServerError,
|
|
3
|
+
UserIdDeactivated,
|
|
4
|
+
EndpointMissmatch,
|
|
5
|
+
APIMissmatch,
|
|
6
|
+
InvalidCustomer,
|
|
7
|
+
UnspecifiedPlatform,
|
|
8
|
+
PlatformNotAuthorized,
|
|
9
|
+
InactivePlatform,
|
|
10
|
+
UnauthorizedPlatform,
|
|
11
|
+
InvalidPlatformKeyType,
|
|
12
|
+
IncorrectPlatformRequest,
|
|
13
|
+
PostOfficesNotFound,
|
|
14
|
+
InvalidContractNumber,
|
|
15
|
+
InvalidPostalCode,
|
|
16
|
+
InvalidDestinationCountry,
|
|
17
|
+
MissingOriginPostalCode
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ExceptionDefinition:
|
|
22
|
+
def __init__(self, exception: type[Exception], description: str, mitigation: str = None) -> None:
|
|
23
|
+
"""
|
|
24
|
+
Initialize class variables.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
exception : type[Exception]
|
|
29
|
+
Exception-type (e.g. ServerError, UserIdDeactivated).
|
|
30
|
+
description : str
|
|
31
|
+
Description of the error to display.
|
|
32
|
+
mitigation : str, optional
|
|
33
|
+
Steps to fix the issue arisen.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
self.exception = exception
|
|
37
|
+
self.description = description
|
|
38
|
+
self.mitigation = mitigation
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
ERROR_MAP: dict[str, ExceptionDefinition] = {
|
|
42
|
+
"Server": ExceptionDefinition(
|
|
43
|
+
ServerError,
|
|
44
|
+
"Rejected by SLM Monitor",
|
|
45
|
+
"You have exceeded the throttle limit for your API key. "
|
|
46
|
+
"You will be blocked from making additional calls for up to a minute."
|
|
47
|
+
),
|
|
48
|
+
"AA001": ExceptionDefinition(
|
|
49
|
+
UserIdDeactivated,
|
|
50
|
+
"The user id for the request has been deactivated. "
|
|
51
|
+
"If you withdrew from the Developer Program, rejoin the program.",
|
|
52
|
+
"From the Developer Program website, select Join Now."
|
|
53
|
+
),
|
|
54
|
+
"AA002": ExceptionDefinition(
|
|
55
|
+
EndpointMissmatch,
|
|
56
|
+
"The username and password of the request do not match the endpoint. "
|
|
57
|
+
"E.g. development key against production endpoint or vice versa.",
|
|
58
|
+
"Merchant requests cannot be sent to the development environment."
|
|
59
|
+
),
|
|
60
|
+
"AA003": ExceptionDefinition(
|
|
61
|
+
APIMissmatch,
|
|
62
|
+
"The API key in the 'Authorization' header does not match "
|
|
63
|
+
"the mailed-by customer number in the request.",
|
|
64
|
+
"Verify your data."
|
|
65
|
+
),
|
|
66
|
+
"AA004": ExceptionDefinition(
|
|
67
|
+
InvalidCustomer,
|
|
68
|
+
"You cannot mail on behalf of the requested customer."
|
|
69
|
+
),
|
|
70
|
+
"AA005": ExceptionDefinition(
|
|
71
|
+
UnspecifiedPlatform,
|
|
72
|
+
"Platform id not specified",
|
|
73
|
+
"The platform-id header variable is empty or not present in the URL. "
|
|
74
|
+
"This should only be encountered during platform development coding."
|
|
75
|
+
),
|
|
76
|
+
"AA006": ExceptionDefinition(
|
|
77
|
+
PlatformNotAuthorized,
|
|
78
|
+
"Platform not authorized",
|
|
79
|
+
"The platform-id specified is incorrect or the merchant subsequently came to "
|
|
80
|
+
"Canada Post and intentionally revoked permission for your platform to submit transactions on its behalf. "
|
|
81
|
+
"The merchant could be asked to revalidate with Canada Post if they "
|
|
82
|
+
"want to re-establish their relationship with the platform. "
|
|
83
|
+
"This error would also occur if the online owner of the platform key voluntarily "
|
|
84
|
+
"withdrew from the Developer Program. In rare cases, Canada Post may have deactivated "
|
|
85
|
+
"the entire platform status due to fraud or misuse concerns."
|
|
86
|
+
),
|
|
87
|
+
"AA007": ExceptionDefinition(
|
|
88
|
+
InactivePlatform,
|
|
89
|
+
"Platform not active",
|
|
90
|
+
"You will receive this error if you have tried to use "
|
|
91
|
+
"Get Merchant Registration Token while your application to become an approved e-commerce "
|
|
92
|
+
"platform with Canada Post is still pending. "
|
|
93
|
+
"You cannot use this service until Canada Post has approved your application. "
|
|
94
|
+
"In rare cases, Canada Post may have deactivated the entire platform status due to fraud or misuse concerns."
|
|
95
|
+
),
|
|
96
|
+
"AA008": ExceptionDefinition(
|
|
97
|
+
UnauthorizedPlatform,
|
|
98
|
+
"Unauthorized Platform",
|
|
99
|
+
"You will receive this error if you are attempting to use Get Merchant"
|
|
100
|
+
" Registration Token service but have not applied to become an e-commerce platform with Canada Post. "
|
|
101
|
+
"To apply, sign in to the Developer Program home page and select Become a Platform."
|
|
102
|
+
),
|
|
103
|
+
"AA009": ExceptionDefinition(
|
|
104
|
+
InvalidPlatformKeyType,
|
|
105
|
+
"Key type not valid for platform-id",
|
|
106
|
+
"If a key other than a merchant key is being used to authenticate a transaction, "
|
|
107
|
+
"the platform-id field must not be specified. Remove the platform-id field from the "
|
|
108
|
+
"request even if you are a registered platform. Only requests done on behalf of a "
|
|
109
|
+
"merchant can specify the platform-id."
|
|
110
|
+
),
|
|
111
|
+
"AA010": ExceptionDefinition(
|
|
112
|
+
IncorrectPlatformRequest,
|
|
113
|
+
"Incorrectly configured platform request.",
|
|
114
|
+
"The platform-id in the header and the platform-id in the URL disagree. "
|
|
115
|
+
"These values must match."
|
|
116
|
+
),
|
|
117
|
+
"E00010": ExceptionDefinition(
|
|
118
|
+
PostOfficesNotFound,
|
|
119
|
+
"No Post Offices found"
|
|
120
|
+
),
|
|
121
|
+
"2550": ExceptionDefinition(
|
|
122
|
+
InvalidContractNumber,
|
|
123
|
+
"The contract number is not valid.",
|
|
124
|
+
"Please enter the correct contract number"
|
|
125
|
+
),
|
|
126
|
+
"7266": ExceptionDefinition(
|
|
127
|
+
InvalidPostalCode,
|
|
128
|
+
"Postal Code must be in format A9A or A9A9A9."
|
|
129
|
+
),
|
|
130
|
+
"8534": ExceptionDefinition(
|
|
131
|
+
InvalidDestinationCountry,
|
|
132
|
+
"A valid destination country must be supplied."
|
|
133
|
+
),
|
|
134
|
+
"9194": ExceptionDefinition(
|
|
135
|
+
MissingOriginPostalCode,
|
|
136
|
+
"origin-postal-code must also be provided when destination-postal-code is provided."
|
|
137
|
+
)
|
|
138
|
+
}
|