Aller directement à la fin des métadonnées
Aller au début des métadonnées
RefJIRA ticketIssue / StoryFull detailsQuestionsSolution
1 Invoice ID (by CiviCRM Sales Tax and Invoicing code) overwrites already existing CviCRM invoice ID (in the civicrm_contribution Table).

Most (all?) payment processors can receive and store an "invoice number" as part of a payment transaction request, as a way of providing a reference from the requesting system (in our case, CiviCRM). This function is not CiviCRM-specific, but reasonably standard across payment processing systems.

CiviCRM generates a random unique string (as a hash, here: ) as a default invoice number that is available to the civicrm payment processor code. Many of them in core use it, and many of the payment processors modeled after Core ones use it too. This invoice number is stored in the invoice_id field in the civicrm_contribution table.

When the CiviCRM Tax and Invoicing code "prints" an invoice (i.e. a PDF invoice is created), it overwrites this invoice_id field and replaces it with a NEW invoice_id - in the form of INV_($contributionID).

The invoice_id is a hash - is unique: $invoiceID = md5(uniqid(rand(), TRUE)); Wiki:

adixon: it's a unique id from a hash function, similar to how git creates unique ids for every commit, etc. If you want to understand this stuff, try this

CiviCRM receives a transaction id (trxn_id) FROM Payment Processors - the invoice_id is what was sent TO Payment Processors - for thorough reconciliation back and forth - looking at successes and failures you will want to preserve the TO and FROM cross references.


Option 1:

To create a new field called "CiviCRM invoice ID" and to store the CiviCRM invoice ID in that field.

CiviCRM tax invoice message template will need to be updated for this, as will any reference in the code for this

Option 2

When CiviCRM creates its "invoice ID" as part of the payment processor transaction, to create this using a sequential numbering policy based on the ID of the contribution. Then this invoice ID can be used for both the printed invoice and also the reference to the Payment Processor.

Option 3:

Don't mess with the current invoice id field, have the public-accessible invoice number be a separate concept and separate field. As an example, see the canadian tax receipting extension, which generates it's own internal sequences/ids.

KarinG: I agree - I was leaning Option 2 last night - but am now convinced Option 3 is the way to go:

  • the Sales Tax and PDF Invoicing functionality is actually strikingly similar to our Canadian Tax Receipting extension:
  • it's important that invoice_id in the Contribution Table stays invoice_id -> as that's what the payment processors call it.

2 Sales Tax and Invoicing must both be enabled at the same time, however in some cases users may only want to enable Sales tax or Invoicing and not both. This is a feature request - to be addressed - after Sales Tax and PDF Invoicing breaks out of Core and into an extension. 
3 Partial payments have been in core since 4.5. The 'invoice_id' whether with hash value or INV_* value will not uniquely identify a payment.


  1. Does this actually matter? i.e. I think a unique id for the invoice/contribution is fine. I don't think the extra breakage and work for this is necessary or worthwhile.
  2. Agreed: this is not relevant - it's perfectly ok to have one invoice and multiple payments.

Create a field on civicrm_financial_trxn to hold old hash value of contribution.invoice_id.

Separately, consider calculating value of INV_* wherever used rather than drawing from db field. Possible challenge: what happens if invoice prefix changed.

  • Aucun
  1. Apr 03, 2017

    Alan Dixon dit :

    re: the hash value in the invoice_id field. I think this is a good thing that should be maintained. I agree the label of the field in the table is confusing in some ways, but having a unique reference id that is passed to the payment processor is really essential for a reliable machine reconciliation. Although using the value returned by the payment processor will work for most cases, the key is to remember that these transactions are working in a context that is really fluid. For example, there could be transactions happening on the payment processor account that are not going through civicrm (e.g. a different automated system). And of course there can be automated payments happening with other payment processors on the same civicrm install. And of course, any particular payment processor is only returning a transaction id that is unique within their context, there is no guarantee of global uniqueness. The hash id is as close as we can get to having a really unique identifier for machine reconciliation, and it's really nice to have it around. Which is not to say it's perfect, either - may payment processors will not accept it as an invoice number because it's too long.

    re: the issue of partial payments (#3) - yes, this is an interesting one, but as I thought about it, maybe it's not a problem? The invoice id as stored at the payment processor shouldn't have to be unique per payment (indeed, there's no assumption in the wider world that an invoice has to be settled with a single payment after all ...), and since the contribution in civicrm is conceptually the same as an invoice number, I think this is actually okay. It does mean that the invoice id does not match up to payments, but that doesn't keep it from being useful.

    So - my general feeling is that we should not be trying to change this invoice id at all, and instead we should be focused on stripping the tax and invoicing out of CiviCRM and into an extension, after maybe doing some quick triage on the existing code to minimize it's negative effects.


  2. Apr 03, 2017

    KarinG dit :

    This is the CDN TaxReceipts log table: cdntaxreceipts_log: strikingly similar to PDF Invoice problem/needs: note that this structure also keeps track of when issued; who issued - and whether it was printed or emailed - and also whether or not a duplicate was issued. Of course receipt_no -> would be invoice_no - here it's even constructed similarly with a Prefix and the primary Contribution ID (it's possible that Tax Receipts have more than on Contribution on them (Annual ones typically do so). There is a second log table that keeps track of which ones belong to this receipt_no - but that's icing on the cake - and not relevant for PDF Invoices.

Creative Commons License
Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution-Share Alike 3.0 United States Licence.