shopify_api 16.1.0 → 16.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.claude/skills/investigating-github-issues/SKILL.md +171 -0
- data/.claude/skills/investigating-github-issues/references/investigation-report-template.md +90 -0
- data/.claude/skills/shared/references/version-maintenance-policy.md +20 -0
- data/.github/CODEOWNERS +1 -1
- data/.github/workflows/gardener-investigate-issue.yml +226 -0
- data/.github/workflows/gardener-notify-event.yml +35 -0
- data/.github/workflows/gardener-notify-slack.yml +116 -0
- data/CHANGELOG.md +11 -0
- data/Gemfile.lock +9 -3
- data/REST_RESOURCES.md +9 -12
- data/docs/usage/oauth.md +4 -5
- data/lib/shopify_api/admin_versions.rb +2 -0
- data/lib/shopify_api/auth/client_credentials.rb +3 -2
- data/lib/shopify_api/auth/refresh_token.rb +3 -2
- data/lib/shopify_api/auth/token_exchange.rb +18 -8
- data/lib/shopify_api/clients/graphql/storefront.rb +3 -2
- data/lib/shopify_api/context.rb +5 -1
- data/lib/shopify_api/errors/invalid_shop_error.rb +9 -0
- data/lib/shopify_api/errors/rest_resource_not_loaded_error.rb +14 -0
- data/lib/shopify_api/rest/resources/2026_04/abandoned_checkout.rb +194 -0
- data/lib/shopify_api/rest/resources/2026_04/access_scope.rb +62 -0
- data/lib/shopify_api/rest/resources/2026_04/apple_pay_certificate.rb +109 -0
- data/lib/shopify_api/rest/resources/2026_04/application_charge.rb +113 -0
- data/lib/shopify_api/rest/resources/2026_04/application_credit.rb +95 -0
- data/lib/shopify_api/rest/resources/2026_04/article.rb +269 -0
- data/lib/shopify_api/rest/resources/2026_04/asset.rb +122 -0
- data/lib/shopify_api/rest/resources/2026_04/assigned_fulfillment_order.rb +92 -0
- data/lib/shopify_api/rest/resources/2026_04/balance.rb +58 -0
- data/lib/shopify_api/rest/resources/2026_04/blog.rb +166 -0
- data/lib/shopify_api/rest/resources/2026_04/cancellation_request.rb +87 -0
- data/lib/shopify_api/rest/resources/2026_04/carrier_service.rb +120 -0
- data/lib/shopify_api/rest/resources/2026_04/checkout.rb +213 -0
- data/lib/shopify_api/rest/resources/2026_04/collect.rb +146 -0
- data/lib/shopify_api/rest/resources/2026_04/collection.rb +114 -0
- data/lib/shopify_api/rest/resources/2026_04/collection_listing.rb +159 -0
- data/lib/shopify_api/rest/resources/2026_04/comment.rb +287 -0
- data/lib/shopify_api/rest/resources/2026_04/country.rb +141 -0
- data/lib/shopify_api/rest/resources/2026_04/currency.rb +61 -0
- data/lib/shopify_api/rest/resources/2026_04/custom_collection.rb +191 -0
- data/lib/shopify_api/rest/resources/2026_04/customer.rb +328 -0
- data/lib/shopify_api/rest/resources/2026_04/deprecated_api_call.rb +61 -0
- data/lib/shopify_api/rest/resources/2026_04/discount_code.rb +226 -0
- data/lib/shopify_api/rest/resources/2026_04/dispute.rb +115 -0
- data/lib/shopify_api/rest/resources/2026_04/dispute_evidence.rb +121 -0
- data/lib/shopify_api/rest/resources/2026_04/dispute_file_upload.rb +85 -0
- data/lib/shopify_api/rest/resources/2026_04/draft_order.rb +279 -0
- data/lib/shopify_api/rest/resources/2026_04/event.rb +152 -0
- data/lib/shopify_api/rest/resources/2026_04/fulfillment.rb +235 -0
- data/lib/shopify_api/rest/resources/2026_04/fulfillment_event.rb +167 -0
- data/lib/shopify_api/rest/resources/2026_04/fulfillment_order.rb +326 -0
- data/lib/shopify_api/rest/resources/2026_04/fulfillment_request.rb +116 -0
- data/lib/shopify_api/rest/resources/2026_04/fulfillment_service.rb +131 -0
- data/lib/shopify_api/rest/resources/2026_04/gift_card.rb +222 -0
- data/lib/shopify_api/rest/resources/2026_04/gift_card_adjustment.rb +122 -0
- data/lib/shopify_api/rest/resources/2026_04/image.rb +161 -0
- data/lib/shopify_api/rest/resources/2026_04/inventory_item.rb +112 -0
- data/lib/shopify_api/rest/resources/2026_04/inventory_level.rb +183 -0
- data/lib/shopify_api/rest/resources/2026_04/location.rb +171 -0
- data/lib/shopify_api/rest/resources/2026_04/locations_for_move.rb +60 -0
- data/lib/shopify_api/rest/resources/2026_04/marketing_event.rb +213 -0
- data/lib/shopify_api/rest/resources/2026_04/metafield.rb +348 -0
- data/lib/shopify_api/rest/resources/2026_04/mobile_platform_application.rb +120 -0
- data/lib/shopify_api/rest/resources/2026_04/order.rb +503 -0
- data/lib/shopify_api/rest/resources/2026_04/order_risk.rb +148 -0
- data/lib/shopify_api/rest/resources/2026_04/page.rb +198 -0
- data/lib/shopify_api/rest/resources/2026_04/payment.rb +98 -0
- data/lib/shopify_api/rest/resources/2026_04/payment_gateway.rb +147 -0
- data/lib/shopify_api/rest/resources/2026_04/payment_transaction.rb +117 -0
- data/lib/shopify_api/rest/resources/2026_04/payout.rb +101 -0
- data/lib/shopify_api/rest/resources/2026_04/policy.rb +73 -0
- data/lib/shopify_api/rest/resources/2026_04/price_rule.rb +227 -0
- data/lib/shopify_api/rest/resources/2026_04/product.rb +227 -0
- data/lib/shopify_api/rest/resources/2026_04/product_listing.rb +200 -0
- data/lib/shopify_api/rest/resources/2026_04/product_resource_feedback.rb +92 -0
- data/lib/shopify_api/rest/resources/2026_04/province.rb +136 -0
- data/lib/shopify_api/rest/resources/2026_04/recurring_application_charge.rb +184 -0
- data/lib/shopify_api/rest/resources/2026_04/redirect.rb +143 -0
- data/lib/shopify_api/rest/resources/2026_04/refund.rb +158 -0
- data/lib/shopify_api/rest/resources/2026_04/resource_feedback.rb +77 -0
- data/lib/shopify_api/rest/resources/2026_04/script_tag.rb +159 -0
- data/lib/shopify_api/rest/resources/2026_04/shipping_zone.rb +87 -0
- data/lib/shopify_api/rest/resources/2026_04/shop.rb +231 -0
- data/lib/shopify_api/rest/resources/2026_04/smart_collection.rb +220 -0
- data/lib/shopify_api/rest/resources/2026_04/storefront_access_token.rb +91 -0
- data/lib/shopify_api/rest/resources/2026_04/tender_transaction.rb +97 -0
- data/lib/shopify_api/rest/resources/2026_04/theme.rb +127 -0
- data/lib/shopify_api/rest/resources/2026_04/transaction.rb +194 -0
- data/lib/shopify_api/rest/resources/2026_04/usage_charge.rb +106 -0
- data/lib/shopify_api/rest/resources/2026_04/user.rb +142 -0
- data/lib/shopify_api/rest/resources/2026_04/variant.rb +212 -0
- data/lib/shopify_api/rest/resources/2026_04/webhook.rb +173 -0
- data/lib/shopify_api/rest/resources/2026_07/abandoned_checkout.rb +194 -0
- data/lib/shopify_api/rest/resources/2026_07/access_scope.rb +62 -0
- data/lib/shopify_api/rest/resources/2026_07/apple_pay_certificate.rb +109 -0
- data/lib/shopify_api/rest/resources/2026_07/application_charge.rb +113 -0
- data/lib/shopify_api/rest/resources/2026_07/application_credit.rb +95 -0
- data/lib/shopify_api/rest/resources/2026_07/article.rb +269 -0
- data/lib/shopify_api/rest/resources/2026_07/asset.rb +122 -0
- data/lib/shopify_api/rest/resources/2026_07/assigned_fulfillment_order.rb +92 -0
- data/lib/shopify_api/rest/resources/2026_07/balance.rb +58 -0
- data/lib/shopify_api/rest/resources/2026_07/blog.rb +166 -0
- data/lib/shopify_api/rest/resources/2026_07/cancellation_request.rb +87 -0
- data/lib/shopify_api/rest/resources/2026_07/carrier_service.rb +120 -0
- data/lib/shopify_api/rest/resources/2026_07/checkout.rb +213 -0
- data/lib/shopify_api/rest/resources/2026_07/collect.rb +146 -0
- data/lib/shopify_api/rest/resources/2026_07/collection.rb +114 -0
- data/lib/shopify_api/rest/resources/2026_07/collection_listing.rb +159 -0
- data/lib/shopify_api/rest/resources/2026_07/comment.rb +287 -0
- data/lib/shopify_api/rest/resources/2026_07/country.rb +141 -0
- data/lib/shopify_api/rest/resources/2026_07/currency.rb +61 -0
- data/lib/shopify_api/rest/resources/2026_07/custom_collection.rb +191 -0
- data/lib/shopify_api/rest/resources/2026_07/customer.rb +328 -0
- data/lib/shopify_api/rest/resources/2026_07/deprecated_api_call.rb +61 -0
- data/lib/shopify_api/rest/resources/2026_07/discount_code.rb +226 -0
- data/lib/shopify_api/rest/resources/2026_07/dispute.rb +115 -0
- data/lib/shopify_api/rest/resources/2026_07/dispute_evidence.rb +121 -0
- data/lib/shopify_api/rest/resources/2026_07/dispute_file_upload.rb +85 -0
- data/lib/shopify_api/rest/resources/2026_07/draft_order.rb +279 -0
- data/lib/shopify_api/rest/resources/2026_07/event.rb +152 -0
- data/lib/shopify_api/rest/resources/2026_07/fulfillment.rb +235 -0
- data/lib/shopify_api/rest/resources/2026_07/fulfillment_event.rb +167 -0
- data/lib/shopify_api/rest/resources/2026_07/fulfillment_order.rb +326 -0
- data/lib/shopify_api/rest/resources/2026_07/fulfillment_request.rb +116 -0
- data/lib/shopify_api/rest/resources/2026_07/fulfillment_service.rb +131 -0
- data/lib/shopify_api/rest/resources/2026_07/gift_card.rb +222 -0
- data/lib/shopify_api/rest/resources/2026_07/gift_card_adjustment.rb +122 -0
- data/lib/shopify_api/rest/resources/2026_07/image.rb +161 -0
- data/lib/shopify_api/rest/resources/2026_07/inventory_item.rb +112 -0
- data/lib/shopify_api/rest/resources/2026_07/inventory_level.rb +183 -0
- data/lib/shopify_api/rest/resources/2026_07/location.rb +171 -0
- data/lib/shopify_api/rest/resources/2026_07/locations_for_move.rb +60 -0
- data/lib/shopify_api/rest/resources/2026_07/marketing_event.rb +213 -0
- data/lib/shopify_api/rest/resources/2026_07/metafield.rb +348 -0
- data/lib/shopify_api/rest/resources/2026_07/mobile_platform_application.rb +120 -0
- data/lib/shopify_api/rest/resources/2026_07/order.rb +503 -0
- data/lib/shopify_api/rest/resources/2026_07/order_risk.rb +148 -0
- data/lib/shopify_api/rest/resources/2026_07/page.rb +198 -0
- data/lib/shopify_api/rest/resources/2026_07/payment.rb +98 -0
- data/lib/shopify_api/rest/resources/2026_07/payment_gateway.rb +147 -0
- data/lib/shopify_api/rest/resources/2026_07/payment_transaction.rb +117 -0
- data/lib/shopify_api/rest/resources/2026_07/payout.rb +101 -0
- data/lib/shopify_api/rest/resources/2026_07/policy.rb +73 -0
- data/lib/shopify_api/rest/resources/2026_07/price_rule.rb +227 -0
- data/lib/shopify_api/rest/resources/2026_07/product.rb +227 -0
- data/lib/shopify_api/rest/resources/2026_07/product_listing.rb +200 -0
- data/lib/shopify_api/rest/resources/2026_07/product_resource_feedback.rb +92 -0
- data/lib/shopify_api/rest/resources/2026_07/province.rb +136 -0
- data/lib/shopify_api/rest/resources/2026_07/recurring_application_charge.rb +184 -0
- data/lib/shopify_api/rest/resources/2026_07/redirect.rb +143 -0
- data/lib/shopify_api/rest/resources/2026_07/refund.rb +158 -0
- data/lib/shopify_api/rest/resources/2026_07/resource_feedback.rb +77 -0
- data/lib/shopify_api/rest/resources/2026_07/script_tag.rb +159 -0
- data/lib/shopify_api/rest/resources/2026_07/shipping_zone.rb +87 -0
- data/lib/shopify_api/rest/resources/2026_07/shop.rb +231 -0
- data/lib/shopify_api/rest/resources/2026_07/smart_collection.rb +220 -0
- data/lib/shopify_api/rest/resources/2026_07/storefront_access_token.rb +91 -0
- data/lib/shopify_api/rest/resources/2026_07/tender_transaction.rb +97 -0
- data/lib/shopify_api/rest/resources/2026_07/theme.rb +127 -0
- data/lib/shopify_api/rest/resources/2026_07/transaction.rb +194 -0
- data/lib/shopify_api/rest/resources/2026_07/usage_charge.rb +106 -0
- data/lib/shopify_api/rest/resources/2026_07/user.rb +142 -0
- data/lib/shopify_api/rest/resources/2026_07/variant.rb +212 -0
- data/lib/shopify_api/rest/resources/2026_07/webhook.rb +173 -0
- data/lib/shopify_api/utils/shop_validator.rb +118 -0
- data/lib/shopify_api/version.rb +1 -1
- data/lib/shopify_api/webhooks/request.rb +17 -10
- data/lib/shopify_api.rb +69 -0
- data/shopify_api.gemspec +2 -0
- metadata +183 -2
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
name: Gardener - Notify Slack
|
|
2
|
+
# Runs after `Gardener - Notify Event` completes and does the real work:
|
|
3
|
+
# applies the devtools-gardener label and posts a summary to Slack.
|
|
4
|
+
#
|
|
5
|
+
# The workflow_run trigger runs this job in the default-branch context with
|
|
6
|
+
# full GITHUB_TOKEN permissions and Actions secret access — this is what
|
|
7
|
+
# lets it succeed for Dependabot-opened PRs, where the upstream event
|
|
8
|
+
# workflow can't label or reach secrets directly.
|
|
9
|
+
on:
|
|
10
|
+
workflow_run:
|
|
11
|
+
workflows: ['Gardener - Notify Event']
|
|
12
|
+
types: [completed]
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
issues: write
|
|
17
|
+
pull-requests: write
|
|
18
|
+
actions: read
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
notify:
|
|
22
|
+
# `conclusion == success` also covers runs where the capture job was
|
|
23
|
+
# skipped by its `if` gate (no matching label, etc.) — in that case
|
|
24
|
+
# no artifact was uploaded, so the download step below no-ops.
|
|
25
|
+
if: github.event.workflow_run.conclusion == 'success'
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
steps:
|
|
28
|
+
- name: Download event payload
|
|
29
|
+
id: download
|
|
30
|
+
continue-on-error: true
|
|
31
|
+
uses: actions/download-artifact@v4
|
|
32
|
+
with:
|
|
33
|
+
name: gardener-event
|
|
34
|
+
run-id: ${{ github.event.workflow_run.id }}
|
|
35
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
36
|
+
|
|
37
|
+
- name: Add devtools-gardener label
|
|
38
|
+
if: steps.download.outcome == 'success'
|
|
39
|
+
env:
|
|
40
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
41
|
+
GH_REPO: ${{ github.repository }}
|
|
42
|
+
run: |
|
|
43
|
+
ACTION=$(jq -r '.action' event.json)
|
|
44
|
+
# On `labeled` events the label is already there — skip.
|
|
45
|
+
if [ "$ACTION" != "opened" ]; then
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
NUMBER=$(jq -r '(.issue // .pull_request).number' event.json)
|
|
49
|
+
if jq -e 'has("pull_request")' event.json > /dev/null; then
|
|
50
|
+
gh pr edit "$NUMBER" --add-label devtools-gardener
|
|
51
|
+
else
|
|
52
|
+
gh issue edit "$NUMBER" --add-label devtools-gardener
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
- name: Post to Slack
|
|
56
|
+
if: steps.download.outcome == 'success'
|
|
57
|
+
continue-on-error: true
|
|
58
|
+
env:
|
|
59
|
+
SLACK_BOT_TOKEN: ${{ secrets.SLACK_GARDENER_BOT_TOKEN }}
|
|
60
|
+
SLACK_CHANNEL_ID: ${{ vars.GARDENER_SLACK_CHANNEL_ID }}
|
|
61
|
+
run: |
|
|
62
|
+
KIND=$(jq -r 'if has("pull_request") then "PR" else "Issue" end' event.json)
|
|
63
|
+
# Pull the body out, truncate, then convert GitHub Markdown to
|
|
64
|
+
# Slack mrkdwn. Links and fenced code blocks are stashed before
|
|
65
|
+
# the HTML-escape pass so their contents survive verbatim (a `&`
|
|
66
|
+
# inside a URL must stay raw, and code content shouldn't be
|
|
67
|
+
# mangled). Blockquote `> ` markers are also stashed so the
|
|
68
|
+
# `>` → `>` escape doesn't break them. Everything else is
|
|
69
|
+
# HTML-escaped so user-supplied `<`, `>`, `&` can't collide
|
|
70
|
+
# with Slack link syntax or injected mentions like <!channel>.
|
|
71
|
+
BODY=$(jq -r '(.issue // .pull_request).body // ""' event.json)
|
|
72
|
+
if [ ${#BODY} -gt 1000 ]; then
|
|
73
|
+
BODY="${BODY:0:1000}…"
|
|
74
|
+
fi
|
|
75
|
+
BODY=$(printf '%s' "$BODY" | perl -0777 -pe '
|
|
76
|
+
my @u;
|
|
77
|
+
s{\[([^\]]+)\]\(([^)]+)\)}{push @u, $2; "\x01$#u\x02$1\x03"}ge;
|
|
78
|
+
my @c;
|
|
79
|
+
s{^```[^\n]*\n(.*?)\n```$}{push @c, $1; "\x04$#c\x05"}gems;
|
|
80
|
+
s/^> /\x06/gm;
|
|
81
|
+
s/^#{1,6}\s+(.+)$/*$1*/gm;
|
|
82
|
+
s/\*\*(.+?)\*\*/*$1*/g;
|
|
83
|
+
s/^(\s*)- \[x\]\s+/$1✓ /gm;
|
|
84
|
+
s/^(\s*)[-*]\s+/$1• /gm;
|
|
85
|
+
s/&/&/g;
|
|
86
|
+
s/</</g;
|
|
87
|
+
s/>/>/g;
|
|
88
|
+
s/\x06/> /g;
|
|
89
|
+
s{\x01(\d+)\x02(.*?)\x03}{"<$u[$1]|$2>"}ge;
|
|
90
|
+
s{\x04(\d+)\x05}{"```\n$c[$1]\n```"}ge;
|
|
91
|
+
')
|
|
92
|
+
jq \
|
|
93
|
+
--arg channel "$SLACK_CHANNEL_ID" \
|
|
94
|
+
--arg kind "$KIND" \
|
|
95
|
+
--arg body "$BODY" \
|
|
96
|
+
'
|
|
97
|
+
def escape: gsub("&";"&") | gsub("<";"<") | gsub(">";">");
|
|
98
|
+
|
|
99
|
+
(.issue // .pull_request) as $i
|
|
100
|
+
| ([$i.labels[]?.name | select(. != "devtools-gardener")]
|
|
101
|
+
| map("`\(.)`") | join(" ")) as $labels
|
|
102
|
+
| (if $kind == "PR"
|
|
103
|
+
then " · \($i.changed_files) files, +\($i.additions)/-\($i.deletions)"
|
|
104
|
+
+ (if $i.draft then " · draft" else "" end)
|
|
105
|
+
else "" end) as $meta
|
|
106
|
+
| [ "*<\($i.html_url)|\($kind) #\($i.number)>* — \(($i.title | escape))",
|
|
107
|
+
"_opened by \($i.user.login)\($meta)_" ]
|
|
108
|
+
+ (if $body != "" then [$body] else [] end)
|
|
109
|
+
+ (if $labels != "" then [$labels] else [] end)
|
|
110
|
+
| join("\n") as $msg
|
|
111
|
+
| { channel: $channel, text: "\($kind) #\($i.number): \($i.title)",
|
|
112
|
+
blocks: [{ type: "section", text: { type: "mrkdwn", text: $msg } }] }
|
|
113
|
+
' event.json | curl -sf -X POST \
|
|
114
|
+
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
|
|
115
|
+
-H 'Content-type: application/json; charset=utf-8' \
|
|
116
|
+
-d @- https://slack.com/api/chat.postMessage
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
Note: For changes to the API, see https://shopify.dev/changelog?filter=api
|
|
4
4
|
## Unreleased
|
|
5
5
|
|
|
6
|
+
## 16.3.0 (2026-08-04)
|
|
7
|
+
- [#1443](https://github.com/Shopify/shopify-api-ruby/pull/1443) Add `ShopifyAPI::Utils::ShopValidator` with `sanitize_shop_domain` and `sanitize!`.
|
|
8
|
+
- [#1443](https://github.com/Shopify/shopify-api-ruby/pull/1443) Derive the target shop for `ShopifyAPI::Auth::TokenExchange.exchange_token` from the session token's `dest` claim. The `shop` argument is now deprecated and will be removed in the next major version.
|
|
9
|
+
- [#1454](https://github.com/Shopify/shopify-api-ruby/pull/1454) Add generated REST resource classes for the 2026-07 API version.
|
|
10
|
+
- [#1457](https://github.com/Shopify/shopify-api-ruby/pull/1457) Allow GraphQL Admin API and direct REST clients to target the 2026-10 API version. Generated REST resource classes for 2026-10 are not bundled yet.
|
|
11
|
+
- [#1457](https://github.com/Shopify/shopify-api-ruby/pull/1457) Raise `ShopifyAPI::Errors::RestResourceNotLoadedError` (a `NameError` subclass) with version-specific guidance when generated REST resources aren't bundled, instead of a bare `uninitialized constant` error.
|
|
12
|
+
|
|
13
|
+
## 16.2.0 (2026-04-13)
|
|
14
|
+
- [#1442](https://github.com/Shopify/shopify-api-ruby/pull/1442) Add support for 2026-04 API version
|
|
15
|
+
- [#1437](https://github.com/Shopify/shopify-api-ruby/pull/1437) Support new `shopify-*` webhook header format
|
|
16
|
+
|
|
6
17
|
## 16.1.0 (2026-01-15)
|
|
7
18
|
- Add support for 2026-01 API version
|
|
8
19
|
|
data/Gemfile.lock
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
shopify_api (16.
|
|
4
|
+
shopify_api (16.3.0)
|
|
5
5
|
activesupport
|
|
6
|
+
addressable (~> 2.7)
|
|
6
7
|
concurrent-ruby
|
|
7
8
|
hash_diff
|
|
8
9
|
httparty
|
|
9
10
|
jwt
|
|
11
|
+
logger
|
|
10
12
|
oj
|
|
11
13
|
openssl
|
|
12
14
|
securerandom
|
|
@@ -60,8 +62,9 @@ GEM
|
|
|
60
62
|
logger (1.6.1)
|
|
61
63
|
method_source (1.0.0)
|
|
62
64
|
mini_mime (1.1.5)
|
|
63
|
-
minitest (5.
|
|
64
|
-
mocha (
|
|
65
|
+
minitest (5.27.0)
|
|
66
|
+
mocha (3.0.1)
|
|
67
|
+
ruby2_keywords (>= 0.0.5)
|
|
65
68
|
multi_xml (0.6.0)
|
|
66
69
|
mutex_m (0.3.0)
|
|
67
70
|
netrc (0.11.0)
|
|
@@ -109,6 +112,7 @@ GEM
|
|
|
109
112
|
rubocop-sorbet (0.6.11)
|
|
110
113
|
rubocop (>= 0.90.0)
|
|
111
114
|
ruby-progressbar (1.13.0)
|
|
115
|
+
ruby2_keywords (0.0.5)
|
|
112
116
|
securerandom (0.3.2)
|
|
113
117
|
sorbet (0.5.11230)
|
|
114
118
|
sorbet-static (= 0.5.11230)
|
|
@@ -151,6 +155,8 @@ GEM
|
|
|
151
155
|
PLATFORMS
|
|
152
156
|
arm64-darwin-21
|
|
153
157
|
arm64-darwin-23
|
|
158
|
+
arm64-darwin-24
|
|
159
|
+
arm64-darwin-25
|
|
154
160
|
universal-darwin-22
|
|
155
161
|
x86_64-linux
|
|
156
162
|
|
data/REST_RESOURCES.md
CHANGED
|
@@ -9,29 +9,27 @@ This guide provides step-by-step instructions for adding a new API version to th
|
|
|
9
9
|
## Step 1: Update API Version Constants
|
|
10
10
|
|
|
11
11
|
### Update admin_versions.rb
|
|
12
|
-
Edit `lib/shopify_api/admin_versions.rb` to add your new version:
|
|
12
|
+
Edit `lib/shopify_api/admin_versions.rb` to add your new version and the next upcoming release candidate:
|
|
13
13
|
|
|
14
14
|
```ruby
|
|
15
15
|
module ShopifyAPI
|
|
16
16
|
module AdminVersions
|
|
17
17
|
SUPPORTED_ADMIN_VERSIONS = T.let([
|
|
18
18
|
"unstable",
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
19
|
+
"2026-07", # Next release candidate (always add the next quarterly version)
|
|
20
|
+
"2026-04", # New version being added
|
|
21
|
+
"2026-01",
|
|
22
22
|
# ... other versions
|
|
23
23
|
], T::Array[String])
|
|
24
|
-
|
|
25
|
-
LATEST_SUPPORTED_ADMIN_VERSION = T.let("2025-07", String) # Update if this is the latest stable
|
|
26
|
-
RELEASE_CANDIDATE_ADMIN_VERSION = T.let("2025-10", String) # Update if this is RC
|
|
27
24
|
end
|
|
28
25
|
end
|
|
29
26
|
```
|
|
30
27
|
|
|
31
28
|
**Version Management:**
|
|
32
|
-
- Add new versions to the top of `SUPPORTED_ADMIN_VERSIONS`
|
|
33
|
-
-
|
|
34
|
-
-
|
|
29
|
+
- Add new versions to the top of `SUPPORTED_ADMIN_VERSIONS` (below "unstable")
|
|
30
|
+
- Also add the **next quarterly version** as the upcoming release candidate
|
|
31
|
+
- Shopify API versions follow a quarterly cadence: 01, 04, 07, 10
|
|
32
|
+
- For example, when adding 2026-04, also add 2026-07
|
|
35
33
|
|
|
36
34
|
## Step 2: Create Directory Structure
|
|
37
35
|
|
|
@@ -147,8 +145,7 @@ bundle exec rake test TEST=test/rest/{NEW_VERSION}/*
|
|
|
147
145
|
## Checklist
|
|
148
146
|
|
|
149
147
|
- [ ] Added new version to `SUPPORTED_ADMIN_VERSIONS` in `admin_versions.rb`
|
|
150
|
-
- [ ]
|
|
151
|
-
- [ ] Updated `RELEASE_CANDIDATE_ADMIN_VERSION` if applicable
|
|
148
|
+
- [ ] Added next quarterly version as release candidate to `SUPPORTED_ADMIN_VERSIONS`
|
|
152
149
|
- [ ] Created `lib/shopify_api/rest/resources/{NEW_VERSION}/` directory
|
|
153
150
|
- [ ] Created `test/rest/{NEW_VERSION}/` directory
|
|
154
151
|
- [ ] Copied all resource files from previous version
|
data/docs/usage/oauth.md
CHANGED
|
@@ -72,9 +72,9 @@ exchange a [session token](https://shopify.dev/docs/apps/auth/session-tokens) (S
|
|
|
72
72
|
#### Input
|
|
73
73
|
| Parameter | Type | Required? | Default Value | Notes |
|
|
74
74
|
| -------------- | ---------------------- | :-------: | :-----------: | ----------------------------------------------------------------------------------------------------------- |
|
|
75
|
-
| `
|
|
76
|
-
| `session_token` | `String` | Yes| - | The session token (Shopify Id Token) provided by App Bridge in either the request 'Authorization' header or URL param when the app is loaded in Admin. |
|
|
75
|
+
| `session_token` | `String` | Yes| - | The session token (Shopify Id Token) provided by App Bridge in either the request 'Authorization' header or URL param when the app is loaded in Admin. Its `dest` claim determines which shop receives the token exchange request. |
|
|
77
76
|
| `requested_token_type` | `TokenExchange::RequestedTokenType` | Yes | - | The type of token requested. Online: `TokenExchange::RequestedTokenType::ONLINE_ACCESS_TOKEN` or offline: `TokenExchange::RequestedTokenType::OFFLINE_ACCESS_TOKEN`. |
|
|
77
|
+
| `shop` | `String` | No | `nil` | **Deprecated**, will be removed in v17.0.0. Ignored for the request host; the shop always comes from the session token `dest` claim. If passed, logs a deprecation warning. |
|
|
78
78
|
|
|
79
79
|
#### Output
|
|
80
80
|
This method returns the new `ShopifyAPI::Auth::Session` object from the token exchange,
|
|
@@ -83,14 +83,13 @@ your app should store this `Session` object to be used later [when making authen
|
|
|
83
83
|
#### Example
|
|
84
84
|
```ruby
|
|
85
85
|
|
|
86
|
-
# `shop` is the shop domain name - "this-is-my-example-shop.myshopify.com"
|
|
87
86
|
# `session_token` is the session token provided by App Bridge either in:
|
|
88
87
|
# - the request 'Authorization' header as `Bearer this-is-the-session_token`
|
|
89
88
|
# - or as a URL param `id_token=this-is-the-session_token`
|
|
89
|
+
# The shop is taken from the token's `dest` claim (see session token documentation).
|
|
90
90
|
|
|
91
|
-
def authenticate(
|
|
91
|
+
def authenticate(session_token)
|
|
92
92
|
session = ShopifyAPI::Auth::TokenExchange.exchange_token(
|
|
93
|
-
shop: shop,
|
|
94
93
|
session_token: session_token,
|
|
95
94
|
requested_token_type: ShopifyAPI::Auth::TokenExchange::RequestedTokenType::OFFLINE_ACCESS_TOKEN,
|
|
96
95
|
# or if you're requesting an online access token:
|
|
@@ -22,7 +22,8 @@ module ShopifyAPI
|
|
|
22
22
|
"ShopifyAPI::Context not setup, please call ShopifyAPI::Context.setup"
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
validated_shop = Utils::ShopValidator.sanitize!(shop)
|
|
26
|
+
shop_session = ShopifyAPI::Auth::Session.new(shop: validated_shop)
|
|
26
27
|
body = {
|
|
27
28
|
client_id: ShopifyAPI::Context.api_key,
|
|
28
29
|
client_secret: ShopifyAPI::Context.api_secret_key,
|
|
@@ -42,7 +43,7 @@ module ShopifyAPI
|
|
|
42
43
|
response_hash = T.cast(response.body, T::Hash[String, T.untyped]).to_h
|
|
43
44
|
|
|
44
45
|
Session.from(
|
|
45
|
-
shop:
|
|
46
|
+
shop: validated_shop,
|
|
46
47
|
access_token_response: Oauth::AccessTokenResponse.from_hash(response_hash),
|
|
47
48
|
)
|
|
48
49
|
end
|
|
@@ -21,7 +21,8 @@ module ShopifyAPI
|
|
|
21
21
|
"ShopifyAPI::Context not setup, please call ShopifyAPI::Context.setup"
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
validated_shop = Utils::ShopValidator.sanitize!(shop)
|
|
25
|
+
shop_session = ShopifyAPI::Auth::Session.new(shop: validated_shop)
|
|
25
26
|
body = {
|
|
26
27
|
client_id: ShopifyAPI::Context.api_key,
|
|
27
28
|
client_secret: ShopifyAPI::Context.api_secret_key,
|
|
@@ -47,7 +48,7 @@ module ShopifyAPI
|
|
|
47
48
|
session_params = T.cast(response.body, T::Hash[String, T.untyped]).to_h
|
|
48
49
|
|
|
49
50
|
Session.from(
|
|
50
|
-
shop
|
|
51
|
+
shop: validated_shop,
|
|
51
52
|
access_token_response: Oauth::AccessTokenResponse.from_hash(session_params),
|
|
52
53
|
)
|
|
53
54
|
end
|
|
@@ -21,12 +21,12 @@ module ShopifyAPI
|
|
|
21
21
|
|
|
22
22
|
sig do
|
|
23
23
|
params(
|
|
24
|
-
shop: String,
|
|
25
24
|
session_token: String,
|
|
26
25
|
requested_token_type: RequestedTokenType,
|
|
26
|
+
shop: T.nilable(String),
|
|
27
27
|
).returns(ShopifyAPI::Auth::Session)
|
|
28
28
|
end
|
|
29
|
-
def exchange_token(
|
|
29
|
+
def exchange_token(session_token:, requested_token_type:, shop: nil)
|
|
30
30
|
unless ShopifyAPI::Context.setup?
|
|
31
31
|
raise ShopifyAPI::Errors::ContextNotSetupError,
|
|
32
32
|
"ShopifyAPI::Context not setup, please call ShopifyAPI::Context.setup"
|
|
@@ -36,10 +36,19 @@ module ShopifyAPI
|
|
|
36
36
|
raise ShopifyAPI::Errors::UnsupportedOauthError,
|
|
37
37
|
"Cannot perform OAuth Token Exchange for non embedded apps." unless ShopifyAPI::Context.embedded?
|
|
38
38
|
|
|
39
|
-
# Validate the session token
|
|
40
|
-
ShopifyAPI::Auth::JwtPayload.new(session_token)
|
|
39
|
+
# Validate the session token and use the shop from the token's `dest` claim
|
|
40
|
+
jwt_payload = ShopifyAPI::Auth::JwtPayload.new(session_token)
|
|
41
|
+
dest_shop = jwt_payload.shop
|
|
42
|
+
|
|
43
|
+
if shop
|
|
44
|
+
ShopifyAPI::Logger.deprecated(
|
|
45
|
+
"The `shop` parameter for `exchange_token` is deprecated and will be removed in v17. " \
|
|
46
|
+
"The shop is now always taken from the session token's `dest` claim.",
|
|
47
|
+
"17.0.0",
|
|
48
|
+
)
|
|
49
|
+
end
|
|
41
50
|
|
|
42
|
-
shop_session = ShopifyAPI::Auth::Session.new(shop:
|
|
51
|
+
shop_session = ShopifyAPI::Auth::Session.new(shop: dest_shop)
|
|
43
52
|
body = {
|
|
44
53
|
client_id: ShopifyAPI::Context.api_key,
|
|
45
54
|
client_secret: ShopifyAPI::Context.api_secret_key,
|
|
@@ -74,7 +83,7 @@ module ShopifyAPI
|
|
|
74
83
|
session_params = T.cast(response.body, T::Hash[String, T.untyped]).to_h
|
|
75
84
|
|
|
76
85
|
Session.from(
|
|
77
|
-
shop:
|
|
86
|
+
shop: dest_shop,
|
|
78
87
|
access_token_response: Oauth::AccessTokenResponse.from_hash(session_params),
|
|
79
88
|
)
|
|
80
89
|
end
|
|
@@ -91,7 +100,8 @@ module ShopifyAPI
|
|
|
91
100
|
"ShopifyAPI::Context not setup, please call ShopifyAPI::Context.setup"
|
|
92
101
|
end
|
|
93
102
|
|
|
94
|
-
|
|
103
|
+
validated_shop = Utils::ShopValidator.sanitize!(shop)
|
|
104
|
+
shop_session = ShopifyAPI::Auth::Session.new(shop: validated_shop)
|
|
95
105
|
body = {
|
|
96
106
|
client_id: ShopifyAPI::Context.api_key,
|
|
97
107
|
client_secret: ShopifyAPI::Context.api_secret_key,
|
|
@@ -120,7 +130,7 @@ module ShopifyAPI
|
|
|
120
130
|
session_params = T.cast(response.body, T::Hash[String, T.untyped]).to_h
|
|
121
131
|
|
|
122
132
|
Session.from(
|
|
123
|
-
shop:
|
|
133
|
+
shop: validated_shop,
|
|
124
134
|
access_token_response: Oauth::AccessTokenResponse.from_hash(session_params),
|
|
125
135
|
)
|
|
126
136
|
end
|
|
@@ -19,9 +19,10 @@ module ShopifyAPI
|
|
|
19
19
|
raise ArgumentError, "Storefront client requires either private_token or public_token to be provided"
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
validated_shop = Utils::ShopValidator.sanitize!(shop)
|
|
22
23
|
session = Auth::Session.new(
|
|
23
|
-
id:
|
|
24
|
-
shop:
|
|
24
|
+
id: validated_shop,
|
|
25
|
+
shop: validated_shop,
|
|
25
26
|
access_token: "",
|
|
26
27
|
is_online: false,
|
|
27
28
|
)
|
data/lib/shopify_api/context.rb
CHANGED
|
@@ -114,7 +114,11 @@ module ShopifyAPI
|
|
|
114
114
|
|
|
115
115
|
unless Dir.exist?(path)
|
|
116
116
|
unless @notified_missing_resources_folder.key?(api_version)
|
|
117
|
-
@logger.warn(
|
|
117
|
+
@logger.warn(
|
|
118
|
+
"shopify_api #{ShopifyAPI::VERSION} does not bundle REST resources for API version " \
|
|
119
|
+
"'#{api_version}', so REST resource classes are unavailable. The GraphQL Admin API and " \
|
|
120
|
+
"the REST client are unaffected.",
|
|
121
|
+
)
|
|
118
122
|
@notified_missing_resources_folder[api_version] = true
|
|
119
123
|
end
|
|
120
124
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module ShopifyAPI
|
|
5
|
+
module Errors
|
|
6
|
+
# Raised when a REST resource class is referenced but this gem version does
|
|
7
|
+
# not bundle REST resources for the active API version.
|
|
8
|
+
#
|
|
9
|
+
# Subclasses NameError so existing `rescue NameError` handling keeps working.
|
|
10
|
+
# Construct it with the missing constant name - `new(message, name)` - so
|
|
11
|
+
# NameError#name keeps returning it, matching the NameError Ruby would raise.
|
|
12
|
+
class RestResourceNotLoadedError < NameError; end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# typed: false
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
########################################################################################################################
|
|
5
|
+
# This file is auto-generated. If you have an issue, please create a GitHub issue. #
|
|
6
|
+
########################################################################################################################
|
|
7
|
+
|
|
8
|
+
module ShopifyAPI
|
|
9
|
+
class AbandonedCheckout < ShopifyAPI::Rest::Base
|
|
10
|
+
extend T::Sig
|
|
11
|
+
|
|
12
|
+
@prev_page_info = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
|
|
13
|
+
@next_page_info = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
|
|
14
|
+
|
|
15
|
+
@api_call_limit = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
|
|
16
|
+
@retry_request_after = T.let(Concurrent::ThreadLocalVar.new { nil }, Concurrent::ThreadLocalVar)
|
|
17
|
+
|
|
18
|
+
sig { params(session: T.nilable(ShopifyAPI::Auth::Session), from_hash: T.nilable(T::Hash[T.untyped, T.untyped])).void }
|
|
19
|
+
def initialize(session: ShopifyAPI::Context.active_session, from_hash: nil)
|
|
20
|
+
|
|
21
|
+
@abandoned_checkout_url = T.let(nil, T.nilable(String))
|
|
22
|
+
@billing_address = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
|
|
23
|
+
@buyer_accepts_marketing = T.let(nil, T.nilable(T::Boolean))
|
|
24
|
+
@buyer_accepts_sms_marketing = T.let(nil, T.nilable(T::Boolean))
|
|
25
|
+
@cart_token = T.let(nil, T.nilable(String))
|
|
26
|
+
@closed_at = T.let(nil, T.nilable(String))
|
|
27
|
+
@completed_at = T.let(nil, T.nilable(String))
|
|
28
|
+
@created_at = T.let(nil, T.nilable(String))
|
|
29
|
+
@currency = T.let(nil, T.nilable(Currency))
|
|
30
|
+
@customer = T.let(nil, T.nilable(Customer))
|
|
31
|
+
@customer_locale = T.let(nil, T.nilable(String))
|
|
32
|
+
@device_id = T.let(nil, T.nilable(Integer))
|
|
33
|
+
@discount_codes = T.let(nil, T.nilable(T::Array[T.untyped]))
|
|
34
|
+
@email = T.let(nil, T.nilable(String))
|
|
35
|
+
@gateway = T.let(nil, T.nilable(String))
|
|
36
|
+
@id = T.let(nil, T.nilable(Integer))
|
|
37
|
+
@landing_site = T.let(nil, T.nilable(String))
|
|
38
|
+
@line_items = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
|
|
39
|
+
@location_id = T.let(nil, T.nilable(Integer))
|
|
40
|
+
@note = T.let(nil, T.nilable(String))
|
|
41
|
+
@phone = T.let(nil, T.nilable(String))
|
|
42
|
+
@presentment_currency = T.let(nil, T.nilable(String))
|
|
43
|
+
@referring_site = T.let(nil, T.nilable(String))
|
|
44
|
+
@shipping_address = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
|
|
45
|
+
@shipping_lines = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
|
|
46
|
+
@sms_marketing_phone = T.let(nil, T.nilable(String))
|
|
47
|
+
@source_name = T.let(nil, T.nilable(String))
|
|
48
|
+
@subtotal_price = T.let(nil, T.nilable(String))
|
|
49
|
+
@tax_lines = T.let(nil, T.nilable(T::Hash[T.untyped, T.untyped]))
|
|
50
|
+
@taxes_included = T.let(nil, T.nilable(T::Boolean))
|
|
51
|
+
@token = T.let(nil, T.nilable(String))
|
|
52
|
+
@total_discounts = T.let(nil, T.nilable(String))
|
|
53
|
+
@total_duties = T.let(nil, T.nilable(String))
|
|
54
|
+
@total_line_items_price = T.let(nil, T.nilable(String))
|
|
55
|
+
@total_price = T.let(nil, T.nilable(String))
|
|
56
|
+
@total_tax = T.let(nil, T.nilable(String))
|
|
57
|
+
@total_weight = T.let(nil, T.nilable(Integer))
|
|
58
|
+
@updated_at = T.let(nil, T.nilable(String))
|
|
59
|
+
@user_id = T.let(nil, T.nilable(Integer))
|
|
60
|
+
|
|
61
|
+
super(session: session, from_hash: from_hash)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
@has_one = T.let({
|
|
65
|
+
currency: Currency,
|
|
66
|
+
customer: Customer
|
|
67
|
+
}, T::Hash[Symbol, Class])
|
|
68
|
+
@has_many = T.let({
|
|
69
|
+
discount_codes: DiscountCode
|
|
70
|
+
}, T::Hash[Symbol, Class])
|
|
71
|
+
@paths = T.let([
|
|
72
|
+
{http_method: :get, operation: :checkouts, ids: [], path: "checkouts.json"},
|
|
73
|
+
{http_method: :get, operation: :checkouts, ids: [], path: "checkouts.json"}
|
|
74
|
+
], T::Array[T::Hash[String, T.any(T::Array[Symbol], String, Symbol)]])
|
|
75
|
+
|
|
76
|
+
sig { returns(T.nilable(String)) }
|
|
77
|
+
attr_reader :abandoned_checkout_url
|
|
78
|
+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
|
|
79
|
+
attr_reader :billing_address
|
|
80
|
+
sig { returns(T.nilable(T::Boolean)) }
|
|
81
|
+
attr_reader :buyer_accepts_marketing
|
|
82
|
+
sig { returns(T.nilable(T::Boolean)) }
|
|
83
|
+
attr_reader :buyer_accepts_sms_marketing
|
|
84
|
+
sig { returns(T.nilable(String)) }
|
|
85
|
+
attr_reader :cart_token
|
|
86
|
+
sig { returns(T.nilable(String)) }
|
|
87
|
+
attr_reader :closed_at
|
|
88
|
+
sig { returns(T.nilable(String)) }
|
|
89
|
+
attr_reader :completed_at
|
|
90
|
+
sig { returns(T.nilable(String)) }
|
|
91
|
+
attr_reader :created_at
|
|
92
|
+
sig { returns(T.nilable(Currency)) }
|
|
93
|
+
attr_reader :currency
|
|
94
|
+
sig { returns(T.nilable(Customer)) }
|
|
95
|
+
attr_reader :customer
|
|
96
|
+
sig { returns(T.nilable(String)) }
|
|
97
|
+
attr_reader :customer_locale
|
|
98
|
+
sig { returns(T.nilable(Integer)) }
|
|
99
|
+
attr_reader :device_id
|
|
100
|
+
sig { returns(T.nilable(T::Array[DiscountCode])) }
|
|
101
|
+
attr_reader :discount_codes
|
|
102
|
+
sig { returns(T.nilable(String)) }
|
|
103
|
+
attr_reader :email
|
|
104
|
+
sig { returns(T.nilable(String)) }
|
|
105
|
+
attr_reader :gateway
|
|
106
|
+
sig { returns(T.nilable(Integer)) }
|
|
107
|
+
attr_reader :id
|
|
108
|
+
sig { returns(T.nilable(String)) }
|
|
109
|
+
attr_reader :landing_site
|
|
110
|
+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
|
|
111
|
+
attr_reader :line_items
|
|
112
|
+
sig { returns(T.nilable(Integer)) }
|
|
113
|
+
attr_reader :location_id
|
|
114
|
+
sig { returns(T.nilable(String)) }
|
|
115
|
+
attr_reader :note
|
|
116
|
+
sig { returns(T.nilable(String)) }
|
|
117
|
+
attr_reader :phone
|
|
118
|
+
sig { returns(T.nilable(String)) }
|
|
119
|
+
attr_reader :presentment_currency
|
|
120
|
+
sig { returns(T.nilable(String)) }
|
|
121
|
+
attr_reader :referring_site
|
|
122
|
+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
|
|
123
|
+
attr_reader :shipping_address
|
|
124
|
+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
|
|
125
|
+
attr_reader :shipping_lines
|
|
126
|
+
sig { returns(T.nilable(String)) }
|
|
127
|
+
attr_reader :sms_marketing_phone
|
|
128
|
+
sig { returns(T.nilable(String)) }
|
|
129
|
+
attr_reader :source_name
|
|
130
|
+
sig { returns(T.nilable(String)) }
|
|
131
|
+
attr_reader :subtotal_price
|
|
132
|
+
sig { returns(T.nilable(T::Hash[T.untyped, T.untyped])) }
|
|
133
|
+
attr_reader :tax_lines
|
|
134
|
+
sig { returns(T.nilable(T::Boolean)) }
|
|
135
|
+
attr_reader :taxes_included
|
|
136
|
+
sig { returns(T.nilable(String)) }
|
|
137
|
+
attr_reader :token
|
|
138
|
+
sig { returns(T.nilable(String)) }
|
|
139
|
+
attr_reader :total_discounts
|
|
140
|
+
sig { returns(T.nilable(String)) }
|
|
141
|
+
attr_reader :total_duties
|
|
142
|
+
sig { returns(T.nilable(String)) }
|
|
143
|
+
attr_reader :total_line_items_price
|
|
144
|
+
sig { returns(T.nilable(String)) }
|
|
145
|
+
attr_reader :total_price
|
|
146
|
+
sig { returns(T.nilable(String)) }
|
|
147
|
+
attr_reader :total_tax
|
|
148
|
+
sig { returns(T.nilable(Integer)) }
|
|
149
|
+
attr_reader :total_weight
|
|
150
|
+
sig { returns(T.nilable(String)) }
|
|
151
|
+
attr_reader :updated_at
|
|
152
|
+
sig { returns(T.nilable(Integer)) }
|
|
153
|
+
attr_reader :user_id
|
|
154
|
+
|
|
155
|
+
class << self
|
|
156
|
+
sig do
|
|
157
|
+
params(
|
|
158
|
+
since_id: T.untyped,
|
|
159
|
+
created_at_min: T.untyped,
|
|
160
|
+
created_at_max: T.untyped,
|
|
161
|
+
updated_at_min: T.untyped,
|
|
162
|
+
updated_at_max: T.untyped,
|
|
163
|
+
status: T.untyped,
|
|
164
|
+
limit: T.untyped,
|
|
165
|
+
session: Auth::Session,
|
|
166
|
+
kwargs: T.untyped
|
|
167
|
+
).returns(T.untyped)
|
|
168
|
+
end
|
|
169
|
+
def checkouts(
|
|
170
|
+
since_id: nil,
|
|
171
|
+
created_at_min: nil,
|
|
172
|
+
created_at_max: nil,
|
|
173
|
+
updated_at_min: nil,
|
|
174
|
+
updated_at_max: nil,
|
|
175
|
+
status: nil,
|
|
176
|
+
limit: nil,
|
|
177
|
+
session: ShopifyAPI::Context.active_session,
|
|
178
|
+
**kwargs
|
|
179
|
+
)
|
|
180
|
+
request(
|
|
181
|
+
http_method: :get,
|
|
182
|
+
operation: :checkouts,
|
|
183
|
+
session: session,
|
|
184
|
+
ids: {},
|
|
185
|
+
params: {since_id: since_id, created_at_min: created_at_min, created_at_max: created_at_max, updated_at_min: updated_at_min, updated_at_max: updated_at_max, status: status, limit: limit}.merge(kwargs).compact,
|
|
186
|
+
body: {},
|
|
187
|
+
entity: nil,
|
|
188
|
+
)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
end
|
|
194
|
+
end
|