Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Gipuzkoa Araba #22

Merged
merged 5 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 49 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ Links to key information for each agency are described in the following subchapt

You must have first created a GOBL Envelope containing an Invoice that you'd like to send to one of the TicketBAI web services.

For the document to accepted, the supplier contained in the invoice should have a "Tax ID" that includes:
For the document to be converted, the supplier contained in the invoice should have a "Tax ID" with the country set to `ES`.

- A country code set to `ES`
- A zone code set to region of one of the three Basque Country tax agencies, i.e. `BI`, `SS`, or `VI`. (We don't consider the address field reliable for this.)
TicketBAI is used by three different tax agencies (Haciendas Forales), each of which has their own API and specific requirements. The `es-tbai-region` extension defined in the GOBL Invoice's `tax` property is used to set the determine the correct API to utilize. This will be set automatically in most cases.

The following is an example of how the GOBL TicketBAI package could be used:

Expand All @@ -47,13 +46,16 @@ import (
)

func main() {
ctx := context.Background()

// Load sample envelope:
data, _ := os.ReadFile("./test/data/sample-invoice.json")

env := new(gobl.Envelope)
if err := json.Unmarshal(data, env); err != nil {
panic(err)
}
zone := ticketbai.ZoneFor(env)

// Prepare software configuration:
soft := &ticketbai.Software{
Expand All @@ -70,8 +72,9 @@ func main() {
panic(err)
}

// Instantiate the TicketBAI client:
tbai, err := ticketbai.New(soft,
// Instantiate the TicketBAI client with sofrward config
// and specific zone.
tc, err := ticketbai.New(soft, zone,
ticketbai.WithCertificate(cert), // Use the certificate previously loaded
ticketbai.WithSupplierIssuer(), // The issuer is the invoice's supplier
ticketbai.InTesting(), // Use the tax agency testing environment
Expand All @@ -81,18 +84,19 @@ func main() {
}

// Create a new TBAI document:
doc, err := tbai.NewDocument(env)
doc, err := tc.Convert(env)
if err != nil {
panic(err)
}

// Create the document fingerprint:
if err = doc.Fingerprint(prev); err != nil {
// Create the document fingerprint
// Assume here that we don't have a previous chain data object.
if err = tc.Fingerprint(doc, nil); err != nil {
panic(err)
}

// Sign the document:
if err := doc.Sign(); err != nil {
if err := tc.Sign(doc, env); err != nil {
panic(err)
}

Expand All @@ -102,8 +106,21 @@ func main() {
panic(err)
}

// Do something with the output
// Do something with the output, you probably want to store
// it somewhere.
fmt.Println("Document created:\n", string(bytes))

// Grab and persist the Chain Data somewhere so you can use this
// for the next call to the Fingerprint method.
cd := doc.ChainData()

// Send to TicketBAI, if rejected, you'll want to fix any
// issues and send in a new XML document. The original
// version should not be modified.
if err := tc.Post(ctx, doc); err != nil {
panic(err)
}

}
```

Expand All @@ -115,13 +132,29 @@ The GOBL TicketBAI package tool also includes a command line helper. You can fin
go install github.com/invopop/gobl.ticketbai
```

Usage is very straightforward:
We recommend using a `.env` file to prepare configuration settings, although all parameters can be set using command line flags. Heres an example:

```
CERTIFICATE_PATH="./test/certs/EntitateOrdezkaria_RepresentanteDeEntidad.p12"
CERTIFICATE_PASSWORD=IZDesa2021
SOFTWARE_COMPANY_NIF=B85905495
SOFTWARE_COMPANY_NAME="Invopop S.L."
SOFTWARE_NAME="Invopop"
SOFTWARE_LICENSE="TBAIBI00000000PRUEBA" # BI & SS
SOFTWARE_VERSION="1.0"
```

To convert a document to XML, run:

```bash
gobl.ticketbai convert ./test/data/invoice.json
gobl.ticketbai convert ./test/data/sample-invoice.json
```

At the moment, it's not possible to add a fingerprint or sign TicketBAI files using the CLI.
To submit to the tax agency testing environment:

```bash
gobl.ticketbai send ./test/data/sample-invoice.json
```

## Limitations

Expand Down Expand Up @@ -180,12 +213,10 @@ Under what situations should the TicketBAI system be expected to function:

## Test Data

Some sample test data is available in the `./test` directory.

If you make any modifications to the source YAML files, the JSON envelopes will need to be updated, for example:
Some sample test data is available in the `./test` directory. To update the JSON documents and regenerate the XML files for testing, use the following command:

```bash
gobl build -i --envelop test/data/invoice-es-es-b2c.yaml > test/data/invoice-es-es-b2c.json
go test ./examples_test.go --update
```

Make sure you have the GOBL CLI installed ([more details](https://docs.gobl.org/quick-start/cli)).
All generate XML documents will be validated against the TicketBAI XSD documents.
41 changes: 41 additions & 0 deletions ca/AAPPNR_cert_sha256.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
-----BEGIN CERTIFICATE-----
MIIHNzCCBSGgAwIBAgIQJMXIqlZvjuhMvqcFXOFkpDALBgkqhkiG9w0BAQswODEL
MAkGA1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMRMwEQYDVQQDDApJemVu
cGUuY29tMB4XDTEwMTAyMDA4MjMzM1oXDTM3MTIxMjIzMDAwMFowgZ0xCzAJBgNV
BAYTAkVTMRQwEgYDVQQKDAtJWkVOUEUgUy5BLjE6MDgGA1UECwwxQVpaIFppdXJ0
YWdpcmkgcHVibGlrb2EgLSBDZXJ0aWZpY2FkbyBwdWJsaWNvIFNDQTE8MDoGA1UE
AwwzRUFFa28gSGVycmkgQWRtaW5pc3RyYXppb2VuIENBIC0gQ0EgQUFQUCBWYXNj
YXMgKDIpMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoIM7nEdI0N1h
rR5T4xuV/usKDoMIasaiKvfLhbwxaNtTt+a7W/6wV5bv3svQFIy3sUXjjdzV1nG2
To2wo/YSPQiOt8exWvOapvL21ogiof+kelWnXFjWaKJI/vThHYLgIYEMj/y4HdtU
ojI646rZwqsb4YGAopwgmkDfUh5jOhV2IcYE3TgJAYWVkj6jku9PLaIsHiarAHjD
PY8dig8a4SRv0gm5Yk7FXLmW1d14oxQBDeHZ7zOEXfpafxdEDO2SNaRJjpkh8XRr
PGqkg2y1Q3gT6b4537jz+StyDIJ3omylmlJsGCwqT7p8mEqjGJ5kC5I2VnjXKuNn
soShc72khWZVUJiJo5SGuAkNE2ZXqltBVm5Jv6QweQKsX6bkcMc4IZok4a+hx8FM
8IBpGf/I94pU6HzGXqCyc1d46drJgDY9mXa+6YDAJFl3xeXOOW2iGCfwXqhiCrKL
MYvyMZzqF3QH5q4nb3ZnehYvraeMFXJXDn+Utqp8vd2r7ShfQJz01KtM4hgKdgSg
jtW+shkVVN5ng/fPN85ovfAH2BHXFfHmQn4zKsYnLitpwYM/7S1HxlT61cdQ7Nnk
3LZTYEgAoOmEmdheklT40WAYakksXGM5VrzG7x9S7s1Tm+Vb5LSThdHC8bxxwyTb
KsDRDNJ84N9fPDO6qHnzaL2upQ43PycCAwEAAaOCAdkwggHVMIHHBgNVHREEgb8w
gbyGFWh0dHA6Ly93d3cuaXplbnBlLmNvbYEPaW5mb0BpemVucGUuY29tpIGRMIGO
MUcwRQYDVQQKDD5JWkVOUEUgUy5BLiAtIENJRiBBMDEzMzcyNjAtUk1lcmMuVml0
b3JpYS1HYXN0ZWl6IFQxMDU1IEY2MiBTODFDMEEGA1UECQw6QXZkYSBkZWwgTWVk
aXRlcnJhbmVvIEV0b3JiaWRlYSAxNCAtIDAxMDEwIFZpdG9yaWEtR2FzdGVpejAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUwKlK90cl
h/+8taaJzoLSRqiJ66MwHwYDVR0jBBgwFoAUHRxlDqjyJXu0kc/ksbHmvVV0bAUw
OgYDVR0gBDMwMTAvBgRVHSAAMCcwJQYIKwYBBQUHAgEWGWh0dHA6Ly93d3cuaXpl
bnBlLmNvbS9jcHMwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8v
b2NzcC5pemVucGUuY29tOjgwOTQwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2Ny
bC5pemVucGUuY29tL2NnaS1iaW4vYXJsMjALBgkqhkiG9w0BAQsDggIBAMbjc3HM
3DG9ubWPkzsF0QsktukpujbTTcGk4h20G7SPRy1DiiTxrRzdAMWGjZioOP3/fKCS
M539qH0M+gsySNie+iKlbSZJUyE635T1tKw+G7bDUapjlH1xyv55NC5I6wCXGC6E
3TEP5B/E7dZD0s9E4lS511ubVZivFgOzMYo1DO96diny/N/V1enaTCpRl1qH1OyL
xUYTijV4ph2gL6exwuG7pxfRcVNHYlrRaXWfTz3F6NBKyULxrI3P/y6JAtN1GqT4
VF/+vMygx22n0DufGepBwTQz6/rr1ulSZ+eMnuJiTXgh/BzQnkUsXTb8mHII25iR
0oYF2qAsk6ecWbLiDpkHKIDHmML21MZE13MS8NSvTHoqJO4LyAmDe6SaeNHtrPlK
b6mzE1BN2ug+ZaX8wLA5IMPFaf0jKhb/Cxu8INsxjt00brsErCc9ip1VNaH0M4bi
1tGxfiew2436FaeyUxW7Pl6G5GgkNbuUc7QIoRy06DdU/U38BxW3uyJMY60zwHvS
FlKAn0OvYp4niKhAJwaBVN3kowmJuOU5Rid+TUnfyxbJ9cttSgzaF3hP/N4zgMEM
5tikXUskeckt8LUK96EH0QyssavAMECUEb/xrupyRdYWwjQGvNLq6T5+fViDGyOw
k+lzD44wofy8paAy9uC9Owae0zMEzhcsyRm7
-----END CERTIFICATE-----
34 changes: 34 additions & 0 deletions ca/RAIZ2007_cert_sha256.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
40 changes: 40 additions & 0 deletions ca/SSLEV_cert_signing_1_2018.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
-----BEGIN CERTIFICATE-----
MIIHGjCCBQKgAwIBAgIQaH23FxdE2iNbP2Jac5P4pTANBgkqhkiG9w0BAQsFADA4
MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
ZW5wZS5jb20wHhcNMTgwNzA2MTIzNjQxWhcNMjgwNzA2MTIzNjQxWjCBgTELMAkG
A1UEBhMCRVMxFDASBgNVBAoMC0laRU5QRSBTLkEuMTgwNgYDVQQLDC9CWiBaaXVy
dGFnaXJpIHB1Ymxpa29hIC0gQ2VydGlmaWNhZG8gcHVibGljbyBFVjEiMCAGA1UE
AwwZQ0EgZGUgQ2VydGlmaWNhZG9zIFNTTCBFVjCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAN1INsruuFEV4Z9tcfhNC9neg6vTQYhJPNFJQmKGJVcELjn3
Scf8kP0jJJOWlDKxYiP1dXjzV0FpK2colXDaV7gHXD912VoPVLmbRyK3UyV5YYTO
TGd84ErKtIceYLa7Hv38zsZnIkL+rfS98QoivMcZhpjRoLY3IUZ9U7j+DX/MkkJ5
u6cXRe1vB8x9FwdWSwTkkLK4+lOhFOW0o5LDnt99Hs8ddi48KEflIbS7qYZty/Wy
SH6pvoi2ZqEAFL4eMIos4TMfV5Pdrd13HAB45Il/kdva0dq6GHfpy3absBZhsxVb
mvdAc1f66Ytr/qoLKSwBxRM/cCpQurnbS74HVgA2xBPEHM75J/YBa5uMgI/yxTzo
EiaGhExhTMUGG+9od8oqhXzDR1ecyxXqndVzf4RJB+zgd4LWnVXM3DJC0WBgmFES
Ucn0fqoyb09RPN5vFtjY/HeAuzm39p1RDclejAWWnQaDAHJrKUsk62zWKpJjuR3m
/WhLo9upz+oWO8hAofLIdxH7BOFPL+OOOsWJ8qqQPZpIZQZkwV02WBaxYufwMjgf
t4anyPrfRgujyIxFmUJxxTl6faL5XngYkZK1f4Ns2hOfn1qKZEX2C9UlCpBrSVQi
QMkM0Q3fnYOa7TBDB/f9yroxmrLmXUuG3VOCZ3rtN70DvcL7KbwiNlX0ld1RAgMB
AAGjggHUMIIB0DCBxwYDVR0RBIG/MIG8hhVodHRwOi8vd3d3Lml6ZW5wZS5jb22B
D2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBD
SUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgx
QzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAw
MTAxMCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
BAMCAQYwHQYDVR0OBBYEFMbt/nf7UVZN/KvV47EME6O/VOObMB8GA1UdIwQYMBaA
FB0cZQ6o8iV7tJHP5LGx5r1VdGwFMDoGA1UdIAQzMDEwLwYEVR0gADAnMCUGCCsG
AQUFBwIBFhlodHRwOi8vd3d3Lml6ZW5wZS5jb20vY3BzMDIGCCsGAQUFBwEBBCYw
JDAiBggrBgEFBQcwAYYWaHR0cDovL29jc3AuaXplbnBlLmNvbTAzBgNVHR8ELDAq
MCigJqAkhiJodHRwOi8vY3JsLml6ZW5wZS5jb20vY2dpLWJpbi9hcmwyMA0GCSqG
SIb3DQEBCwUAA4ICAQBYRlfC3xiMdbPZfP7j+5iHtfH1sCFGWfUF8PdWR5CGQHXq
9gybOYNDYBg8fQNIl3wKMZCI7WoXn+8e3eUUzKblhzU+009CNc2bPHIW4nCn8nak
JAcy3ZvDFO9G9K00aiu/aTgLDXnvR71crRx1vTOu30K2Lq9sJNzc8DeJWKmXY4Vu
J6C5AgwRsmtRlIBhudOyKTeXU72dRDEFejt8bGOt3gIuSEgrlPGEIP1LRnVVyAnR
RWfMOvDjwS5DQQs1j9/YIKS/w9pGB40QsCzUBsHd3N6VCtTi59ZDXky0DrA1c1ae
QtyXc90PfqYTwwEwYnQHsR6U0gk8SUB6xSn1nwUuWmHriJtmQGphGw4ax76sEJXN
k7XUJeclyKFCUK8gX6fYMb/l0hu2O93sEyfGJF9uIcqvduqEjRWQY36F/xO4r/ZH
ndVrI4vMlYN0Xiz/tPS61b3kkrWUVsknKfic8cuBiqGgop1ni0RNylpVk95UsROm
3Cfdcf1fdwVA6poiiYQiINhWb6mF0P7+DcfccC3llMYvxsfrx+11jt8YCQYI8FF6
5FxPCt+YEBO2hnOnPMK3cA8Yvu5ol1fkE/5tcpcjPeRrvuPy/l+at2pj8hv8f4FW
MX6Gj8zt8+AoAprvXeQRaiEO4FL5alTv1Rqkv7i0HCGIpc+Ct2ApdcBtC4uSTA==
-----END CERTIFICATE-----
16 changes: 16 additions & 0 deletions ca/ca.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Package ca is used to provide the root certificates used by the TicketBAI
// services. Certificates where sourced from:
//
// - https://www.izenpe.eus/descarga-de-certificados/webize01-cndoctecnica/es/
//
// And converted to PEM format:
//
// openssl x509 -in AAPPNR_cert_sha256.crt -outform PEM -out AAPPNR_cert_sha256.pem
package ca

import "embed"

//go:embed *.pem

// Content contains the root certificates used by the TicketBAI services.
var Content embed.FS
77 changes: 34 additions & 43 deletions cancel_document.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,77 +6,68 @@ import (
"time"

"github.com/invopop/gobl"
"github.com/invopop/gobl.ticketbai/internal/doc"
"github.com/invopop/gobl.ticketbai/doc"
"github.com/invopop/gobl/addons/es/tbai"
"github.com/invopop/gobl/bill"
"github.com/invopop/gobl/l10n"
"github.com/invopop/xmldsig"
)

// CancelDocument is a wrapper around the internal AnulaTicketBAI document.
type CancelDocument struct {
env *gobl.Envelope
inv *bill.Invoice
tbai *doc.AnulaTicketBAI // output

client *Client
}

// NewCancelDocument creates a new AnulaTicketBAI document from the provided
// GenerateCancel creates a new AnulaTicketBAI document from the provided
// GOBL Envelope.
func (c *Client) NewCancelDocument(env *gobl.Envelope) (*CancelDocument, error) {
d := new(CancelDocument)

// Set the client for later use
d.client = c

func (c *Client) GenerateCancel(env *gobl.Envelope) (*doc.AnulaTicketBAI, error) {
// Extract the Invoice
var ok bool
d.env = env
d.inv, ok = d.env.Extract().(*bill.Invoice)
inv, ok := env.Extract().(*bill.Invoice)
if !ok {
return nil, ErrOnlyInvoices
return nil, ErrValidation.withMessage("only invoices are supported")
}

if d.inv.Supplier.TaxID.Country != l10n.ES.Tax() {
return nil, ErrNotSpanish
if inv.Supplier.TaxID.Country != l10n.ES.Tax() {
return nil, ErrValidation.withMessage("only spanish invoices are supported")
}
zone := zoneFor(inv)
if zone == "" {
return nil, ErrValidation.withMessage("invalid zone")
}

// Extract the time when the invoice was posted to TicketBAI gateway
ts, err := extractPostTime(d.env)
ts, err := extractPostTime(env)
if err != nil {
return nil, err
}

// Create the document
d.tbai, err = doc.NewAnulaTicketBAI(d.inv, ts)
cd, err := doc.NewAnulaTicketBAI(inv, ts)
if err != nil {
return nil, err
}

return d, nil
return cd, nil
}

// Fingerprint generates a finger print for the TicketBAI document using the
// FingerprintCancel generates a finger print for the TicketBAI document using the
// data provided from the previous invoice data.
func (d *CancelDocument) Fingerprint() error {
c := d.client // shortcut

conf := &doc.FingerprintConfig{
License: c.software.License,
NIF: c.software.NIF,
SoftwareName: c.software.Name,
SoftwareVersion: c.software.Version,
func (c *Client) FingerprintCancel(cd *doc.AnulaTicketBAI) error {
conf := &doc.Software{
License: c.software.License,
NIF: c.software.NIF,
Name: c.software.Name,
Version: c.software.Version,
}
return d.tbai.Fingerprint(conf)
return cd.Fingerprint(conf)
}

// Sign is used to generate the XML DSig components of the final XML document.
func (d *CancelDocument) Sign() error {
c := d.client // shortcut

dID := d.env.Head.UUID.String()
if err := d.tbai.Sign(dID, c.cert, c.issuerRole, xmldsig.WithCurrentTime(c.CurrentTime)); err != nil {
// SignCancel is used to generate the XML DSig components of the final XML document.
func (c *Client) SignCancel(cd *doc.AnulaTicketBAI, env *gobl.Envelope) error {
inv, ok := env.Extract().(*bill.Invoice)
if !ok {
return ErrValidation.withMessage("only invoices are supported")
}
zone := zoneFor(inv)
if zone == "" {
return ErrValidation.withMessage("invalid zone: '%s'", zone)
}
dID := env.Head.UUID.String()
if err := cd.Sign(dID, c.cert, c.issuerRole, zone, xmldsig.WithCurrentTime(c.CurrentTime)); err != nil {
return fmt.Errorf("signing: %w", err)
}

Expand Down
Loading