lukasaron / terraform-provider-stripe Goto Github PK
View Code? Open in Web Editor NEWTerraform Stripe Provider
Home Page: https://registry.terraform.io/providers/lukasaron/stripe/latest
License: Mozilla Public License 2.0
Terraform Stripe Provider
Home Page: https://registry.terraform.io/providers/lukasaron/stripe/latest
License: Mozilla Public License 2.0
In stripe_promotion_code resource, expires_at
and restrictions.minimum_amount
are being misinterpreted as 0
s when they are not set (due to stripe go client library).
This leads into two problems:
expires_at
set to 0
or null
and that will raise an error as stripe does not accepts an expiration date in the past (Unix Epoch Time).minimum_amount
running terraform plan
no matter you have done apply
.For the above to be handled, nil
and 0
values for certain fields should be interpreted the same way and do consider them a change.
Hello,
Thank you for this awesome provider, I have been using it on multiple projects, It's better than anything out there currently.
Lately I've been wanting to to add some products with the "Package Pricing" option but the provider doesn't offer this option yet.
This pricing model exists in Stripe.
Example : 40$ per 100units, 70$ per 200units.
It would be cool to have this added to the module if you have some time ! If not I could also find some time to submit a PR to implement this since I'm the only one who needs it atm.
Thank you !
After upgrade from 1.6.0 to 1.6.3 I had this error:
│ Error: business_profile: '': source data must be an array or slice, got struct
│
│ with stripe_portal_configuration.portal_configuration,
│ on 12_stripe.tf line 21, in resource "stripe_portal_configuration" "portal_configuration":
│ 21: resource "stripe_portal_configuration" "portal_configuration" {
│
╵
╷
│ Error: features: '': source data must be an array or slice, got struct
│
│ with stripe_portal_configuration.portal_configuration,
│ on 12_stripe.tf line 21, in resource "stripe_portal_configuration" "portal_configuration":
│ 21: resource "stripe_portal_configuration" "portal_configuration" {
│
╵
The resource config is:
resource "stripe_portal_configuration" "portal_configuration" {
business_profile {
privacy_policy_url = "https://${local.domain_landing}/privacy"
terms_of_service_url = "https://${local.domain_landing}/terms"
}
default_return_url = "http://${local.domain_app}/"
features {
customer_update {
enabled = true
allowed_updates = ["email", "address"]
}
invoice_history {
enabled = false
}
payment_method_update {
enabled = true
}
}
}
Versions:
Terraform v1.3.9
on darwin_arm64
Error: {"status":400,"message":"This product cannot be deleted because it has one or more user-created prices.","request_id":"req_...","request_log_url":"https://dashboard.stripe.com/test/logs/req_...?t=1705116524","type":"invalid_request_error"}
│
This provider already archives prices when deleted from state. Is it possible to modify the provider so that when a product is deleted, if it has prices, the product will be archived instead of deleted?
Hello,
I found a bug about free pricing, and would like to report it.
unit_amount
to -1.like this;
resource "stripe_price" "free_price" {
product = stripe_product.example.id
currency = "usd"
billing_scheme = "per_unit"
unit_amount = -1
tax_behaviour = "unspecified"
}
Do terraform apply
.
Do terraform plan
.
I expected to be No changes.
, but it actually was replaced
.
Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# stripe_price.example must be replaced
-/+ resource "stripe_price" "free_price" {
~ id = "price_1MjHlDAoExos3Ym4w6AKoNw3" -> (known after apply)
- metadata = {} -> null
~ type = "one_time" -> (known after apply)
~ unit_amount = 0 -> -1 # forces replacement
# (6 unchanged attributes hidden)
}
Set unit_amount
to 0 after apply, terraform plan
will be No Changes
.
I reffered:
Versions:
Terraform v1.3.9
on darwin_arm64
+ provider registry.terraform.io/lukasaron/stripe v1.6.3
When I run terraform plan
I get this change:
# module.account2_resources.stripe_promotion_code.promo_XX must be replaced
-/+ resource "stripe_promotion_code" "promo_XX" {
- expires_at = "1970-01-01T00:00:00Z" -> null # forces replacement
~ id = "promo_XX" -> (known after apply)
# (5 unchanged attributes hidden)
# (1 unchanged block hidden)
}
1970-01-01T00:00:00Z is 0 timestamp!
on every change of a product, terraform doesn't resolve the dependency of deleting the prices first to then change the product
If you have a price with a recurring block but do not set the interval_count
it will always show in a plan as being changed to null.
This is because when it is set there is no default value but when it is read from the stripe API there always is a value, which then gets written into the state.
I noticed that metadata entries are only added or the value updated, but not removed or key updated.
For example if I add a metadata field to a resource (I tested this on price)
metadata = {
foo = "bar"
}
Then I change it to
metadata = {
bar = "foo"
}
I end up with foo
and bar
as metadata keys with their respective values.
My expectation is that the foo
key should have been removed.
I have resolved this by setting foo = ""
and running an apply, then removing from the terraform resource declaration, but I think we could resolve this better on the provider. This is necessary otherwise the terraform plan always picks this up as a pending change when comparing to source.
I believe that the fix is to send to stripe the value of the keys to be removed as an empty string.
Hey @lukasaron, thanks for this helpful provider!
It would be nice to be able to set the tax_code when creating a product.
We changed the tax behavior on the Stripe admin panel, which "cannot be updated later on". To match the settings in our terraform code, I changed tax_behaviour
property to match the setting on the site. This property is accepted in this form, including the letter U. However the Stripe API does not recognize this, since it specifies tax_behavior
(without the U). I noticed that the currency_options
object also specifies tax_behavior
(without the U).
Currently I am bumping into this error message with the U: You cannot update tax_behavior
field once it has been specified.
Without the U, I get the following: An argument named "tax_behavior" is not expected here. Did you mean "tax_behaviour"?
Hello,
It's possible to update the stripe sdk to have the new stripe API VERSION with "2024-04-10", instead of actually :
2023-10-16 ?
best regards,
@lukasaron thank your work! There is one more bug report.
Reproducing steps:
resource "stripe_product" "product" {
name = "minimalist product"
}
resource "stripe_price" "price" {
product = stripe_product.product.id
currency = "usd"
active = true
billing_scheme = "per_unit"
unit_amount = 14999
recurring {
interval = "month"
interval_count = 1
usage_type = "licensed"
}
}
terraform console
and check stripe_price.price resource. unit_amount will be correct. Record id for future import.terraform state rm stripe_price.price
terraform import stripe_price.price price_XXX
. Use id from step 2.terraform console
and check stripe_price.price resource. unit_amount will be tonumber(null)
instead of correct value.minimum_amount
and minimum_amount_currency
fields are not required in promotion code restrictions.
When creating a volume based tiered price, the request is including all the possible amount params with default to "0" for the ones not specified.
example.tf
resource "stripe_product" "product" {
name = "Product"
}
resource "stripe_price" "price" {
product = stripe_product.product.id
billing_scheme = "tiered"
tiers_mode = "volume"
currency = "usd"
tax_behaviour = "exclusive"
tiers {
up_to = 24
unit_amount = 10000
}
recurring {
interval = "year"
interval_count = 1
}
}
Output
Error: {"status":400,"message":"You may only specify one of these parameters: unit_amount, unit_amount_decimal.","param":"tiers[0][unit_amount]","request_id":"req_xxx","type":"invalid_request_error"}
Dashboard Body for request
{
"active": "true",
"billing_scheme": "tiered",
"currency": "usd",
"product": "prod_xxx",
"recurring": {
"interval": "year",
"interval_count": "1",
"usage_type": "licensed"
},
"tax_behavior": "exclusive",
"tiers": {
"0": {
"flat_amount": "0",
"flat_amount_decimal": "0",
"unit_amount": "10000",
"unit_amount_decimal": "0",
"up_to": "24"
}
},
"tiers_mode": "volume"
}
Dashboard Body for response
{
"error": {
"message": "You may only specify one of these parameters: unit_amount, unit_amount_decimal.",
"param": "tiers[0][unit_amount]",
"type": "invalid_request_error"
}
}
Hey, I've been trying to use your provider to create some price objects in Stripe, but have found that you currently do not support currency_options
attribute (https://stripe.com/docs/api/prices/create#create_price-currency_options).
Would you be willing to add it?
Hi
Is it possible to do feature list for product? I couldn't find anything for it.
I've created a product with a price:
resource "stripe_product" "tier_1" {
name = "item 1"
unit_label = "week"
}
resource "stripe_price" "tier_1" {
product = stripe_product.tier_1.id
currency = "aud"
billing_scheme = "per_unit"
unit_amount = "10"
recurring {
interval = "week"
interval_count = 1
}
}
When I run terraform apply
, the plan shows that stripe_price.tier_1
must be replaced:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement
Terraform will perform the following actions:
# stripe_price.tier_1 must be replaced
-/+ resource "stripe_price" "tier_1" {
~ id = "<sensitive>" -> (known after apply)
- metadata = {} -> null
- tax_behaviour = "unspecified" -> null
~ type = "recurring" -> (known after apply)
- unit_amount_decimal = 10 -> null # forces replacement
# (6 unchanged attributes hidden)
~ recurring {
# (3 unchanged attributes hidden)
}
}
The original price resource isn't deleted but a new one is created.
First of all, thank you for creating this excellent Stripe provider for Terraform.
It has been incredibly helpful in managing our Stripe resources.
We appreciate your hard work and dedication to the project.
I'm trying to create a Stripe Price resource with a custom unit amount using your provider. However, I'm encountering issues with the syntax and configuration. Using v3.0.2
.
Initially, I tried to add the custom_unit_amount
block at the top level:
resource "stripe_price" "prepaid_credits_price" {
currency = "usd"
product = stripe_product.<SOME_OTHER_PRODUCT>.id
nickname = "prepaid-user-can-enter-between-5-and-500"
custom_unit_amount {
enabled = true
minimum = 500
maximum = 50000
preset = 1000
}
}
this resulted in the error: Blocks of type "custom_unit_amount" are not expected here.
Since the custom_unit_amount block wasn't accepted at the top level, I tried to include it within the currency_options
block. Initially, I attempted to use "usd" as the currency, but received an error stating that the currency option matches the top-level currency. So, I switched to using "jpy" as an example:
resource "stripe_price" "prepaid_credits_price" {
currency = "usd"
product = stripe_product.<SOME_OTHER_PRODUCT>.id
nickname = "prepaid-user-can-enter-between-5-and-500"
currency_options {
#currency = "usd" # error: "You are specifying a currency option that matches the top-level currency for this price. Please remove this currency option and it will be added automatically on creation."
currency = "jpy"
custom_unit_amount {
enabled = true
minimum = 500
maximum = 50000
preset = 1000
}
}
}
However, this also resulted in an error:
Cannot specify custom_unit_amount on a currency_option without also specifying custom_unit_amount on the top level price, or vice versa.
Could you help on this? Aplogies if my explanation and details are not clear.
I understand the whole process is different but the following Python code worked when I tested previously and trying to create it from terraform.
stripe.Price.create(
currency="usd",
product=<SOME_OTHER_ID_PRODUCT_ID>,
nickname="prepaid-user-can-enter-between-5-and-500",
custom_unit_amount= {
"enabled": True,
"minimum": 5 00,
"maximum": 50000,
"preset": 1000,
}
)
Thanks.
Hi,
I want to create a Product by specifying an ID, but it doesn't work.
Does this provider supports specifying product IDs?
My .tf is following;
terraform {
required_providers {
stripe = {
source = "lukasaron/stripe"
version = "= 1.6.3"
}
}
}
provider "stripe" {}
resource "stripe_product" "myplan" {
id = "prod_myplan"
name = "My Plan"
}
apply results;
Terraform used the selected providers to generate the following execution plan.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# stripe_product.myplan will be created
+ resource "stripe_product" "myplan" {
+ active = true
+ id = (known after apply)
+ name = "My Plan"
}
Plan: 1 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
stripe_product.myplan: Creating...
stripe_product.myplan: Creation complete after 0s [id=prod_NSKLZrMRKodugv]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
I expected the ID to be prod_myplan
, but it is actually prod_NSKLZrMRKodugv
.
I reffered:
Versions:
Terraform v1.3.9
on darwin_arm64
+ provider registry.terraform.io/lukasaron/stripe v1.6.3
After running a terraform destroy, it completes successfully but the webhooks created are still on my account.
Thanks for this provider. I'm running into an issue where I create a customer portal through terraform and it finishes successfully but when I go to the dashboard, I don't see it. Am I missing something?
The error in the title appears when following the example of tiers in the terraform provider documentation of the resource stripe_price
Workaround is using flat_amount_decimal
attribute and removing a for free tier
Stripe API supports "is_default" attribute on the portal configuration object (https://stripe.com/docs/api/customer_portal/configuration) which indicates that the configuration can be seen and edited in the stripe dashboard/portal. It would be great to be able to have this attribute in the stripe_portal_configuration resource..
Context: I create 63 subscription products with 2 prices each, and hit the HTTP 429 wall.
Error: {"code":"rate_limit","doc_url":"https://stripe.com/docs/error-codes/rate-limit","status":429,"message":"Testmode request rate limit exceeded, the rate limits in testmode are lower than livemode. You can learn more about rate limits here https://stripe.com/docs/rate-limits.","type":"invalid_request_error"}
│
│ with stripe_product.local_template["abp"],
│ on stripe.tf line 91, in resource "stripe_product" "local_template":
│ 91: resource "stripe_product" "local_template" {
More context here: https://stripe.com/docs/error-codes/rate-limit
Running a large volume of closely-spaced requests can lead to rate limiting. Often this is part of an analytical or migration operation. When engaging in these activities, you should try to control the request rate on the client side (see Handling limiting gracefully).
Cheers, and keep up the good work.
I chose this repository out of several StripeProvider repositories because it is the most recently maintained and well documented. Thank you for the development!!
By the way, I noticed that I can't set ZeroPrice in the PriceObject tier settings.
For example, in someone else's Provider, the ! = nil condition, but
This product is ! = 0 condition for this product.
I noticed this when I tried to create a TierPrice where less than 100 users are free and 101 users are paid, but I couldn't create it with Terraform.
Proposal.
Would you like to modify it to accept zero-price?
Hello @lukasaron!
I came across this provider on the Terraform Registry and love the idea of configuring Stripe resources with it.
For the stripe_card
resource, I'm wondering if I could convince you to add a notice along the lines of:
Using the
stripe_card
resource may potentially leak credit card information into your Terraform State.
Please see these recommendations on how to treat sensitive data in Terraform State.
I feel that a notice like this might bring this to a bit more attention.
Thank you for your work on the provider!
Hello @lukasaron , just noticed there was an error with the goreleaser
github action. https://github.com/lukasaron/terraform-provider-stripe/actions/runs/3202577144/jobs/5231736372
Any chance you can have a look so we can get a new release?
Thank you for your quick response :)
May be a known issue, but I noticed that any time I do a terraform apply
, customer portal always suggests products
under subscription_product
have changed. Wanted to check if there is a workaround or if I am doing something incorrectly.
Thank you
Reproduce:
You will see that the price resource is destroyed and recreated every time although nothing was changed in it
It would be awesome to be able to create a PaymentLink resource.
https://stripe.com/docs/api/payment_links/payment_links
I'm happy to help and open a PR if you guide me some bit on how to best contribute :)
It would be nice to be able to use terraform import
to import existing webhook resources
Thanks for providing the terraform module!
We would like to use it for creating a webhook and in general that works just fine. However we would like to create the webhooks in "developer mode". Could you add the livemode parameter to the module?
resource "stripe_webhook_endpoint" "webhook_pr" {
url = "https://someurl.com"
description = "webhook"
enabled_events = [
"invoice.created",
"invoice.payment_succeeded",
"invoice.payment_failed",
]
**livemode = false**
}
When you create a webhook on Stripe's website, you are given an option that says "Listen to events on connected accounts". Checking this option will change the endpoint type. Does the stripe_webhook_endpoint
resource support this option? I couldn't see an argument in the docs that looked like it would fit.
There doesn't seem to be a way to associate a default_price
to a Product.
I assume this is because it's not possible to do it at creation of the Product (Price depends on the creation of the Product). One idea would be to model it like an "attachment", akin to aws_iam_user_policy_attachment which can happen after both the Product and Price exist.
As a workaround I'm using hashicorp/http
to send the Product update request manually.
data "http" "stripe_api_set_default_price" {
url = "https://api.stripe.com/v1/products/${stripe_product.my_product.id}"
method = "POST"
request_headers = {
Accept = "application/json"
"Content-Type" = "application/x-www-form-urlencoded"
Authorization = sensitive("Bearer ${var.api_key}")
}
request_body = "default_price=${stripe_price.my_price.id}"
lifecycle {
postcondition {
condition = contains([200, 201, 204], self.status_code)
error_message = "Stripe default price POST request returned invalid status code"
}
}
depends_on = [stripe_price.my_price]
}
The resource config is:
resource "stripe_product" "base" {
name = "Base"
active = true
shippable = false
}
resource "stripe_price" "base" {
product = stripe_product.base.id
currency = "usd"
active = true
billing_scheme = "per_unit"
tax_behaviour = "inclusive"
unit_amount = 999
recurring {
interval = "month"
interval_count = 1
usage_type = "licensed"
}
}
resource "stripe_product" "premium" {
name = "premium"
active = true
shippable = false
}
resource "stripe_price" "premium" {
product = stripe_product.premium.id
currency = "usd"
active = true
billing_scheme = "per_unit"
tax_behaviour = "inclusive"
unit_amount = 9999
recurring {
interval = "month"
interval_count = 1
usage_type = "licensed"
}
}
resource "stripe_portal_configuration" "portal_configuration" {
business_profile {
headline = "SITE"
privacy_policy_url = "https://domain.com/privacy-policy"
terms_of_service_url = "https://domain.com/terms-of-use"
}
default_return_url = "https://domain.com/"
features {
customer_update {
enabled = true
allowed_updates = ["tax_id"]
}
invoice_history {
enabled = true
}
payment_method_update {
enabled = true
}
subscription_pause {
enabled = false
}
subscription_cancel {
enabled = true
cancellation_reason {
enabled = true
options = ["too_expensive", "missing_features", "switched_service", "unused", "customer_service", "too_complex", "low_quality", "other"]
}
mode = "at_period_end"
proration_behavior = "none"
}
subscription_update {
enabled = true
default_allowed_updates = ["price"]
proration_behavior = "none"
products {
product = stripe_product.base.id
prices = [stripe_price.base.id]
}
products {
product = stripe_product.premium.id
prices = [stripe_price.premium.id]
}
}
}
}
terraform plan after every apply will have:
resource "stripe_portal_configuration" "portal_configuration" {
id = "bpc_ID"
# (3 unchanged attributes hidden)
~ features {
~ subscription_update {
# (3 unchanged attributes hidden)
+ products {
+ prices = [
+ "price_ID",
]
+ product = "prod_ID"
}
+ products {
+ prices = [
+ "price_ID",
]
+ product = "prod_ID"
}
}
# (5 unchanged blocks hidden)
}
# (2 unchanged blocks hidden)
}
It would be great to be able to manage restricted API keys through terraform:
From the Stripe API docs it doesn't seem to be possible to create a Plan with multiple currencies, so I'm guessing it's not possible with this provider too ...
https://stripe.com/docs/api/plans/create
As it's not possible to update a Plan with additional currencies also, I am wondering how Stripe expect businesses to present more than one currency when using the API.
Any input appreciated.
Hi, we noticed a bug in our repository that if you alias your stripe provider like this:
provider "stripe" {
alias = "stripe_account_1"
api_key = var.stripe_account_1_api_key
}
it will not read out the api_key
property correctly. It will therefore ask you for it in the manual prompt and fail in CI/CD. With the env var STRIPE_API_KEY
it works.
When updating a price, a new price is created (which I know is expected as prices are not deletable via api), but nothing happens with the old one.
My expectation was that the original price gets archived when updated, which I believe would give us a better working flow where we don't need to actually go into the dashboard and archive it (set it as inactive), or create duplicates on the terraform file (basically creating a duplicate of the price thats is being updated, and set the original active
as false
)
Example:
resource "stripe_product" "test" {
name = "Test"
}
resource "stripe_price" "test_price" {
product = stripe_product.test.id
currency = "usd"
unit_amount = 100
billing_scheme = "per_unit"
}
Then I update the price to 200
resource "stripe_price" "test_price" {
product = stripe_product.test.id
currency = "usd"
unit_amount = 200
billing_scheme = "per_unit"
}
Terraform plan looks good:
Terraform will perform the following actions:
# stripe_price.test_price3 must be replaced
-/+ resource "stripe_price" "test_price" {
active = true
billing_scheme = "per_unit"
currency = "usd"
~ id = "price_1L3QzvGSY3yttFEYXbw4aRbB" -> (known after apply)
- metadata = {} -> null
product = "prod_Lkwn9obUtoxp2j"
- tax_behaviour = "unspecified" -> null
transfer_lookup_key = false
~ type = "one_time" -> (known after apply)
~ unit_amount = 100 -> 200 # forces replacement
}
Plan: 1 to add, 0 to change, 1 to destroy.
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
What I believe should happen, is that the 100 price entry should be archived (set active status to false).
https://stripe.com/docs/api/prices/object#price_object-type
The type property must be settable or be implicitely set to one_time
if recurring block is not set
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.