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.