github.com/stripe/stripe-go/v76@v76.25.0/README.md (about) 1 # Go Stripe 2 [](https://pkg.go.dev/github.com/stripe/stripe-go/v76) 3 [](https://github.com/stripe/stripe-go/actions/workflows/ci.yml?query=branch%3Amaster) 4 [](https://coveralls.io/github/stripe/stripe-go?branch=master) 5 6 The official [Stripe][stripe] Go client library. 7 8 ## Requirements 9 10 - Go 1.15 or later 11 12 ## Installation 13 14 Make sure your project is using Go Modules (it will have a `go.mod` file in its 15 root if it already is): 16 17 ``` sh 18 go mod init 19 ``` 20 21 Then, reference stripe-go in a Go program with `import`: 22 23 ``` go 24 import ( 25 "github.com/stripe/stripe-go/v76" 26 "github.com/stripe/stripe-go/v76/customer" 27 ) 28 ``` 29 30 Run any of the normal `go` commands (`build`/`install`/`test`). The Go 31 toolchain will resolve and fetch the stripe-go module automatically. 32 33 Alternatively, you can also explicitly `go get` the package into a project: 34 35 ```bash 36 go get -u github.com/stripe/stripe-go/v76 37 ``` 38 39 ## Documentation 40 41 For a comprehensive list of examples, check out the [API 42 documentation][api-docs]. 43 44 See [video demonstrations][youtube-playlist] covering how to use the library. 45 46 For details on all the functionality in this library, see the [Go 47 documentation][goref]. 48 49 Below are a few simple examples: 50 51 ### Customers 52 53 ```go 54 params := &stripe.CustomerParams{ 55 Description: stripe.String("Stripe Developer"), 56 Email: stripe.String("gostripe@stripe.com"), 57 PreferredLocales: stripe.StringSlice([]string{"en", "es"}), 58 } 59 60 c, err := customer.New(params) 61 ``` 62 63 ### PaymentIntents 64 65 ```go 66 params := &stripe.PaymentIntentListParams{ 67 Customer: stripe.String(customer.ID), 68 } 69 70 i := paymentintent.List(params) 71 for i.Next() { 72 pi := i.PaymentIntent() 73 } 74 75 if err := i.Err(); err != nil { 76 // handle 77 } 78 ``` 79 80 ### Events 81 82 ```go 83 i := event.List(nil) 84 for i.Next() { 85 e := i.Event() 86 87 // access event data via e.GetObjectValue("resource_name_based_on_type", "resource_property_name") 88 // alternatively you can access values via e.Data.Object["resource_name_based_on_type"].(map[string]interface{})["resource_property_name"] 89 90 // access previous attributes via e.GetPreviousValue("resource_name_based_on_type", "resource_property_name") 91 // alternatively you can access values via e.Data.PrevPreviousAttributes["resource_name_based_on_type"].(map[string]interface{})["resource_property_name"] 92 } 93 ``` 94 95 Alternatively, you can use the `event.Data.Raw` property to unmarshal to the 96 appropriate struct. 97 98 ### Authentication with Connect 99 100 There are two ways of authenticating requests when performing actions on behalf 101 of a connected account, one that uses the `Stripe-Account` header containing an 102 account's ID, and one that uses the account's keys. Usually the former is the 103 recommended approach. [See the documentation for more information][connect]. 104 105 To use the `Stripe-Account` approach, use `SetStripeAccount()` on a `ListParams` 106 or `Params` class. For example: 107 108 ```go 109 // For a list request 110 listParams := &stripe.CustomerListParams{} 111 listParams.SetStripeAccount("acct_123") 112 ``` 113 114 ```go 115 // For any other kind of request 116 params := &stripe.CustomerParams{} 117 params.SetStripeAccount("acct_123") 118 ``` 119 120 To use a key, pass it to `API`'s `Init` function: 121 122 ```go 123 124 import ( 125 "github.com/stripe/stripe-go/v76" 126 "github.com/stripe/stripe-go/v76/client" 127 ) 128 129 stripe := &client.API{} 130 stripe.Init("access_token", nil) 131 ``` 132 133 ### Google AppEngine 134 135 If you're running the client in a Google AppEngine environment, you'll need to 136 create a per-request Stripe client since the `http.DefaultClient` is not 137 available. Here's a sample handler: 138 139 ```go 140 import ( 141 "fmt" 142 "net/http" 143 144 "google.golang.org/appengine" 145 "google.golang.org/appengine/urlfetch" 146 147 "github.com/stripe/stripe-go/v76" 148 "github.com/stripe/stripe-go/v76/client" 149 ) 150 151 func handler(w http.ResponseWriter, r *http.Request) { 152 c := appengine.NewContext(r) 153 httpClient := urlfetch.Client(c) 154 155 sc := client.New("sk_test_123", stripe.NewBackends(httpClient)) 156 157 params := &stripe.CustomerParams{ 158 Description: stripe.String("Stripe Developer"), 159 Email: stripe.String("gostripe@stripe.com"), 160 } 161 customer, err := sc.Customers.New(params) 162 if err != nil { 163 fmt.Fprintf(w, "Could not create customer: %v", err) 164 } 165 fmt.Fprintf(w, "Customer created: %v", customer.ID) 166 } 167 ``` 168 169 ## Usage 170 171 While some resources may contain more/less APIs, the following pattern is 172 applied throughout the library for a given `$resource$`: 173 174 ### Without a Client 175 176 If you're only dealing with a single key, you can simply import the packages 177 required for the resources you're interacting with without the need to create a 178 client. 179 180 ```go 181 import ( 182 "github.com/stripe/stripe-go/v76" 183 "github.com/stripe/stripe-go/v76/$resource$" 184 ) 185 186 // Setup 187 stripe.Key = "sk_key" 188 189 // Set backend (optional, useful for mocking) 190 // stripe.SetBackend("api", backend) 191 192 // Create 193 resource, err := $resource$.New(&stripe.$Resource$Params{}) 194 195 // Get 196 resource, err = $resource$.Get(id, &stripe.$Resource$Params{}) 197 198 // Update 199 resource, err = $resource$.Update(id, &stripe.$Resource$Params{}) 200 201 // Delete 202 resourceDeleted, err := $resource$.Del(id, &stripe.$Resource$Params{}) 203 204 // List 205 i := $resource$.List(&stripe.$Resource$ListParams{}) 206 for i.Next() { 207 resource := i.$Resource$() 208 } 209 210 if err := i.Err(); err != nil { 211 // handle 212 } 213 ``` 214 215 ### With a Client 216 217 If you're dealing with multiple keys, it is recommended you use `client.API`. 218 This allows you to create as many clients as needed, each with their own 219 individual key. 220 221 ```go 222 import ( 223 "github.com/stripe/stripe-go/v76" 224 "github.com/stripe/stripe-go/v76/client" 225 ) 226 227 // Setup 228 sc := &client.API{} 229 sc.Init("sk_key", nil) // the second parameter overrides the backends used if needed for mocking 230 231 // Create 232 $resource$, err := sc.$Resource$s.New(&stripe.$Resource$Params{}) 233 234 // Get 235 $resource$, err = sc.$Resource$s.Get(id, &stripe.$Resource$Params{}) 236 237 // Update 238 $resource$, err = sc.$Resource$s.Update(id, &stripe.$Resource$Params{}) 239 240 // Delete 241 $resource$Deleted, err := sc.$Resource$s.Del(id, &stripe.$Resource$Params{}) 242 243 // List 244 i := sc.$Resource$s.List(&stripe.$Resource$ListParams{}) 245 for i.Next() { 246 $resource$ := i.$Resource$() 247 } 248 249 if err := i.Err(); err != nil { 250 // handle 251 } 252 ``` 253 254 ### Accessing the Last Response 255 256 Use `LastResponse` on any `APIResource` to look at the API response that 257 generated the current object: 258 259 ``` go 260 c, err := coupon.New(...) 261 requestID := coupon.LastResponse.RequestID 262 ``` 263 264 Similarly, for `List` operations, the last response is available on the list 265 object attached to the iterator: 266 267 ``` go 268 it := coupon.List(...) 269 for it.Next() { 270 // Last response *NOT* on the individual iterator object 271 // it.Coupon().LastResponse // wrong 272 273 // But rather on the list object, also accessible through the iterator 274 requestID := it.CouponList().LastResponse.RequestID 275 } 276 ``` 277 278 See the definition of [`APIResponse`][apiresponse] for available fields. 279 280 Note that where API resources are nested in other API resources, only 281 `LastResponse` on the top-level resource is set. 282 283 ### Automatic Retries 284 285 The library automatically retries requests on intermittent failures like on a 286 connection error, timeout, or on certain API responses like a status `409 287 Conflict`. [Idempotency keys][idempotency-keys] are always added to requests to 288 make any such subsequent retries safe. 289 290 By default, it will perform up to two retries. That number can be configured 291 with `MaxNetworkRetries`: 292 293 ```go 294 import ( 295 "github.com/stripe/stripe-go/v76" 296 "github.com/stripe/stripe-go/v76/client" 297 ) 298 299 config := &stripe.BackendConfig{ 300 MaxNetworkRetries: stripe.Int64(0), // Zero retries 301 } 302 303 sc := &client.API{} 304 sc.Init("sk_key", &stripe.Backends{ 305 API: stripe.GetBackendWithConfig(stripe.APIBackend, config), 306 Uploads: stripe.GetBackendWithConfig(stripe.UploadsBackend, config), 307 }) 308 309 coupon, err := sc.Coupons.New(...) 310 ``` 311 312 ### Configuring Logging 313 314 By default, the library logs error messages only (which are sent to `stderr`). 315 Configure default logging using the global `DefaultLeveledLogger` variable: 316 317 ```go 318 stripe.DefaultLeveledLogger = &stripe.LeveledLogger{ 319 Level: stripe.LevelInfo, 320 } 321 ``` 322 323 Or on a per-backend basis: 324 325 ```go 326 config := &stripe.BackendConfig{ 327 LeveledLogger: &stripe.LeveledLogger{ 328 Level: stripe.LevelInfo, 329 }, 330 } 331 ``` 332 333 It's possible to use non-Stripe leveled loggers as well. Stripe expects loggers 334 to comply to the following interface: 335 336 ```go 337 type LeveledLoggerInterface interface { 338 Debugf(format string, v ...interface{}) 339 Errorf(format string, v ...interface{}) 340 Infof(format string, v ...interface{}) 341 Warnf(format string, v ...interface{}) 342 } 343 ``` 344 345 Some loggers like [Logrus][logrus] and Zap's [SugaredLogger][zapsugaredlogger] 346 support this interface out-of-the-box so it's possible to set 347 `DefaultLeveledLogger` to a `*logrus.Logger` or `*zap.SugaredLogger` directly. 348 For others it may be necessary to write a thin shim layer to support them. 349 350 ### Expanding Objects 351 352 All [expandable objects][expandableobjects] in stripe-go take the form of a 353 full resource struct, but unless expansion is requested, only the `ID` field of 354 that struct is populated. Expansion is requested by calling `AddExpand` on 355 parameter structs. For example: 356 357 ``` go 358 // 359 // *Without* expansion 360 // 361 c, _ := charge.Get("ch_123", nil) 362 363 c.Customer.ID // Only ID is populated 364 c.Customer.Name // All other fields are always empty 365 366 // 367 // With expansion 368 // 369 p := &stripe.ChargeParams{} 370 p.AddExpand("customer") 371 c, _ = charge.Get("ch_123", p) 372 373 c.Customer.ID // ID is still available 374 c.Customer.Name // Name is now also available (if it had a value) 375 ``` 376 ### How to use undocumented parameters and properties 377 378 stripe-go is a typed library and it supports all public properties or parameters. 379 380 Stripe sometimes launches private beta features which introduce new properties or parameters that are not immediately public. These will not have typed accessors in the stripe-go library but can still be used. 381 382 #### Parameters 383 384 To pass undocumented parameters to Stripe using stripe-go you need to use the `AddExtra()` method, as shown below: 385 386 ```go 387 388 params := &stripe.CustomerParams{ 389 Email: stripe.String("jenny.rosen@example.com") 390 } 391 392 params.AddExtra("secret_feature_enabled", "true") 393 params.AddExtra("secret_parameter[primary]","primary value") 394 params.AddExtra("secret_parameter[secondary]","secondary value") 395 396 customer, err := customer.Create(params) 397 ``` 398 399 #### Properties 400 401 You can access undocumented properties returned by Stripe by querying the raw response JSON object. An example of this is shown below: 402 403 ```go 404 customer, _ = customer.Get("cus_1234", nil); 405 406 var rawData map[string]interface{} 407 _ = json.Unmarshal(customer.LastResponse.RawJSON, &rawData) 408 409 secret_feature_enabled, _ := string(rawData["secret_feature_enabled"].(bool)) 410 411 secret_parameter, ok := rawData["secret_parameter"].(map[string]interface{}) 412 if ok { 413 primary := secret_parameter["primary"].(string) 414 secondary := secret_parameter["secondary"].(string) 415 } 416 ``` 417 418 ### Webhook signing 419 Stripe can optionally sign the webhook events it sends to your endpoint, allowing you to validate that they were not sent by a third-party. You can read more about it [here](https://stripe.com/docs/webhooks/signatures). 420 421 #### Testing Webhook signing 422 You can use `stripe.webhook.GenerateTestSignedPayload` to mock webhook events that come from Stripe: 423 424 ```go 425 payload := map[string]interface{}{ 426 "id": "evt_test_webhook", 427 "object": "event", 428 "api_version": stripe.APIVersion, 429 } 430 testSecret := "whsec_test_secret" 431 432 payloadBytes, err := json.Marshal(payload) 433 434 signedPayload := webhook.GenerateTestSignedPayload(&webhook.UnsignedPayload{Payload: payloadBytes, Secret: testSecret}) 435 event, err := webhook.ConstructEvent(signedPayload.Payload, signedPayload.Header, signedPayload.Secret) 436 437 if event.ID == payload["id"] { 438 // Do something with the mocked signed event 439 } else { 440 // Handle invalid event payload 441 } 442 ``` 443 444 ### Writing a Plugin 445 446 If you're writing a plugin that uses the library, we'd appreciate it if you 447 identified using `stripe.SetAppInfo`: 448 449 ```go 450 stripe.SetAppInfo(&stripe.AppInfo{ 451 Name: "MyAwesomePlugin", 452 URL: "https://myawesomeplugin.info", 453 Version: "1.2.34", 454 }) 455 ``` 456 457 This information is passed along when the library makes calls to the Stripe 458 API. Note that while `Name` is always required, `URL` and `Version` are 459 optional. 460 461 ### Telemetry 462 463 By default, the library sends telemetry to Stripe regarding request latency and feature usage. These 464 numbers help Stripe improve the overall latency of its API for all users, and 465 improve popular features. 466 467 You can disable this behavior if you prefer: 468 469 ```go 470 config := &stripe.BackendConfig{ 471 EnableTelemetry: stripe.Bool(false), 472 } 473 ``` 474 475 ### Mocking clients for unit tests 476 477 To mock a Stripe client for a unit tests using [GoMock](https://github.com/golang/mock): 478 479 1. Generate a `Backend` type mock. 480 ``` 481 mockgen -destination=mocks/backend.go -package=mocks github.com/stripe/stripe-go/v76 Backend 482 ``` 483 2. Use the `Backend` mock to initialize and call methods on the client. 484 ```go 485 486 import ( 487 "example/hello/mocks" 488 "testing" 489 490 "github.com/golang/mock/gomock" 491 "github.com/stretchr/testify/assert" 492 "github.com/stripe/stripe-go/v76" 493 "github.com/stripe/stripe-go/v76/account" 494 ) 495 496 func UseMockedStripeClient(t *testing.T) { 497 // Create a mock controller 498 mockCtrl := gomock.NewController(t) 499 defer mockCtrl.Finish() 500 // Create a mock stripe backend 501 mockBackend := mocks.NewMockBackend(mockCtrl) 502 client := account.Client{B: mockBackend, Key: "key_123"} 503 504 // Set up a mock call 505 mockBackend.EXPECT().Call("GET", "/v1/accounts/acc_123", gomock.Any(), gomock.Any(), gomock.Any()). 506 // Return nil error 507 Return(nil). 508 Do(func(method string, path string, key string, params stripe.ParamsContainer, v *stripe.Account) { 509 // Set the return value for the method 510 *v = stripe.Account{ 511 ID: "acc_123", 512 } 513 }).Times(1) 514 515 // Call the client method 516 acc, _ := client.GetByID("acc_123", nil) 517 518 // Asset the result 519 assert.Equal(t, acc.ID, "acc_123") 520 } 521 ``` 522 523 ### Beta SDKs 524 525 Stripe has features in the beta phase that can be accessed via the beta version of this package. 526 We would love for you to try these and share feedback with us before these features reach the stable phase. 527 To install a beta version of stripe-go use the commit notation of the `go get` command to point to a beta tag: 528 529 ``` 530 go get -u github.com/stripe/stripe-go/v76@v73.3.0-beta.1 531 ``` 532 533 > **Note** 534 > There can be breaking changes between beta versions. 535 536 We highly recommend keeping an eye on when the beta feature you are interested in goes from beta to stable so that you can move from using a beta version of the SDK to the stable version. 537 538 If your beta feature requires a `Stripe-Version` header to be sent, set the `stripe.APIVersion` field using the `stripe.AddBetaVersion` function to set it: 539 540 > **Note** 541 > The `APIVersion` can only be set in beta versions of the library. 542 543 ```go 544 stripe.AddBetaVersion("feature_beta", "v3") 545 ``` 546 547 ## Support 548 549 New features and bug fixes are released on the latest major version of the Stripe Go client library. If you are on an older major version, we recommend that you upgrade to the latest in order to use the new features and bug fixes including those for security vulnerabilities. Older major versions of the package will continue to be available for use, but will not be receiving any updates. 550 551 ## Development 552 553 Pull requests from the community are welcome. If you submit one, please keep 554 the following guidelines in mind: 555 556 1. Code must be `go fmt` compliant. 557 2. All types, structs and funcs should be documented. 558 3. Ensure that `make test` succeeds. 559 560 ## Test 561 562 The test suite needs testify's `require` package to run: 563 564 github.com/stretchr/testify/require 565 566 Before running the tests, make sure to grab all of the package's dependencies: 567 568 go get -t -v 569 570 It also depends on [stripe-mock][stripe-mock], so make sure to fetch and run it from a 571 background terminal ([stripe-mock's README][stripe-mock-usage] also contains 572 instructions for installing via Homebrew and other methods): 573 574 go get -u github.com/stripe/stripe-mock 575 stripe-mock 576 577 Run all tests: 578 579 make test 580 581 Run tests for one package: 582 583 go test ./invoice 584 585 Run a single test: 586 587 go test ./invoice -run TestInvoiceGet 588 589 For any requests, bug or comments, please [open an issue][issues] or [submit a 590 pull request][pulls]. 591 592 [api-docs]: https://stripe.com/docs/api/?lang=go 593 [api-changelog]: https://stripe.com/docs/upgrades 594 [apiresponse]: https://godoc.org/github.com/stripe/stripe-go#APIResponse 595 [connect]: https://stripe.com/docs/connect/authentication 596 [depgomodsupport]: https://github.com/golang/dep/pull/1963 597 [expandableobjects]: https://stripe.com/docs/api/expanding_objects 598 [goref]: https://pkg.go.dev/github.com/stripe/stripe-go 599 [gomodrevert]: https://github.com/stripe/stripe-go/pull/774 600 [gomodvsdep]: https://github.com/stripe/stripe-go/pull/712 601 [idempotency-keys]: https://stripe.com/docs/api/idempotent_requests?lang=go 602 [issues]: https://github.com/stripe/stripe-go/issues/new 603 [logrus]: https://github.com/sirupsen/logrus/ 604 [modules]: https://github.com/golang/go/wiki/Modules 605 [package-management]: https://code.google.com/p/go-wiki/wiki/PackageManagementTools 606 [pulls]: https://github.com/stripe/stripe-go/pulls 607 [stripe]: https://stripe.com 608 [stripe-mock]: https://github.com/stripe/stripe-mock 609 [stripe-mock-usage]: https://github.com/stripe/stripe-mock#usage 610 [youtube-playlist]: https://www.youtube.com/playlist?list=PLy1nL-pvL2M5eqpSBR9KL7K0lcnWo0V0a 611 [zapsugaredlogger]: https://godoc.org/go.uber.org/zap#SugaredLogger 612 613 <!-- 614 # vim: set tw=79: 615 -->