-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 809a57c
Showing
11 changed files
with
481 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
|
||
|
||
PKG_VERSION := 0.1.0 | ||
GIT_COMMIT ?= $(shell git rev-parse --short HEAD 2> /dev/null || true) | ||
BUILD_DATE := $(shell date -u +%Y-%m-%dT%T 2> /dev/null) | ||
|
||
|
||
.PHONY: clean | ||
clean: ## Remove temporary files and build artifacts | ||
go clean -v ./... | ||
rm -rf bin | ||
rm -f coverage.out | ||
|
||
.PHONY: cover | ||
cover: test-unit ## Run unit tests and open the coverage report | ||
go tool cover -html=coverage.out | ||
|
||
.PHONY: fmt | ||
fmt: ## Run gofmt on all files | ||
gofmt -s -w . | ||
|
||
.PHONY: lint | ||
lint: ## Lint project source files | ||
docker run --rm -v $(shell pwd):/app -w /app golangci/golangci-lint:v1.39.0 golangci-lint run | ||
|
||
.PHONY: test-unit | ||
test-unit: ## Run unit tests | ||
go test -race -cover -run Unit -coverprofile=coverage.out -covermode=atomic ./... | ||
|
||
.PHONY: version | ||
version: ## Print the version | ||
@echo "${PKG_VERSION}" | ||
|
||
.PHONY: help | ||
help: ## Print usage information | ||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort | ||
|
||
.DEFAULT_GOAL := help |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/hoanhan101/veryfi-go/veryfi" | ||
"github.com/hoanhan101/veryfi-go/veryfi/scheme" | ||
) | ||
|
||
func main() { | ||
timeout, err := time.ParseDuration("10s") | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
client, err := veryfi.NewClientV7(&veryfi.Options{ | ||
ClientID: "vrfZz1LVPAlaGpTb9Co29t0yerWpLsc3o0JXgxA", | ||
Username: "hoanhan101", | ||
APIKey: "5745c55a456b752ba0d78d673c7c095b", | ||
HTTP: veryfi.HTTPOptions{ | ||
Timeout: timeout, | ||
Retry: veryfi.RetryOptions{ | ||
Count: 1, | ||
}, | ||
}, | ||
}) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
resp, err := client.ProcessDocumentURL(scheme.DocumentURLOptions{ | ||
FileURL: "https://templates.invoicehome.com/invoice-template-us-neat-750px.png", | ||
DocumentSharedOptions: scheme.DocumentSharedOptions{ | ||
Tags: []string{"electric", "repair", "ny"}, | ||
}, | ||
}) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
fmt.Printf("%+v", resp) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module github.com/hoanhan101/veryfi-go | ||
|
||
go 1.16 | ||
|
||
require ( | ||
github.com/creasty/defaults v1.5.1 | ||
github.com/go-resty/resty/v2 v2.6.0 | ||
github.com/pkg/errors v0.9.1 | ||
golang.org/x/tools v0.1.0 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
github.com/creasty/defaults v1.5.1 h1:j8WexcS3d/t4ZmllX4GEkl4wIB/trOr035ajcLHCISM= | ||
github.com/creasty/defaults v1.5.1/go.mod h1:FPZ+Y0WNrbqOVw+c6av63eyHUAl6pMHZwqLPvXUZGfY= | ||
github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKYS4= | ||
github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q= | ||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= | ||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= | ||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | ||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c= | ||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= | ||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= | ||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= | ||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package veryfi | ||
|
||
import ( | ||
"github.com/hoanhan101/veryfi-go/veryfi/scheme" | ||
) | ||
|
||
// Client API for Veryfi. | ||
type Client interface { | ||
// Config returns the unified configuration info. | ||
Config() *Options | ||
|
||
// ProcessDocumentURL processes a file using a URL. | ||
ProcessDocumentURL(scheme.DocumentURLOptions) (*scheme.Document, error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
package veryfi | ||
|
||
import ( | ||
"fmt" | ||
"github.com/pkg/errors" | ||
|
||
"github.com/go-resty/resty/v2" | ||
"github.com/hoanhan101/veryfi-go/veryfi/scheme" | ||
) | ||
|
||
// httpClient implements a Veryfi API Client. | ||
type httpClient struct { | ||
// options is the global config options of the client. | ||
options *Options | ||
|
||
// client holds the resty.Client. | ||
client *resty.Client | ||
|
||
// apiVersion is the current API version of Veryfi that we are | ||
// communicating with. | ||
apiVersion string | ||
} | ||
|
||
// NewClientV7 returns a new instance of a client for v7 API. | ||
func NewClientV7(opts *Options) (Client, error) { | ||
c, err := createClient(opts) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to create a client") | ||
} | ||
|
||
return &httpClient{ | ||
options: opts, | ||
client: c, | ||
apiVersion: "v7", | ||
}, nil | ||
} | ||
|
||
// createClient setups a resty client with configured options. | ||
func createClient(opts *Options) (*resty.Client, error) { | ||
err := setDefaults(opts) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
// Create a resty client with configured options. | ||
client := resty.New() | ||
client = client. | ||
SetTimeout(opts.HTTP.Timeout). | ||
SetRetryCount(int(opts.HTTP.Retry.Count)). | ||
SetRetryWaitTime(opts.HTTP.Retry.WaitTime). | ||
SetRetryMaxWaitTime(opts.HTTP.Retry.MaxWaitTime) | ||
|
||
return client, nil | ||
} | ||
|
||
// Config returns the client configuration options. | ||
func (c *httpClient) Config() *Options { | ||
return c.options | ||
} | ||
|
||
// ProcessDocumentURL returns the processed document using URL. | ||
func (c *httpClient) ProcessDocumentURL(opts scheme.DocumentURLOptions) (*scheme.Document, error) { | ||
out := new(*scheme.Document) | ||
if err := c.post(documentURI, opts, out); err != nil { | ||
return nil, err | ||
} | ||
|
||
return *out, nil | ||
} | ||
|
||
// get performs a GET request against Veryfi API. | ||
// func (c *httpClient) get(uri string, params map[string]string, okScheme interface{}) error { | ||
// errScheme := new(scheme.Error) | ||
// _, err := c.setBaseURL().R().SetQueryParams(params).SetResult(okScheme).SetError(errScheme).Get(uri) | ||
// return check(err, errScheme) | ||
|
||
// } | ||
|
||
// post performs a POST request against Veryfi API. | ||
func (c *httpClient) post(uri string, body interface{}, okScheme interface{}) error { | ||
errScheme := new(scheme.Error) | ||
_, err := c.setBaseURL().R(). | ||
SetBody(body). | ||
SetHeaders(map[string]string{ | ||
"Content-Type": "application/json", | ||
"Accept": "application/json", | ||
"CLIENT-ID": c.options.ClientID, | ||
"AUTHORIZATION": fmt.Sprintf("apikey %s:%s", c.options.Username, c.options.APIKey), | ||
}). | ||
SetResult(okScheme). | ||
SetError(errScheme). | ||
Post(uri) | ||
|
||
return check(err, errScheme) | ||
} | ||
|
||
// setBaseURL returns a client that uses Veryfi's base URL. | ||
func (c *httpClient) setBaseURL() *resty.Client { | ||
return c.client.SetHostURL(buildURL(c.options.EnvironmentURL, "api", c.apiVersion)) | ||
} | ||
|
||
// check validates returned response from Veryfi. | ||
func check(err error, errResp *scheme.Error) error { | ||
if err != nil { | ||
return errors.Wrap(err, "failed to make a request to Veryfi") | ||
} | ||
|
||
if *errResp != (scheme.Error{}) { | ||
return errors.Errorf( | ||
"got a %v error response from Veryfi at %v, saying %v, with context: %v", | ||
errResp.HTTPCode, errResp.Timestamp, errResp.Description, errResp.Context, | ||
) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package veryfi | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/creasty/defaults" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
// Options is the root config options | ||
type Options struct { | ||
// EnvironmentURL provided by Veryfi without trailing `/` or http scheme. | ||
EnvironmentURL string `default:"api.veryfi.com"` | ||
|
||
// ClientID provided by Veryfi. | ||
ClientID string `default:"-"` | ||
|
||
// Username provided by Veryfi. | ||
Username string `default:"-"` | ||
|
||
// APIKey provided by Veryfi. | ||
APIKey string `default:"-"` | ||
|
||
// HTTP specifies the options for http protocol, used by a http client. | ||
HTTP HTTPOptions | ||
} | ||
|
||
// HTTPOptions is the config options for http protocol, | ||
type HTTPOptions struct { | ||
// Timeout specifies a time limit for a http request. | ||
Timeout time.Duration `default:"3s"` | ||
|
||
// Retry specifies the options for retry mechanism. | ||
Retry RetryOptions | ||
} | ||
|
||
// RetryOptions is the config options for backoff retry mechanism. Its strategy | ||
// is to increase retry intervals after each failed attempt, until some maximum | ||
// value. | ||
type RetryOptions struct { | ||
// Count specifies the number of retry attempts. Zero value means no retry. | ||
Count uint `default:"3"` | ||
|
||
// WaitTime specifies the wait time before retrying request. It is | ||
// increased after each attempt. | ||
WaitTime time.Duration `default:"100ms"` | ||
|
||
// MaxWaitTime specifies the maximum wait time, the cap, of all retry | ||
// requests that are made. | ||
MaxWaitTime time.Duration `default:"3s"` | ||
} | ||
|
||
// setDefaults setups default options. | ||
func setDefaults(opts *Options) error { | ||
if opts == nil { | ||
return errors.New("options can not be nil") | ||
} | ||
|
||
if err := defaults.Set(opts); err != nil { | ||
return errors.New("failed to set default configs") | ||
} | ||
|
||
return nil | ||
} |
Oops, something went wrong.