Fulfillment Serviceobject
Contains functions for verifying fulfillment service requests.
See the fulfillment service documentation for more information.
Verifies requests coming from Shopify to fulfillment service apps
- Anchor to requestrequestRequestrequired
AuthenticateFulfillmentService
- request
Request
Promise<FulfillmentServiceContext>
(
request: Request,
) => Promise<FulfillmentServiceContext>
FulfillmentServiceContext
- admin
An admin context for the fulfillment service request. Returned only if there is a session for the shop.
AdminApiContext
- payload
The payload from the fulfillment service request.
FulfillmentServicePayload
- session
A session with an offline token for the shop. Returned only if there is a session for the shop.
Session
export interface FulfillmentServiceContext {
/**
* A session with an offline token for the shop.
*
* Returned only if there is a session for the shop.
* @example
* <caption>Shopify session for the fulfillment service notification request.</caption>
* <description>Use the session associated with this request.</description>
* ```ts
* // /app/routes/fulfillment_service_notification.tsx
* import { ActionFunctionArgs } from "react-router";
* import { authenticate } from "../shopify.server";
*
* export const action = async ({ request }: ActionFunctionArgs) => {
* const { session, admin } = await authenticate.fulfillmentService(request);
*
* console.log(session.id)
*
* return new Response();
* };
* ```
* */
session: Session;
/**
*
* An admin context for the fulfillment service request.
*
* Returned only if there is a session for the shop.
* @example
* <caption>Shopify session for the fulfillment service request.</caption>
* <description>Use the session associated with this request to use the Admin GraphQL API </description>
* ```ts
* // /app/routes/fulfillment_order_notification.ts
* import { ActionFunctionArgs } from "react-router";
* import { authenticate } from "../shopify.server";
*
* export async function action({ request }: ActionFunctionArgs) {
* const { admin, session } = await authenticate.fulfillmentService(request);
*
* console.log(session.id)
*
* return new Response();
* }
* ```
*/
admin: AdminApiContext;
/**
* The payload from the fulfillment service request.
*
* @example
* <caption>Fulfillment service request payload.</caption>
* <description>Get the request's POST payload.</description>
* ```ts
* /app/routes/fulfillment_order_notification.ts
* import { ActionFunction } from "react-router";
* import { authenticate } from "../shopify.server";
*
* export const action: ActionFunction = async ({ request }) => {
* const { payload } = await authenticate.fulfillmentService(request);
* if(payload.kind === 'FULFILLMENT_REQUEST') {
* // handle fulfillment request
* } else if (payload.kind === 'CANCELLATION_REQUEST') {
* // handle cancellation request
* };
* return new Response();
* ```
*/
payload: FulfillmentServicePayload;
}
AdminApiContext
- graphql
Methods for interacting with the Shopify Admin GraphQL API
GraphQLClient<AdminOperations>
export interface AdminApiContext {
/**
* Methods for interacting with the Shopify Admin GraphQL API
*
* {@link https://shopify.dev/docs/api/admin-graphql}
* {@link https://github.com/Shopify/shopify-app-js/blob/main/packages/apps/shopify-api/docs/reference/clients/Graphql.md}
*
* @example
* <caption>Querying the GraphQL API.</caption>
* <description>Use `admin.graphql` to make query / mutation requests.</description>
* ```ts
* // /app/routes/**\/*.ts
* import { ActionFunctionArgs } from "react-router";
* import { authenticate } from "../shopify.server";
*
* export const action = async ({ request }: ActionFunctionArgs) => {
* const { admin } = await authenticate.admin(request);
*
* const response = await admin.graphql(
* `#graphql
* mutation populateProduct($input: ProductInput!) {
* productCreate(input: $input) {
* product {
* id
* }
* }
* }`,
* {
* variables: {
* input: { title: "Product Name" },
* },
* },
* );
*
* const productData = await response.json();
* return ({
* productId: productData.data?.productCreate?.product?.id,
* });
* }
* ```
*
* ```ts
* // /app/shopify.server.ts
* import { shopifyApp } from "@shopify/shopify-app-react-router/server";
*
* const shopify = shopifyApp({
* // ...
* });
* export default shopify;
* export const authenticate = shopify.authenticate;
* ```
*
* @example
* <caption>Handling GraphQL errors.</caption>
* <description>Catch `GraphqlQueryError` errors to see error messages from the API.</description>
* ```ts
* // /app/routes/**\/*.ts
* import { ActionFunctionArgs } from "react-router";
* import { authenticate } from "../shopify.server";
*
* export const action = async ({ request }: ActionFunctionArgs) => {
* const { admin } = await authenticate.admin(request);
*
* try {
* const response = await admin.graphql(
* `#graphql
* query incorrectQuery {
* products(first: 10) {
* nodes {
* not_a_field
* }
* }
* }`,
* );
*
* return ({ data: await response.json() });
* } catch (error) {
* if (error instanceof GraphqlQueryError) {
* // error.body.errors:
* // { graphQLErrors: [
* // { message: "Field 'not_a_field' doesn't exist on type 'Product'" }
* // ] }
* return ({ errors: error.body?.errors }, { status: 500 });
* }
* return ({ message: "An error occurred" }, { status: 500 });
* }
* }
* ```
*
* ```ts
* // /app/shopify.server.ts
* import { shopifyApp } from "@shopify/shopify-app-react-router/server";
*
* const shopify = shopifyApp({
* // ...
* });
* export default shopify;
* export const authenticate = shopify.authenticate;
* ```
*/
graphql: GraphQLClient<AdminOperations>;
}
GraphQLClient
- query
Operation extends keyof Operations
- options
GraphQLQueryOptions<Operation, Operations>
interface Promise<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
}, interface Promise<T> {}, Promise: PromiseConstructor, interface Promise<T> {
readonly [Symbol.toStringTag]: string;
}, interface Promise<T> {
/**
* Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The
* resolved value cannot be modified from the callback.
* @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected).
* @returns A Promise for the completion of the callback.
*/
finally(onfinally?: (() => void) | undefined | null): Promise<T>;
}
<
Operation extends keyof Operations,
>(
query: Operation,
options?: GraphQLQueryOptions<Operation, Operations>,
) => Promise<GraphQLResponse<Operation, Operations>>
GraphQLQueryOptions
- apiVersion
The version of the API to use for the request.
ApiVersion
- headers
Additional headers to include in the request.
Record<string, any>
- signal
An optional AbortSignal to cancel the request.
AbortSignal
- tries
The total number of times to try the request if it fails.
number
- variables
The variables to pass to the operation.
ApiClientRequestOptions<Operation, Operations>["variables"]
export interface GraphQLQueryOptions<
Operation extends keyof Operations,
Operations extends AllOperations,
> {
/**
* The variables to pass to the operation.
*/
variables?: ApiClientRequestOptions<Operation, Operations>['variables'];
/**
* The version of the API to use for the request.
*/
apiVersion?: ApiVersion;
/**
* Additional headers to include in the request.
*/
headers?: Record<string, any>;
/**
* The total number of times to try the request if it fails.
*/
tries?: number;
/**
* An optional AbortSignal to cancel the request.
*/
signal?: AbortSignal;
}
FulfillmentServicePayload
Record<string, any> & {
kind: string;
}
Consume a fulfillment service notification request
/app/routes/**.ts
examples
Consume a fulfillment service notification request
description
Handle a fulfillment service notification call
/app/routes/**.ts
import {type ActionFunctionArgs} from 'react-router'; import {authenticate} from '../shopify.server'; export const action = async ({request}: ActionFunctionArgs) => { const {admin, payload} = await authenticate.fulfillmentService(request); const kind = payload.kind; if (kind === 'FULFILLMENT_REQUEST') { const response = await admin?.graphql( `#graphql query { shop { assignedFulfillmentOrders(first: 10, assignmentStatus: FULFILLMENT_REQUESTED) { edges { node { id destination { firstName lastName } lineItems(first: 10) { edges { node { id productTitle sku remainingQuantity } } } merchantRequests(first: 10, kind: FULFILLMENT_REQUEST) { edges { node { message } } } } } } } }`, ); const fulfillments = await response.json(); console.log(fulfillments); } return new Response(); };
Anchor to examplesExamples
Anchor to example-shopify-session-for-the-fulfillment-service-requestShopify session for the fulfillment service request
Use the session associated with this request to use the Admin GraphQL API
Shopify session for the fulfillment service request
/app/routes/fulfillment_order_notification.ts
examples
Shopify session for the fulfillment service request
description
Use the session associated with this request to use the Admin GraphQL API
/app/routes/fulfillment_order_notification.ts
import { ActionFunctionArgs } from "react-router"; import { authenticate } from "../shopify.server"; export async function action({ request }: ActionFunctionArgs) { const { admin, session } = await authenticate.fulfillmentService(request); console.log(session.id) return new Response(); }
Anchor to example-payloadpayload
Anchor to example-fulfillment-service-request-payloadFulfillment service request payload
Get the request's POST payload.
Fulfillment service request payload
Example
examples
Fulfillment service request payload
description
Get the request's POST payload.
Example
/app/routes/fulfillment_order_notification.ts import { ActionFunction } from "react-router"; import { authenticate } from "../shopify.server"; export const action: ActionFunction = async ({ request }) => { const { payload } = await authenticate.fulfillmentService(request); if(payload.kind === 'FULFILLMENT_REQUEST') { // handle fulfillment request } else if (payload.kind === 'CANCELLATION_REQUEST') { // handle cancellation request }; return new Response();
Anchor to example-sessionsession
Anchor to example-shopify-session-for-the-fulfillment-service-notification-requestShopify session for the fulfillment service notification request
Use the session associated with this request.
Shopify session for the fulfillment service notification request
/app/routes/fulfillment_service_notification.tsx
examples
Shopify session for the fulfillment service notification request
description
Use the session associated with this request.
/app/routes/fulfillment_service_notification.tsx
import { ActionFunctionArgs } from "react-router"; import { authenticate } from "../shopify.server"; export const action = async ({ request }: ActionFunctionArgs) => { const { session, admin } = await authenticate.fulfillmentService(request); console.log(session.id) return new Response(); };