roam/aweber/20210302135423-stripe_api.org
2021-09-01 16:57:39 -04:00

30 KiB

Stripe API

Product

  stripe products create \
      --stripe-account=$account \
      --name="Example Product (Org-Roam Doc)" \
      -d "images[0]"="https://www.orgroam.com/img/logo.png" \
      | jq -r .id
prod_JBeWfGHNqBcy5B

Non-Recurring Price

  stripe prices create \
      --stripe-account=$account \
      --product=$product \
      --unit-amount=-1 \
      --currency=jpy \
      -d "nickname"="Non-Recurring"
{
  "error": {
    "message": "This value must be less than or equal to 999999999999 (it currently is '9999999999991').",
    "param": "unit_amount",
    "type": "invalid_request_error"
  }
}

Recurring Price

  stripe prices create \
      --stripe-account=$account \
      --product=$product \
      --unit-amount=999 \
      --currency=usd \
      -d "nickname"="Recurring" \
      -d "recurring[interval]"="month" \
      | jq -r .id
price_1IZHFZIoFf3wvXpRtHW5EKFo

Customer

  stripe customers create \
      --stripe-account=$account \
      --description="Org Roam Docs Customer" \
      --name="Correl Roush" \
      --email="correl+stripe.roam.docs@gmail.com" \
      | jq -r .id
cus_JBeXOsWSmfXrDX

One-Time Invoicing

We set up a purchase for the client to then complete by confirming the payment intent with payment information.

Create invoice item

  stripe invoiceitems create \
    --stripe-account=$account \
    --customer=$customer \
    --price=$price \
    | jq -r .id
ii_1IZHGHIoFf3wvXpRnP7xBsbd

Create invoice

  stripe invoices create \
      --stripe-account="$account" \
      --customer="$customer" \
      | jq -r .id
in_1IZHGOIoFf3wvXpRuP2Og77y
  stripe invoices finalize_invoice \
      --stripe-account=$account \
      $invoice
{
  "id": "in_1IZHGOIoFf3wvXpRuP2Og77y",
  "object": "invoice",
  "account_country": "US",
  "account_name": "Correl's Stuff",
  "account_tax_ids": null,
  "amount_due": 350,
  "amount_paid": 0,
  "amount_remaining": 350,
  "application_fee_amount": null,
  "attempt_count": 0,
  "attempted": false,
  "auto_advance": false,
  "billing_reason": "manual",
  "charge": null,
  "collection_method": "charge_automatically",
  "created": 1616771272,
  "currency": "usd",
  "custom_fields": null,
  "customer": "cus_JBeXOsWSmfXrDX",
  "customer_address": null,
  "customer_email": "correl+stripe.roam.docs@gmail.com",
  "customer_name": "Correl Roush",
  "customer_phone": null,
  "customer_shipping": null,
  "customer_tax_exempt": "none",
  "customer_tax_ids": [

  ],
  "default_payment_method": null,
  "default_source": null,
  "default_tax_rates": [

  ],
  "description": null,
  "discount": null,
  "discounts": [

  ],
  "due_date": null,
  "ending_balance": 0,
  "footer": null,
  "hosted_invoice_url": "https://invoice.stripe.com/i/acct_1IGnMkIoFf3wvXpR/invst_JBeZpwIUNWNhG3JLRP5QBZ2RpKeDs8t",
  "invoice_pdf": "https://pay.stripe.com/invoice/acct_1IGnMkIoFf3wvXpR/invst_JBeZpwIUNWNhG3JLRP5QBZ2RpKeDs8t/pdf",
  "last_finalization_error": null,
  "lines": {
    "object": "list",
    "data": [
      {
        "id": "il_1IZHGHIoFf3wvXpRMwwv5nhW",
        "object": "line_item",
        "amount": 350,
        "currency": "usd",
        "description": "Example Product (Org-Roam Doc)",
        "discount_amounts": [

        ],
        "discountable": true,
        "discounts": [

        ],
        "invoice_item": "ii_1IZHGHIoFf3wvXpRnP7xBsbd",
        "livemode": false,
        "metadata": {
        },
        "period": {
          "end": 1616771265,
          "start": 1616771265
        },
        "plan": null,
        "price": {
          "id": "price_1IZHFSIoFf3wvXpRHwH3GRm8",
          "object": "price",
          "active": true,
          "billing_scheme": "per_unit",
          "created": 1616771214,
          "currency": "usd",
          "livemode": false,
          "lookup_key": null,
          "metadata": {
          },
          "nickname": "Non-Recurring",
          "product": "prod_JBeWfGHNqBcy5B",
          "recurring": null,
          "tiers_mode": null,
          "transform_quantity": null,
          "type": "one_time",
          "unit_amount": 350,
          "unit_amount_decimal": "350"
        },
        "proration": false,
        "quantity": 1,
        "subscription": null,
        "tax_amounts": [

        ],
        "tax_rates": [

        ],
        "type": "invoiceitem"
      }
    ],
    "has_more": false,
    "total_count": 1,
    "url": "/v1/invoices/in_1IZHGOIoFf3wvXpRuP2Og77y/lines"
  },
  "livemode": false,
  "metadata": {
  },
  "next_payment_attempt": null,
  "number": "0EBAE885-0001",
  "on_behalf_of": null,
  "paid": false,
  "payment_intent": "pi_1IZHH8IoFf3wvXpRKYVCxVtO",
  "payment_settings": {
    "payment_method_options": null,
    "payment_method_types": null
  },
  "period_end": 1616771272,
  "period_start": 1616771272,
  "post_payment_credit_notes_amount": 0,
  "pre_payment_credit_notes_amount": 0,
  "receipt_number": null,
  "starting_balance": 0,
  "statement_descriptor": null,
  "status": "open",
  "status_transitions": {
    "finalized_at": 1616771318,
    "marked_uncollectible_at": null,
    "paid_at": null,
    "voided_at": null
  },
  "subscription": null,
  "subtotal": 350,
  "tax": null,
  "total": 350,
  "total_discount_amounts": [

  ],
  "total_tax_amounts": [

  ],
  "transfer_data": null,
  "webhooks_delivered_at": 1616771274
}

Pay the invoice

  stripe payment_intents confirm $intent \
      --payment-method=pm_card_visa
{
  "id": "pi_1IZG0gIoFf3wvXpRMv4JIJlv",
  "object": "payment_intent",
  "amount": 350,
  "amount_capturable": 0,
  "amount_received": 350,
  "application": null,
  "application_fee_amount": null,
  "canceled_at": null,
  "cancellation_reason": null,
  "capture_method": "automatic",
  "charges": {
    "object": "list",
    "data": [
      {
        "id": "ch_1IZG1rIoFf3wvXpRVFw1lFw7",
        "object": "charge",
        "amount": 350,
        "amount_captured": 350,
        "amount_refunded": 0,
        "application": null,
        "application_fee": null,
        "application_fee_amount": null,
        "balance_transaction": "txn_1IZG1rIoFf3wvXpR7ROwaORh",
        "billing_details": {
          "address": {
            "city": null,
            "country": null,
            "line1": null,
            "line2": null,
            "postal_code": null,
            "state": null
          },
          "email": null,
          "name": null,
          "phone": null
        },
        "calculated_statement_descriptor": "CORRELS STUFF",
        "captured": true,
        "created": 1616766527,
        "currency": "usd",
        "customer": "cus_JBNQ85gmNWdWB3",
        "description": "Payment for Invoice",
        "destination": null,
        "dispute": null,
        "disputed": false,
        "failure_code": null,
        "failure_message": null,
        "fraud_details": {
        },
        "invoice": "in_1IZG0YIoFf3wvXpR6aGs4GtD",
        "livemode": false,
        "metadata": {
        },
        "on_behalf_of": null,
        "order": null,
        "outcome": {
          "network_status": "approved_by_network",
          "reason": null,
          "risk_level": "normal",
          "risk_score": 39,
          "seller_message": "Payment complete.",
          "type": "authorized"
        },
        "paid": true,
        "payment_intent": "pi_1IZG0gIoFf3wvXpRMv4JIJlv",
        "payment_method": "pm_1IZG1qIoFf3wvXpRX3NUaXbF",
        "payment_method_details": {
          "card": {
            "brand": "visa",
            "checks": {
              "address_line1_check": null,
              "address_postal_code_check": null,
              "cvc_check": null
            },
            "country": "US",
            "exp_month": 3,
            "exp_year": 2022,
            "fingerprint": "ueUYSX2U2UUDmYpO",
            "funding": "credit",
            "installments": null,
            "last4": "4242",
            "network": "visa",
            "three_d_secure": null,
            "wallet": null
          },
          "type": "card"
        },
        "receipt_email": null,
        "receipt_number": null,
        "receipt_url": "https://pay.stripe.com/receipts/acct_1IGnMkIoFf3wvXpR/ch_1IZG1rIoFf3wvXpRVFw1lFw7/rcpt_JBdIhBejsEXLYLJMLjteIt8UWMMh5md",
        "refunded": false,
        "refunds": {
          "object": "list",
          "data": [

          ],
          "has_more": false,
          "total_count": 0,
          "url": "/v1/charges/ch_1IZG1rIoFf3wvXpRVFw1lFw7/refunds"
        },
        "review": null,
        "shipping": null,
        "source": null,
        "source_transfer": null,
        "statement_descriptor": null,
        "statement_descriptor_suffix": null,
        "status": "succeeded",
        "transfer_data": null,
        "transfer_group": null
      }
    ],
    "has_more": false,
    "total_count": 1,
    "url": "/v1/charges?payment_intent=pi_1IZG0gIoFf3wvXpRMv4JIJlv"
  },
  "client_secret": "pi_1IZG0gIoFf3wvXpRMv4JIJlv_secret_48XYkW8i6bDhBOtA7AE6R9drd",
  "confirmation_method": "automatic",
  "created": 1616766454,
  "currency": "usd",
  "customer": "cus_JBNQ85gmNWdWB3",
  "description": "Payment for Invoice",
  "invoice": "in_1IZG0YIoFf3wvXpR6aGs4GtD",
  "last_payment_error": null,
  "livemode": false,
  "metadata": {
  },
  "next_action": null,
  "on_behalf_of": null,
  "payment_method": "pm_1IZG1qIoFf3wvXpRX3NUaXbF",
  "payment_method_options": {
    "card": {
      "installments": null,
      "network": null,
      "request_three_d_secure": "automatic"
    }
  },
  "payment_method_types": [
    "card"
  ],
  "receipt_email": null,
  "review": null,
  "setup_future_usage": null,
  "shipping": null,
  "source": null,
  "statement_descriptor": null,
  "statement_descriptor_suffix": null,
  "status": "succeeded",
  "transfer_data": null,
  "transfer_group": null
}

One-Time Invoicing (Payment method first)

By having the client prepare the payment intent before requesting the purchase, we can handle invoicing and completing the purchase on our end without further input from the client.

Create a payment method

  stripe payment_methods create \
      --stripe-account=$account \
      --type=card \
      -d "card[number]"=4242424242424242 \
      -d "card[exp_month]"=3 \
      -d "card[exp_year]"=2022 \
      -d "card[cvc]"=314 \
      | jq -r '.id'
pm_1J5FujIoFf3wvXpRgemyYO93

Attach the payment method to the customer

  stripe payment_methods attach "$payment_method" \
      --stripe-account=$account \
      --customer="$customer"
{
  "id": "pm_1IZHILIoFf3wvXpR3oRjPoMx",
  "object": "payment_method",
  "billing_details": {
    "address": {
      "city": null,
      "country": null,
      "line1": null,
      "line2": null,
      "postal_code": null,
      "state": null
    },
    "email": null,
    "name": null,
    "phone": null
  },
  "card": {
    "brand": "visa",
    "checks": {
      "address_line1_check": null,
      "address_postal_code_check": null,
      "cvc_check": "pass"
    },
    "country": "US",
    "exp_month": 3,
    "exp_year": 2022,
    "fingerprint": "C5qD8oSCGvVCbtcH",
    "funding": "credit",
    "generated_from": null,
    "last4": "4242",
    "networks": {
      "available": [
        "visa"
      ],
      "preferred": null
    },
    "three_d_secure_usage": {
      "supported": true
    },
    "wallet": null
  },
  "created": 1616771394,
  "customer": "cus_JBeXOsWSmfXrDX",
  "livemode": false,
  "metadata": {
  },
  "type": "card"
}

Create invoice item

  stripe invoiceitems create \
    --stripe-account=$account \
    --customer=$customer \
    --price=$price \
    | jq -r .id
ii_1IZJF0IoFf3wvXpROwCaDRo0

Create invoice

  stripe invoices create \
      --stripe-account="$account" \
      --customer="$customer" \
      --auto-advance=false \
      -d "application_fee_amount"=35 \
      -d "default_payment_method"=$payment_method \
      | jq -r .id
in_1IZJF5IoFf3wvXpRu9PnTZIl

Pay Invoice

  stripe invoices pay \
      --stripe-account=$account \
      $invoice
{
  "id": "in_1IZJF5IoFf3wvXpRu9PnTZIl",
  "object": "invoice",
  "account_country": "US",
  "account_name": "Correl's Stuff",
  "account_tax_ids": null,
  "amount_due": 350,
  "amount_paid": 350,
  "amount_remaining": 0,
  "application_fee_amount": 35,
  "attempt_count": 1,
  "attempted": true,
  "auto_advance": false,
  "billing_reason": "manual",
  "charge": "ch_1IZJFdIoFf3wvXpRfCT89Njs",
  "collection_method": "charge_automatically",
  "created": 1616778879,
  "currency": "usd",
  "custom_fields": null,
  "customer": "cus_JBeXOsWSmfXrDX",
  "customer_address": null,
  "customer_email": "correl+stripe.roam.docs@gmail.com",
  "customer_name": "Correl Roush",
  "customer_phone": null,
  "customer_shipping": null,
  "customer_tax_exempt": "none",
  "customer_tax_ids": [

  ],
  "default_payment_method": "pm_1IZHILIoFf3wvXpR3oRjPoMx",
  "default_source": null,
  "default_tax_rates": [

  ],
  "description": null,
  "discount": null,
  "discounts": [

  ],
  "due_date": null,
  "ending_balance": 0,
  "footer": null,
  "hosted_invoice_url": "https://invoice.stripe.com/i/acct_1IGnMkIoFf3wvXpR/invst_JBgcIFGvkWp3ZnI1HxNWwAZl7ccRzbY",
  "invoice_pdf": "https://pay.stripe.com/invoice/acct_1IGnMkIoFf3wvXpR/invst_JBgcIFGvkWp3ZnI1HxNWwAZl7ccRzbY/pdf",
  "last_finalization_error": null,
  "lines": {
    "object": "list",
    "data": [
      {
        "id": "il_1IZJF0IoFf3wvXpRdhrY6NFl",
        "object": "line_item",
        "amount": 350,
        "currency": "usd",
        "description": "Example Product (Org-Roam Doc)",
        "discount_amounts": [

        ],
        "discountable": true,
        "discounts": [

        ],
        "invoice_item": "ii_1IZJF0IoFf3wvXpROwCaDRo0",
        "livemode": false,
        "metadata": {
        },
        "period": {
          "end": 1616778874,
          "start": 1616778874
        },
        "plan": null,
        "price": {
          "id": "price_1IZHFSIoFf3wvXpRHwH3GRm8",
          "object": "price",
          "active": true,
          "billing_scheme": "per_unit",
          "created": 1616771214,
          "currency": "usd",
          "livemode": false,
          "lookup_key": null,
          "metadata": {
          },
          "nickname": "Non-Recurring",
          "product": "prod_JBeWfGHNqBcy5B",
          "recurring": null,
          "tiers_mode": null,
          "transform_quantity": null,
          "type": "one_time",
          "unit_amount": 350,
          "unit_amount_decimal": "350"
        },
        "proration": false,
        "quantity": 1,
        "subscription": null,
        "tax_amounts": [

        ],
        "tax_rates": [

        ],
        "type": "invoiceitem"
      }
    ],
    "has_more": false,
    "total_count": 1,
    "url": "/v1/invoices/in_1IZJF5IoFf3wvXpRu9PnTZIl/lines"
  },
  "livemode": false,
  "metadata": {
  },
  "next_payment_attempt": null,
  "number": "0EBAE885-0013",
  "on_behalf_of": null,
  "paid": true,
  "payment_intent": "pi_1IZJFcIoFf3wvXpR60FJfbvD",
  "payment_settings": {
    "payment_method_options": null,
    "payment_method_types": null
  },
  "period_end": 1619449837,
  "period_start": 1616771437,
  "post_payment_credit_notes_amount": 0,
  "pre_payment_credit_notes_amount": 0,
  "receipt_number": null,
  "starting_balance": 0,
  "statement_descriptor": null,
  "status": "paid",
  "status_transitions": {
    "finalized_at": 1616778912,
    "marked_uncollectible_at": null,
    "paid_at": 1616778912,
    "voided_at": null
  },
  "subscription": null,
  "subtotal": 350,
  "tax": null,
  "total": 350,
  "total_discount_amounts": [

  ],
  "total_tax_amounts": [

  ],
  "transfer_data": null,
  "webhooks_delivered_at": 1616778880
}

Error handling

  • Bad payment methods will fail to attach to the customer, stopping the purchase flow before we attempt to set up the invoice.
  • Failure to create an invoice leaves the invoice item on the customer. Because we do not re-use customers, this will not be invoiced and charged.
  • Invoice creation leaves the invoice in a draft state, from which it will not progress without an action being taken.
  • Payment failure results in the invoice being in a failed state, and it will not retry payment.
  • Customer can be cleaned up at any point, which will clean up all data pertaining to it (invoice items, draft / failed invoices).

Attempting to attach a test payment method to a live customer

  stripe payment_methods attach "$payment_method" \
      --live -p correl \
      --customer="$customer"
{
  "error": {
    "code": "resource_missing",
    "doc_url": "https://stripe.com/docs/error-codes/resource-missing",
    "message": "No such paymentmethod: 'pm_1J5FujIoFf3wvXpRgemyYO93'; a similar object exists in test mode, but a live mode key was used to make this request.",
    "param": "payment_method",
    "type": "invalid_request_error"
  }
}

Subscriptions

Subscriptions require that a customer and payment method are already available. This means we'll need to have the client prepare a payment method, then pass that to us to be attached to the customer we create. We'll then be able to build the subscription, and the payment will be processed by Stripe.

Create a payment method

  stripe payment_methods create \
      --stripe-account=$account \
      --type=card \
      -d "card[number]"=4242424242424242 \
      -d "card[exp_month]"=3 \
      -d "card[exp_year]"=2022 \
      -d "card[cvc]"=314 \
      | jq -r '.id'
pm_1IZHILIoFf3wvXpR3oRjPoMx

Attach the payment method to the customer

  stripe payment_methods attach "$payment_method" \
      --stripe-account=$account \
      --customer="$customer"
{
  "id": "pm_1IZHILIoFf3wvXpR3oRjPoMx",
  "object": "payment_method",
  "billing_details": {
    "address": {
      "city": null,
      "country": null,
      "line1": null,
      "line2": null,
      "postal_code": null,
      "state": null
    },
    "email": null,
    "name": null,
    "phone": null
  },
  "card": {
    "brand": "visa",
    "checks": {
      "address_line1_check": null,
      "address_postal_code_check": null,
      "cvc_check": "pass"
    },
    "country": "US",
    "exp_month": 3,
    "exp_year": 2022,
    "fingerprint": "C5qD8oSCGvVCbtcH",
    "funding": "credit",
    "generated_from": null,
    "last4": "4242",
    "networks": {
      "available": [
        "visa"
      ],
      "preferred": null
    },
    "three_d_secure_usage": {
      "supported": true
    },
    "wallet": null
  },
  "created": 1616771394,
  "customer": "cus_JBeXOsWSmfXrDX",
  "livemode": false,
  "metadata": {
  },
  "type": "card"
}

Set the payment method as the default

  stripe customers update "$customer" \
      --stripe-account=$account \
      -d "invoice_settings[default_payment_method]=$payment_method"
{
  "id": "cus_JBeXOsWSmfXrDX",
  "object": "customer",
  "address": null,
  "balance": 0,
  "created": 1616771128,
  "currency": "usd",
  "default_source": null,
  "delinquent": false,
  "description": "Org Roam Docs Customer",
  "discount": null,
  "email": "correl+stripe.roam.docs@gmail.com",
  "invoice_prefix": "0EBAE885",
  "invoice_settings": {
    "custom_fields": null,
    "default_payment_method": "pm_1IZHILIoFf3wvXpR3oRjPoMx",
    "footer": null
  },
  "livemode": false,
  "metadata": {
  },
  "name": "Correl Roush",
  "next_invoice_sequence": 2,
  "phone": null,
  "preferred_locales": [

  ],
  "shipping": null,
  "tax_exempt": "none"
}

Create subscription

  stripe subscriptions create \
      --stripe-account=$account \
      --customer="$customer" \
      -d "items[0][price]"=$price
{
  "id": "sub_JBec2LL8kvDiPi",
  "object": "subscription",
  "application_fee_percent": null,
  "billing_cycle_anchor": 1616771437,
  "billing_thresholds": null,
  "cancel_at": null,
  "cancel_at_period_end": false,
  "canceled_at": null,
  "collection_method": "charge_automatically",
  "created": 1616771437,
  "current_period_end": 1619449837,
  "current_period_start": 1616771437,
  "customer": "cus_JBeXOsWSmfXrDX",
  "days_until_due": null,
  "default_payment_method": null,
  "default_source": null,
  "default_tax_rates": [

  ],
  "discount": null,
  "ended_at": null,
  "items": {
    "object": "list",
    "data": [
      {
        "id": "si_JBecQCXkjKpi2j",
        "object": "subscription_item",
        "billing_thresholds": null,
        "created": 1616771438,
        "metadata": {
        },
        "plan": {
          "id": "price_1IZHFZIoFf3wvXpRtHW5EKFo",
          "object": "plan",
          "active": true,
          "aggregate_usage": null,
          "amount": 999,
          "amount_decimal": "999",
          "billing_scheme": "per_unit",
          "created": 1616771221,
          "currency": "usd",
          "interval": "month",
          "interval_count": 1,
          "livemode": false,
          "metadata": {
          },
          "nickname": "Recurring",
          "product": "prod_JBeWfGHNqBcy5B",
          "tiers_mode": null,
          "transform_usage": null,
          "trial_period_days": null,
          "usage_type": "licensed"
        },
        "price": {
          "id": "price_1IZHFZIoFf3wvXpRtHW5EKFo",
          "object": "price",
          "active": true,
          "billing_scheme": "per_unit",
          "created": 1616771221,
          "currency": "usd",
          "livemode": false,
          "lookup_key": null,
          "metadata": {
          },
          "nickname": "Recurring",
          "product": "prod_JBeWfGHNqBcy5B",
          "recurring": {
            "aggregate_usage": null,
            "interval": "month",
            "interval_count": 1,
            "trial_period_days": null,
            "usage_type": "licensed"
          },
          "tiers_mode": null,
          "transform_quantity": null,
          "type": "recurring",
          "unit_amount": 999,
          "unit_amount_decimal": "999"
        },
        "quantity": 1,
        "subscription": "sub_JBec2LL8kvDiPi",
        "tax_rates": [

        ]
      }
    ],
    "has_more": false,
    "total_count": 1,
    "url": "/v1/subscription_items?subscription=sub_JBec2LL8kvDiPi"
  },
  "latest_invoice": "in_1IZHJ3IoFf3wvXpR6u3Yylyu",
  "livemode": false,
  "metadata": {
  },
  "next_pending_invoice_item_invoice": null,
  "pause_collection": null,
  "pending_invoice_item_interval": null,
  "pending_setup_intent": null,
  "pending_update": null,
  "plan": {
    "id": "price_1IZHFZIoFf3wvXpRtHW5EKFo",
    "object": "plan",
    "active": true,
    "aggregate_usage": null,
    "amount": 999,
    "amount_decimal": "999",
    "billing_scheme": "per_unit",
    "created": 1616771221,
    "currency": "usd",
    "interval": "month",
    "interval_count": 1,
    "livemode": false,
    "metadata": {
    },
    "nickname": "Recurring",
    "product": "prod_JBeWfGHNqBcy5B",
    "tiers_mode": null,
    "transform_usage": null,
    "trial_period_days": null,
    "usage_type": "licensed"
  },
  "quantity": 1,
  "schedule": null,
  "start_date": 1616771437,
  "status": "active",
  "transfer_data": null,
  "trial_end": null,
  "trial_start": null
}

Failure cases

Stripe provides a set of credit card numbers for eliciting various responses from their API.

Charge failure

  payment_method=$(stripe payment_methods create \
      --stripe-account=$account \
      --type=card \
      -d "card[number]"=4000000000000341 \
      -d "card[exp_month]"=3 \
      -d "card[exp_year]"=2022 \
      -d "card[cvc]"=314 \
      | jq -r '.id')
  stripe payment_methods attach "$payment_method" \
      --stripe-account=$account \
      --customer="$customer" \
      >/dev/null
  # stripe customers update "$customer" \
  #     --stripe-account=$account \
  #     -d "invoice_settings[default_payment_method]=$payment_method" >/dev/null
  stripe subscriptions create \
      --stripe-account=$account \
      --customer="$customer" \
      -d "default_payment_method"=$payment_method \
      -d "items[0][price]"=$price
{
  "id": "sub_JgoaKuIlHIVW7l",
  "object": "subscription",
  "application_fee_percent": null,
  "automatic_tax": {
    "enabled": false
  },
  "billing_cycle_anchor": 1623958380,
  "billing_thresholds": null,
  "cancel_at": null,
  "cancel_at_period_end": false,
  "canceled_at": null,
  "collection_method": "charge_automatically",
  "created": 1623958380,
  "current_period_end": 1626550380,
  "current_period_start": 1623958380,
  "customer": "cus_JBeXOsWSmfXrDX",
  "days_until_due": null,
  "default_payment_method": "pm_1J3QxSIoFf3wvXpRCCwKw9Cj",
  "default_source": null,
  "default_tax_rates": [

  ],
  "discount": null,
  "ended_at": null,
  "items": {
    "object": "list",
    "data": [
      {
        "id": "si_Jgoa4zrlQvwRbA",
        "object": "subscription_item",
        "billing_thresholds": null,
        "created": 1623958381,
        "metadata": {
        },
        "plan": {
          "id": "price_1IZHFZIoFf3wvXpRtHW5EKFo",
          "object": "plan",
          "active": true,
          "aggregate_usage": null,
          "amount": 999,
          "amount_decimal": "999",
          "billing_scheme": "per_unit",
          "created": 1616771221,
          "currency": "usd",
          "interval": "month",
          "interval_count": 1,
          "livemode": false,
          "metadata": {
          },
          "nickname": "Recurring",
          "product": "prod_JBeWfGHNqBcy5B",
          "tiers_mode": null,
          "transform_usage": null,
          "trial_period_days": null,
          "usage_type": "licensed"
        },
        "price": {
          "id": "price_1IZHFZIoFf3wvXpRtHW5EKFo",
          "object": "price",
          "active": true,
          "billing_scheme": "per_unit",
          "created": 1616771221,
          "currency": "usd",
          "livemode": false,
          "lookup_key": null,
          "metadata": {
          },
          "nickname": "Recurring",
          "product": "prod_JBeWfGHNqBcy5B",
          "recurring": {
            "aggregate_usage": null,
            "interval": "month",
            "interval_count": 1,
            "trial_period_days": null,
            "usage_type": "licensed"
          },
          "tiers_mode": null,
          "transform_quantity": null,
          "type": "recurring",
          "unit_amount": 999,
          "unit_amount_decimal": "999"
        },
        "quantity": 1,
        "subscription": "sub_JgoaKuIlHIVW7l",
        "tax_rates": [

        ]
      }
    ],
    "has_more": false,
    "total_count": 1,
    "url": "/v1/subscription_items?subscription=sub_JgoaKuIlHIVW7l"
  },
  "latest_invoice": "in_1J3QxUIoFf3wvXpRyWAuAxGq",
  "livemode": false,
  "metadata": {
  },
  "next_pending_invoice_item_invoice": null,
  "pause_collection": null,
  "pending_invoice_item_interval": null,
  "pending_setup_intent": null,
  "pending_update": null,
  "plan": {
    "id": "price_1IZHFZIoFf3wvXpRtHW5EKFo",
    "object": "plan",
    "active": true,
    "aggregate_usage": null,
    "amount": 999,
    "amount_decimal": "999",
    "billing_scheme": "per_unit",
    "created": 1616771221,
    "currency": "usd",
    "interval": "month",
    "interval_count": 1,
    "livemode": false,
    "metadata": {
    },
    "nickname": "Recurring",
    "product": "prod_JBeWfGHNqBcy5B",
    "tiers_mode": null,
    "transform_usage": null,
    "trial_period_days": null,
    "usage_type": "licensed"
  },
  "quantity": 1,
  "schedule": null,
  "start_date": 1623958380,
  "status": "incomplete",
  "transfer_data": null,
  "trial_end": null,
  "trial_start": null
}

A Unified Purchasing Experience