1 | |
2 |
|
3 | |
4 | * Process Return |
5 | * Process the items of an open return: mark the given return line items ({ id, quantity }) as processed and optionally refund the customer. To refund, pass the order's paid transaction id (refund_transaction_id), the amount to send back to it and the order's currency_code; refund_shipping refunds the full shipping. Replaces the deprecated returnRefund. Needs the write_returns scope. |
6 | */ |
7 | export async function main( |
8 | auth: RT.Shopify, |
9 | return_id: string, |
10 | return_line_items: { id: string; quantity: number }[], |
11 | refund_transaction_id: string | undefined, |
12 | refund_amount: number | undefined, |
13 | currency_code: string | undefined, |
14 | refund_shipping: boolean | undefined, |
15 | notify_customer: boolean | undefined, |
16 | note: string | undefined |
17 | ) { |
18 | if (refund_transaction_id && (refund_amount == null || !currency_code)) { |
19 | throw new Error( |
20 | "refund_amount and currency_code are required with refund_transaction_id" |
21 | ) |
22 | } |
23 |
|
24 | const response = await fetch( |
25 | `https://${auth.store_name}.myshopify.com/admin/api/2026-10/graphql.json`, |
26 | { |
27 | method: "POST", |
28 | headers: { |
29 | "X-Shopify-Access-Token": auth.token, |
30 | "Content-Type": "application/json", |
31 | Accept: "application/json", |
32 | }, |
33 | body: JSON.stringify({ |
34 | query: `mutation ($input: ReturnProcessInput!) { returnProcess(input: $input) { return { id name status closedAt returnLineItems(first: 50) { nodes { id quantity processedQuantity unprocessedQuantity refundedQuantity } } refunds(first: 10) { nodes { id createdAt totalRefundedSet { shopMoney { amount currencyCode } } } } } userErrors { field message code } } }`, |
35 | variables: { |
36 | input: { |
37 | returnId: return_id.startsWith("gid://") |
38 | ? return_id |
39 | : `gid://shopify/Return/${return_id}`, |
40 | returnLineItems: return_line_items.map((li) => ({ |
41 | id: li.id.startsWith("gid://") |
42 | ? li.id |
43 | : `gid://shopify/ReturnLineItem/${li.id}`, |
44 | quantity: li.quantity, |
45 | })), |
46 | financialTransfer: refund_transaction_id |
47 | ? { |
48 | issueRefund: { |
49 | orderTransactions: [ |
50 | { |
51 | parentId: refund_transaction_id.startsWith("gid://") |
52 | ? refund_transaction_id |
53 | : `gid://shopify/OrderTransaction/${refund_transaction_id}`, |
54 | transactionAmount: { |
55 | amount: refund_amount, |
56 | currencyCode: currency_code, |
57 | }, |
58 | }, |
59 | ], |
60 | }, |
61 | } |
62 | : undefined, |
63 | refundShipping: refund_shipping ? { fullRefund: true } : undefined, |
64 | notifyCustomer: notify_customer || undefined, |
65 | note: note || undefined, |
66 | }, |
67 | }, |
68 | }), |
69 | } |
70 | ) |
71 |
|
72 | if (!response.ok) { |
73 | throw new Error(`${response.status} ${await response.text()}`) |
74 | } |
75 |
|
76 | const { data, errors } = await response.json() |
77 | if (errors) { |
78 | throw new Error(JSON.stringify(errors)) |
79 | } |
80 |
|
81 | if (data.returnProcess.userErrors.length) { |
82 | throw new Error(JSON.stringify(data.returnProcess.userErrors)) |
83 | } |
84 |
|
85 | return data.returnProcess |
86 | } |
87 |
|