https://github.com/chargebee/chargebee-go
Go library for the Chargebee API.
https://github.com/chargebee/chargebee-go
chargebee go
Last synced: 4 months ago
JSON representation
Go library for the Chargebee API.
- Host: GitHub
- URL: https://github.com/chargebee/chargebee-go
- Owner: chargebee
- License: mit
- Created: 2018-06-07T13:23:38.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2026-02-16T08:52:59.000Z (4 months ago)
- Last Synced: 2026-02-16T16:29:30.736Z (4 months ago)
- Topics: chargebee, go
- Language: Go
- Homepage: https://apidocs.chargebee.com/docs/api?lang=go
- Size: 1.71 MB
- Stars: 25
- Watchers: 31
- Forks: 25
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Security: SECURITY.md
Awesome Lists containing this project
README
# Chargebee Go Client Library
> [!NOTE]
> [](https://discord.gg/S3SXDzXHAg)
>
> We are trialing a Discord server for developers building with Chargebee. Limited spots are open on a first-come basis. Join [here](https://discord.gg/gpsNqnhDm2) if interested.
This is the official Go library for integrating with Chargebee
- 📘 For a complete reference of available APIs, check out our [API Documentation](https://apidocs.chargebee.com/docs/api/?lang=go).
- 🧪 To explore and test API capabilities interactively, head over to our [API Explorer](https://api-explorer.chargebee.com).
**Go version**: v3 and v2 of the library require Go v1.3 or higher.
## Library versions
***
The versioning scheme of this library is inspired by [SemVer](https://semver.org/) and the format is `v{MAJOR}.{MINOR}.{PATCH}`. For example, `v3.0.0` and `v2.5.1` are valid library versions.
The following table provides some details for each major version:
| Library major version | Status | Compatible API versions | **Branch** |
|----------------------------|----------|-----------------------------------------------------------------------------------------------------|---------------|
| v3 | Active | [v2](https://apidocs.chargebee.com/docs/api/v2?lang=go) and [v1](https://apidocs.chargebee.com/docs/api/v1?lang=go) | `master` |
| v2 | Inactive | [v2](https://apidocs.chargebee.com/docs/api/v2?lang=go) and [v1](https://apidocs.chargebee.com/docs/api/v1?lang=go) | `chargebee-v2`|
A couple of terms used in the above table are explained below:
- **Status**: The current development status for the library version. An **Active** major version is currently being maintained and continues to get backward-compatible changes.
- **Branch**: The branch in this repository containing the source code for the latest release of the library version. Every version of the library has been [tagged](https://github.com/chargebee/chargebee-go/tags). You can check out the source code for any version using its tag.
🔴 **Attention**: The support for v2 will eventually be discontinued on **December 31st 2023** and will no longer receive any further updates. We strongly recommend [upgrading to v3](https://github.com/chargebee/chargebee-go/wiki/Migration-guide-for-v3) as soon as possible.
**Note:** See the [changelog](CHANGELOG.md) for a history of changes.
## Install the library
***
Install the latest version of the library with the following commands:
### Install v3
``` shell
go get github.com/chargebee/chargebee-go/v3
```
### Install v2
``` shell
go get github.com/chargebee/chargebee-go
```
## Use the library
***
Some examples for using the library are listed below.
### Create a customer and subscription
```go
import (
"fmt"
"github.com/chargebee/chargebee-go/v3"
subscriptionAction "github.com/chargebee/chargebee-go/v3/actions/subscription"
"github.com/chargebee/chargebee-go/v3/models/subscription"
)
func main() {
chargebee.Configure("{site_api_key}", "{site}")
res, err := subscriptionAction.Create(&subscription.CreateRequestParams{
PlanId: "cbdemo_grow",
BillingCycles: chargebee.Int32(3),
AutoCollection: enum.AutoCollectionOff,
Customer: &subscription.CreateCustomerParams{
Email: "john@user.com",
FirstName: "John",
LastName: "Doe",
Locale: "fr-CA",
Phone: "+1-949-999-9999",
AutoCollection: enum.AutoCollectionOff,
}}).Request()
if err != nil {
panic(err)
}else{
Subscription := res.Subscription
Customer := res.Customer
Invoice := res.Invoice
}
}
```
### Create a subscription with addons, metadata, and coupons
```go
import (
"fmt"
"github.com/chargebee/chargebee-go/v3"
subscriptionAction "github.com/chargebee/chargebee-go/v3/actions/subscription"
"github.com/chargebee/chargebee-go/v3/models/subscription"
)
func main() {
chargebee.Configure("{site_api_key}", "{site}")
res, err := subscriptionAction.Create(&subscription.CreateRequestParams{
PlanId: "cbdemo_grow",
BillingCycles: chargebee.Int32(3),
AutoCollection: enum.AutoCollectionOff,
Customer: &subscription.CreateCustomerParams{
Email: "john@user.com",
FirstName: "John",
LastName: "Doe",
Locale: "fr-CA",
Phone: "+1-949-999-9999",
AutoCollection: enum.AutoCollectionOff,
},
BillingAddress: &subscription.CreateBillingAddressParams{
FirstName: "John",
LastName: "Doe",
Line1: "PO Box 9999",
City: "Walnut",
State: "California",
Zip: "91789",
Country: "US",
},
MetaData: map[string]interface{}{
"features": map[string]interface{}{
"usage-limit": "5GB",
"speed-within-quota": "2MBbps",
"post-usage-quota": "512kbps",
},
},
Addons: []*subscription.CreateAddonParams{
{
Id: "cbdemo_conciergesupport",
},
{
Id: "cbdemo_additionaluser",
Quantity: chargebee.Int32(2),
},
},
CouponIds: []string{"cbdemo_earlybird"},
}).Request()
if err != nil {
panic(err)
}else{
Subscription := res.Subscription
Customer := res.Customer
Card := res.Card
Invoice := res.Invoice
UnbilledCharges := res.UnbilledCharges
}
}
```
### Create a subscription with custom headers, custom fields and custom context
```go
import (
"fmt"
"github.com/chargebee/chargebee-go/v3"
subscriptionAction "github.com/chargebee/chargebee-go/v3/actions/subscription"
"github.com/chargebee/chargebee-go/v3/models/subscription"
)
func main() {
chargebee.Configure("{site_api_key}", "{site}")
res, err := subscriptionAction.Create(&subscription.CreateRequestParams{
PlanId: "cbdemo_grow",
}).Headers("chargebee-request-origin-ip", "192.168.1.2").Contexts(ctx).AddParams("cf_gender","Female").Request() // Customer level custom field.
if err != nil {
panic(err)
}else{
Subscription := res.Subscription
Customer := res.Customer
Card := res.Card
Invoice := res.Invoice
UnbilledCharges := res.UnbilledCharges
}
}
```
### Retrieve a filtered list of subscriptions
```go
import (
"fmt"
"github.com/chargebee/chargebee-go/v3"
subscriptionAction "github.com/chargebee/chargebee-go/v3/actions/subscription"
"github.com/chargebee/chargebee-go/v3/filter"
"github.com/chargebee/chargebee-go/v3/models/subscription"
)
func main() {
chargebee.Configure("{site_api_key}", "{site}")
res, err := subscriptionAction.List(&subscription.ListRequestParams{
Limit: chargebee.Int32(5),
Id: &filter.StringFilter{
In: []string{"cbdemo_john-sub", "cbdemo_ricky-sub"},
},
PlanId: &filter.StringFilter{
IsNot: "basic",
},
Status: &filter.EnumFilter{
Is: subscriptionEnum.StatusActive,
},
SortBy: &filter.SortFilter{
Asc: "created_at",
},
}).ListRequest()
if err != nil {
panic(err)
}else{
for i := range res.List {
Subscription := res.List[i].Subscription
Customer := res.List[i].Customer
Card := res.List[i].Card
}
}
}
```
### Create an idempotent request
[Idempotency keys](https://apidocs.chargebee.com/docs/api/idempotency?prod_cat_ver=2) are passed along with request headers to allow a safe retry of POST requests.
```go
import (
"fmt"
"github.com/chargebee/chargebee-go/v3"
customerAction "github.com/chargebee/chargebee-go/v3/actions/customer"
"github.com/chargebee/chargebee-go/v3/models/customer"
)
func main() {
chargebee.Configure("{site_api_key}", "{site}")
res, err := customerAction.Create(&customer.CreateRequestParams{
FirstName: "John",
LastName: "Doe",
Email: "john@test.com",
})
.SetIdempotencyKey("ghggh") // Replace <> with a unique string
.Request()
if err != nil {
fmt.Println(err)
} else {
Customer := res.Customer
fmt.Println(Customer)
}
headerValue := res.GetResponseHeaders() // Retrieves response headers
fmt.Println(headerValue)
idempotencyReplayedValue := res.IsIdempotencyReplayed()// Retrieves idempotency replayed header value
fmt.Println(idempotencyReplayedValue)
}
```
`IsIdempotencyReplayed()` method can be accessed to differentiate between original and replayed requests.
### Handle webhooks
Use the `webhook` package to parse and route webhook payloads from Chargebee.
High-level: route events with callbacks using `WebhookHandler`:
```go
package main
import (
"log"
"net/http"
"github.com/chargebee/chargebee-go/v3/webhook"
)
func main() {
handler := &webhook.WebhookHandler{
// Optional: protect endpoint (e.g., Basic Auth)
RequestValidator: webhook.BasicAuthValidator(func(user, pass string) bool {
return user == "admin" && pass == "secret"
}),
OnError: webhook.BasicAuthErrorHandler, // Optional: standard auth error responses
// Register only the events you care about
OnSubscriptionCreated: func(e webhook.SubscriptionCreatedEvent) error {
log.Printf("Subscription created event %s", e.Id)
return nil
},
OnPaymentSucceeded: func(e webhook.PaymentSucceededEvent) error {
log.Printf("Payment succeeded for customer: %v", e.Content.Customer)
return nil
},
}
http.Handle("/chargebee/webhooks", handler.HTTPHandler())
log.Fatal(http.ListenAndServe(":8080", nil))
}
```
Low-level: parse just the event type and unmarshal yourself:
```go
package main
import (
"encoding/json"
"io"
"net/http"
"github.com/chargebee/chargebee-go/v3/enum"
"github.com/chargebee/chargebee-go/v3/webhook"
)
func cbWebhook(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
evtType, err := webhook.ParseEventType(body) // validates api_version too
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
switch evtType {
case enum.EventTypeSubscriptionCreated:
var e webhook.SubscriptionCreatedEvent
if err := json.Unmarshal(body, &e); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// handle e
default:
// ignore or log
}
w.WriteHeader(http.StatusOK)
}
```
#### Unhandled events
By default, if an incoming webhook’s event type is unknown or you have not registered a corresponding handler on `WebhookHandler`, the SDK treats it as an error. When using `HTTPHandler()`, this results in a 500 response unless you provide a custom `OnError` handler.
If you prefer to acknowledge unknown/unregistered events (return 200) and just log them, set `OnUnhandledEvent` to a function that returns `nil`:
```go
import (
"log"
"github.com/chargebee/chargebee-go/v3/enum"
"github.com/chargebee/chargebee-go/v3/webhook"
)
handler := &webhook.WebhookHandler{
OnUnhandledEvent: func(t enum.EventType, body []byte) error {
log.Printf("Ignoring unhandled event: %s", t)
return nil // swallow as OK
},
}
```
## Use the test suite
***
Use [Testify's `require`](https://github.com/stretchr/testify/#require-package) package to run the test suite
```shell
go get github.com/stretchr/testify/require
```
## Handle errors
***
```go
_,err := //Go Library call
if err != nil {
if goErr,ok := err.(*chargebee.Error); ok {
//Identify the type of Error
switch goErr.Type {
case chargebee.PaymentError:
// First check for card parameters entered by the user.
// We recommend you to validate the input at the client side itself to catch simple mistakes.
if goErr.Param == "card[number]" {
// Ask your user to recheck the card number. A better way is to use
// Stripe's https://github.com/stripe/jquery.payment for validating it in the client side itself.
//}else if(goErr.Param == <other card params>){
//Similarly check for other card parameters entered by the user.
//....
} else {
// Verfication or processing failures.
// Provide a standard message to your user to recheck his card details or provide a different card.
// Like 'Sorry,there was a problem when processing your card, please check the details and try again'.
}
case chargebee.InvalidRequestError:
// For coupons you could decide to provide specific messages by using
// the 'api_error_code' attribute in the ex.
if goErr.Param == "coupon" {
if goErr.APIErrorCode == "resource_not_found" {
// Inform user to recheck his coupon code.
} else if goErr.APIErrorCode == "resource_limit_exhausted" {
// Inform user that the coupon code has expired.
} else if goErr.APIErrorCode == "invalid_request" {
// Inform user that the coupon code is not applicable for his plan(/addons).
} else {
// Inform user to recheck his coupon code.
}
} else {
// Since you would have validated all other parameters on your side itself,
// this could probably be a bug in your code. Provide a generic message to your users.
}
case chargebee.OperationFailedError:
// Indicates that the request parameters were right but the request couldn't be completed.
// The reasons might be "api_request_limit_exceeded" or could be due to an issue in ChargeBee side.
// These should occur very rarely and mostly be of temporary nature.
// You could ask your user to retry after some time.
default :
// These are unhandled exceptions (Could be due to a bug in your code or very rarely in client library).
// The errors from ChargeBee such as authentication failures will come here.
// You could ask users contact your support.
}
}
}
```
### Retry Handling
Chargebee's SDK includes built-in retry logic to handle temporary network issues and server-side errors. This feature is **disabled by default** but can be **enabled when needed**.
#### Key features include:
- **Automatic retries for specific HTTP status codes**: Retries are automatically triggered for status codes `500`, `502`, `503`, and `504`.
- **Exponential backoff**: Retry delays increase exponentially to prevent overwhelming the server.
- **Rate limit management**: If a `429 Too Many Requests` response is received with a `Retry-After` header, the SDK waits for the specified duration before retrying.
> *Note: Exponential backoff and max retries do not apply in this case.*
- **Customizable retry behavior**: Retry logic can be configured using the `retryConfig` parameter in the environment configuration.
#### Example: Customizing Retry Logic
You can enable and configure the retry logic by passing a `retryConfig` object when initializing the Chargebee environment:
```go
import (
"fmt"
"github.com/chargebee/chargebee-go/v3"
customerAction "github.com/chargebee/chargebee-go/v3/actions/customer"
"github.com/chargebee/chargebee-go/v3/models/customer"
)
func main() {
chargebee.Configure("{site_api_key}", "{site}")
retryConfig := &chargebee.RetryConfig{
Enabled: true,
MaxRetries: 3,
DelayMs: 500,
RetryOn: map[int]struct{}{500: {}, 503: {}},
}
chargebee.WithRetryConfig(retryConfig)
}
// ... your Chargebee API operations below ...
```
#### Example: Rate Limit retry logic
You can enable and configure the retry logic for rate-limit by passing a `retryConfig` object when initializing the Chargebee environment:
```go
import (
"fmt"
"github.com/chargebee/chargebee-go/v3"
customerAction "github.com/chargebee/chargebee-go/v3/actions/customer"
"github.com/chargebee/chargebee-go/v3/models/customer"
)
func main() {
chargebee.Configure("{site_api_key}", "{site}")
retryConfig := &chargebee.RetryConfig{
Enabled: true,
MaxRetries: 3,
DelayMs: 500,
RetryOn: map[int]struct{}{429: {}},
}
chargebee.WithRetryConfig(retryConfig)
}
// ... your Chargebee API operations below ...
```
## Contribution
***
You may contribute patches to any of the **Active** versions of this library. To do so, raise a PR against the [respective branch](#library-versions).
If you find something amiss, you are welcome to create an [issue](https://github.com/chargebee/chargebee-go/issues).
## API documentation
***
The API documentation for the Go library can be found in our [API reference](https://apidocs.chargebee.com/docs/api?lang=go).
## License
***
See the [LICENSE](LICENSE).
---