From bfdf931fe49f74157bb8fb9bf045cc6300a22597 Mon Sep 17 00:00:00 2001 From: Sid Y Date: Thu, 9 Apr 2026 21:32:36 -0700 Subject: [PATCH 1/4] Add MCF Fulfillment Outbound V1 Java code recipes and update README - Three Java recipes: Create and Track, Create and Cancel, Create On-Hold and Ship - Updated README with MCF use cases linking both Java and Python recipes - Removed unreleased Prime shipping payload from Python constants --- code-recipes/README.md | 3 + .../fulfillment_outbound_v1/McfConstants.java | 104 ++++++++++ .../McfCreateAndCancelOrderRecipe.java | 139 +++++++++++++ .../McfCreateAndTrackOrderRecipe.java | 180 ++++++++++++++++ .../McfCreateOnHoldAndShipOrderRecipe.java | 193 ++++++++++++++++++ .../McfCreateAndCancelOrderRecipeTest.java | 24 +++ .../McfCreateAndTrackOrderRecipeTest.java | 24 +++ ...McfCreateOnHoldAndShipOrderRecipeTest.java | 25 +++ .../fulfillment_outbound_v1/constants.py | 32 --- 9 files changed, 692 insertions(+), 32 deletions(-) create mode 100644 code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java create mode 100644 code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipe.java create mode 100644 code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipe.java create mode 100644 code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java create mode 100644 code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipeTest.java create mode 100644 code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipeTest.java create mode 100644 code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipeTest.java diff --git a/code-recipes/README.md b/code-recipes/README.md index 389ee3e7..62446e16 100644 --- a/code-recipes/README.md +++ b/code-recipes/README.md @@ -23,3 +23,6 @@ Code recipes provides easy to read sample code for common use cases of Amazon Se | Pricing | Fetch Price | [Link](java/src/main/java/pricing/FetchPriceRecipe.java) | - | - | [Docs](https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v0-reference) | | Pricing | Calculate New Price | [Link](java/src/main/java/pricing/CalculateNewPriceRecipe.java) | - | - | [Docs](https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v0-reference) | | Pricing | Submit Price | [Link](java/src/main/java/pricing/SubmitPriceRecipe.java) | - | - | [Docs](https://developer-docs.amazon.com/sp-api/docs/listings-items-api-v2021-08-01-reference#patchlistingsitem) | +| Multichannel Fulfillment | Create an MCF order, retrieve the order details and track the order delivery | [Link](java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipe.java) | [Link](python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/mcf_create_and_track_order_recipe.py) | - | [Docs](https://developer-docs.amazon.com/sp-api/docs/fulfillment-outbound-api-v2020-07-01-reference) | +| Multichannel Fulfillment | Create an MCF order and cancel the order prior to fulfillment | [Link](java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipe.java) | [Link](python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/mcf_create_and_cancel_order_recipe.py) | - | [Docs](https://developer-docs.amazon.com/sp-api/docs/fulfillment-outbound-api-v2020-07-01-reference) | +| Multichannel Fulfillment | Create an MCF order On Hold and update the order to be shipped, retrieve the order details and track the order delivery | [Link](java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java) | [Link](python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/mcf_create_onhold_and_ship_order_recipe.py) | - | [Docs](https://developer-docs.amazon.com/sp-api/docs/fulfillment-outbound-api-v2020-07-01-reference) | diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java new file mode 100644 index 00000000..acb7e728 --- /dev/null +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java @@ -0,0 +1,104 @@ +package multichannel_fulfillment.fulfillment_outbound_v1; + +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.*; + +import java.util.Arrays; + +/** + * Sample constants for the MCF (Multichannel Fulfillment) order processing recipes. + * + *

When adapting these for your own application, replace the placeholder values + * marked with angle brackets (e.g., <recipient-name>) with real data.

+ * + *

DEVELOPER NOTES:

+ * + */ +public class McfConstants { + + public static final String SAMPLE_SELLER_FULFILLMENT_ORDER_ID = "MCF-TEST-ORDER-001"; + + /** + * Build a sample getFulfillmentPreview request body. + */ + public static GetFulfillmentPreviewRequest samplePreviewRequest() { + Address address = new Address() + .name("") + .addressLine1("") + .city("") + .stateOrRegion("") + .postalCode("") + .countryCode("US"); + + GetFulfillmentPreviewItem item = new GetFulfillmentPreviewItem() + .sellerSku("MY-SKU-001") + .quantity(1) + .sellerFulfillmentOrderItemId("item-001"); + + return new GetFulfillmentPreviewRequest() + .address(address) + .items(Arrays.asList(item)); + } + + /** + * Build a sample createFulfillmentOrder request body. + */ + public static CreateFulfillmentOrderRequest sampleCreateOrderRequest() { + Address address = new Address() + .name("") + .addressLine1("") + .city("") + .stateOrRegion("") + .postalCode("") + .countryCode("US"); + + CreateFulfillmentOrderItem item = new CreateFulfillmentOrderItem() + .sellerSku("MY-SKU-001") + .sellerFulfillmentOrderItemId("item-001") + .quantity(1); + + return new CreateFulfillmentOrderRequest() + .sellerFulfillmentOrderId(SAMPLE_SELLER_FULFILLMENT_ORDER_ID) + .displayableOrderId("TEST-DISPLAY-001") + .displayableOrderDate("2026-03-27T00:00:00Z") + .displayableOrderComment("MCF code recipe test order") + .shippingSpeedCategory(ShippingSpeedCategory.STANDARD) + .destinationAddress(address) + .items(Arrays.asList(item)); + } + + /** + * Build a sample createFulfillmentOrder request body with Hold action. + * The order is created but NOT shipped until you call updateFulfillmentOrder + * with fulfillmentAction=Ship to release it. + */ + public static CreateFulfillmentOrderRequest sampleCreateOrderRequestOnHold() { + Address address = new Address() + .name("") + .addressLine1("") + .city("") + .stateOrRegion("") + .postalCode("") + .countryCode("US"); + + CreateFulfillmentOrderItem item = new CreateFulfillmentOrderItem() + .sellerSku("MY-SKU-001") + .sellerFulfillmentOrderItemId("item-001") + .quantity(1); + + return new CreateFulfillmentOrderRequest() + .sellerFulfillmentOrderId(SAMPLE_SELLER_FULFILLMENT_ORDER_ID) + .displayableOrderId("TEST-DISPLAY-001") + .displayableOrderDate("2026-03-27T00:00:00Z") + .displayableOrderComment("MCF code recipe test order - On Hold") + .shippingSpeedCategory(ShippingSpeedCategory.STANDARD) + .fulfillmentAction(FulfillmentAction.HOLD) + .destinationAddress(address) + .items(Arrays.asList(item)); + } +} diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipe.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipe.java new file mode 100644 index 00000000..5429defb --- /dev/null +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipe.java @@ -0,0 +1,139 @@ +package multichannel_fulfillment.fulfillment_outbound_v1; + +import software.amazon.spapi.api.fulfillment.outbound.v2020_07_01.FbaOutboundApi; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.*; +import util.Constants; +import util.Recipe; + +/** + * Multichannel Fulfillment (MCF) Create and Cancel Order Recipe + * =============================================================== + * + *

This recipe demonstrates the cancel order workflow in four steps:

+ *
    + *
  1. getFulfillmentPreview – Check shipping options and fees.
  2. + *
  3. createFulfillmentOrder – Submit the MCF order.
  4. + *
  5. cancelFulfillmentOrder – Cancel the order before it ships.
  6. + *
  7. getFulfillmentOrder – Confirm the order status is now CANCELLED.
  8. + *
+ * + *

Real-world notes:

+ *
    + *
  • Cancellation is only possible while the order is in a cancellable state + * (typically before it enters the shipping process).
  • + *
  • If the order has already shipped, cancelFulfillmentOrder will return an error.
  • + *
+ * + *

DEVELOPER NOTES — Adapting this recipe for production:

+ *
    + *
  1. Remove the {@code .endpoint(Constants.BACKEND_URL)} call in the API builder.
  2. + *
  3. Replace the placeholder LWA credentials with real values.
  4. + *
  5. Update the sample payloads in {@code McfConstants}.
  6. + *
+ * + *

API version: Fulfillment Outbound v2020-07-01

+ */ +public class McfCreateAndCancelOrderRecipe extends Recipe { + + private final FbaOutboundApi fbaOutboundApi; + + public McfCreateAndCancelOrderRecipe() { + // DEVELOPER NOTE: For production, remove .endpoint(Constants.BACKEND_URL) + this.fbaOutboundApi = new FbaOutboundApi.Builder() + .lwaAuthorizationCredentials(lwaCredentials) + .endpoint(Constants.BACKEND_URL) + .build(); + } + + @Override + protected void start() { + System.out.println("======================================================================"); + System.out.println("MCF Create and Cancel Order Recipe"); + System.out.println("======================================================================"); + + // Step 1 – Preview shipping options + getFulfillmentPreview(); + + // Step 2 – Create the order + createFulfillmentOrder(); + String orderId = McfConstants.SAMPLE_SELLER_FULFILLMENT_ORDER_ID; + + // Step 3 – Cancel the order + cancelFulfillmentOrder(orderId); + + // Step 4 – Verify the order is cancelled + getFulfillmentOrder(orderId); + + System.out.println("\n======================================================================"); + System.out.println("✅ MCF create and cancel order workflow completed successfully."); + System.out.println("======================================================================"); + } + + // -- Step 1: Get Fulfillment Preview -------------------------------------- + + private GetFulfillmentPreviewResponse getFulfillmentPreview() { + System.out.println("\n--- Step 1: Get Fulfillment Preview ---"); + try { + GetFulfillmentPreviewResponse response = fbaOutboundApi.getFulfillmentPreview( + McfConstants.samplePreviewRequest()); + System.out.println("✅ Fulfillment preview retrieved successfully."); + return response; + } catch (Exception e) { + System.err.println("Error getting fulfillment preview: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 2: Create Fulfillment Order ------------------------------------- + + private CreateFulfillmentOrderResponse createFulfillmentOrder() { + System.out.println("\n--- Step 2: Create Fulfillment Order ---"); + try { + CreateFulfillmentOrderResponse response = fbaOutboundApi.createFulfillmentOrder( + McfConstants.sampleCreateOrderRequest()); + System.out.println("✅ Fulfillment order created: " + + McfConstants.SAMPLE_SELLER_FULFILLMENT_ORDER_ID); + return response; + } catch (Exception e) { + System.err.println("Error creating fulfillment order: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 3: Cancel Fulfillment Order ------------------------------------- + + /** + * Cancel the order before it ships. + * NOTE: This will fail if the order has already entered the shipping process. + */ + private CancelFulfillmentOrderResponse cancelFulfillmentOrder(String sellerFulfillmentOrderId) { + System.out.println("\n--- Step 3: Cancel Fulfillment Order ---"); + try { + CancelFulfillmentOrderResponse response = fbaOutboundApi.cancelFulfillmentOrder( + sellerFulfillmentOrderId); + System.out.println("✅ Fulfillment order cancelled: " + sellerFulfillmentOrderId); + return response; + } catch (Exception e) { + System.err.println("Error cancelling fulfillment order: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 4: Get Fulfillment Order (verify cancellation) ------------------ + + /** + * Verify the order status is now CANCELLED or CANCELLED_BY_SELLER. + */ + private GetFulfillmentOrderResponse getFulfillmentOrder(String sellerFulfillmentOrderId) { + System.out.println("\n--- Step 4: Get Fulfillment Order (verify cancellation) ---"); + try { + GetFulfillmentOrderResponse response = fbaOutboundApi.getFulfillmentOrder( + sellerFulfillmentOrderId); + System.out.println("✅ Fulfillment order details retrieved for: " + sellerFulfillmentOrderId); + return response; + } catch (Exception e) { + System.err.println("Error getting fulfillment order: " + e.getMessage()); + throw new RuntimeException(e); + } + } +} diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipe.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipe.java new file mode 100644 index 00000000..b2c1e440 --- /dev/null +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipe.java @@ -0,0 +1,180 @@ +package multichannel_fulfillment.fulfillment_outbound_v1; + +import software.amazon.spapi.api.fulfillment.outbound.v2020_07_01.FbaOutboundApi; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.*; +import util.Constants; +import util.Recipe; + +import java.util.ArrayList; +import java.util.List; + +/** + * Multichannel Fulfillment (MCF) Create and Track Order Recipe + * ============================================================== + * + *

This recipe demonstrates the standard MCF workflow in four steps:

+ *
    + *
  1. getFulfillmentPreview – Check shipping options, estimated dates, and fees.
  2. + *
  3. createFulfillmentOrder – Submit the order for fulfillment.
  4. + *
  5. getFulfillmentOrder – Poll the order to get status and package details.
  6. + *
  7. getPackageTrackingDetails – Get carrier tracking info for each package.
  8. + *
+ * + *

DEVELOPER NOTES — Adapting this recipe for production:

+ *
    + *
  1. Remove the {@code .endpoint(Constants.BACKEND_URL)} call in the API builder. + * The SDK will automatically route to the correct SP-API endpoint.
  2. + *
  3. Replace the placeholder LWA credentials in the base {@code Recipe} class + * with your real credentials, ideally loaded from environment variables.
  4. + *
  5. Update the sample payloads in {@code McfConstants} with real addresses, + * SKUs, and order IDs from your seller account.
  6. + *
+ * + *

API version: Fulfillment Outbound v2020-07-01

+ */ +public class McfCreateAndTrackOrderRecipe extends Recipe { + + private final FbaOutboundApi fbaOutboundApi; + + public McfCreateAndTrackOrderRecipe() { + // DEVELOPER NOTE: For production, remove .endpoint(Constants.BACKEND_URL) + this.fbaOutboundApi = new FbaOutboundApi.Builder() + .lwaAuthorizationCredentials(lwaCredentials) + .endpoint(Constants.BACKEND_URL) + .build(); + } + + @Override + protected void start() { + System.out.println("======================================================================"); + System.out.println("MCF Create and Track Order Recipe"); + System.out.println("======================================================================"); + + // Step 1 – Preview shipping options + GetFulfillmentPreviewResponse preview = getFulfillmentPreview(); + + // Step 2 – Create the order + createFulfillmentOrder(); + String orderId = McfConstants.SAMPLE_SELLER_FULFILLMENT_ORDER_ID; + + // Step 3 – Get order status and package details + GetFulfillmentOrderResponse order = getFulfillmentOrder(orderId); + + // Step 4 – Track each package using packageNumbers from Step 3 + List packageNumbers = extractPackageNumbers(order); + if (!packageNumbers.isEmpty()) { + for (int pkgNum : packageNumbers) { + getPackageTrackingDetails(pkgNum); + } + } else { + System.out.println("No packages found yet — order may still be processing."); + } + + System.out.println("\n======================================================================"); + System.out.println("✅ MCF create and track order workflow completed successfully."); + System.out.println("======================================================================"); + } + + // -- Step 1: Get Fulfillment Preview -------------------------------------- + + /** + * Call getFulfillmentPreview to see available shipping speeds, + * estimated delivery dates, and estimated fees. + */ + private GetFulfillmentPreviewResponse getFulfillmentPreview() { + System.out.println("\n--- Step 1: Get Fulfillment Preview ---"); + try { + GetFulfillmentPreviewResponse response = fbaOutboundApi.getFulfillmentPreview( + McfConstants.samplePreviewRequest()); + System.out.println("✅ Fulfillment preview retrieved successfully."); + return response; + } catch (Exception e) { + System.err.println("Error getting fulfillment preview: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 2: Create Fulfillment Order ------------------------------------- + + /** + * Call createFulfillmentOrder to submit the MCF order. + * A successful response means the order was accepted. + */ + private CreateFulfillmentOrderResponse createFulfillmentOrder() { + System.out.println("\n--- Step 2: Create Fulfillment Order ---"); + try { + CreateFulfillmentOrderResponse response = fbaOutboundApi.createFulfillmentOrder( + McfConstants.sampleCreateOrderRequest()); + System.out.println("✅ Fulfillment order created: " + + McfConstants.SAMPLE_SELLER_FULFILLMENT_ORDER_ID); + return response; + } catch (Exception e) { + System.err.println("Error creating fulfillment order: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 3: Get Fulfillment Order ---------------------------------------- + + /** + * Call getFulfillmentOrder to check the order status and retrieve + * package-level details (including packageNumber for tracking). + */ + private GetFulfillmentOrderResponse getFulfillmentOrder(String sellerFulfillmentOrderId) { + System.out.println("\n--- Step 3: Get Fulfillment Order ---"); + try { + GetFulfillmentOrderResponse response = fbaOutboundApi.getFulfillmentOrder( + sellerFulfillmentOrderId); + System.out.println("✅ Fulfillment order details retrieved for: " + sellerFulfillmentOrderId); + return response; + } catch (Exception e) { + System.err.println("Error getting fulfillment order: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 4: Get Package Tracking Details ---------------------------------- + + /** + * Call getPackageTrackingDetails to get carrier and tracking info. + * + *

Key fields in the response: trackingNumber, carrierCode, trackingEvents.

+ */ + private GetPackageTrackingDetailsResponse getPackageTrackingDetails(int packageNumber) { + System.out.println("\n--- Step 4: Get Package Tracking Details (package " + packageNumber + ") ---"); + try { + GetPackageTrackingDetailsResponse response = fbaOutboundApi.getPackageTrackingDetails( + packageNumber); + System.out.println("✅ Tracking details retrieved for package: " + packageNumber); + return response; + } catch (Exception e) { + System.err.println("Error getting tracking details: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Helper: extract package numbers from getFulfillmentOrder response ----- + + /** + * Extract packageNumber values from the getFulfillmentOrder response. + * These are needed to call getPackageTrackingDetails. + */ + private List extractPackageNumbers(GetFulfillmentOrderResponse orderResponse) { + List packageNumbers = new ArrayList<>(); + if (orderResponse == null + || orderResponse.getPayload() == null + || orderResponse.getPayload().getFulfillmentShipments() == null) { + return packageNumbers; + } + for (FulfillmentShipment shipment : orderResponse.getPayload().getFulfillmentShipments()) { + if (shipment.getFulfillmentShipmentPackage() != null) { + for (FulfillmentShipmentPackage pkg : shipment.getFulfillmentShipmentPackage()) { + if (pkg.getPackageNumber() != null) { + packageNumbers.add(pkg.getPackageNumber()); + } + } + } + } + return packageNumbers; + } +} diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java new file mode 100644 index 00000000..68929771 --- /dev/null +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java @@ -0,0 +1,193 @@ +package multichannel_fulfillment.fulfillment_outbound_v1; + +import software.amazon.spapi.api.fulfillment.outbound.v2020_07_01.FbaOutboundApi; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.*; +import util.Constants; +import util.Recipe; + +import java.util.ArrayList; +import java.util.List; + +/** + * Multichannel Fulfillment (MCF) Create On-Hold and Ship Order Recipe + * ===================================================================== + * + *

This recipe demonstrates the on-hold order workflow in five steps:

+ *
    + *
  1. getFulfillmentPreview – Check shipping options and fees.
  2. + *
  3. createFulfillmentOrder – Submit the order with fulfillmentAction=Hold.
  4. + *
  5. updateFulfillmentOrder – Release the hold and request shipment.
  6. + *
  7. getFulfillmentOrder – Get order status and package details.
  8. + *
  9. getPackageTrackingDetails – Get carrier tracking info.
  10. + *
+ * + *

Real-world notes:

+ *
    + *
  • The Hold action is useful for payment validation, fraud checks, or + * waiting for customer confirmation before shipping.
  • + *
  • Once updated to Ship, the order enters the normal fulfillment pipeline.
  • + *
  • You can also change address, shipping speed, or displayable info while on hold.
  • + *
+ * + *

DEVELOPER NOTES — Adapting this recipe for production:

+ *
    + *
  1. Remove the {@code .endpoint(Constants.BACKEND_URL)} call in the API builder.
  2. + *
  3. Replace the placeholder LWA credentials with real values.
  4. + *
  5. Update the sample payloads in {@code McfConstants}.
  6. + *
+ * + *

API version: Fulfillment Outbound v2020-07-01

+ */ +public class McfCreateOnHoldAndShipOrderRecipe extends Recipe { + + private final FbaOutboundApi fbaOutboundApi; + + public McfCreateOnHoldAndShipOrderRecipe() { + // DEVELOPER NOTE: For production, remove .endpoint(Constants.BACKEND_URL) + this.fbaOutboundApi = new FbaOutboundApi.Builder() + .lwaAuthorizationCredentials(lwaCredentials) + .endpoint(Constants.BACKEND_URL) + .build(); + } + + @Override + protected void start() { + System.out.println("======================================================================"); + System.out.println("MCF Create On-Hold and Ship Order Recipe"); + System.out.println("======================================================================"); + + // Step 1 – Preview shipping options + getFulfillmentPreview(); + + // Step 2 – Create order on Hold + createFulfillmentOrder(); + String orderId = McfConstants.SAMPLE_SELLER_FULFILLMENT_ORDER_ID; + + // Step 3 – Release hold and ship + updateFulfillmentOrder(orderId); + + // Step 4 – Get order status and package details + GetFulfillmentOrderResponse order = getFulfillmentOrder(orderId); + + // Step 5 – Track each package + List packageNumbers = extractPackageNumbers(order); + if (!packageNumbers.isEmpty()) { + for (int pkgNum : packageNumbers) { + getPackageTrackingDetails(pkgNum); + } + } else { + System.out.println("No packages found yet — order may still be processing."); + } + + System.out.println("\n======================================================================"); + System.out.println("✅ MCF create on-hold and ship order workflow completed successfully."); + System.out.println("======================================================================"); + } + + // -- Step 1: Get Fulfillment Preview -------------------------------------- + + private GetFulfillmentPreviewResponse getFulfillmentPreview() { + System.out.println("\n--- Step 1: Get Fulfillment Preview ---"); + try { + GetFulfillmentPreviewResponse response = fbaOutboundApi.getFulfillmentPreview( + McfConstants.samplePreviewRequest()); + System.out.println("✅ Fulfillment preview retrieved successfully."); + return response; + } catch (Exception e) { + System.err.println("Error getting fulfillment preview: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 2: Create Fulfillment Order (on Hold) --------------------------- + + /** + * Create the order with fulfillmentAction=Hold. + * The order is NOT shipped until explicitly released via updateFulfillmentOrder. + */ + private CreateFulfillmentOrderResponse createFulfillmentOrder() { + System.out.println("\n--- Step 2: Create Fulfillment Order (Hold) ---"); + try { + CreateFulfillmentOrderResponse response = fbaOutboundApi.createFulfillmentOrder( + McfConstants.sampleCreateOrderRequestOnHold()); + System.out.println("✅ Fulfillment order created on Hold: " + + McfConstants.SAMPLE_SELLER_FULFILLMENT_ORDER_ID); + return response; + } catch (Exception e) { + System.err.println("Error creating fulfillment order: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 3: Update Fulfillment Order (release hold, ship) ---------------- + + /** + * Release the hold and request shipment by setting fulfillmentAction to Ship. + */ + private UpdateFulfillmentOrderResponse updateFulfillmentOrder(String sellerFulfillmentOrderId) { + System.out.println("\n--- Step 3: Update Fulfillment Order (Ship) ---"); + try { + UpdateFulfillmentOrderRequest updateBody = new UpdateFulfillmentOrderRequest() + .fulfillmentAction(FulfillmentAction.SHIP); + + UpdateFulfillmentOrderResponse response = fbaOutboundApi.updateFulfillmentOrder( + sellerFulfillmentOrderId, updateBody); + System.out.println("✅ Order released from hold — shipment requested."); + return response; + } catch (Exception e) { + System.err.println("Error updating fulfillment order: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 4: Get Fulfillment Order ---------------------------------------- + + private GetFulfillmentOrderResponse getFulfillmentOrder(String sellerFulfillmentOrderId) { + System.out.println("\n--- Step 4: Get Fulfillment Order ---"); + try { + GetFulfillmentOrderResponse response = fbaOutboundApi.getFulfillmentOrder( + sellerFulfillmentOrderId); + System.out.println("✅ Fulfillment order details retrieved for: " + sellerFulfillmentOrderId); + return response; + } catch (Exception e) { + System.err.println("Error getting fulfillment order: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Step 5: Get Package Tracking Details ---------------------------------- + + private GetPackageTrackingDetailsResponse getPackageTrackingDetails(int packageNumber) { + System.out.println("\n--- Step 5: Get Package Tracking Details (package " + packageNumber + ") ---"); + try { + GetPackageTrackingDetailsResponse response = fbaOutboundApi.getPackageTrackingDetails( + packageNumber); + System.out.println("✅ Tracking details retrieved for package: " + packageNumber); + return response; + } catch (Exception e) { + System.err.println("Error getting tracking details: " + e.getMessage()); + throw new RuntimeException(e); + } + } + + // -- Helper: extract package numbers -------------------------------------- + + private List extractPackageNumbers(GetFulfillmentOrderResponse orderResponse) { + List packageNumbers = new ArrayList<>(); + if (orderResponse == null + || orderResponse.getPayload() == null + || orderResponse.getPayload().getFulfillmentShipments() == null) { + return packageNumbers; + } + for (FulfillmentShipment shipment : orderResponse.getPayload().getFulfillmentShipments()) { + if (shipment.getFulfillmentShipmentPackage() != null) { + for (FulfillmentShipmentPackage pkg : shipment.getFulfillmentShipmentPackage()) { + if (pkg.getPackageNumber() != null) { + packageNumbers.add(pkg.getPackageNumber()); + } + } + } + } + return packageNumbers; + } +} diff --git a/code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipeTest.java b/code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipeTest.java new file mode 100644 index 00000000..c04f2be6 --- /dev/null +++ b/code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipeTest.java @@ -0,0 +1,24 @@ +package multichannel_fulfillment.fulfillment_outbound_v1; + +import util.RecipeTest; + +import java.util.List; + +/** + * Test for the MCF Create and Cancel Order Recipe. + * Workflow: preview → create → cancel → verify cancellation. + */ +public class McfCreateAndCancelOrderRecipeTest extends RecipeTest { + + protected McfCreateAndCancelOrderRecipeTest() { + super( + new McfCreateAndCancelOrderRecipe(), + List.of( + "mcf-v1-getFulfillmentPreview", + "mcf-v1-createFulfillmentOrder", + "mcf-v1-cancelFulfillmentOrder", + "mcf-v1-getFulfillmentOrder-cancelled" + ) + ); + } +} diff --git a/code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipeTest.java b/code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipeTest.java new file mode 100644 index 00000000..68d1c0fe --- /dev/null +++ b/code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipeTest.java @@ -0,0 +1,24 @@ +package multichannel_fulfillment.fulfillment_outbound_v1; + +import util.RecipeTest; + +import java.util.List; + +/** + * Test for the MCF Create and Track Order Recipe. + * Workflow: preview → create → get order → track package. + */ +public class McfCreateAndTrackOrderRecipeTest extends RecipeTest { + + protected McfCreateAndTrackOrderRecipeTest() { + super( + new McfCreateAndTrackOrderRecipe(), + List.of( + "mcf-v1-getFulfillmentPreview", + "mcf-v1-createFulfillmentOrder", + "mcf-v1-getFulfillmentOrder", + "mcf-v1-getPackageTrackingDetails" + ) + ); + } +} diff --git a/code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipeTest.java b/code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipeTest.java new file mode 100644 index 00000000..988feb6f --- /dev/null +++ b/code-recipes/java/src/test/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipeTest.java @@ -0,0 +1,25 @@ +package multichannel_fulfillment.fulfillment_outbound_v1; + +import util.RecipeTest; + +import java.util.List; + +/** + * Test for the MCF Create On-Hold and Ship Order Recipe. + * Workflow: preview → create (Hold) → update (Ship) → get order → track package. + */ +public class McfCreateOnHoldAndShipOrderRecipeTest extends RecipeTest { + + protected McfCreateOnHoldAndShipOrderRecipeTest() { + super( + new McfCreateOnHoldAndShipOrderRecipe(), + List.of( + "mcf-v1-getFulfillmentPreview", + "mcf-v1-createFulfillmentOrder", + "mcf-v1-updateFulfillmentOrder", + "mcf-v1-getFulfillmentOrder", + "mcf-v1-getPackageTrackingDetails" + ) + ); + } +} diff --git a/code-recipes/python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/constants.py b/code-recipes/python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/constants.py index 578014a7..ce275639 100644 --- a/code-recipes/python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/constants.py +++ b/code-recipes/python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/constants.py @@ -60,38 +60,6 @@ # "featureConstraints": [{"featureName": "BLANK_BOX", "featureFulfillmentPolicy": "Required"}], } -# -- Step 2 (alternate version for Prime orders): createFulfillmentOrder with Prime shipping ------------ -# Use this payload instead of sample_create_order_request when the merchant -# is enrolled in Prime and wants to offer Prime shipping speeds. -sample_create_order_request_prime = { - "sellerFulfillmentOrderId": "MCF-TEST-ORDER-001", - "displayableOrderId": "TEST-DISPLAY-001", - "displayableOrderDate": "2026-03-27T00:00:00Z", - "displayableOrderComment": "MCF code recipe test order - Prime", - "shippingSpeedCategory": "Standard", - "destinationAddress": { - "name": "", - "addressLine1": "", - "city": "", - "stateOrRegion": "", - "postalCode": "", - "countryCode": "US", - }, - "items": [ - { - "sellerSku": "MY-SKU-001", - "sellerFulfillmentOrderItemId": "item-001", - "quantity": 1, - } - ], - "featureConstraints": [ - { - "featureName": "PRIME_ELIGIBILITY", - "featureFulfillmentPolicy": "Required", - } - ], -} - # -- Step 2 (alternate version for Hold orders): createFulfillmentOrder with Hold action --------------- # Use this payload to create an order that is NOT shipped immediately. # The order stays on hold until you call updateFulfillmentOrder with From 7f71d4f4a3fb13e96c90c37b448976c1ba404be3 Mon Sep 17 00:00:00 2001 From: Sid Y Date: Mon, 13 Apr 2026 14:09:00 -0700 Subject: [PATCH 2/4] Replace wildcard imports with explicit class imports --- .../fulfillment_outbound_v1/McfConstants.java | 8 +++++++- .../McfCreateAndCancelOrderRecipe.java | 5 ++++- .../McfCreateAndTrackOrderRecipe.java | 7 ++++++- .../McfCreateOnHoldAndShipOrderRecipe.java | 10 +++++++++- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java index acb7e728..9303ac56 100644 --- a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java @@ -1,6 +1,12 @@ package multichannel_fulfillment.fulfillment_outbound_v1; -import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.*; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.Address; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.CreateFulfillmentOrderItem; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.CreateFulfillmentOrderRequest; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.FulfillmentAction; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentPreviewItem; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentPreviewRequest; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.ShippingSpeedCategory; import java.util.Arrays; diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipe.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipe.java index 5429defb..a72529fa 100644 --- a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipe.java +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndCancelOrderRecipe.java @@ -1,7 +1,10 @@ package multichannel_fulfillment.fulfillment_outbound_v1; import software.amazon.spapi.api.fulfillment.outbound.v2020_07_01.FbaOutboundApi; -import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.*; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.CancelFulfillmentOrderResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.CreateFulfillmentOrderResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentOrderResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentPreviewResponse; import util.Constants; import util.Recipe; diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipe.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipe.java index b2c1e440..d4e332b3 100644 --- a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipe.java +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateAndTrackOrderRecipe.java @@ -1,7 +1,12 @@ package multichannel_fulfillment.fulfillment_outbound_v1; import software.amazon.spapi.api.fulfillment.outbound.v2020_07_01.FbaOutboundApi; -import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.*; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.CreateFulfillmentOrderResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.FulfillmentShipment; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.FulfillmentShipmentPackage; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentOrderResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentPreviewResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetPackageTrackingDetailsResponse; import util.Constants; import util.Recipe; diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java index 68929771..bf7a9a81 100644 --- a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java @@ -1,7 +1,15 @@ package multichannel_fulfillment.fulfillment_outbound_v1; import software.amazon.spapi.api.fulfillment.outbound.v2020_07_01.FbaOutboundApi; -import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.*; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.CreateFulfillmentOrderResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.FulfillmentAction; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.FulfillmentShipment; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.FulfillmentShipmentPackage; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentOrderResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentPreviewResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetPackageTrackingDetailsResponse; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.UpdateFulfillmentOrderRequest; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.UpdateFulfillmentOrderResponse; import util.Constants; import util.Recipe; From 456187eda5931930df94c6391e6c1f366a7f7dfc Mon Sep 17 00:00:00 2001 From: Sid Y Date: Wed, 15 Apr 2026 13:11:29 -0700 Subject: [PATCH 3/4] Fix compile errors: use typed list classes, OffsetDateTime, and correct updateFulfillmentOrder parameter order --- .../fulfillment_outbound_v1/McfConstants.java | 23 ++++++++++++++----- .../McfCreateOnHoldAndShipOrderRecipe.java | 2 +- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java index 9303ac56..6318ca1f 100644 --- a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java @@ -2,13 +2,15 @@ import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.Address; import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.CreateFulfillmentOrderItem; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.CreateFulfillmentOrderItemList; import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.CreateFulfillmentOrderRequest; import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.FulfillmentAction; import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentPreviewItem; +import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentPreviewItemList; import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.GetFulfillmentPreviewRequest; import software.amazon.spapi.models.fulfillment.outbound.v2020_07_01.ShippingSpeedCategory; -import java.util.Arrays; +import org.threeten.bp.OffsetDateTime; /** * Sample constants for the MCF (Multichannel Fulfillment) order processing recipes. @@ -46,9 +48,12 @@ public static GetFulfillmentPreviewRequest samplePreviewRequest() { .quantity(1) .sellerFulfillmentOrderItemId("item-001"); + GetFulfillmentPreviewItemList itemList = new GetFulfillmentPreviewItemList(); + itemList.add(item); + return new GetFulfillmentPreviewRequest() .address(address) - .items(Arrays.asList(item)); + .items(itemList); } /** @@ -68,14 +73,17 @@ public static CreateFulfillmentOrderRequest sampleCreateOrderRequest() { .sellerFulfillmentOrderItemId("item-001") .quantity(1); + CreateFulfillmentOrderItemList itemList = new CreateFulfillmentOrderItemList(); + itemList.add(item); + return new CreateFulfillmentOrderRequest() .sellerFulfillmentOrderId(SAMPLE_SELLER_FULFILLMENT_ORDER_ID) .displayableOrderId("TEST-DISPLAY-001") - .displayableOrderDate("2026-03-27T00:00:00Z") + .displayableOrderDate(OffsetDateTime.parse("2026-03-27T00:00:00Z")) .displayableOrderComment("MCF code recipe test order") .shippingSpeedCategory(ShippingSpeedCategory.STANDARD) .destinationAddress(address) - .items(Arrays.asList(item)); + .items(itemList); } /** @@ -97,14 +105,17 @@ public static CreateFulfillmentOrderRequest sampleCreateOrderRequestOnHold() { .sellerFulfillmentOrderItemId("item-001") .quantity(1); + CreateFulfillmentOrderItemList itemList = new CreateFulfillmentOrderItemList(); + itemList.add(item); + return new CreateFulfillmentOrderRequest() .sellerFulfillmentOrderId(SAMPLE_SELLER_FULFILLMENT_ORDER_ID) .displayableOrderId("TEST-DISPLAY-001") - .displayableOrderDate("2026-03-27T00:00:00Z") + .displayableOrderDate(OffsetDateTime.parse("2026-03-27T00:00:00Z")) .displayableOrderComment("MCF code recipe test order - On Hold") .shippingSpeedCategory(ShippingSpeedCategory.STANDARD) .fulfillmentAction(FulfillmentAction.HOLD) .destinationAddress(address) - .items(Arrays.asList(item)); + .items(itemList); } } diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java index bf7a9a81..6f57dec9 100644 --- a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfCreateOnHoldAndShipOrderRecipe.java @@ -139,7 +139,7 @@ private UpdateFulfillmentOrderResponse updateFulfillmentOrder(String sellerFulfi .fulfillmentAction(FulfillmentAction.SHIP); UpdateFulfillmentOrderResponse response = fbaOutboundApi.updateFulfillmentOrder( - sellerFulfillmentOrderId, updateBody); + updateBody, sellerFulfillmentOrderId); System.out.println("✅ Order released from hold — shipment requested."); return response; } catch (Exception e) { From 547692a1616d0ee2539183011157ba66790d4a79 Mon Sep 17 00:00:00 2001 From: Sid Y Date: Thu, 30 Apr 2026 22:53:44 -0700 Subject: [PATCH 4/4] Add explanatory comments to MCF constants payload examples (Python and Java) --- .../fulfillment_outbound_v1/McfConstants.java | 63 ++++++++++++------- .../fulfillment_outbound_v1/constants.py | 36 +++++++---- 2 files changed, 64 insertions(+), 35 deletions(-) diff --git a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java index 6318ca1f..29ac1e07 100644 --- a/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java +++ b/code-recipes/java/src/main/java/multichannel_fulfillment/fulfillment_outbound_v1/McfConstants.java @@ -13,7 +13,7 @@ import org.threeten.bp.OffsetDateTime; /** - * Sample constants for the MCF (Multichannel Fulfillment) order processing recipes. + * Sample Payloads for the MCF (Multichannel Fulfillment) order processing recipes. * *

When adapting these for your own application, replace the placeholder values * marked with angle brackets (e.g., <recipient-name>) with real data.

@@ -31,6 +31,9 @@ public class McfConstants { public static final String SAMPLE_SELLER_FULFILLMENT_ORDER_ID = "MCF-TEST-ORDER-001"; + // -- Step 1: getFulfillmentPreview request body -------------------------------- + // Use this to check shipping speeds, estimated delivery dates, and fees before committing to an order. + /** * Build a sample getFulfillmentPreview request body. */ @@ -39,14 +42,14 @@ public static GetFulfillmentPreviewRequest samplePreviewRequest() { .name("") .addressLine1("") .city("") - .stateOrRegion("") - .postalCode("") + .stateOrRegion("") // e.g., "WA", "CA", "NY" + .postalCode("") // e.g., "98101" .countryCode("US"); GetFulfillmentPreviewItem item = new GetFulfillmentPreviewItem() - .sellerSku("MY-SKU-001") + .sellerSku("MY-SKU-001") // Your FBA-enrolled SKU .quantity(1) - .sellerFulfillmentOrderItemId("item-001"); + .sellerFulfillmentOrderItemId("item-001"); // Your unique line-item ID GetFulfillmentPreviewItemList itemList = new GetFulfillmentPreviewItemList(); itemList.add(item); @@ -54,8 +57,15 @@ public static GetFulfillmentPreviewRequest samplePreviewRequest() { return new GetFulfillmentPreviewRequest() .address(address) .items(itemList); + // Optional fields you may add: + // .shippingSpeedCategories(Arrays.asList(ShippingSpeedCategory.STANDARD, ShippingSpeedCategory.EXPEDITED, ShippingSpeedCategory.PRIORITY)) + // + // .featureConstraints(...) — Features can be BLANK_BOX or BLOCK_AMZL } + // -- Step 2: createFulfillmentOrder request body ------------------------------- + // Use this to actually submit the MCF order for fulfillment. + /** * Build a sample createFulfillmentOrder request body. */ @@ -69,27 +79,36 @@ public static CreateFulfillmentOrderRequest sampleCreateOrderRequest() { .countryCode("US"); CreateFulfillmentOrderItem item = new CreateFulfillmentOrderItem() - .sellerSku("MY-SKU-001") - .sellerFulfillmentOrderItemId("item-001") + .sellerSku("MY-SKU-001") // Must match an FBA-enrolled SKU + .sellerFulfillmentOrderItemId("item-001") // Your unique line-item ID .quantity(1); CreateFulfillmentOrderItemList itemList = new CreateFulfillmentOrderItemList(); itemList.add(item); return new CreateFulfillmentOrderRequest() - .sellerFulfillmentOrderId(SAMPLE_SELLER_FULFILLMENT_ORDER_ID) - .displayableOrderId("TEST-DISPLAY-001") - .displayableOrderDate(OffsetDateTime.parse("2026-03-27T00:00:00Z")) - .displayableOrderComment("MCF code recipe test order") - .shippingSpeedCategory(ShippingSpeedCategory.STANDARD) + .sellerFulfillmentOrderId(SAMPLE_SELLER_FULFILLMENT_ORDER_ID) // Your unique order ID (max 40 chars) + .displayableOrderId("TEST-DISPLAY-001") // Shown to the customer on packing slip + .displayableOrderDate(OffsetDateTime.parse("2026-03-27T00:00:00Z")) // Order date shown to customer + .displayableOrderComment("MCF code recipe test order") // Comment on packing slip + .shippingSpeedCategory(ShippingSpeedCategory.STANDARD) // STANDARD | EXPEDITED | PRIORITY .destinationAddress(address) .items(itemList); + // Optional fields you may add: + // .notificationEmails(Arrays.asList("customer@example.com")) + // .featureConstraints(...) — Features can be BLANK_BOX or BLOCK_AMZL + // .fulfillmentPolicy(FulfillmentPolicy.FILL_OR_KILL) + // FillOrKill - it's all-or-nothing, ideal when partial fulfillment isn't acceptable. + // FillAll - All fulfillable items are shipped. Any unfulfillable items remain open for the seller to decide. + // FillAllAvailable - All fulfillable items are shipped immediately. All unfulfillable items are automatically cancelled. } + // -- Step 2 (alternate): createFulfillmentOrder with Hold action --------------- + // Use this payload to create an order that is NOT shipped immediately. + // The order stays on hold until you call updateFulfillmentOrder with fulfillmentAction=Ship to release it. + /** * Build a sample createFulfillmentOrder request body with Hold action. - * The order is created but NOT shipped until you call updateFulfillmentOrder - * with fulfillmentAction=Ship to release it. */ public static CreateFulfillmentOrderRequest sampleCreateOrderRequestOnHold() { Address address = new Address() @@ -101,20 +120,20 @@ public static CreateFulfillmentOrderRequest sampleCreateOrderRequestOnHold() { .countryCode("US"); CreateFulfillmentOrderItem item = new CreateFulfillmentOrderItem() - .sellerSku("MY-SKU-001") - .sellerFulfillmentOrderItemId("item-001") + .sellerSku("MY-SKU-001") // Must match an FBA-enrolled SKU + .sellerFulfillmentOrderItemId("item-001") // Your unique line-item ID .quantity(1); CreateFulfillmentOrderItemList itemList = new CreateFulfillmentOrderItemList(); itemList.add(item); return new CreateFulfillmentOrderRequest() - .sellerFulfillmentOrderId(SAMPLE_SELLER_FULFILLMENT_ORDER_ID) - .displayableOrderId("TEST-DISPLAY-001") - .displayableOrderDate(OffsetDateTime.parse("2026-03-27T00:00:00Z")) - .displayableOrderComment("MCF code recipe test order - On Hold") - .shippingSpeedCategory(ShippingSpeedCategory.STANDARD) - .fulfillmentAction(FulfillmentAction.HOLD) + .sellerFulfillmentOrderId(SAMPLE_SELLER_FULFILLMENT_ORDER_ID) // Your unique order ID (max 40 chars) + .displayableOrderId("TEST-DISPLAY-001") // Shown to the customer on packing slip + .displayableOrderDate(OffsetDateTime.parse("2026-03-27T00:00:00Z")) // Order date shown to customer + .displayableOrderComment("MCF code recipe test order") // Comment on packing slip + .shippingSpeedCategory(ShippingSpeedCategory.STANDARD) // STANDARD | EXPEDITED | PRIORITY + .fulfillmentAction(FulfillmentAction.HOLD) // Hold = do not ship yet .destinationAddress(address) .items(itemList); } diff --git a/code-recipes/python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/constants.py b/code-recipes/python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/constants.py index ce275639..fdc2191a 100644 --- a/code-recipes/python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/constants.py +++ b/code-recipes/python/src/recipes/multichannel_fulfillment/fulfillment_outbound_v1/constants.py @@ -1,5 +1,5 @@ """ -Sample constants for the MCF (Multichannel Fulfillment) order processing recipes. +Sample Payloads for the MCF (Multichannel Fulfillment) order processing recipes. These provide realistic sample payloads for the MCF workflows. When adapting these for your own application, replace the placeholder values marked with @@ -9,8 +9,8 @@ """ # -- Step 1: getFulfillmentPreview request body -------------------------------- -# Use this to check shipping speeds, estimated delivery dates, and fees -# BEFORE committing to an order. +# Use this to check shipping speeds, estimated delivery dates, and fees before committing to an order. + sample_preview_request = { "address": { "name": "", @@ -29,6 +29,13 @@ ], # Optional fields you may add: # "shippingSpeedCategories": ["Standard", "Expedited", "Priority"], + # + # "featureConstraints": [ + # { + # "featureName": "BLOCK_AMZL", # Features can be BLANK_BOX or BLOCK_AMZL + # "featureFulfillmentPolicy": "Required" + # } + # ] } @@ -57,19 +64,22 @@ ], # Optional fields you may add: # "notificationEmails": ["customer@example.com"], - # "featureConstraints": [{"featureName": "BLANK_BOX", "featureFulfillmentPolicy": "Required"}], + # "featureConstraints": [{"featureName": "BLANK_BOX", "featureFulfillmentPolicy": "Required"}], # Features can be BLANK_BOX or BLOCK_AMZL + # "fulfillmentPolicy": "FillOrKill" # FillorKill | FillAll | FillAllAvailable + # FillorKill - it's all-or-nothing, ideal when partial fulfillment isn't acceptable. + # FillAll - All fulfillable items are shipped. Any unfulfillable items remain open for the seller to decide. + # FillAllAvailable - All fulfillable items are shipped immediately. All unfulfillable items are automatically cancelled. } # -- Step 2 (alternate version for Hold orders): createFulfillmentOrder with Hold action --------------- # Use this payload to create an order that is NOT shipped immediately. -# The order stays on hold until you call updateFulfillmentOrder with -# fulfillmentAction=Ship to release it. +# The order stays on hold until you call updateFulfillmentOrder with "fulfillmentAction"="Ship" to release it. sample_create_order_request_on_hold = { - "sellerFulfillmentOrderId": "MCF-TEST-ORDER-001", - "displayableOrderId": "TEST-DISPLAY-001", - "displayableOrderDate": "2026-03-27T00:00:00Z", - "displayableOrderComment": "MCF code recipe test order - On Hold", - "shippingSpeedCategory": "Standard", + "sellerFulfillmentOrderId": "MCF-TEST-ORDER-001", # Your unique order ID (max 40 chars) + "displayableOrderId": "TEST-DISPLAY-001", # Shown to the customer on packing slip + "displayableOrderDate": "2026-03-27T00:00:00Z", # Order date shown to customer + "displayableOrderComment": "MCF code recipe test order", # Comment on packing slip + "shippingSpeedCategory": "Standard", # Standard | Expedited | Priority "fulfillmentAction": "Hold", # Hold = do not ship yet "destinationAddress": { "name": "", @@ -81,8 +91,8 @@ }, "items": [ { - "sellerSku": "MY-SKU-001", - "sellerFulfillmentOrderItemId": "item-001", + "sellerSku": "MY-SKU-001", # Must match an FBA-enrolled SKU + "sellerFulfillmentOrderItemId": "item-001", # Your unique line-item ID "quantity": 1, } ],