I am trying to grab some data from the struct of the stripe response objects for subscriptions. Here is link to the structure of the response object stribe subscription object
Here is what i have and what am trying to do
type SubscriptionDetails struct {
CustomerId string `json:"customer_id"`
SubscritpionId string `json:"subscritpion_id"`
StartAt time.Time `json:"start_at"`
EndAt time.Time `json:"end_at"`
Interval string `json:"interval"`
Plan string `json:"plan"`
PlanId string `json:"plan_id"`
SeatCount uint8 `json:"seat_count"`
PricePerSeat float64 `json:"price_per_seat"`
}
func CreateStripeSubscription(CustomerId string, planId string) (*SubscriptionDetails, error) {
stripe.Key = StripeKey
params := &stripe.SubscriptionParams{
Customer: stripe.String(CustomerId),
Items: []*stripe.SubscriptionItemsParams{
&stripe.SubscriptionItemsParams{
Price: stripe.String(planId),
},
},
}
result, err := sub.New(params)
if err != nil {
return nil, err
}
data := &SubscriptionDetails{}
data.CustomerId = result.Customer
data.SubscritpionId = result.ID
data.StartAt = result.CurrentPeriodStart
data.EndAt = result.CurrentPeriodEnd
data.Interval = result.Items.Data.Price.Recurring.Interval
data.Plan = result.Items.Data.Price.Nickname
data.SeatCount = result.Items.Data.Quantity
data.PricePerSeat = result.Items.Data.Price.UnitAmount
return data, nil
}
there are some items that are easy to get directly like ID field i got easily with result.ID and no complaints but for other items here are the error messages am getting
cannot use result.CurrentPeriodStart (type int64) as type time.Time in assignment
...
cannot use result.Customer (type *stripe.Customer) as type string in assignment
...
result.Items.Data.price undefined (type []*stripe.SubscriptionItem has no field or method price)
So how do i get the data for data.CustomerId and data.PricePerSeat?
UPDATE:
here is structure of the subscription object from stripe
type FilesStripeCreateSubscription struct {
ID string `json:"id"`
CancelAt interface{} `json:"cancel_at"`
CancelAtPeriodEnd bool `json:"cancel_at_period_end"`
CanceledAt interface{} `json:"canceled_at"`
CurrentPeriodEnd int64 `json:"current_period_end"`
CurrentPeriodStart int64 `json:"current_period_start"`
Customer string `json:"customer"`
Items struct {
Data []struct {
ID string `json:"id"`
BillingThresholds interface{} `json:"billing_thresholds"`
Created int64 `json:"created"`
Metadata struct {
} `json:"metadata"`
Object string `json:"object"`
Price struct {
ID string `json:"id"`
Active bool `json:"active"`
Currency string `json:"currency"`
CustomUnitAmount interface{} `json:"custom_unit_amount"`
Metadata struct {
} `json:"metadata"`
Nickname string `json:"nickname"`
Object string `json:"object"`
Product string `json:"product"`
Recurring struct {
AggregateUsage interface{} `json:"aggregate_usage"`
Interval string `json:"interval"`
IntervalCount int64 `json:"interval_count"`
UsageType string `json:"usage_type"`
} `json:"recurring"`
TaxBehavior string `json:"tax_behavior"`
TiersMode interface{} `json:"tiers_mode"`
TransformQuantity interface{} `json:"transform_quantity"`
Type string `json:"type"`
UnitAmount int64 `json:"unit_amount"`
UnitAmountDecimal int64 `json:"unit_amount_decimal,string"`
} `json:"price"`
Quantity int64 `json:"quantity"`
Subscription string `json:"subscription"`
TaxRates []interface{} `json:"tax_rates"`
} `json:"data"`
} `json:"items"`
}
Lets first go over the code which works under the hood, what is being returned and then we look at the problems one at a time.
When we call sub.New() method with params it returns Subscription type
Note: I will only show limited definition for types since adding the complete structure will make the answer big and not specific to the question context
Lets Look Subscription type
type Subscription struct {
...
// Start of the current period that the subscription has been invoiced for.
CurrentPeriodStart int64 `json:"current_period_start"`
// ID of the customer who owns the subscription.
Customer *Customer `json:"customer"`
...
// List of subscription items, each with an attached price.
Items *SubscriptionItemList `json:"items"`
...
}
Let looks over the first error
cannot use result.CurrentPeriodStart (type int64) as type time.Time in assignment
According to the Subscription type we can see CurrentPeriodStart is of type int64 while you are trying to set it to StartAt field of SubscriptionDetails type which is of type time.Time since the types are different one type cannot be assigned to other, to solve the issue we need to explicitly convert it to time.Time which can be done as follows:
data.StartAt = time.Unix(result.CurrentPeriodStart, 0)
time.Unix method creates time.Time type from the passed int64 value and return which we can assign to StartAt field
Now lets move on to the second error
cannot use result.Customer (type *stripe.Customer) as type string in assignment
As we can see from Subscription definition Customer field is of type *Customer it is not string type since you are trying to assign *Customer type to CustomerId field of string type which is not possible that causes the above error, referred data is incorrect then where is the correct data the correct data is available inside *Customer type withing ID field which can be retrieved as follows
data.CustomerId = result.Customer.ID
Lets go over the last error
result.Items.Data.price undefined (type []*stripe.SubscriptionItem has no field or method price)
Again if we look at Subscription definition we can see Items field is of type *SubscriptionItemList type and if we look at *SubscriptionItemList definition
type SubscriptionItemList struct {
APIResource
ListMeta
Data []*SubscriptionItem `json:"data"`
}
It contains a field name Data and Data is of type []*SubscriptionItem notice it is slice [] of *SubscriptionItem, which is the cause of the error since Data field is slice of *SubscriptionItem we can solve the problem as below:
data.PricePerSeat = result.Items.Data[0].price.UnitAmount
There are few more errors which can occur that I would like to point out please continue reading below to solve those issue
Now lets look at *SubscriptionItem definition
type SubscriptionItem struct {
...
Price *Price `json:"price"`
...
}
It contains Price field notice the name starts with capital letter and in shared code it is referred with small letter which can cause another issue and finally if we look at Price definition
type Price struct {
...
// The unit amount in %s to be charged, represented as a whole integer if possible. Only set if `billing_scheme=per_unit`.
UnitAmount int64 `json:"unit_amount"`
// The unit amount in %s to be charged, represented as a decimal string with at most 12 decimal places. Only set if `billing_scheme=per_unit`.
UnitAmountDecimal float64 `json:"unit_amount_decimal,string"`
...
}
It contains UnitAmount field which is what we are using, but there is a catch here UnitAmount is of type int64 but PricePerSeat is of type float64 assigning different type to each other will again cause error so either you can convert int64 to float64 or even better you can use UnitAmountDecimal field available within Price type containing the same data in float64 format which will reduce the explicit conversion that we would have to do when using UnitAmount field, so as per the explanation we get below solution
data.PricePerSeat = result.Items.Data[0].Price.UnitAmountDecimal
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With