Documentation
¶
Index ¶
- Constants
- func BuildSOAPPayload(...) string
- func ExtractPACResponseText(soapResponse string) (string, error)
- type CFDI
- type CFDIRequest
- type Complemento
- type Concepto
- type ConceptoImpuestos
- type Conceptos
- type DoctoImpuestosDR
- type DoctoRelacionado
- type Emisor
- type Impuestos
- type ImpuestosP
- type PACConfig
- type PACResponse
- type Pago
- type Pagos
- type Receptor
- type Retencion
- type RetencionP
- type RetencionesPWrapper
- type RetencionesWrapper
- type Totales
- type Traslado
- type TrasladoDR
- type TrasladoP
- type TrasladosDRWrapper
- type TrasladosPWrapper
- type TrasladosWrapper
Constants ¶
const DefaultSOAPAction = "urn:document#documentServer#generateInvoiceVersion4"
DefaultSOAPAction is the SOAPAction header value proven against the cfdi360 generateInvoiceVersion4 operation.
Variables ¶
This section is empty.
Functions ¶
func BuildSOAPPayload ¶
func BuildSOAPPayload(url, document, docType, fileType, commercio, user, password, invoicePassword string) string
BuildSOAPPayload escapes the XML document and wraps it in a SOAP 1.1 envelope byte-compatible with the legacy PHP SoapClient request that the cfdi360 sandbox accepted (verified end-to-end):
- "SOAP-ENV" envelope prefix;
- Auth header children (<userName>/<password>) carry no extra namespace;
- <cer/> and <key/> are emitted self-closing and empty;
- only &, < and > are escaped inside <document>; double quotes are left untouched (legal inside element text content).
func ExtractPACResponseText ¶
ExtractPACResponseText extracts the meaningful text from a SOAP response. It finds content containing "SUCCESS" between XML tags and returns it. Expected format: "SUCCESS:url_xml,url_pdf".
Types ¶
type CFDI ¶
type CFDI struct {
XMLName xml.Name `xml:"cfdi:Comprobante"`
XmlnsCFDI string `xml:"xmlns:cfdi,attr"`
XmlnsXsi string `xml:"xmlns:xsi,attr"`
XmlnsPago20 *string `xml:"xmlns:pago20,attr,omitempty"`
XsiSchemaLocation string `xml:"xsi:schemaLocation,attr"`
Version string `xml:"Version,attr"`
Serie string `xml:"Serie,attr"`
Folio string `xml:"Folio,attr"`
Fecha string `xml:"Fecha,attr"`
CondicionesDePago string `xml:"CondicionesDePago,attr,omitempty"`
SubTotal string `xml:"SubTotal,attr"`
Descuento string `xml:"Descuento,attr,omitempty"`
Moneda string `xml:"Moneda,attr"`
TipoCambio string `xml:"TipoCambio,attr,omitempty"`
Total string `xml:"Total,attr"`
TipoDeComprobante string `xml:"TipoDeComprobante,attr"`
Exportacion string `xml:"Exportacion,attr"`
MetodoPago string `xml:"MetodoPago,attr,omitempty"`
FormaPago string `xml:"FormaPago,attr,omitempty"`
LugarExpedicion string `xml:"LugarExpedicion,attr"`
Confirmacion string `xml:"Confirmacion,attr,omitempty"`
// NoCertificado, Certificado and Sello are always emitted, even when
// empty. The PAC requires their presence before stamping; omitting them
// triggers "El comprobante no contiene el número de serie del
// certificado de sello digital" (verified against cfdi360 sandbox).
NoCertificado string `xml:"NoCertificado,attr"`
Certificado string `xml:"Certificado,attr"`
Sello string `xml:"Sello,attr"`
Emisor Emisor `xml:"cfdi:Emisor"`
Receptor Receptor `xml:"cfdi:Receptor"`
Conceptos Conceptos
Impuestos *Impuestos `xml:"cfdi:Impuestos,omitempty"`
Complemento *Complemento `xml:"cfdi:Complemento,omitempty"`
}
CFDI represents the root Comprobante element for CFDI 4.0.
type CFDIRequest ¶
type CFDIRequest struct {
Timbrar bool `json:"timbrar"`
Version string `json:"Version"`
Serie string `json:"Serie"`
Folio string `json:"Folio"`
Fecha string `json:"Fecha"`
CondicionesDePago string `json:"CondicionesDePago,omitempty"`
SubTotal string `json:"SubTotal,omitempty"`
Descuento string `json:"Descuento,omitempty"`
Moneda string `json:"Moneda,omitempty"`
TipoCambio string `json:"TipoCambio,omitempty"`
Total string `json:"Total,omitempty"`
TipoDeComprobante string `json:"TipoDeComprobante"`
Exportacion string `json:"Exportacion"`
MetodoPago string `json:"MetodoPago,omitempty"`
FormaPago string `json:"FormaPago,omitempty"`
LugarExpedicion string `json:"LugarExpedicion"`
Confirmacion string `json:"Confirmacion,omitempty"`
Emisor Emisor `json:"Emisor"`
Receptor Receptor `json:"Receptor"`
Conceptos []Concepto `json:"Conceptos"`
Complemento *Complemento `json:"Complemento,omitempty"`
// DocumentType is the SOAP documentType sent to the PAC. Empty means the
// default "1" (Ingreso) is used.
DocumentType string `json:"documentType,omitempty"`
// FileType is the SOAP fileType sent to the PAC: "0" = TXT, "1" = XML.
// Empty means the default "1" (XML) is used. The service always builds
// XML, so this should normally stay "1".
FileType string `json:"fileType,omitempty"`
// Commercio is the SOAP commercio flag sent to the PAC. Empty means "0".
Commercio string `json:"commercio,omitempty"`
}
CFDIRequest is the structured input used to generate a CFDI 4.0.
func (*CFDIRequest) FromJSON ¶
func (req *CFDIRequest) FromJSON(data []byte) error
FromJSON decodes a CFDIRequest from its JSON representation.
func (*CFDIRequest) ParseCFDItoXML ¶
func (req *CFDIRequest) ParseCFDItoXML() string
ParseCFDItoXML builds the CFDI 4.0 XML string from the request.
Notes verified against the cfdi360 sandbox:
- Sello/NoCertificado/Certificado are always emitted (empty), see cfdi.go.
- A stale or missing Fecha is refreshed: the SAT rejects comprobantes older than 72 hours.
- An explicit zero Descuento is omitted entirely.
- Concept-level amounts are emitted exactly as provided; callers must send tax Importes already rounded to 2 decimals (Validate enforces this). Global tax totals are computed as the exact sum of the given values using integer arithmetic.
func (*CFDIRequest) Validate ¶
func (req *CFDIRequest) Validate() (bool, []string)
Validate checks required fields and arithmetic consistency of the request. Arithmetic errors are reported with SAT-style Spanish messages so callers can surface them directly to users (the HTTP handler maps them to a 400 response).
type Complemento ¶
type Complemento struct {
Pagos *Pagos `xml:"pago20:Pagos,omitempty" json:"Pagos,omitempty"`
}
Complemento holds tax complements, currently Pagos 2.0.
type Concepto ¶
type Concepto struct {
ClaveProdServ string `xml:"ClaveProdServ,attr" json:"ClaveProdServ"`
NoIdentificacion string `xml:"NoIdentificacion,attr,omitempty" json:"NoIdentificacion,omitempty"`
Cantidad string `xml:"Cantidad,attr" json:"Cantidad"`
ClaveUnidad string `xml:"ClaveUnidad,attr" json:"ClaveUnidad"`
Unidad string `xml:"Unidad,attr,omitempty" json:"Unidad,omitempty"`
Descripcion string `xml:"Descripcion,attr" json:"Descripcion"`
ValorUnitario string `xml:"ValorUnitario,attr" json:"ValorUnitario"`
Importe string `xml:"Importe,attr" json:"Importe"`
Descuento string `xml:"Descuento,attr,omitempty" json:"Descuento,omitempty"`
ObjetoImp string `xml:"ObjetoImp,attr" json:"ObjetoImp"`
Impuestos *ConceptoImpuestos `xml:"cfdi:Impuestos,omitempty" json:"Impuestos,omitempty"`
}
Concepto is a single line item of the invoice.
type ConceptoImpuestos ¶
type ConceptoImpuestos struct {
Traslados *TrasladosWrapper `xml:"cfdi:Traslados,omitempty" json:"Traslados,omitempty"`
Retenciones *RetencionesWrapper `xml:"cfdi:Retenciones,omitempty" json:"Retenciones,omitempty"`
}
ConceptoImpuestos are the taxes of a single line item.
func (*ConceptoImpuestos) UnmarshalJSON ¶
func (ci *ConceptoImpuestos) UnmarshalJSON(data []byte) error
UnmarshalJSON allows simpler JSON input where Traslados/Retenciones are plain arrays instead of wrapped objects.
type Conceptos ¶
type Conceptos struct {
XMLName xml.Name `xml:"cfdi:Conceptos"`
Concepto []Concepto `xml:"cfdi:Concepto"`
}
Conceptos groups the invoice line items.
type DoctoImpuestosDR ¶
type DoctoImpuestosDR struct {
TrasladosDR *TrasladosDRWrapper `xml:"pago20:TrasladosDR,omitempty" json:"TrasladosDR,omitempty"`
}
DoctoImpuestosDR holds taxes of a related document.
func (*DoctoImpuestosDR) UnmarshalJSON ¶
func (didr *DoctoImpuestosDR) UnmarshalJSON(data []byte) error
UnmarshalJSON allows simpler JSON input for related-document taxes.
type DoctoRelacionado ¶
type DoctoRelacionado struct {
IdDocumento string `xml:"IdDocumento,attr" json:"IdDocumento"`
Serie string `xml:"Serie,attr,omitempty" json:"Serie,omitempty"`
Folio string `xml:"Folio,attr,omitempty" json:"Folio,omitempty"`
MonedaDR string `xml:"MonedaDR,attr" json:"MonedaDR"`
EquivalenciaDR string `xml:"EquivalenciaDR,attr,omitempty" json:"EquivalenciaDR,omitempty"`
NumParcialidad string `xml:"NumParcialidad,attr" json:"NumParcialidad"`
ImpSaldoAnt string `xml:"ImpSaldoAnt,attr" json:"ImpSaldoAnt"`
ImpPagado string `xml:"ImpPagado,attr" json:"ImpPagado"`
ImpSaldoInsoluto string `xml:"ImpSaldoInsoluto,attr" json:"ImpSaldoInsoluto"`
ObjetoImpDR string `xml:"ObjetoImpDR,attr" json:"ObjetoImpDR"`
ImpuestosDR *DoctoImpuestosDR `xml:"pago20:ImpuestosDR,omitempty" json:"ImpuestosDR,omitempty"`
}
DoctoRelacionado links a payment to the original invoice.
type Emisor ¶
type Emisor struct {
Rfc string `xml:"Rfc,attr" json:"Rfc"`
Nombre string `xml:"Nombre,attr" json:"Nombre"`
RegimenFiscal string `xml:"RegimenFiscal,attr" json:"RegimenFiscal"`
}
Emisor is the issuer of the invoice.
type Impuestos ¶
type Impuestos struct {
TotalImpuestosTrasladados string `xml:"TotalImpuestosTrasladados,attr,omitempty" json:"TotalImpuestosTrasladados,omitempty"`
TotalImpuestosRetenidos string `xml:"TotalImpuestosRetenidos,attr,omitempty" json:"TotalImpuestosRetenidos,omitempty"`
Retenciones *RetencionesWrapper `xml:"cfdi:Retenciones,omitempty" json:"Retenciones,omitempty"`
Traslados *TrasladosWrapper `xml:"cfdi:Traslados,omitempty" json:"Traslados,omitempty"`
}
Impuestos are the total taxes of the invoice.
func (*Impuestos) UnmarshalJSON ¶
UnmarshalJSON allows simpler JSON input for the invoice-level taxes.
type ImpuestosP ¶ added in v0.9.7
type ImpuestosP struct {
TotalImpuestosTrasladadosP string `xml:"TotalImpuestosTrasladadosP,attr,omitempty" json:"TotalImpuestosTrasladadosP,omitempty"`
TotalImpuestosRetenidosP string `xml:"TotalImpuestosRetenidosP,attr,omitempty" json:"TotalImpuestosRetenidosP,omitempty"`
RetencionesP *RetencionesPWrapper `xml:"pago20:RetencionesP,omitempty" json:"RetencionesP,omitempty"`
TrasladosP *TrasladosPWrapper `xml:"pago20:TrasladosP,omitempty" json:"TrasladosP,omitempty"`
}
ImpuestosP are the total taxes of a payment (pago20:ImpuestosP).
func (*ImpuestosP) UnmarshalJSON ¶ added in v0.9.7
func (ip *ImpuestosP) UnmarshalJSON(data []byte) error
UnmarshalJSON allows simpler JSON input for payment-level taxes.
type PACConfig ¶
type PACConfig struct {
// URL is the PAC webservice endpoint. It is used as the request URL, as
// the SOAP operation namespace in the envelope, and as the base for the
// auto-derived SOAPAction header.
URL string
// Username is the SOAP user, sent inside the SOAP Auth header.
Username string
// Password is the SOAP password, sent inside the SOAP Auth header.
Password string
// InvoicePassword is the certificate (FIEL/CSD) password, sent as the
// "password" parameter of the generateInvoiceVersion4 body.
InvoicePassword string
// SOAPAction is the HTTP SOAPAction header value. When empty it
// defaults to DefaultSOAPAction, the value accepted by cfdi360.
SOAPAction string
// Timeout is the request timeout in seconds.
Timeout int
}
PACConfig holds the settings required to reach a PAC provider via SOAP.
func DefaultConfig ¶
func DefaultConfig() *PACConfig
DefaultConfig returns a PACConfig with sensible defaults. The default URL points to a placeholder provider; set URL and credentials explicitly in production. SOAPAction is left empty so DefaultSOAPAction is used.
type PACResponse ¶
type PACResponse struct {
Success bool `json:"success"`
XML string `json:"xml,omitempty"`
PACResponse *string `json:"pac_response"`
Error string `json:"error,omitempty"`
}
PACResponse is the outcome of a stamping request.
func StampCFDI ¶
func StampCFDI(cfg *PACConfig, xmlContent, docType, fileType, commercio string) (*PACResponse, error)
StampCFDI sends the CFDI XML to the PAC for stamping and returns the raw response. docType is the SOAP documentType; when empty, "1" is used. fileType is the SOAP fileType ("0"=TXT, "1"=XML); when empty, "1" is used. commercio is the SOAP commercio flag; when empty, "0" is used. If cfg is nil, DefaultConfig is used.
type Pago ¶
type Pago struct {
FechaPago string `xml:"FechaPago,attr" json:"FechaPago"`
FormaDePagoP string `xml:"FormaDePagoP,attr" json:"FormaDePagoP"`
MonedaP string `xml:"MonedaP,attr" json:"MonedaP"`
TipoCambioP string `xml:"TipoCambioP,attr,omitempty" json:"TipoCambioP,omitempty"`
Monto string `xml:"Monto,attr" json:"Monto"`
DoctoRelacionado []DoctoRelacionado `xml:"pago20:DoctoRelacionado" json:"DoctoRelacionado"`
ImpuestosP *ImpuestosP `xml:"pago20:ImpuestosP,omitempty" json:"ImpuestosP,omitempty"`
}
Pago is a single payment in a Pagos 2.0 complement.
type Pagos ¶
type Pagos struct {
Version string `xml:"Version,attr" json:"Version"`
Totales Totales `xml:"pago20:Totales" json:"Totales"`
Pago []Pago `xml:"pago20:Pago" json:"Pago"`
}
Pagos is the Pagos 2.0 complement.
type Receptor ¶
type Receptor struct {
Rfc string `xml:"Rfc,attr" json:"Rfc"`
Nombre string `xml:"Nombre,attr" json:"Nombre"`
DomicilioFiscalReceptor string `xml:"DomicilioFiscalReceptor,attr" json:"DomicilioFiscalReceptor"`
RegimenFiscalReceptor string `xml:"RegimenFiscalReceptor,attr" json:"RegimenFiscalReceptor"`
UsoCFDI string `xml:"UsoCFDI,attr" json:"UsoCFDI"`
}
Receptor is the recipient of the invoice.
type Retencion ¶
type Retencion struct {
Base string `xml:"Base,attr" json:"Base"`
Impuesto string `xml:"Impuesto,attr" json:"Impuesto"`
TipoFactor string `xml:"TipoFactor,attr" json:"TipoFactor"`
TasaOCuota string `xml:"TasaOCuota,attr" json:"TasaOCuota"`
Importe string `xml:"Importe,attr" json:"Importe"`
}
Retencion represents a withholding tax.
type RetencionP ¶ added in v0.9.7
type RetencionP struct {
ImpuestoP string `xml:"ImpuestoP,attr" json:"ImpuestoP"`
ImporteP string `xml:"ImporteP,attr" json:"ImporteP"`
}
RetencionP represents a withholding tax at payment level.
type RetencionesPWrapper ¶ added in v0.9.7
type RetencionesPWrapper struct {
RetencionP []RetencionP `xml:"pago20:RetencionP" json:"RetencionP"`
}
RetencionesPWrapper wraps a list of retenciones at payment level.
type RetencionesWrapper ¶
type RetencionesWrapper struct {
Retencion []Retencion `xml:"cfdi:Retencion" json:"Retencion"`
}
RetencionesWrapper wraps a list of retenciones.
type Totales ¶
type Totales struct {
TotalTrasladosBaseIVA16 string `xml:"TotalTrasladosBaseIVA16,attr" json:"TotalTrasladosBaseIVA16"`
TotalTrasladosImpuestoIVA16 string `xml:"TotalTrasladosImpuestoIVA16,attr" json:"TotalTrasladosImpuestoIVA16"`
MontoTotalPagos string `xml:"MontoTotalPagos,attr" json:"MontoTotalPagos"`
}
Totales are the totals of a Pagos 2.0 complement.
type Traslado ¶
type Traslado struct {
Base string `xml:"Base,attr" json:"Base"`
Impuesto string `xml:"Impuesto,attr" json:"Impuesto"`
TipoFactor string `xml:"TipoFactor,attr" json:"TipoFactor"`
TasaOCuota string `xml:"TasaOCuota,attr" json:"TasaOCuota"`
Importe string `xml:"Importe,attr" json:"Importe"`
}
Traslado represents an additive tax (e.g. IVA).
type TrasladoDR ¶
type TrasladoDR struct {
BaseDR string `xml:"BaseDR,attr" json:"BaseDR"`
ImpuestoDR string `xml:"ImpuestoDR,attr" json:"ImpuestoDR"`
TipoFactorDR string `xml:"TipoFactorDR,attr" json:"TipoFactorDR"`
TasaOCuotaDR string `xml:"TasaOCuotaDR,attr" json:"TasaOCuotaDR"`
ImporteDR string `xml:"ImporteDR,attr" json:"ImporteDR"`
}
TrasladoDR is a traslado of a related document.
type TrasladoP ¶ added in v0.9.7
type TrasladoP struct {
BaseP string `xml:"BaseP,attr" json:"BaseP"`
ImpuestoP string `xml:"ImpuestoP,attr" json:"ImpuestoP"`
TipoFactorP string `xml:"TipoFactorP,attr" json:"TipoFactorP"`
TasaOCuotaP string `xml:"TasaOCuotaP,attr" json:"TasaOCuotaP"`
ImporteP string `xml:"ImporteP,attr" json:"ImporteP"`
}
TrasladoP represents an additive tax at payment level.
type TrasladosDRWrapper ¶
type TrasladosDRWrapper struct {
TrasladoDR []TrasladoDR `xml:"pago20:TrasladoDR" json:"TrasladoDR"`
}
TrasladosDRWrapper wraps a list of traslados DR.
type TrasladosPWrapper ¶ added in v0.9.7
type TrasladosPWrapper struct {
TrasladoP []TrasladoP `xml:"pago20:TrasladoP" json:"TrasladoP"`
}
TrasladosPWrapper wraps a list of traslados at payment level.
type TrasladosWrapper ¶
type TrasladosWrapper struct {
Traslado []Traslado `xml:"cfdi:Traslado" json:"Traslado"`
}
TrasladosWrapper wraps a list of traslados.