-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- The command does not yet implement all api methods, just generate authorize URL, exchange device code, download invoice, validate invoice.
- Loading branch information
Showing
12 changed files
with
705 additions
and
19 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 @@ | ||
// Copyright 2024 Victor Dodon | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License | ||
|
||
package cmd | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// apiCmd represents the auth command | ||
var apiCmd = &cobra.Command{ | ||
Use: "api", | ||
Short: "e-factura API calls", | ||
} | ||
|
||
func init() { | ||
apiCmd.PersistentFlags().String(flagNameOauthClientID, "", "OAuth2 client ID") | ||
_ = apiCmd.MarkPersistentFlagRequired(flagNameOauthClientID) | ||
apiCmd.PersistentFlags().String(flagNameOauthClientSecret, "", "OAuth2 client secret") | ||
_ = apiCmd.MarkPersistentFlagRequired(flagNameOauthClientSecret) | ||
apiCmd.PersistentFlags().String(flagNameOAuthRedirectURL, "", "OAuth2 redirect URL. This needs to match one of the URLs for the OAuth2 app in SPV.") | ||
_ = apiCmd.MarkPersistentFlagRequired(flagNameOAuthRedirectURL) | ||
apiCmd.PersistentFlags().String(flagNameOAuthToken, "", "JSON-encoded OAuth2 token. The access token should not necessarily be valid, but rather only the refresh token.") | ||
_ = apiCmd.MarkPersistentFlagRequired(flagNameOAuthToken) | ||
|
||
rootCmd.AddCommand(apiCmd) | ||
} |
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,94 @@ | ||
// Copyright 2024 Victor Dodon | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License | ||
|
||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"io" | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
const ( | ||
flagNameDownloadID = "id" | ||
flagNameDownloadOutFile = "out" | ||
) | ||
|
||
// apiDownloadCmd represents the `api download` command | ||
var apiDownloadCmd = &cobra.Command{ | ||
Use: "download", | ||
Short: "Download an Invoice zip", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
ctx := context.Background() | ||
client, err := newEfacturaClient(ctx, cmd) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return err | ||
} | ||
|
||
fvDownloadID, err := cmd.Flags().GetInt64(flagNameDownloadID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
res, err := client.DownloadInvoice(ctx, fvDownloadID) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return err | ||
} | ||
if !res.IsOk() { | ||
cmd.SilenceUsage = true | ||
return fmt.Errorf("error downloading invoice %d: %s", fvDownloadID, res.Error.Error) | ||
} | ||
|
||
fvOutFile, err := cmd.Flags().GetString(flagNameDownloadOutFile) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
out := os.Stdout | ||
if fvOutFile != "" { | ||
out, err = os.OpenFile(fvOutFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return err | ||
} | ||
defer func() { | ||
if err := out.Close(); err != nil { | ||
fmt.Fprintf(os.Stderr, "error closing file: %v\n", err) | ||
} | ||
}() | ||
} | ||
if _, err := io.Copy(out, bytes.NewReader(res.Zip)); err != nil { | ||
cmd.SilenceUsage = true | ||
fmt.Fprintf(os.Stderr, "error copying data for invoice %d: %v\n", fvDownloadID, err) | ||
return err | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
|
||
func init() { | ||
apiDownloadCmd.Flags().Int64(flagNameDownloadID, 0, "Download ID for the Invoice zip") | ||
_ = apiDownloadCmd.MarkFlagRequired(flagNameDownloadID) | ||
|
||
apiDownloadCmd.Flags().String(flagNameDownloadOutFile, "", "Write output to this file instead of stdout") | ||
|
||
apiCmd.AddCommand(apiDownloadCmd) | ||
} |
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,75 @@ | ||
// Copyright 2024 Victor Dodon | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License | ||
|
||
package cmd | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"github.com/printesoi/e-factura-go/efactura" | ||
"github.com/spf13/cobra" | ||
"os" | ||
) | ||
|
||
const ( | ||
flagNameUploadInvoiceXML = "invoice-xml" | ||
) | ||
|
||
// apiValidateInvoiceCmd represents the `api download` command | ||
var apiValidateInvoiceCmd = &cobra.Command{ | ||
Use: "validate-invoice", | ||
Short: "Validate Invoice UBL XML", | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
ctx := context.Background() | ||
|
||
fvInvoiceXML, err := cmd.Flags().GetString(flagNameUploadInvoiceXML) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
xmlData, err := os.ReadFile(fvInvoiceXML) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return fmt.Errorf("failed to read file: %w", err) | ||
} | ||
|
||
client, err := newEfacturaClient(ctx, cmd) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return err | ||
} | ||
|
||
validateRes, err := client.ValidateXML(ctx, bytes.NewReader(xmlData), efactura.ValidateStandardFACT1) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return fmt.Errorf("failed to validate Invoice UBL XML: %w", err) | ||
} | ||
if validateRes.IsOk() { | ||
fmt.Println("successfully validated Invoice UBL XML") | ||
} else { | ||
cmd.SilenceUsage = true | ||
return fmt.Errorf("validate Invoice UBL XML failed: %s", validateRes.GetFirstMessage()) | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
|
||
func init() { | ||
apiValidateInvoiceCmd.Flags().String(flagNameUploadInvoiceXML, "", "Path of the Invoice XML file to validate") | ||
_ = apiValidateInvoiceCmd.MarkFlagRequired(flagNameUploadInvoiceXML) | ||
|
||
apiCmd.AddCommand(apiValidateInvoiceCmd) | ||
} |
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,36 @@ | ||
// Copyright 2024 Victor Dodon | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License | ||
|
||
package cmd | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// authCmd represents the auth command | ||
var authCmd = &cobra.Command{ | ||
Use: "auth", | ||
Short: "OAuth2 protocol for ANAF APIs", | ||
} | ||
|
||
func init() { | ||
authCmd.PersistentFlags().String(flagNameOauthClientID, "", "OAuth2 client ID") | ||
_ = authCmd.MarkPersistentFlagRequired(flagNameOauthClientID) | ||
authCmd.PersistentFlags().String(flagNameOauthClientSecret, "", "OAuth2 client secret") | ||
_ = authCmd.MarkPersistentFlagRequired(flagNameOauthClientSecret) | ||
authCmd.PersistentFlags().String(flagNameOAuthRedirectURL, "", "OAuth2 redirect URL. This needs to match one of the URLs for the OAuth2 app in SPV.") | ||
_ = authCmd.MarkPersistentFlagRequired(flagNameOAuthRedirectURL) | ||
|
||
rootCmd.AddCommand(authCmd) | ||
} |
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,68 @@ | ||
// Copyright 2024 Victor Dodon | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License | ||
|
||
package cmd | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
|
||
"github.com/spf13/cobra" | ||
) | ||
|
||
const ( | ||
flagNameOAuthDeviceCode = "oauth-device-code" | ||
) | ||
|
||
// authExchangeCodeCmd represents the `accounts get-list` command | ||
var authExchangeCodeCmd = &cobra.Command{ | ||
Use: "exchange-code", | ||
Short: "Exchange an OAuth device code for a token", | ||
Long: `Exchange an OAuth device code for a token`, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
oauth2Cfg, err := newOAuth2Config(cmd) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return err | ||
} | ||
|
||
fvCode, err := cmd.Flags().GetString(flagNameOAuthDeviceCode) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
token, err := oauth2Cfg.Exchange(context.Background(), fvCode) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return err | ||
} | ||
|
||
tokenJSON, err := json.Marshal(token) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return err | ||
} | ||
|
||
fmt.Println(string(tokenJSON)) | ||
return nil | ||
}, | ||
} | ||
|
||
func init() { | ||
authExchangeCodeCmd.Flags().String(flagNameOAuthDeviceCode, "", "OAuth2 device code to be exchanged for a token") | ||
_ = authExchangeCodeCmd.MarkFlagRequired(flagNameOAuthDeviceCode) | ||
|
||
authCmd.AddCommand(authExchangeCodeCmd) | ||
} |
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,73 @@ | ||
// Copyright 2024 Victor Dodon | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License | ||
|
||
package cmd | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
|
||
"github.com/pkg/browser" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
const ( | ||
flagNameAuthGetAuthorizeLinkState = "oauth-state" | ||
flagNameAuthGetAuthorizeLinkOpen = "open" | ||
) | ||
|
||
// authGetAuthorizeLinkCmd represents the `accounts get-list` command | ||
var authGetAuthorizeLinkCmd = &cobra.Command{ | ||
Use: "get-authorize-link", | ||
Short: "Get OAuth2 authorize link", | ||
Long: `Get OAuth2 authorize link`, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
oauth2Cfg, err := newOAuth2Config(cmd) | ||
if err != nil { | ||
cmd.SilenceUsage = true | ||
return err | ||
} | ||
|
||
fvState, err := cmd.Flags().GetString(flagNameAuthGetAuthorizeLinkState) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fvOpen, err := cmd.Flags().GetBool(flagNameAuthGetAuthorizeLinkOpen) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
authURL := oauth2Cfg.AuthCodeURL(fvState) | ||
fmt.Printf("%s\n", authURL) | ||
|
||
if fvOpen { | ||
// Discard info messages from browser package printed to Stdout. | ||
browser.Stdout = io.Discard | ||
if err := browser.OpenURL(authURL); err != nil { | ||
cmd.SilenceUsage = true | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
}, | ||
} | ||
|
||
func init() { | ||
authGetAuthorizeLinkCmd.Flags().String(flagNameAuthGetAuthorizeLinkState, "", "OAuth2 state param") | ||
authGetAuthorizeLinkCmd.Flags().Bool(flagNameAuthGetAuthorizeLinkOpen, false, "Open the authorize link in the default browser") | ||
|
||
authCmd.AddCommand(authGetAuthorizeLinkCmd) | ||
} |
Oops, something went wrong.