shopify_client/admin/subscription/
remote.rs1use crate::common::ServiceContext;
2use crate::{
3 common::{http::execute_graphql, types::APIError},
4 types::subscription::{
5 ActiveSubscriptionsResp, AppPricingInterval, CancelSubscriptionResp,
6 CreateCombinedSubscriptionRequest, CreateRecurringSubscriptionRequest,
7 CreateSubscriptionResp, CreateUsageRecordRequest, CreateUsageRecordResp,
8 CreateUsageSubscriptionRequest, ExtendTrialResp, MoneyInput, UpdateCappedAmountResp,
9 },
10};
11
12use serde_json::json;
13
14pub async fn create_recurring_subscription(
15 ctx: &ServiceContext,
16 request: &CreateRecurringSubscriptionRequest,
17) -> Result<CreateSubscriptionResp, APIError> {
18 let interval = request.interval.unwrap_or(AppPricingInterval::Every30Days);
19 let test = request.test.unwrap_or(false);
20
21 let query = r#"
22 mutation appSubscriptionCreate($name: String!, $returnUrl: URL!, $lineItems: [AppSubscriptionLineItemInput!]!, $test: Boolean, $trialDays: Int) {
23 appSubscriptionCreate(name: $name, returnUrl: $returnUrl, lineItems: $lineItems, test: $test, trialDays: $trialDays) {
24 appSubscription {
25 id
26 name
27 status
28 lineItems {
29 id
30 plan {
31 pricingDetails {
32 __typename
33 ... on AppRecurringPricing {
34 price {
35 amount
36 currencyCode
37 }
38 interval
39 }
40 }
41 }
42 }
43 createdAt
44 currentPeriodEnd
45 returnUrl
46 trialDays
47 test
48 }
49 confirmationUrl
50 userErrors {
51 field
52 message
53 }
54 }
55 }
56 "#;
57
58 let mut line_item = json!({
59 "plan": {
60 "appRecurringPricingDetails": {
61 "price": {
62 "amount": request.price,
63 "currencyCode": request.currency_code
64 },
65 "interval": interval
66 }
67 }
68 });
69
70 if let Some(discount) = &request.discount {
71 line_item["plan"]["appRecurringPricingDetails"]["discount"] = json!(discount);
72 }
73
74 let variables = json!({
75 "name": request.name,
76 "returnUrl": request.return_url,
77 "lineItems": [line_item],
78 "test": test,
79 "trialDays": request.trial_days
80 });
81
82 execute_graphql(ctx, query, variables).await
83}
84
85pub async fn create_usage_subscription(
86 ctx: &ServiceContext,
87 request: &CreateUsageSubscriptionRequest,
88) -> Result<CreateSubscriptionResp, APIError> {
89 let test = request.test.unwrap_or(false);
90
91 let query = r#"
92 mutation appSubscriptionCreate($name: String!, $returnUrl: URL!, $lineItems: [AppSubscriptionLineItemInput!]!, $test: Boolean, $trialDays: Int) {
93 appSubscriptionCreate(name: $name, returnUrl: $returnUrl, lineItems: $lineItems, test: $test, trialDays: $trialDays) {
94 appSubscription {
95 id
96 name
97 status
98 lineItems {
99 id
100 plan {
101 pricingDetails {
102 __typename
103 ... on AppUsagePricing {
104 cappedAmount {
105 amount
106 currencyCode
107 }
108 terms
109 balanceUsed {
110 amount
111 currencyCode
112 }
113 interval
114 }
115 }
116 }
117 }
118 createdAt
119 currentPeriodEnd
120 returnUrl
121 trialDays
122 test
123 }
124 confirmationUrl
125 userErrors {
126 field
127 message
128 }
129 }
130 }
131 "#;
132
133 let variables = json!({
134 "name": request.name,
135 "returnUrl": request.return_url,
136 "lineItems": [{
137 "plan": {
138 "appUsagePricingDetails": {
139 "cappedAmount": {
140 "amount": request.capped_amount,
141 "currencyCode": request.currency_code
142 },
143 "terms": request.terms
144 }
145 }
146 }],
147 "test": test,
148 "trialDays": request.trial_days
149 });
150
151 execute_graphql(ctx, query, variables).await
152}
153
154pub async fn create_combined_subscription(
155 ctx: &ServiceContext,
156 request: &CreateCombinedSubscriptionRequest,
157) -> Result<CreateSubscriptionResp, APIError> {
158 let interval = request.interval.unwrap_or(AppPricingInterval::Every30Days);
159 let test = request.test.unwrap_or(false);
160
161 let query = r#"
162 mutation appSubscriptionCreate($name: String!, $returnUrl: URL!, $lineItems: [AppSubscriptionLineItemInput!]!, $test: Boolean, $trialDays: Int) {
163 appSubscriptionCreate(name: $name, returnUrl: $returnUrl, lineItems: $lineItems, test: $test, trialDays: $trialDays) {
164 appSubscription {
165 id
166 name
167 status
168 lineItems {
169 id
170 plan {
171 pricingDetails {
172 __typename
173 ... on AppRecurringPricing {
174 price {
175 amount
176 currencyCode
177 }
178 interval
179 }
180 ... on AppUsagePricing {
181 cappedAmount {
182 amount
183 currencyCode
184 }
185 terms
186 balanceUsed {
187 amount
188 currencyCode
189 }
190 interval
191 }
192 }
193 }
194 }
195 createdAt
196 currentPeriodEnd
197 returnUrl
198 trialDays
199 test
200 }
201 confirmationUrl
202 userErrors {
203 field
204 message
205 }
206 }
207 }
208 "#;
209
210 let mut recurring_line_item = json!({
211 "plan": {
212 "appRecurringPricingDetails": {
213 "price": {
214 "amount": request.recurring_price,
215 "currencyCode": request.recurring_currency_code
216 },
217 "interval": interval
218 }
219 }
220 });
221
222 if let Some(discount) = &request.discount {
223 recurring_line_item["plan"]["appRecurringPricingDetails"]["discount"] = json!(discount);
224 }
225
226 let usage_line_item = json!({
227 "plan": {
228 "appUsagePricingDetails": {
229 "cappedAmount": {
230 "amount": request.capped_amount,
231 "currencyCode": request.usage_currency_code
232 },
233 "terms": request.terms
234 }
235 }
236 });
237
238 let variables = json!({
239 "name": request.name,
240 "returnUrl": request.return_url,
241 "lineItems": [recurring_line_item, usage_line_item],
242 "test": test,
243 "trialDays": request.trial_days
244 });
245
246 execute_graphql(ctx, query, variables).await
247}
248
249pub async fn cancel_subscription(
250 ctx: &ServiceContext,
251 subscription_id: &String,
252 prorate: bool,
253) -> Result<CancelSubscriptionResp, APIError> {
254 let query = r#"
255 mutation appSubscriptionCancel($id: ID!, $prorate: Boolean) {
256 appSubscriptionCancel(id: $id, prorate: $prorate) {
257 appSubscription {
258 id
259 name
260 status
261 lineItems {
262 id
263 plan {
264 pricingDetails {
265 __typename
266 ... on AppRecurringPricing {
267 price {
268 amount
269 currencyCode
270 }
271 interval
272 }
273 ... on AppUsagePricing {
274 cappedAmount {
275 amount
276 currencyCode
277 }
278 terms
279 balanceUsed {
280 amount
281 currencyCode
282 }
283 interval
284 }
285 }
286 }
287 }
288 }
289 userErrors {
290 field
291 message
292 }
293 }
294 }
295 "#;
296
297 let variables = json!({
298 "id": subscription_id,
299 "prorate": prorate
300 });
301
302 execute_graphql(ctx, query, variables).await
303}
304
305pub async fn extend_trial(
306 ctx: &ServiceContext,
307 subscription_id: &String,
308 days: i32,
309) -> Result<ExtendTrialResp, APIError> {
310 let query = r#"
311 mutation appSubscriptionTrialExtend($id: ID!, $days: Int!) {
312 appSubscriptionTrialExtend(id: $id, days: $days) {
313 appSubscription {
314 id
315 name
316 status
317 trialDays
318 }
319 userErrors {
320 field
321 message
322 }
323 }
324 }
325 "#;
326
327 let variables = json!({
328 "id": subscription_id,
329 "days": days
330 });
331
332 execute_graphql(ctx, query, variables).await
333}
334
335pub async fn update_capped_amount(
336 ctx: &ServiceContext,
337 line_item_id: &String,
338 capped_amount: &MoneyInput,
339) -> Result<UpdateCappedAmountResp, APIError> {
340 let query = r#"
341 mutation appSubscriptionLineItemUpdate($id: ID!, $cappedAmount: MoneyInput!) {
342 appSubscriptionLineItemUpdate(id: $id, cappedAmount: $cappedAmount) {
343 appSubscription {
344 id
345 name
346 status
347 lineItems {
348 id
349 plan {
350 pricingDetails {
351 __typename
352 ... on AppUsagePricing {
353 cappedAmount {
354 amount
355 currencyCode
356 }
357 terms
358 balanceUsed {
359 amount
360 currencyCode
361 }
362 interval
363 }
364 }
365 }
366 }
367 }
368 userErrors {
369 field
370 message
371 }
372 }
373 }
374 "#;
375
376 let variables = json!({
377 "id": line_item_id,
378 "cappedAmount": {
379 "amount": capped_amount.amount,
380 "currencyCode": capped_amount.currency_code
381 }
382 });
383
384 execute_graphql(ctx, query, variables).await
385}
386
387pub async fn create_usage_record(
388 ctx: &ServiceContext,
389 request: &CreateUsageRecordRequest,
390) -> Result<CreateUsageRecordResp, APIError> {
391 let query = r#"
392 mutation appUsageRecordCreate($subscriptionLineItemId: ID!, $price: MoneyInput!, $description: String!, $idempotencyKey: String) {
393 appUsageRecordCreate(subscriptionLineItemId: $subscriptionLineItemId, price: $price, description: $description, idempotencyKey: $idempotencyKey) {
394 appUsageRecord {
395 id
396 description
397 price {
398 amount
399 currencyCode
400 }
401 createdAt
402 }
403 userErrors {
404 field
405 message
406 }
407 }
408 }
409 "#;
410
411 let variables = json!({
412 "subscriptionLineItemId": request.subscription_line_item_id,
413 "price": {
414 "amount": request.price,
415 "currencyCode": request.currency_code
416 },
417 "description": request.description,
418 "idempotencyKey": request.idempotency_key
419 });
420
421 execute_graphql(ctx, query, variables).await
422}
423
424pub async fn get_active_subscriptions(
425 ctx: &ServiceContext,
426) -> Result<ActiveSubscriptionsResp, APIError> {
427 let query = r#"
428 query {
429 currentAppInstallation {
430 activeSubscriptions {
431 id
432 name
433 status
434 lineItems {
435 id
436 plan {
437 pricingDetails {
438 __typename
439 ... on AppRecurringPricing {
440 price {
441 amount
442 currencyCode
443 }
444 interval
445 }
446 ... on AppUsagePricing {
447 cappedAmount {
448 amount
449 currencyCode
450 }
451 terms
452 balanceUsed {
453 amount
454 currencyCode
455 }
456 interval
457 }
458 }
459 }
460 }
461 createdAt
462 currentPeriodEnd
463 returnUrl
464 trialDays
465 test
466 }
467 }
468 }
469 "#;
470
471 let variables = json!({});
472
473 execute_graphql(ctx, query, variables).await
474}