Skip to content

Commit ba06ae5

Browse files
committed
fix(fedex): correct API parameter structure for MFA endpoints
Update FedexRegistrationService to match actual API structure from documentation. Parameters must be wrapped in specific keys: - address_validation for registerAddress - pin_method for requestPin - pin_validation for validatePin - invoice_validation for submitInvoice All methods support optional easypost_details object. Updated tests to provide properly structured parameters.
1 parent 173fa21 commit ba06ae5

File tree

2 files changed

+148
-39
lines changed

2 files changed

+148
-39
lines changed

src/main/java/com/easypost/service/FedexRegistrationService.java

Lines changed: 104 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -25,92 +25,164 @@ public class FedexRegistrationService {
2525
* Register the billing address for a FedEx account.
2626
*
2727
* @param fedexAccountNumber The FedEx account number.
28-
* @param params Map of parameters for address registration.
29-
* If params does not contain "name", a UUID will be auto-generated.
30-
* Optional: "easypost_details" object for additional metadata like
31-
* "reference" or "description".
28+
* @param params Map of parameters containing "address_validation" with address fields
29+
* (name, street1, city, state, postal_code, country_code).
30+
* If "address_validation.name" is not provided, a UUID will be
31+
* auto-generated.
32+
* Optional: "easypost_details" object with "carrier_account_id".
3233
* @return FedexRegistration object.
3334
* @throws EasyPostException when the request fails.
3435
*/
3536
public FedexRegistration registerAddress(final String fedexAccountNumber, final Map<String, Object> params)
3637
throws EasyPostException {
37-
Map<String, Object> processedParams = ensureNameParameter(params);
38+
Map<String, Object> wrappedParams = wrapAddressValidation(params);
3839
String endpoint = String.format("fedex_registrations/%s/address", fedexAccountNumber);
3940

40-
return Requestor.request(RequestMethod.POST, endpoint, processedParams, FedexRegistration.class, client);
41+
return Requestor.request(RequestMethod.POST, endpoint, wrappedParams, FedexRegistration.class, client);
4142
}
4243

4344
/**
4445
* Request a PIN for FedEx account verification.
4546
*
4647
* @param fedexAccountNumber The FedEx account number.
47-
* @param params Map of parameters for PIN request.
48-
* Required: "pin_method" - one of "SMS", "CALL", or "EMAIL".
49-
* If params does not contain "name", a UUID will be auto-generated.
50-
* Optional: "easypost_details" object for additional metadata.
48+
* @param params Map of parameters containing "pin_method" with "option" field.
49+
* The "option" value must be one of "SMS", "CALL", or "EMAIL".
50+
* Example: {"pin_method": {"option": "SMS"}}
5151
* @return FedexRegistration object.
5252
* @throws EasyPostException when the request fails.
5353
*/
5454
public FedexRegistration requestPin(final String fedexAccountNumber, final Map<String, Object> params)
5555
throws EasyPostException {
56-
Map<String, Object> processedParams = ensureNameParameter(params);
5756
String endpoint = String.format("fedex_registrations/%s/pin", fedexAccountNumber);
5857

59-
return Requestor.request(RequestMethod.POST, endpoint, processedParams, FedexRegistration.class, client);
58+
return Requestor.request(RequestMethod.POST, endpoint, params, FedexRegistration.class, client);
6059
}
6160

6261
/**
6362
* Validate the PIN entered by the user for FedEx account verification.
6463
*
6564
* @param fedexAccountNumber The FedEx account number.
66-
* @param params Map of parameters for PIN validation.
67-
* Required: PIN value provided by the user.
68-
* If params does not contain "name", a UUID will be auto-generated.
69-
* Optional: "easypost_details" object for additional metadata.
65+
* @param params Map of parameters containing "pin_validation" with "pin_code" and
66+
* "name" fields. If "pin_validation.name" is not provided, a UUID will be
67+
* auto-generated.
68+
* Optional: "easypost_details" object with "carrier_account_id".
7069
* @return FedexRegistration object.
7170
* @throws EasyPostException when the request fails.
7271
*/
7372
public FedexRegistration validatePin(final String fedexAccountNumber, final Map<String, Object> params)
7473
throws EasyPostException {
75-
Map<String, Object> processedParams = ensureNameParameter(params);
74+
Map<String, Object> wrappedParams = wrapPinValidation(params);
7675
String endpoint = String.format("fedex_registrations/%s/pin/validate", fedexAccountNumber);
7776

78-
return Requestor.request(RequestMethod.POST, endpoint, processedParams, FedexRegistration.class, client);
77+
return Requestor.request(RequestMethod.POST, endpoint, wrappedParams, FedexRegistration.class, client);
7978
}
8079

8180
/**
8281
* Submit invoice information to complete FedEx account registration.
8382
*
8483
* @param fedexAccountNumber The FedEx account number.
85-
* @param params Map of parameters for invoice submission.
86-
* Required: Invoice information.
87-
* If params does not contain "name", a UUID will be auto-generated.
88-
* Optional: "easypost_details" object for additional metadata.
84+
* @param params Map of parameters containing "invoice_validation" with invoice fields
85+
* (name, invoice_number, invoice_date, invoice_amount, invoice_currency).
86+
* If "invoice_validation.name" is not provided, a UUID will be
87+
* auto-generated.
88+
* Optional: "easypost_details" object with "carrier_account_id".
8989
* @return FedexRegistration object.
9090
* @throws EasyPostException when the request fails.
9191
*/
9292
public FedexRegistration submitInvoice(final String fedexAccountNumber, final Map<String, Object> params)
9393
throws EasyPostException {
94-
Map<String, Object> processedParams = ensureNameParameter(params);
94+
Map<String, Object> wrappedParams = wrapInvoiceValidation(params);
9595
String endpoint = String.format("fedex_registrations/%s/invoice", fedexAccountNumber);
9696

97-
return Requestor.request(RequestMethod.POST, endpoint, processedParams, FedexRegistration.class, client);
97+
return Requestor.request(RequestMethod.POST, endpoint, wrappedParams, FedexRegistration.class, client);
9898
}
9999

100100
/**
101-
* Ensures the "name" parameter exists in the params map.
101+
* Wraps address validation parameters and ensures the "name" field exists.
102102
* If not present, generates a UUID (with hyphens removed) as the name.
103-
* This follows the pattern used in the web UI implementation.
104103
*
105104
* @param params The original parameters map.
106-
* @return A new map with the "name" parameter ensured.
105+
* @return A new map with properly wrapped address_validation and easypost_details.
106+
*/
107+
@SuppressWarnings("unchecked")
108+
private Map<String, Object> wrapAddressValidation(final Map<String, Object> params) {
109+
Map<String, Object> wrappedParams = new HashMap<>();
110+
111+
if (params.containsKey("address_validation")) {
112+
Map<String, Object> addressValidation = new HashMap<>(
113+
(Map<String, Object>) params.get("address_validation"));
114+
ensureNameField(addressValidation);
115+
wrappedParams.put("address_validation", addressValidation);
116+
}
117+
118+
if (params.containsKey("easypost_details")) {
119+
wrappedParams.put("easypost_details", params.get("easypost_details"));
120+
}
121+
122+
return wrappedParams;
123+
}
124+
125+
/**
126+
* Wraps PIN validation parameters and ensures the "name" field exists.
127+
* If not present, generates a UUID (with hyphens removed) as the name.
128+
*
129+
* @param params The original parameters map.
130+
* @return A new map with properly wrapped pin_validation and easypost_details.
131+
*/
132+
@SuppressWarnings("unchecked")
133+
private Map<String, Object> wrapPinValidation(final Map<String, Object> params) {
134+
Map<String, Object> wrappedParams = new HashMap<>();
135+
136+
if (params.containsKey("pin_validation")) {
137+
Map<String, Object> pinValidation = new HashMap<>(
138+
(Map<String, Object>) params.get("pin_validation"));
139+
ensureNameField(pinValidation);
140+
wrappedParams.put("pin_validation", pinValidation);
141+
}
142+
143+
if (params.containsKey("easypost_details")) {
144+
wrappedParams.put("easypost_details", params.get("easypost_details"));
145+
}
146+
147+
return wrappedParams;
148+
}
149+
150+
/**
151+
* Wraps invoice validation parameters and ensures the "name" field exists.
152+
* If not present, generates a UUID (with hyphens removed) as the name.
153+
*
154+
* @param params The original parameters map.
155+
* @return A new map with properly wrapped invoice_validation and easypost_details.
156+
*/
157+
@SuppressWarnings("unchecked")
158+
private Map<String, Object> wrapInvoiceValidation(final Map<String, Object> params) {
159+
Map<String, Object> wrappedParams = new HashMap<>();
160+
161+
if (params.containsKey("invoice_validation")) {
162+
Map<String, Object> invoiceValidation = new HashMap<>(
163+
(Map<String, Object>) params.get("invoice_validation"));
164+
ensureNameField(invoiceValidation);
165+
wrappedParams.put("invoice_validation", invoiceValidation);
166+
}
167+
168+
if (params.containsKey("easypost_details")) {
169+
wrappedParams.put("easypost_details", params.get("easypost_details"));
170+
}
171+
172+
return wrappedParams;
173+
}
174+
175+
/**
176+
* Ensures the "name" field exists in the provided map.
177+
* If not present, generates a UUID (with hyphens removed) as the name.
178+
* This follows the pattern used in the web UI implementation.
179+
*
180+
* @param map The map to ensure the "name" field in.
107181
*/
108-
private Map<String, Object> ensureNameParameter(final Map<String, Object> params) {
109-
Map<String, Object> processedParams = new HashMap<>(params);
110-
if (!processedParams.containsKey("name") || processedParams.get("name") == null) {
182+
private void ensureNameField(final Map<String, Object> map) {
183+
if (!map.containsKey("name") || map.get("name") == null) {
111184
String uuid = UUID.randomUUID().toString().replace("-", "");
112-
processedParams.put("name", uuid);
185+
map.put("name", uuid);
113186
}
114-
return processedParams;
115187
}
116188
}

src/test/java/com/easypost/FedexRegistrationTest.java

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,20 @@ public static void setup() throws EasyPostException {
3434
public void testRegisterAddress() throws EasyPostException {
3535
vcr.setUpTest("register_address");
3636

37+
Map<String, Object> addressValidation = new HashMap<>();
38+
addressValidation.put("name", "Test Account");
39+
addressValidation.put("street1", "179 N Harbor Dr");
40+
addressValidation.put("city", "Redondo Beach");
41+
addressValidation.put("state", "CA");
42+
addressValidation.put("postal_code", "90277");
43+
addressValidation.put("country_code", "US");
44+
45+
Map<String, Object> easypostDetails = new HashMap<>();
46+
easypostDetails.put("carrier_account_id", "ca_123456778");
47+
3748
Map<String, Object> params = new HashMap<>();
38-
params.put("billing_address", Fixtures.caAddress1());
49+
params.put("address_validation", addressValidation);
50+
params.put("easypost_details", easypostDetails);
3951

4052
FedexRegistration registration = vcr.client.fedexRegistration.registerAddress(TEST_FEDEX_ACCOUNT_NUMBER,
4153
params);
@@ -53,8 +65,11 @@ public void testRegisterAddress() throws EasyPostException {
5365
public void testRequestPin() throws EasyPostException {
5466
vcr.setUpTest("request_pin");
5567

68+
Map<String, Object> pinMethod = new HashMap<>();
69+
pinMethod.put("option", "SMS");
70+
5671
Map<String, Object> params = new HashMap<>();
57-
params.put("pin_method", "SMS");
72+
params.put("pin_method", pinMethod);
5873

5974
FedexRegistration registration = vcr.client.fedexRegistration.requestPin(TEST_FEDEX_ACCOUNT_NUMBER, params);
6075

@@ -71,8 +86,16 @@ public void testRequestPin() throws EasyPostException {
7186
public void testValidatePin() throws EasyPostException {
7287
vcr.setUpTest("validate_pin");
7388

89+
Map<String, Object> pinValidation = new HashMap<>();
90+
pinValidation.put("pin_code", "123456");
91+
pinValidation.put("name", "Test Account");
92+
93+
Map<String, Object> easypostDetails = new HashMap<>();
94+
easypostDetails.put("carrier_account_id", "ca_123456778");
95+
7496
Map<String, Object> params = new HashMap<>();
75-
params.put("pin", "123456");
97+
params.put("pin_validation", pinValidation);
98+
params.put("easypost_details", easypostDetails);
7699

77100
FedexRegistration registration = vcr.client.fedexRegistration.validatePin(TEST_FEDEX_ACCOUNT_NUMBER, params);
78101

@@ -89,9 +112,19 @@ public void testValidatePin() throws EasyPostException {
89112
public void testSubmitInvoice() throws EasyPostException {
90113
vcr.setUpTest("submit_invoice");
91114

115+
Map<String, Object> invoiceValidation = new HashMap<>();
116+
invoiceValidation.put("name", "Test Account");
117+
invoiceValidation.put("invoice_number", "INV-12345");
118+
invoiceValidation.put("invoice_date", "2025-01-01");
119+
invoiceValidation.put("invoice_amount", "100.00");
120+
invoiceValidation.put("invoice_currency", "USD");
121+
122+
Map<String, Object> easypostDetails = new HashMap<>();
123+
easypostDetails.put("carrier_account_id", "ca_123456778");
124+
92125
Map<String, Object> params = new HashMap<>();
93-
params.put("invoice_number", "INV-12345");
94-
params.put("invoice_date", "2025-01-01");
126+
params.put("invoice_validation", invoiceValidation);
127+
params.put("easypost_details", easypostDetails);
95128

96129
FedexRegistration registration = vcr.client.fedexRegistration.submitInvoice(TEST_FEDEX_ACCOUNT_NUMBER, params);
97130

@@ -108,10 +141,14 @@ public void testSubmitInvoice() throws EasyPostException {
108141
public void testAutoGenerateName() throws EasyPostException {
109142
vcr.setUpTest("auto_generate_name");
110143

144+
Map<String, Object> pinValidation = new HashMap<>();
145+
pinValidation.put("pin_code", "123456");
146+
// name is intentionally not provided to test auto-generation
147+
111148
Map<String, Object> params = new HashMap<>();
112-
params.put("pin_method", "EMAIL");
149+
params.put("pin_validation", pinValidation);
113150

114-
FedexRegistration registration = vcr.client.fedexRegistration.requestPin(TEST_FEDEX_ACCOUNT_NUMBER, params);
151+
FedexRegistration registration = vcr.client.fedexRegistration.validatePin(TEST_FEDEX_ACCOUNT_NUMBER, params);
115152

116153
assertInstanceOf(FedexRegistration.class, registration);
117154
assertNotNull(registration.getId());

0 commit comments

Comments
 (0)