Auto-capture payments when an order is created, with Mechanic.

Mechanic is an automation development platform for Shopify. :)

Auto-capture payments when an order is created

by Isaac Bowen (team@usemechanic.com)

This task runs immediately after an order is created, and captures an authorized transaction if one is present. Optionally, choose to only auto-capture orders of a certain risk level, or choose to only capture funds for line items that do not require shipping.

Runs when an order is created. Configuration includes number of minutes to wait before capturing, capture orders with a high risk level, capture orders with a medium risk level, capture orders with a low risk level, and only capture for line items that do not require shipping.

15-day free trial – unlimited tasks

Documentation

This task runs immediately after an order is created. If you are selectively capturing by risk level, and if you have additional apps informing an order's risk level, increase "Number of minutes to wait before capturing" to make sure those apps have time to contribute their data.

Developer details

Mechanic is designed to benefit everybody: merchants, customers, developers, agencies, Gurus, everybody.

That’s why we make it easy to configure automation without code, why we make it easy to tweak the underlying code once tasks are installed, and why we publish it all here for everyone to learn from.

Events
when an order is created (shopify/orders/create)
Options
number of minutes to wait before capturing (number), capture orders with a high risk level (boolean), capture orders with a medium risk level (boolean), capture orders with a low risk level (boolean), only capture for line items that do not require shipping (boolean)
Script
{% assign n = options.number_of_minutes_to_wait_before_capturing__number %}
{% if n != blank and n <= 0 %}
  {"error": "'Number of minutes to wait before capturing' must be positive! :)"}
{% endif %}

{% capture query %}
  query {
    order(id: {{ order.admin_graphql_api_id | json }}) {
      id
      riskLevel
      transactions(first: 1, capturable: true) {
        id
        totalUnsettledSet {
          shopMoney {
            amount
          }
        }
      }
      lineItems(first: 250) {
        pageInfo {
          hasNextPage
        }
        edges {
          node {
            requiresShipping
            discountedTotalSet {
              shopMoney {
                amount
              }
            }
          }
        }
      }
    }
  }
{% endcapture %}

{% assign result = query | shopify %}

{% if event.preview %}
  {% if options.capture_orders_with_a_high_risk_level__boolean %}
    {% assign preview_risk_level = "HIGH" %}
  {% elsif options.capture_orders_with_a_medium_risk_level__boolean %}
    {% assign preview_risk_level = "MEDIUM" %}
  {% elsif options.capture_orders_with_a_low_risk_level__boolean %}
    {% assign preview_risk_level = "LOW" %}
  {% endif %}
  
  {% capture result_json %}
    {
      "data": {
        "order": {
          "id": "gid://shopify/Order/1234567890",
          "capturable": true,
          "riskLevel": {{ preview_risk_level | json }},
          "transactions": [
            {
              "id": "gid://shopify/OrderTransaction/1234567890",
              "totalUnsettledSet": {
                "shopMoney": {
                  "amount": "200.0"
                }
              }
            }
          ],
          "lineItems": {
            "pageInfo": {
              "hasNextPage": false
            },
            "edges": [
              {
                "node": {
                  "requiresShipping": true,
                  "discountedTotalSet": {
                    "shopMoney": {
                      "amount": "10.0"
                    }
                  }
                }
              },
              {
                "node": {
                  "requiresShipping": false,
                  "discountedTotalSet": {
                    "shopMoney": {
                      "amount": "100.0"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  {% endcapture %}

  {% assign result = result_json | parse_json %}
{% endif %}

{% assign orderNode = result.data.order %}
{% assign capturableTransactionNode = orderNode.transactions.first %}

{% assign do_capture = false %}
{% if capturableTransactionNode %}
  {% if orderNode.riskLevel == "HIGH" and options.capture_orders_with_a_high_risk_level__boolean %}
    {% assign do_capture = true %}
  {% elsif orderNode.riskLevel == "MEDIUM" and options.capture_orders_with_a_medium_risk_level__boolean %}
    {% assign do_capture = true %}
  {% elsif orderNode.riskLevel == "LOW" and options.capture_orders_with_a_low_risk_level__boolean %}
    {% assign do_capture = true %}
  {% endif %}
{% endif %}

{% if do_capture %}
  {% assign maximum_amount_to_capture = capturableTransactionNode.totalUnsettledSet.shopMoney.amount | times: 1 %}

  {% if options.only_capture_for_line_items_that_do_not_require_shipping__boolean %}
    {% assign lineItemNodes_noShipping = orderNode.lineItems.edges | map: "node" | where: "requiresShipping", false %}

    {% if lineItemNodes_noShipping.size == orderNode.lineItems.edges.size and orderNode.lineItems.pageInfo.hasNextPage == false %}
      {% comment %}
        Automatically include taxes/etc if every line item qualifies
      {% endcomment %}
      {% assign amount_to_capture = maximum_amount_to_capture %}
    {% else %}
      {% assign amount_to_capture = 0 %}
      {% for lineItemNode in lineItemNodes_noShipping %}
        {% assign amount_to_capture = amount_to_capture | plus: lineItemNode.discountedTotalSet.shopMoney.amount %}
      {% endfor %}

      {% if amount_to_capture > maximum_amount_to_capture %}
        {% assign amount_to_capture = maximum_amount_to_capture %}
      {% endif %}
    {% endif %}
  {% else %}
    {% assign amount_to_capture = maximum_amount_to_capture %}
  {% endif %}

  {% action "shopify" %}
    mutation {
      orderCapture(
        input: {
          id: {{ orderNode.id | json }}
          parentTransactionId: {{ capturableTransactionNode.id | json }}
          amount: {{ amount_to_capture | json }}
        }
      ) {
        transaction {
          status
        }
        userErrors {
          field
          message
        }
      }
    }
  {% endaction %}
{% endif %}
Mechanic tasks are written in Liquid, which makes them easy to write and easy to modify. Learn more about our platform.
Defaults
Capture orders with a low risk level
true