Skip to main content

Monitoring and resiliency

It's highly recommended to instrument your integration with sufficient logging to gain insights into any errors thrown by your system. At a minimum, failure paths in your event handlers should all be considered, and notifications should alert your team of issues as needed.

Shopify provides webhook subscriptions and APIs enabling multiple ways for you to monitor activity in your shop. The below guidelines are applicable to Shop Pay Wallet.


Anchor to Webhook ConfigurationWebhook Configuration

At a minimum, you should be to setting up the following webhooks:

Webhook TopicDescription
ORDERS_CREATEA webhook is sent every time an order is created.
ORDER_TRANSACTIONS_CREATEA webhook is sent every time an order transaction is created.
DISPUTES_CREATEA webhook is sent every time a dispute is created. This requires the read_shopify_payments_disputes scope on your custom app.
DISPUTES_UPDATEA webhook is sent every time a dispute is updated. This requires the read_shopify_payments_disputes scope on your custom app.

It's important to note that webhook delivery may be delayed, and must therefore never be depended on for real-time critical workflows such as completing a customer checkout.

To learn more, see the webhooks documentation, and our webhook topic resources for GraphQL and REST APIs.


Anchor to Creating a Webhook SubscriptionCreating a Webhook Subscription

Example of creating new webhook subscription for the topic "ORDERS_CREATE" using the webhookSubscriptionCreate mutation:

Mutation

mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {
webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) {
webhookSubscription {
id
topic
format
uri
}
userErrors {
field
message
}
}
}

Input

{
"topic": "ORDERS_CREATE",
"webhookSubscription": {
"uri": "https://yoursite.com/webhooks/orders_create",
"format": "JSON"
}
}

Response

{
"webhookSubscriptionCreate": {
"webhookSubscription": {
"id": "gid://shopify/WebhookSubscription/1",
"topic": "ORDERS_CREATE",
"format": "JSON",
"uri": "https://yoursite.com/webhooks/orders_create"
},
"userErrors": []
}
}

A dispute, also known as a chargeback or inquiry, occurs when a customer questions the legitimacy of a charge with their financial institution.

To effectively manage disputes, you must either subscribe to the appropriate webhook topics and use the Shopify Admin API as necessary, or manage the disputes through the Shopify admin.

When a dispute is filed, you're able to provide additional information to support the legitimacy of the charge before the time limit. In any case, Shopify will ensure that evidence is submitted on your behalf, whether you take action or not.

Orders may also be eligible for Shopify Protect, in which case Shopify will reimburse you for the disputed amount and chargeback fee if it is lost.

For more information on dispute management, see the Shopify Payments Disputes Documentation.


Orders in Shopify will undergo a risk assessment after order creation. You can either query the OrderRiskSummary, or you can subscribe to the ORDERS_RISK_ASSESSMENT_CHANGED webhook. Orders can trigger automation events using Shopify Flow – see the flow reference risk examples for details.


Anchor to Recovering from errorsRecovering from errors

Although an order created event will be fired client-side when an order is completed, it's possible that a customer may close the window before the event is dispatched. In order to reconcile in such cases it is recommended to have a reconciliation job running on a schedule.


While webhook deliveries are recommended as the primary method for Shopify to trigger actions in your system, reconciliation jobs should always be implemented as well, as they serve multiple purposes:

  • In case the Shop Pay window is closed before the paymentcomplete event is dispatched
  • As a backup to webhooks, since webhooks may fail to be processed
  • To retrieve data which may not otherwise be available via webhook subscription

Anchor to Retrieving order data using the source identifierRetrieving order data using the source identifier

You can find shopPayPaymentRequestReceipts by their source_identifier (provided on ShopPayRequestSessionCreate mutation), which should correspond to the order in your system. For example, if the source identifier provided by your system for a given order was your-source-id-1, then you could issue a GraphQL request like below:

{
shopPayPaymentRequestReceipts(first:10, query: "source_identifier:'your-source-id-1'") {
nodes {
token
sourceIdentifier
processingStatus {
state
message
errorCode
}
order {
id
sourceIdentifier
transactions(first: 10) {
id
kind
errorCode
}
fulfillmentOrders(first: 10) {
nodes {
id
}
}
}
paymentRequest {
total {
amount
currencyCode
}
}
}
}
}

Note that while the above example request could result in multiple matching receipts, there will only be one corresponding order for a successfully completed receipt. The order may have multiple transactions (including failed payment attempts), fulfillmentOrders and lineItems.

Because of this, your system must filter the results received. For example with transactions you would filter by kind: "authorization" and status: "success" to identify the transaction authorization ID needed when capturing payment.

It's recommended to modify this example query to only retrieve the data required by your system, and introduce pagination where necessary.

Anchor to Retrieving order data using the receipt tokenRetrieving order data using the receipt token

Alternatively, order data can be retrieved using the shopPayPaymentRequestReceipt query. The receipt token is returned from the ShopPayPaymentRequestSessionSubmit mutation. This query can be used to find the status of the payment request receipt. The status can be processing, completed, action_required (for example, if the customer needs to complete a 3DS authentication. This is automatically handled by Shop Pay popup), or failed. The processingStatus message and errorCode can be used to provide more information about the status for failed receipts.

query {
shopPayPaymentRequestReceipt(token: "<token>") {
token
sourceIdentifier
processingStatus {
state
message
errorCode
}
order {
id
sourceIdentifier
transactions(first: 10) {
id
kind
errorCode
}
fulfillmentOrders(first: 10) {
nodes {
id
}
}
}
paymentRequest {
total {
amount
currencyCode
}
}
}
}

Was this page helpful?