Skip to content

Instantly share code, notes, and snippets.

@zsy715
Last active July 2, 2021 14:30
Show Gist options
  • Save zsy715/4c8cb8586401d6635f26107e3dd52b9d to your computer and use it in GitHub Desktop.
Save zsy715/4c8cb8586401d6635f26107e3dd52b9d to your computer and use it in GitHub Desktop.

Before we start thinking about rebilling, we need to roughly know the architecture of subscription. Open questions would be

  • Do we need a database?
  • What can we get from Shopify subscription endpoint?
  • What would be the most basic requirements?

Scenarios

  • Customers purchase subscription -> Shopify triggers initial billing, generates orders and new subscription contracts
  • Birchbox requests billing attempts -> Shopify bills customers and creates new orders
  • Birchbox ships orders -> Shopify creates fulfillments

What to track?

These can be achieved with shopify endpoint(no database required)

subscription contract renewal(out of scope for initial launch)

  • Subscription contracts generate new orders for merchants to fulfill at subscription renewal time. They're also the mechanism by which apps will bill customers for their subscriptions. https://shopify.dev/tutorials/create-manage-subscription-contracts#create-a-billing-attempt
  • Subscription contracts might not be immediately available when an order is created. It's best to rely on subscription contract webhooks to be notified when contracts are created.

billing attempt

Successful billing attempts create new orders

proposal

  • cron job to get a list of active subscription contracts with next billing date before cutoff date(assume all plans are billed at the same date)
  • webhooks subscription_billing_attempts/success and subscription_billing_attempts/failure for subscription status update and billing status update
  • db optional for billing cycles and billing status

design chart https://lucid.app/lucidchart/invitations/accept/inv_06cf4806-1c91-4b72-aead-f15635cb946d?viewport_loc=-152%2C144%2C1579%2C768%2C0_0

Technical Details

fetch list of active subscription contracts

  • shopify bulk operation query subscriptionContracts(The output won't be ready immediately)
  • get id of bulk operation from response, save id to database, send id to SQS(retry for output/failures)

find out contracts that meet billing criterias

  • SQS consumer retries until bulk operation is completed.
  • get url, update url to database, get jsonl object from url, read object and dispatch json objects or contract id(TBD) to SQS
  • billing criterias:
    • subscriptionContractStatus = ACTIVE
    • subscriptionContract nextBillDate is 5th day of current month
    • subscriptionContract billingAttempts: get latest one
      • status should be READY(it's complete. We should avoid billing customers multiple times)
      • lastPaymentStatus could either be SUCCEEDED or FAILED
        • SUCCEEDED last billing attempt should be in last month(initial monthly billing)
        • FAILED last billing attempt should be in current month(monthly billing retry)

bill customers based on contract id

  • SQS consumer gets message and then call subscriptionBillingAttemptCreate mutation(need to handle shopify rate limit)
  • Webhook subscription_billing_attempts/failure, subscription_billing_attempts/success to alter nextBillingDate
sample response
{
  "id": null,
  "admin_graphql_api_id": null,
  "idempotency_key": "9a453d81-d41d-403e-806f-714dee215ff9",
  "order_id": 1,
  "admin_graphql_api_order_id": "gid:\/\/shopify\/Order\/1",
  "subscription_contract_id": 9998878778,
  "admin_graphql_api_subscription_contract_id": "gid:\/\/shopify\/SubscriptionContract\/9998878778",
  "ready": true,
  "error_message": null,
  "error_code": null
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment