Giter VIP home page Giter VIP logo

openapi's Introduction

Go Stripe

Go Reference Build Status Coverage Status

The official Stripe Go client library.

Requirements

  • Go 1.15 or later

Installation

Make sure your project is using Go Modules (it will have a go.mod file in its root if it already is):

go mod init

Then, reference stripe-go in a Go program with import:

import (
	"github.com/stripe/stripe-go/v78"
	"github.com/stripe/stripe-go/v78/customer"
)

Run any of the normal go commands (build/install/test). The Go toolchain will resolve and fetch the stripe-go module automatically.

Alternatively, you can also explicitly go get the package into a project:

go get -u github.com/stripe/stripe-go/v78

Documentation

For a comprehensive list of examples, check out the API documentation.

See video demonstrations covering how to use the library.

For details on all the functionality in this library, see the Go documentation.

Below are a few simple examples:

Customers

params := &stripe.CustomerParams{
	Description:      stripe.String("Stripe Developer"),
	Email:            stripe.String("[email protected]"),
	PreferredLocales: stripe.StringSlice([]string{"en", "es"}),
}

c, err := customer.New(params)

PaymentIntents

params := &stripe.PaymentIntentListParams{
	Customer: stripe.String(customer.ID),
}

i := paymentintent.List(params)
for i.Next() {
	pi := i.PaymentIntent()
}

if err := i.Err(); err != nil {
	// handle
}

Events

i := event.List(nil)
for i.Next() {
	e := i.Event()

	// access event data via e.GetObjectValue("resource_name_based_on_type", "resource_property_name")
	// alternatively you can access values via e.Data.Object["resource_name_based_on_type"].(map[string]interface{})["resource_property_name"]

	// access previous attributes via e.GetPreviousValue("resource_name_based_on_type", "resource_property_name")
	// alternatively you can access values via e.Data.PrevPreviousAttributes["resource_name_based_on_type"].(map[string]interface{})["resource_property_name"]
}

Alternatively, you can use the event.Data.Raw property to unmarshal to the appropriate struct.

Authentication with Connect

There are two ways of authenticating requests when performing actions on behalf of a connected account, one that uses the Stripe-Account header containing an account's ID, and one that uses the account's keys. Usually the former is the recommended approach. See the documentation for more information.

To use the Stripe-Account approach, use SetStripeAccount() on a ListParams or Params class. For example:

// For a list request
listParams := &stripe.CustomerListParams{}
listParams.SetStripeAccount("acct_123")
// For any other kind of request
params := &stripe.CustomerParams{}
params.SetStripeAccount("acct_123")

To use a key, pass it to API's Init function:

import (
	"github.com/stripe/stripe-go/v78"
	"github.com/stripe/stripe-go/v78/client"
)

stripe := &client.API{}
stripe.Init("access_token", nil)

Google AppEngine

If you're running the client in a Google AppEngine environment, you'll need to create a per-request Stripe client since the http.DefaultClient is not available. Here's a sample handler:

import (
	"fmt"
	"net/http"

	"google.golang.org/appengine"
	"google.golang.org/appengine/urlfetch"

	"github.com/stripe/stripe-go/v78"
	"github.com/stripe/stripe-go/v78/client"
)

func handler(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	httpClient := urlfetch.Client(c)

	sc := client.New("sk_test_123", stripe.NewBackends(httpClient))

	params := &stripe.CustomerParams{
		Description: stripe.String("Stripe Developer"),
		Email:       stripe.String("[email protected]"),
	}
	customer, err := sc.Customers.New(params)
	if err != nil {
		fmt.Fprintf(w, "Could not create customer: %v", err)
	}
	fmt.Fprintf(w, "Customer created: %v", customer.ID)
}

Usage

While some resources may contain more/less APIs, the following pattern is applied throughout the library for a given $resource$:

Without a Client

If you're only dealing with a single key, you can simply import the packages required for the resources you're interacting with without the need to create a client.

import (
	"github.com/stripe/stripe-go/v78"
	"github.com/stripe/stripe-go/v78/$resource$"
)

// Setup
stripe.Key = "sk_key"

// Set backend (optional, useful for mocking)
// stripe.SetBackend("api", backend)

// Create
resource, err := $resource$.New(&stripe.$Resource$Params{})

// Get
resource, err = $resource$.Get(id, &stripe.$Resource$Params{})

// Update
resource, err = $resource$.Update(id, &stripe.$Resource$Params{})

// Delete
resourceDeleted, err := $resource$.Del(id, &stripe.$Resource$Params{})

// List
i := $resource$.List(&stripe.$Resource$ListParams{})
for i.Next() {
	resource := i.$Resource$()
}

if err := i.Err(); err != nil {
	// handle
}

With a Client

If you're dealing with multiple keys, it is recommended you use client.API. This allows you to create as many clients as needed, each with their own individual key.

import (
	"github.com/stripe/stripe-go/v78"
	"github.com/stripe/stripe-go/v78/client"
)

// Setup
sc := &client.API{}
sc.Init("sk_key", nil) // the second parameter overrides the backends used if needed for mocking

// Create
$resource$, err := sc.$Resource$s.New(&stripe.$Resource$Params{})

// Get
$resource$, err = sc.$Resource$s.Get(id, &stripe.$Resource$Params{})

// Update
$resource$, err = sc.$Resource$s.Update(id, &stripe.$Resource$Params{})

// Delete
$resource$Deleted, err := sc.$Resource$s.Del(id, &stripe.$Resource$Params{})

// List
i := sc.$Resource$s.List(&stripe.$Resource$ListParams{})
for i.Next() {
	$resource$ := i.$Resource$()
}

if err := i.Err(); err != nil {
	// handle
}

Accessing the Last Response

Use LastResponse on any APIResource to look at the API response that generated the current object:

c, err := coupon.New(...)
requestID := coupon.LastResponse.RequestID

Similarly, for List operations, the last response is available on the list object attached to the iterator:

it := coupon.List(...)
for it.Next() {
    // Last response *NOT* on the individual iterator object
    // it.Coupon().LastResponse // wrong

    // But rather on the list object, also accessible through the iterator
    requestID := it.CouponList().LastResponse.RequestID
}

See the definition of APIResponse for available fields.

Note that where API resources are nested in other API resources, only LastResponse on the top-level resource is set.

Automatic Retries

The library automatically retries requests on intermittent failures like on a connection error, timeout, or on certain API responses like a status 409 Conflict. Idempotency keys are always added to requests to make any such subsequent retries safe.

By default, it will perform up to two retries. That number can be configured with MaxNetworkRetries:

import (
	"github.com/stripe/stripe-go/v78"
	"github.com/stripe/stripe-go/v78/client"
)

config := &stripe.BackendConfig{
    MaxNetworkRetries: stripe.Int64(0), // Zero retries
}

sc := &client.API{}
sc.Init("sk_key", &stripe.Backends{
    API:     stripe.GetBackendWithConfig(stripe.APIBackend, config),
    Uploads: stripe.GetBackendWithConfig(stripe.UploadsBackend, config),
})

coupon, err := sc.Coupons.New(...)

Configuring Logging

By default, the library logs error messages only (which are sent to stderr). Configure default logging using the global DefaultLeveledLogger variable:

stripe.DefaultLeveledLogger = &stripe.LeveledLogger{
    Level: stripe.LevelInfo,
}

Or on a per-backend basis:

config := &stripe.BackendConfig{
    LeveledLogger: &stripe.LeveledLogger{
        Level: stripe.LevelInfo,
    },
}

It's possible to use non-Stripe leveled loggers as well. Stripe expects loggers to comply to the following interface:

type LeveledLoggerInterface interface {
	Debugf(format string, v ...interface{})
	Errorf(format string, v ...interface{})
	Infof(format string, v ...interface{})
	Warnf(format string, v ...interface{})
}

Some loggers like Logrus and Zap's SugaredLogger support this interface out-of-the-box so it's possible to set DefaultLeveledLogger to a *logrus.Logger or *zap.SugaredLogger directly. For others it may be necessary to write a thin shim layer to support them.

Expanding Objects

All expandable objects in stripe-go take the form of a full resource struct, but unless expansion is requested, only the ID field of that struct is populated. Expansion is requested by calling AddExpand on parameter structs. For example:

//
// *Without* expansion
//
c, _ := charge.Get("ch_123", nil)

c.Customer.ID    // Only ID is populated
c.Customer.Name  // All other fields are always empty

//
// With expansion
//
p := &stripe.ChargeParams{}
p.AddExpand("customer")
c, _ = charge.Get("ch_123", p)

c.Customer.ID    // ID is still available
c.Customer.Name  // Name is now also available (if it had a value)

How to use undocumented parameters and properties

stripe-go is a typed library and it supports all public properties or parameters.

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.

Parameters

To pass undocumented parameters to Stripe using stripe-go you need to use the AddExtra() method, as shown below:

	params := &stripe.CustomerParams{
		Email: stripe.String("[email protected]")
	}

	params.AddExtra("secret_feature_enabled", "true")
	params.AddExtra("secret_parameter[primary]","primary value")
	params.AddExtra("secret_parameter[secondary]","secondary value")

	customer, err := customer.Create(params)

Properties

You can access undocumented properties returned by Stripe by querying the raw response JSON object. An example of this is shown below:

customer, _ = customer.Get("cus_1234", nil);

var rawData map[string]interface{}
_ = json.Unmarshal(customer.LastResponse.RawJSON, &rawData)

secret_feature_enabled, _ := string(rawData["secret_feature_enabled"].(bool))

secret_parameter, ok := rawData["secret_parameter"].(map[string]interface{})
if ok {
	primary := secret_parameter["primary"].(string)
	secondary := secret_parameter["secondary"].(string)
} 

Webhook signing

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.

Testing Webhook signing

You can use stripe.webhook.GenerateTestSignedPayload to mock webhook events that come from Stripe:

payload := map[string]interface{}{
	"id":          "evt_test_webhook",
	"object":      "event",
	"api_version": stripe.APIVersion,
}
testSecret := "whsec_test_secret"

payloadBytes, err := json.Marshal(payload)

signedPayload := webhook.GenerateTestSignedPayload(&webhook.UnsignedPayload{Payload: payloadBytes, Secret: testSecret})
event, err := webhook.ConstructEvent(signedPayload.Payload, signedPayload.Header, signedPayload.Secret)

if event.ID == payload["id"] {
	// Do something with the mocked signed event
} else {
	// Handle invalid event payload
}

Writing a Plugin

If you're writing a plugin that uses the library, we'd appreciate it if you identified using stripe.SetAppInfo:

stripe.SetAppInfo(&stripe.AppInfo{
	Name:    "MyAwesomePlugin",
	URL:     "https://myawesomeplugin.info",
	Version: "1.2.34",
})

This information is passed along when the library makes calls to the Stripe API. Note that while Name is always required, URL and Version are optional.

Telemetry

By default, the library sends telemetry to Stripe regarding request latency and feature usage. These numbers help Stripe improve the overall latency of its API for all users, and improve popular features.

You can disable this behavior if you prefer:

config := &stripe.BackendConfig{
	EnableTelemetry: stripe.Bool(false),
}

Mocking clients for unit tests

To mock a Stripe client for a unit tests using GoMock:

  1. Generate a Backend type mock.
mockgen -destination=mocks/backend.go -package=mocks github.com/stripe/stripe-go/v78 Backend
  1. Use the Backend mock to initialize and call methods on the client.
import (
	"example/hello/mocks"
	"testing"

	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/assert"
	"github.com/stripe/stripe-go/v78"
	"github.com/stripe/stripe-go/v78/account"
)

func UseMockedStripeClient(t *testing.T) {
	// Create a mock controller
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()
	// Create a mock stripe backend
	mockBackend := mocks.NewMockBackend(mockCtrl)
	client := account.Client{B: mockBackend, Key: "key_123"}

	// Set up a mock call
	mockBackend.EXPECT().Call("GET", "/v1/accounts/acc_123", gomock.Any(), gomock.Any(), gomock.Any()).
		// Return nil error
		Return(nil).
		Do(func(method string, path string, key string, params stripe.ParamsContainer, v *stripe.Account) {
			// Set the return value for the method
			*v = stripe.Account{
				ID: "acc_123",
			}
		}).Times(1)

	// Call the client method
	acc, _ := client.GetByID("acc_123", nil)

	// Asset the result
	assert.Equal(t, acc.ID, "acc_123")
}

Beta SDKs

Stripe has features in the beta phase that can be accessed via the beta version of this package. We would love for you to try these and share feedback with us before these features reach the stable phase. To install a beta version of stripe-go use the commit notation of the go get command to point to a beta tag:

go get -u github.com/stripe/stripe-go/[email protected]

Note There can be breaking changes between beta versions.

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.

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:

Note The APIVersion can only be set in beta versions of the library.

stripe.AddBetaVersion("feature_beta", "v3")

Support

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.

Development

Pull requests from the community are welcome. If you submit one, please keep the following guidelines in mind:

  1. Code must be go fmt compliant.
  2. All types, structs and funcs should be documented.
  3. Ensure that make test succeeds.

Test

The test suite needs testify's require package to run:

github.com/stretchr/testify/require

Before running the tests, make sure to grab all of the package's dependencies:

go get -t -v

It also depends on stripe-mock, so make sure to fetch and run it from a background terminal (stripe-mock's README also contains instructions for installing via Homebrew and other methods):

go get -u github.com/stripe/stripe-mock
stripe-mock

Run all tests:

make test

Run tests for one package:

go test ./invoice

Run a single test:

go test ./invoice -run TestInvoiceGet

For any requests, bug or comments, please open an issue or submit a pull request.

openapi's People

Contributors

alexander-stripe avatar andrewyang-stripe avatar anniel-stripe avatar apakulov-stripe avatar brandur avatar brandur-stripe avatar cjavilla-stripe avatar ctrudeau-stripe avatar danwang-stripe avatar daz-stripe avatar dcr-stripe avatar etsai-stripe avatar fay-stripe avatar foresthu-stripe avatar gearnode avatar grey-stripe avatar jkakar-stripe avatar kamil-stripe avatar mickjermsurawong-stripe avatar ob-stripe avatar pakrym-stripe avatar paulasjes-stripe avatar qaisjp avatar rattrayalex-stripe avatar remi-stripe avatar richardm-stripe avatar stripe-openapi[bot] avatar tmaxwell-stripe avatar yejia-stripe avatar zhiqu-stripe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

openapi's Issues

Get Subset of spec2.json

The tool I am using fails because spec2.json swagger file is too big. I just need APIs to charge customer credit card and retrieve the past payments. How can I do that?
Thanks!

Generating openapi?

How are you generating the openapi? The bin script looks like it copies the files out of ~/stripe/pay-server/. I'm wondering if you're using a library to generate the OpenAPI JSON from the code.

file_upload schema values for purpose

I've seen instances where file_upload objects have a purpose with values of "business_logo" or even "sigma_scheduled_query". Neither the schema nor the hosted API docs indicate these as possible values. Should the spec be updated to include these, and are there others we're missing?

v3 spec is invalid

I try to use your openapi with https://github.com/swagger-api/swagger-codegen

run this command:

docker run --rm -v ${PWD}:/local swaggerapi/swagger-codegen-cli generate \
    -i https://github.com/stripe/openapi/blob/master/openapi/spec3.json \
    -l rust \
    -o /local/out2/rust

result:

[main] INFO io.swagger.parser.Swagger20Parser - reading from https://github.com/stripe/openapi/blob/master/openapi/spec3.json
[main] INFO io.swagger.parser.Swagger20Parser - reading from https://github.com/stripe/openapi/blob/master/openapi/spec3.json
[main] ERROR io.swagger.parser.SwaggerCompatConverter - failed to read resource listing
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('<' (code 60)): expected a valid value (number, String, array, object, 'true', 'false' or 'null')
 at [Source: (StringReader); line: 7, column: 2]
	at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1798)
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:663)
	at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar(ParserMinimalBase.java:561)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddValue(ReaderBasedJsonParser.java:1892)
	at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:747)
	at com.fasterxml.jackson.databind.ObjectMapper._readTreeAndClose(ObjectMapper.java:4030)
	at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:2539)
	at io.swagger.parser.SwaggerCompatConverter.readResourceListing(SwaggerCompatConverter.java:193)
	at io.swagger.parser.SwaggerCompatConverter.read(SwaggerCompatConverter.java:122)
	at io.swagger.parser.SwaggerParser.read(SwaggerParser.java:75)
	at io.swagger.codegen.config.CodegenConfigurator.toClientOptInput(CodegenConfigurator.java:431)
	at io.swagger.codegen.cmd.Generate.run(Generate.java:283)
	at io.swagger.codegen.SwaggerCodegen.main(SwaggerCodegen.java:35)
[main] WARN io.swagger.codegen.ignore.CodegenIgnoreProcessor - Output directory does not exist, or is inaccessible. No file (.swagger-codegen-ignore) will be evaluated.
Exception in thread "main" java.lang.RuntimeException: missing swagger input or config!
	at io.swagger.codegen.DefaultGenerator.generate(DefaultGenerator.java:735)
	at io.swagger.codegen.cmd.Generate.run(Generate.java:285)
	at io.swagger.codegen.SwaggerCodegen.main(SwaggerCodegen.java:35)

operationIds are not unique

Unique string used to identify the operation. The id MUST be unique among all operations described in the API

It appears to be

operationId: AllTransactions

Which is the culprit. Applies to both spec2 and spec3.

swagger-codegen fails

Should swagger-codegen succeed in building spec2.json or spec2.yaml? I am getting the following:

  Tag: default
  Operation: Create3DSecure
  Resource: post /v1/3d_secure
  Definitions: {account=io.swagger.models.ModelImpl@18b21fca, account_debit_account=io.swagger.models.ModelImpl@3372b161, account_decline_charge_on=io.swagger.models.ModelImpl@b29ecc58, account_tos_acceptance=io.swagger.models.ModelImpl@11eeb12e, account_verification=io.swagger.models.ModelImpl@4e23beef, account_with_keys=io.swagger.models.ModelImpl@5a54cb3a, address=io.swagger.models.ModelImpl@a5eb90b2, alipay_account=io.swagger.models.ModelImpl@f5050f17, apple_pay_domain=io.swagger.models.ModelImpl@827c2072, application=io.swagger.models.ModelImpl@a048ba69, authorization=io.swagger.models.ModelImpl@88dcae6, backwards_compatible_platform_earning=io.swagger.models.ModelImpl@87a58727, balance=io.swagger.models.ModelImpl@799013db, balance_transaction=io.swagger.models.ModelImpl@afbbfe67, bank_account=io.swagger.models.ModelImpl@2adef309, bitcoin_receiver=io.swagger.models.ModelImpl@9d641c16, bitcoin_transaction=io.swagger.models.ModelImpl@cf233639, card=io.swagger.models.ModelImpl@bcd5b9e3, charge=io.swagger.models.ModelImpl@7f4792b5, charge_outcome=io.swagger.models.ModelImpl@3b18fe54, country_spec=io.swagger.models.ModelImpl@d4343175, coupon=io.swagger.models.ModelImpl@87ee77eb, customer=io.swagger.models.ModelImpl@a4417221, customer_shipping=io.swagger.models.ModelImpl@b5d1d50c, customer_source=io.swagger.models.ModelImpl@8e26206, delivery_estimate=io.swagger.models.ModelImpl@121256f6, discount=io.swagger.models.ModelImpl@722c9a8a, dispute=io.swagger.models.ModelImpl@846f0633, event=io.swagger.models.ModelImpl@21086177, event_data=io.swagger.models.ModelImpl@fcc02ad, external_account_source=io.swagger.models.ModelImpl@e885132e, fee=io.swagger.models.ModelImpl@4feaea84, fee_refund=io.swagger.models.ModelImpl@83d5709d, file=io.swagger.models.ModelImpl@9c2ca4c, inventory=io.swagger.models.ModelImpl@4aa15b61, invoice=io.swagger.models.ModelImpl@4930db3d, invoice_item=io.swagger.models.ModelImpl@dc109079, invoice_line_item=io.swagger.models.ModelImpl@9d856f83, issued_card=io.swagger.models.ModelImpl@61150390, legacy_transfer=io.swagger.models.ModelImpl@b1da5b97, legal_entity=io.swagger.models.ModelImpl@8f70d302, legal_entity_additional_owner=io.swagger.models.ModelImpl@31cd3acf, legal_entity_address=io.swagger.models.ModelImpl@fa79e15c, legal_entity_dob=io.swagger.models.ModelImpl@f0c5b8fd, legal_entity_japan_address=io.swagger.models.ModelImpl@6e015581, legal_entity_verification=io.swagger.models.ModelImpl@b3041dc7, login_link=io.swagger.models.ModelImpl@304aefd7, merchant_data=io.swagger.models.ModelImpl@6042bb20, order=io.swagger.models.ModelImpl@4d3772b4, order_item=io.swagger.models.ModelImpl@8263655d, order_return=io.swagger.models.ModelImpl@438af2f9, package_dimensions=io.swagger.models.ModelImpl@760132f6, payout=io.swagger.models.ModelImpl@2a43a262, plan=io.swagger.models.ModelImpl@904497e6, platform_earning=io.swagger.models.ModelImpl@7aede5eb, platform_fee=io.swagger.models.ModelImpl@3c10bde7, product=io.swagger.models.ModelImpl@66ebb904, refund=io.swagger.models.ModelImpl@8dac76f6, reserve_transaction=io.swagger.models.ModelImpl@917c8d39, review=io.swagger.models.ModelImpl@b436ee78, rule=io.swagger.models.ModelImpl@a36beb49, shipping=io.swagger.models.ModelImpl@c19d562d, shipping_method=io.swagger.models.ModelImpl@bb79e1f6, sku=io.swagger.models.ModelImpl@2aa70ebf, source=io.swagger.models.ModelImpl@9311b156, source_code_verification_flow=io.swagger.models.ModelImpl@ab39138c, source_owner=io.swagger.models.ModelImpl@2d948b54, source_receiver_flow=io.swagger.models.ModelImpl@9a93e4c2, source_redirect_flow=io.swagger.models.ModelImpl@5d89d06d, status_transitions=io.swagger.models.ModelImpl@50a24d, subscription=io.swagger.models.ModelImpl@9dd7f78, subscription_item=io.swagger.models.ModelImpl@f57570c2, three_d_secure=io.swagger.models.ModelImpl@a03bc70e, token=io.swagger.models.ModelImpl@e9c7d270, token_bank_account=io.swagger.models.ModelImpl@5dd6cf3c, token_card=io.swagger.models.ModelImpl@d1ec5ab, transaction=io.swagger.models.ModelImpl@f04bf896, transfer=io.swagger.models.ModelImpl@c8c86292, transfer_recipient=io.swagger.models.ModelImpl@9ad48c12, transfer_recipient_transfer=io.swagger.models.ModelImpl@656a9b, transfer_reversal=io.swagger.models.ModelImpl@f19ae4b0, transfer_schedule=io.swagger.models.ModelImpl@bde15914, upcoming_invoice=io.swagger.models.ModelImpl@237da7e9}
  Exception: null
	at io.swagger.codegen.DefaultGenerator.processOperation(DefaultGenerator.java:861)
	at io.swagger.codegen.DefaultGenerator.processPaths(DefaultGenerator.java:764)
	at io.swagger.codegen.DefaultGenerator.generateApis(DefaultGenerator.java:388)
	at io.swagger.codegen.DefaultGenerator.generate(DefaultGenerator.java:700)
	at io.swagger.codegen.cmd.Generate.run(Generate.java:241)
	at io.swagger.codegen.SwaggerCodegen.main(SwaggerCodegen.java:43)
Caused by: java.lang.NullPointerException
	at io.swagger.codegen.DefaultCodegen.isDataTypeBinary(DefaultCodegen.java:2644)
	at io.swagger.codegen.DefaultCodegen.fromParameter(DefaultCodegen.java:2595)
	at io.swagger.codegen.DefaultCodegen.fromOperation(DefaultCodegen.java:2170)
	at io.swagger.codegen.DefaultGenerator.processOperation(DefaultGenerator.java:808)
	... 5 more```

Request: Recurring coupon support for non-monthly periods

Hello,

Currently, Stripe Subscriptions and Prices allow me to set a recurring period of days, months, years, etc but the Coupon object I attach to those subscriptions only understands months.

I would like it if the coupon object either prorated (a coupon recurring 2 months took [2/12]% off an annual payment one time) or for coupons to understand different billing periods than monthly.

If this is the wrong place for this request, please let me know and I'd be happy to make it in the right place. In general, I think the coupon objects could use some love, especially after the improvements brought about by the new Prices API.

Swagger-codegen OpenAPI 2.0 fails

I've run swagger codegen with spec2.json and I got the following issue

[main] ERROR io.swagger.codegen.Codegen - Could not process operation:
Tag: Tag {
name: default
description: null
externalDocs: null
extensions:{}}
Operation: UpdateAccountBankAccount
.....

Reading the specification file [spec2.json] https://github.com/stripe/openapi/blob/master/openapi/spec2.json), I've found the issue is the way it describes an array of strings not following the specification.

 "type": ["array","string" ]

instead of the standard way

 "type": "array",
 "items": "string"

After doing that the swagger-codegen works fine.

Why is product.type nullable?

product.type appears as nullable in the spec. That seems impossible given the nature of products. Is it an artifact of some kind?

account schema missing transfers_enabled?

The account schema maybe appears to be missing transfers_enabled.

I'm not sure if this key went away with a new version of the API, but it does seem to indicate that we're perhaps not able to use different versions of this spec for different API versions. Is that accurate?

Request for Supporting Rust Lang

It would be great if Stripe could provide language support for Rust. The unofficial Rust stripe client libraries are incomplete. I've tried generating a rust client from the openapi specification, however, the v5 openapi-generator-cli fails with numerous errors.

Rust is probably low on your priority list, but it would greatly benefit the community if you could provide official support.

Thanks for the consideration.

Request: Include max length for string fields

Can the max length of string fields be included in the spec somehow?

We need it in dj-stripe to be able to store whatever the API throws at us. Creating arbitrary text fields for everything is inconvenient, and not compatible with some databases (eg. some of them need to be unique and mysql doesn't like unique indices on text fields).

v2 spec is invalid

I set out to create a custom strip client using swagger-codegen and was rewarded by a HUGE list of errors and warnings. I settled in to dig through spec2.yaml to see if I could figure out what was broken and what needed to be done to fix it. In the end I was able to clean it up and successfully generate my client code. Being a rather large document, it seemed that trying to fix it manually was a losing proposition so I ended up writing some code to fix up the document by overriding the preprocessSwagger method in the base DefaultCodegen class. Fortunately, provides me with the list of issues I discovered as well as the fix for each, which I can share with you here. The issues I discovered fall into one of three categories:

  1. violations of OpenAPI v2 spec
  2. violations of JSON Schema Validation spec
  3. things that cause swagger-codegen to fail or produce poor code

This is just a quick summary of the issues I found and fixed. If you like I can provide much more detail, including the locations within the document where each of these issues can be found.

Issues

Invalid property declarations

Untyped properties

There are many property declarations that do not have a type attribute. This is valid JSON Schema, corresponding to the "any" type, but this is not valid Swagger. swagger-codegen detects the missing type attribute of properties, emits a warning message and sets it to ERROR_UNKNOWN, resulting in generated code that fails to compile. There are a total of 181 such errors.

Arrays without items

There are many array properties that are missing an items attribute. This is valid JSON Schema, which defaults to items to the empty schema ({}), which corresponds to an object with no properties. This is not valid Swagger, which states that items is a required attribute of an array property definition. There are a total of 101 such errors. 7 occur within schema definitions, 94 occur within definitions of the expand query parameter.

Arrays without type

There are a number of properties defined with have an items attribute without any type attribute. swagger-codegen sets the missing type attribute to ERROR_UNKNOWN, resulting in generated code that fails to compile. There are 6 such definitions.

Empty schemas

There are a number of schemas and properties whose type is defined as the empty schema ({}). Valid according to JSON Schema but not according to Swagger. There are 21 such definitions.

Non-unique operationId

The Swagger spec states that each value of operationId must be globally unique within each document. There are 29 instances of an operationId that duplicate an existing operationId.

Non-unique Body Parameter names

This one isn't a violation of either JSON Schema or Swagger but does present challenges for swagger-codegen. When swagger-codegen does its work, it uses the names of schemas to derive the name of the interface/class it will create. When it discovers a new schema that has the same name as an existing schema, it increments a counter and creates a new unique name by appending the counter value to the duplicate name. This results in the generation of client/server code that although valid is very confusing and difficult to use. For example, the schema for every body parameter definition is named payload and there are 90 such definitions.

Schema naming

Anonymous schemas

Once again not a violation of JSON Schema or Swagger but results in low quality generated code. When swagger-codegen encounters a schema definition without a name (ie - any schema not defined in definitions) it uses a rule to generate a unique name based on where the anonymous schema is found in the definition to use when creating its interface/class code, resulting in generated client/server code that is again confusing and difficult to use. This seems to be most prevalent in the definition of response schemas. There are 20 response schemas defined in-line which results in interface/class names such as InlineResponse2001.

Non-unique schema names

Another issue that results in low quality generated code. There a number of schemas sharing the same name. In each case, it appears to be a redefinition of the same schema. There are 20 such repeated schema definitions.

Request: Integer sizes / ranges / max value

Along the lines of my previous requests, it'd be good to have the ranges of values for various definitions. For example:

                tax_percent:
                  description: A non-negative decimal (with at most four decimal places)
                    between 0 and 100. This represents the percentage of the subscription
                    invoice subtotal that will be calculated and added as tax to the
                    final amount in each billing period. For example, a plan which
                    charges $10/month with a `tax_percent` of `20.0` will charge $12
                    per invoice. To unset a previously-set value, pass an empty string.
                  nullable: true
                  type: number

This could have something like min_value:0 and max_value:100.

Another example:

        quantity:
          description: The usage quantity for the specified date.
          type: integer

I don't know whether to use an int32 or an int64 to store this. Would be useful to know.

Finally, there are 41 instances of type: number and 554 instances of type: integer in the spec. What's the difference between the two?

spec3 vs spec3.sdk

A newbie question here - I'm trying to understand the difference between openapi/spec3.json and openapi/spec3.sdk.json. Could you explain the context for using these two specs?

operationId's not unique

The operationId's are not unique in the stripe spec, e.g. the operationId "DeleteAccountExternalAccount" appears 4 times.

Spec:
operationId: "Unique string used to identify the operation. The id MUST be unique among all operations described in the API."

Mark deprecated features in the spec

Hey There!

I have a few questions about the OpenAPI spec:

  1. I noticed the Create Charge endpoint (POST /v1/charges) in the spec had an extra parameter defined in the request body called card that I could not find in the latest docs.
                  "card": {
                    "anyOf": [
                      {
                        "properties": {
                          "address_city": {
                            "maxLength": 5000,
                            "type": "string"
                          },
                         // ...
                        },
                        "required": [
                          "exp_month",
                          "exp_year",
                          "number"
                        ],
                        "title": "customer_payment_source_card",
                        "type": "object"
                      },
                      {
                        "maxLength": 5000,
                        "type": "string"
                      }
                    ],
                    "description": "A token, like the ones returned by [Stripe.js](https://stripe.com/docs/stripe.js).",
                    "x-stripeBypassValidation": true
                  },

I was wondering how in-sync the OpenAPI spec is with API docs and the actual released API in general. Is that a new field that will be added in a later version, or just a typo and shouldn't be there?

  1. I also noticed that some parameters in the request body, mainly objects, are defined with anyOf and lists between the properties of the object or an empty enum, like the following from POST /v1/customers:
                  "address": {
                    "anyOf": [
                      {
                        "properties": {
                          "city": {
                            "maxLength": 5000,
                            "type": "string"
                          },
                          // ...
                        },
                        "required": [
                          "line1"
                        ],
                        "title": "address",
                        "type": "object"
                      },
                      {
                        "enum": [
                          ""
                        ],
                        "type": "string"
                      }
                    ],
                    "description": "The customer's address."
                  },

Does that imply that the address object is an optional parameter, as it's mentioned in the docs, and that's just hows its represented in the OpenAPI spec?

I'd appreciate it if someone can help shed some light on my questions.

Thanks!

Timestamps are not indicated in the spec

Example:

        webhooks_delivered_at:
          description: The time at which webhooks for this invoice were successfully
            delivered (if the invoice had no webhooks to deliver, this will match
            `date`). Invoice payment is delayed until webhooks are delivered, or until
            all webhook delivery attempts have been exhausted.
          nullable: true
          type: integer

This has type:integer, but the docs show it as type: timestamp.

token appears to be missing pii

The PII token types appear to be missing from the token object. It looks like the type is missing the possibility of there being a pii type.

The online API docs appear to be incomplete:

Type of the token: card or bank_account.

Some fields are coming back as null when they're not set to nullable

Hi there!
We've been using your openapi spec to build our integration with stripe. We found that a few fields are not marked as nullable, though they come as null (or just unset) when getting those resources through your endpoints. In some cases the documentation string of those fields indicate that they might be null, but they spec doesn't say so.
I originally sent this as a PR (#60) so the diff is easier to read. Reposting here for visibility

Request: Split `period` into two types

It would be nice if period was split up into two types, one might be called period and the the other closed_period.

This would allow us to differentiate between :

  1. periods where start and end might be null and therefore possibly open-ended. This one maps to the current period type.
  2. periods that always have a start and end date (not nullable), we could call this one closed_period. Many instances of the existing period type could be moved into this type.

Right now, null-checking on periods is super annoying, even when I can reasonable assume those values will not be null. However, making assumptions is a bad idea, so this should be represented by concrete types that explicitly delineate when the period is definitely closed, and the start and end non-null.

Represent upcoming invoices separately from invoices with ids

When using the upcoming invoice endpoint, the response represents an invoice that doesn't exist yet, and does not have an id.

Note that when you are viewing an upcoming invoice, you are simply viewing a preview โ€“ the invoice has not yet been created. As such, the upcoming invoice will not show up in invoice listing calls, and you cannot use the API to pay or edit the invoice. If you want to change the amount that your customer will be billed, you can add, remove, or update pending invoice items, or update the customerโ€™s discount.

The openapi spec for Invoice here, however, does not mark id as nullable: true. Which means that code generators will not make it optional, and could fail while parsing.

subscription_item.subscription is nullable

According to the spec:

        subscription:
          description: The `subscription` this `subscription_item` belongs to.
          maxLength: 5000
          nullable: true
          type: string

How does the nullable make sense here?

Invalid fields on subscription fixture

I'm working on an Elixir library for Stripe and using stripe-mock for testing. Stripe-mock pulls from these fixtures for data. Since the library is quite out-of-date, I've written some code which checks for fields returned from the API which are unexpected (most of the time, this means the library is out of date with the newest API version).

However, I just noticed that subscriptions have several fields which they definitely should not have:

17:59:04.553 [error] Extra keys were received but ignored when converting Stripe object subscription: [:account_balance, :billing, :days_until_due, :max_occurrences, :on_behalf_of, :retains_own_balance]

I've double checked with the published API docs and these are clearly fields from other objects. Was this intentional or just a copy-paste typo? If unintentional, I'm happy to do a quick PR to remove these from the fixtures.

These are the offending lines:

openapi/openapi/fixtures.yaml

Lines 1201 to 1262 in dea2739

subscription:
account_balance: 0
application_fee_percent: 0.0
billing: ''
cancel_at_period_end: false
canceled_at: 1234567890
created: 1234567890
current_period_end: 1234567890
current_period_start: 1234567890
customer: cus_ADmuABetLS15eF
days_until_due: 0
discount: {}
ended_at: 1234567890
id: sub_AKa4uss8vCMAZC
items:
data:
- created: 1490133192
id: si_19zuuiDSlTMT26Mk9HayBPe9
object: subscription_item
plan:
amount: 2000
created: 1488566449
currency: usd
id: gold
interval: month
interval_count: 1
livemode: false
metadata: {}
name: Gold Special
object: plan
statement_descriptor:
trial_period_days:
quantity: 1
has_more: false
object: list
total_count: 1
url: "/v1/subscription_items?subscription=sub_AKa4uss8vCMAZC"
livemode: false
max_occurrences: 0
metadata: {}
object: subscription
on_behalf_of: ''
plan:
amount: 2000
created: 1488566449
currency: usd
id: gold
interval: month
interval_count: 1
livemode: false
metadata: {}
name: Gold Special
object: plan
statement_descriptor:
trial_period_days:
quantity: 1
retains_own_balance: false
start: 1234567890
status: active
tax_percent: 0.0
trial_end: 1234567890
trial_start: 1234567890

refund vs. payment_refund

Looking through the spec I don't understand why there is both a refund and a payment_refund type of object. They don't seem to have any concrete difference even. What's this about?

maxLength values are wrong

It seems that most string fields have been give a maxLength of 5000 instead of a real value.

Here are just a couple of examples.

Currency code:
image

Object id:
image

Docs state that:

You can safely assume object IDs we generate will never exceed 255 characters

For us, it's important to know the maxLength of fields when saving entities in a database to set a correct NVARCHAR or NCHAR length value in columns.

Any chance this will be fixed?

subscription_proration_date nullability

        subscription_proration_date:
          description: Only set for upcoming invoices that preview prorations. The
            time used to calculate prorations.
          type: integer

So I don't understand that field and it's inconsistent with the rest of the API. It's not marked as nullable, but it's marked as optional. It sounds like it won't ever show up as null but it will simply not show up.

Is that correct? Isn't it simpler to just call it nullable?

Missing securitydefinition, tags, summary etc.

We are building the stripe integration for our customers (https://www.ultradox.com) based on the stripe API spec.
It is working to some degree, but it would be very nice to some more info in the spec.
Even if I badly missed the Christmas deadline, here comes my wishlist:

  1. Add a security definition and security
    As stripe is using a mixture of basic auth and api key, this would be the perfect declaration for us to auto-generate our integration:
  "securityDefinitions": {
    "apiKey": {
      "type": "basic",
      "x-summary" : "Access your stripe account",
      "x-header-user" : "API Key",
      "x-placeholder-user" : "sk_live_ASasduihgZGAUd342abcd",
      "x-password-supported" : false,
      "x-instructions": "Enter your [stripe secret key](https://dashboard.stripe.com/account/apikeys)"
    }
  },
  "security": [
    {
      "apiKey": []
    }
  ],
...
  1. Tags etc.
    We are grouping the operations based on tags and are also creating the documentation from the spec.
    It would be great to have additional info to be able to generate the docs similar to the stripe docs.
    Example for a complete operation including tags and summary (as it appears in the stripe api reference):
    "/v1/balance": {
      "get": {
        "tags": [
          "Balance"
        ],
        "summary:" "Retrieve balance",
        "description": "Retrieves the current account balance, based on the authentication that was used to make the request.",
        "operationId": "BalanceRetrieve",
...

Request: Tag commits with Stripe API versions

Hi there!

Would it be possible to create tags with stripe api versions (e.g. 2019-05-16)? The dj-stripe library contributors are working on automatically generating fixtures, and we'd love to be able to pull down fixtures/schema by api version.

Best,
Alex

`metadata.nullable` is inconsistent (E.g. customer vs subscription)

Both the Customer and Subscription schema have a metadata property:

  "metadata": {
      "additionalProperties": {
          "maxLength": 500,
          "type": "string"
      },
      "description": "...",
      "type": "object"
  },

But the Subscription lists metadata in the required fields list:

        "required": [

            "metadata",
        ],

Does this imply that the metadata field is nullable for the customer object, but not for the subscription object?

Why is metadata required on the subscription but not the customer?

The docs both show this for both objects (no required tag):

image

Incorrect expandable fields

Hi there,

It seems to me that some fields have been incorrectly defined as expandable fields.

Here are a few that are marked as expandable in spec3.json but that are not labeled as expandable in the API docs.

account:
business_profile,capabilities,company,individual,requirements,settings,tos_acceptance

balance:
available,connect_reserved,pending

customer:
address,invoice_settings,shipping

And more...

Unless I'm missing something?

Uncertainty on when invoice.subscription is to be expanded.

Hi there!
I'm wrapping my head around x-expandableFields and x-expansionResources. I thought I got this right but there's a case that confuses me.
Let's take invoice.subscription. it's not an expandableFIeld and it's still anyOf(str, ref(subscription)). So far, every time I get an invoice, I see the subscription automatically expanded. So my questions are:

  • can subscription in this case come un-expanded and just as a string?
  • is there any way of controlling this behavior?
    I notice that the field is hinted with an x-expansionResources, which if I understand correctly, hints that the id form of this field is a reference to the indicated (subscription) resource. I'm just unsure if I'm missing something here.

My intention is to reduce the type ambiguity of the return types, so consumers don't need to check whether -- in this case -- the subscription is an id or the actual object. I can deal with expandableFields most of the times, but this one seems off.

Thank you!!

External Account should support an object

When creating an account, the external_account property currently has the following spec:

"external_account": {
 "description": "A card or bank account to attach to the account. You can provide either a token, like the ones returned by [Stripe.js](https://stripe.com/docs/stripe.js), or a dictionary, as documented in the `external_account` parameter for [bank account](https://stripe.com/docs/api#account_create_bank_account) creation. <br><br>By default, providing an external account sets it as the new default external account for its currency, and deletes the old default if one exists. To add additional external accounts without replacing the existing default for the currency, use the bank account or card creation API.",
 "maxLength": 5000,
 "type": "string",
 "x-stripeBypassValidation": true
},

The description says, You can provide either a token, like the ones returned by [Stripe.js](https://stripe.com/docs/stripe.js), or a dictionary however the type does not reflect this. I encountered this issue when using the stripe-mock server and attempting to post an object as the external_account parameter.

Use the new OpenAPI webhooks and callbacks to describe Stripe webhooks

In OpenAPI 3.0 there is already a "callbacks" parameter describing the webhooks triggered by an API call.

In the new OpenAPI 3.1 there is also a webhooks root description for out of bands webhook events like the one Stripe uses.
See https://github.com/OAI/OpenAPI-Specification/releases/tag/3.1.0-rc0

Could you please improve the Stripe Open API definitions to include both webhooks and callbacks descriptions in the Stripe OpenAPI specification?

Cannot create bank account tokens

Token.create([bank_account:[account_number:'000123456789', routing_number:'110000000', country:'US', currency:'usd', account_holder_name:'Yono Sono', account_holder_type: 'individual']])

gets me back a card token

{
  "bank_account": null,
  "card": {
    "account": null,
    "address_city": null,
    "address_country": null,
    "address_line1": null,
    "address_line1_check": null,
    "address_line2": null,
    "address_state": null,
    "address_zip": null,
    "address_zip_check": null,
    "available_payout_methods": null,
    "brand": "Visa",
    "country": "US",
    "currency": null,
    "customer": null,
    "cvc_check": "pass",
    "default_for_currency": null,
    "deleted": null,
    "description": null,
    "dynamic_last4": null,
    "exp_month": 8,
    "exp_year": 2021,
    "fingerprint": "Xt5EWLLDS7FJjR1c",
    "funding": "credit",
    "id": "card_1HCXiP2eZvKYlo2CAf6RdzXJ",
    "iin": null,
    "issuer": null,
    "last4": "4242",
    "metadata": {},
    "name": null,
    "object": "card",
    "recipient": null,
    "tokenization_method": null
  },
  "client_ip": null,
  "created": 1234567890,
  "email": null,
  "id": "tok_FDnXUXUs0sZgjsc",
  "livemode": false,
  "object": "token",
  "type": "card",
  "used": false
}

Consistency between review.rules_features.card_brand/card_country and source.brand/country

Hey -- I'm guessing this isn't the correct tracker for this, but wasn't sure where to file this issue.

Here are parts of a review and card object, identifying the same card (as part of a single charge being reviewed):

{
  "review": {
    "id": "prv_XXXXXXXXXXXXXXXXXXX",
    "object": "review",
    "charge": "ch_XXXXXXXXXXXXXXXXXXXXXXXX",
    "rules_features": {
      "card_brand": "visa",
      "card_country": "fr",
      "card_funding": "credit",
      "ip_country": "fr",
      "risk_level": "normal",
      "risk_score": null
    }
  },
  "source": {
    "id": "card_XXXXXXXXXXXXXXXXXXXXXXXX",
    "object": "card",
    "address_city": null,
    "address_country": null,
    "address_line1": null,
    "address_line1_check": null,
    "address_line2": null,
    "address_state": null,
    "address_zip": null,
    "address_zip_check": null,
    "brand": "Visa",
    "country": "FR"
  }
}

The results of country and brand have different capitalization. This is a little frustrating because it means they require separate enums (albeit essentially identical ones).

Could this inconsistency be resolved? Lowercase makes the most sense but I also know that the card brand enum (with its whitespace and mixed case) is well established by now, unlike the review one...

Use more definitions instead of repeating type data?

Hi, in at least the v2 spec, in JSON Pointer speak this:

/paths/~1v1~1accounts/post/parameters/0/schema/properties/legal_entity/additional_owners/properties

has string keys of "0", "1", ... and each of those values is identical:

                        "0": {
                          "properties": {
                            "address": {
                              "properties": {
                                "city": {
                                  "type": [
                                    "string"
                                  ]
                                },

etc. These could all each instead be:

                        "0": { "$ref": "#/definitions/legal_entity_definition" },

or similar. Out of the currently 41k line spec, that would already save about 100 x 30 = 3k. There are probably more examples.

Plan missing trial_period_days?

I noticed that the plan schema appears to be missing a trial_period_days, and while the Stripe documentation does not reference this key, it does appear to exist in the example response.

Undocumented fields on charge and refund fixtures

This issue is very similar to #6. charge and refund fixtures contain fields which are not documented in the official docs.

21:55:32.464 [error] Extra keys were received but ignored when converting Stripe object charge: [:alternate_statement_descriptors, :application_fees_refunded, :application_fees_refunded_currency, :authorization_code, :captured_at, :fee_balance_transactions]

21:55:32.464 [error] Extra keys were received but ignored when converting Stripe object refund: [:description, :fee_balance_transactions, :type]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.