func (s *BackendConfiguration) NewRequest(method, path, key, contentType string, body io.Reader, params *Params) (*http.Request, error) {
	if !strings.HasPrefix(path, "/") {
		path = "/" + path
	}
	path = s.URL + path
	req, err := http.NewRequest(method, path, body)
	if err != nil {
		if LogLevel > 0 {
			Logger.Printf("Cannot create Stripe request: %v\n", err)
		}
		return nil, err
	}
	authorization := "Bearer " + key
	req.Header.Add("Authorization", authorization)
	req.Header.Add("Stripe-Version", apiversion)
	req.Header.Add("User-Agent", encodedUserAgent)
	req.Header.Add("Content-Type", contentType)
	req.Header.Add("X-Stripe-Client-User-Agent", encodedStripeUserAgent)
	if params != nil {
		if params.Context != nil {
			req = req.WithContext(params.Context)
		}
		if idempotency := strings.TrimSpace(params.IdempotencyKey); idempotency != "" {
			if len(idempotency) > 255 {
				return nil, errors.New("Cannot use an IdempotencyKey longer than 255 characters long.")
			}
			req.Header.Add("Idempotency-Key", idempotency)
		}
		if account := strings.TrimSpace(params.Account); account != "" {
			req.Header.Add("Stripe-Account", account)
		}
		if stripeAccount := strings.TrimSpace(params.StripeAccount); stripeAccount != "" {
			req.Header.Add("Stripe-Account", stripeAccount)
		}
		for k, v := range params.Headers {
			for _, line := range v {
				req.Header.Add(k, line)
			}
		}
	}
	return req, nil
}
NewRequest is used by Call to generate an http.Request. It handles encoding
parameters and attaching the appropriate headers.
package stripe
import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"sync"
	"time"
	"github.com/stripe/stripe-go/form"
)
const (
	apiURL     = "https://api.stripe.com/v1"
	uploadsURL = "https://uploads.stripe.com/v1"
)
const apiversion = "2017-05-25"
const clientversion = "28.12.0"
const defaultHTTPTimeout = 80 * time.Second
const TotalBackends = 2
const UnknownPlatform = "unknown platform"
type AppInfo struct {
	Name    string `json:"name"`
	URL     string `json:"url"`
	Version string `json:"version"`
}
func (a *AppInfo) formatUserAgent() string {
	str := a.Name
	if a.Version != "" {
		str += "/" + a.Version
	}
	if a.URL != "" {
		str += " (" + a.URL + ")"
	}
	return str
}
type Backend interface {
	Call(method, path, key string, body *form.Values, params *Params, v interface{}) error
	CallMultipart(method, path, key, boundary string, body io.Reader, params *Params, v interface{}) error
}
type BackendConfiguration struct {
	Type       SupportedBackend
	URL        string
	HTTPClient *http.Client
}
type SupportedBackend string
const (
	APIBackend SupportedBackend = "api"
	APIURL string = "https://api.stripe.com/v1"
	UploadsBackend SupportedBackend = "uploads"
	UploadsURL string = "https://uploads.stripe.com/v1"
)
type Backends struct {
	API, Uploads Backend
	mu           sync.RWMutex
}
type stripeClientUserAgent struct {
	Application     *AppInfo `json:"application"`
	BindingsVersion string   `json:"bindings_version"`
	Language        string   `json:"lang"`
	LanguageVersion string   `json:"lang_version"`
	Publisher       string   `json:"publisher"`
	Uname           string   `json:"uname"`
}
var Key string
var LogLevel = 2
var Logger Printfer
type Printfer interface {
	Printf(format string, v ...interface{})
}
func init() {
	Logger = log.New(os.Stderr, "", log.LstdFlags)
	initUserAgent()
}
var appInfo *AppInfo
var httpClient = &http.Client{Timeout: defaultHTTPTimeout}
var backends Backends
var encodedStripeUserAgent string
var encodedUserAgent string
func SetHTTPClient(client *http.Client) {
	httpClient = client
}
func NewBackends(httpClient *http.Client) *Backends {
	return &Backends{
		API: &BackendConfiguration{
			APIBackend, APIURL, httpClient},
		Uploads: &BackendConfiguration{
			UploadsBackend, UploadsURL, httpClient},
	}
}
func GetBackend(backend SupportedBackend) Backend {
	switch backend {
	case APIBackend:
		backends.mu.RLock()
		ret := backends.API
		backends.mu.RUnlock()
		if ret != nil {
			return ret
		}
		backends.mu.Lock()
		defer backends.mu.Unlock()
		backends.API = &BackendConfiguration{backend, apiURL, httpClient}
		return backends.API
	case UploadsBackend:
		backends.mu.RLock()
		ret := backends.Uploads
		backends.mu.RUnlock()
		if ret != nil {
			return ret
		}
		backends.mu.Lock()
		defer backends.mu.Unlock()
		backends.Uploads = &BackendConfiguration{backend, uploadsURL, httpClient}
		return backends.Uploads
	}
	return nil
}
func SetBackend(backend SupportedBackend, b Backend) {
	switch backend {
	case APIBackend:
		backends.API = b
	case UploadsBackend:
		backends.Uploads = b
	}
}
func (s *BackendConfiguration) Call(method, path, key string, form *form.Values, params *Params, v interface{}) error {
	var body io.Reader
	if form != nil && !form.Empty() {
		data := form.Encode()
		if strings.ToUpper(method) == "GET" {
			path += "?" + data
		} else {
			body = bytes.NewBufferString(data)
		}
	}
	req, err := s.NewRequest(method, path, key, "application/x-www-form-urlencoded", body, params)
	if err != nil {
		return err
	}
	if err := s.Do(req, v); err != nil {
		return err
	}
	return nil
}
func (s *BackendConfiguration) CallMultipart(method, path, key, boundary string, body io.Reader, params *Params, v interface{}) error {
	contentType := "multipart/form-data; boundary=" + boundary
	req, err := s.NewRequest(method, path, key, contentType, body, params)
	if err != nil {
		return err
	}
	if err := s.Do(req, v); err != nil {
		return err
	}
	return nil
}