WebServiceDevelopment / PrivateInvoice

P2P based invoicing system where anyone can create their own Node
https://privateinvoice.io/
Apache License 2.0
1 stars 0 forks source link

Update Invoice with Presentation Status Messages #6

Closed wsdOgawa closed 2 years ago

wsdOgawa commented 2 years ago

Abstract

Once we have the same Invoice distributed across two nodes, we will need to manage the state between them.

The flow for an Invoice is after send, the invoice can either be confirmed, or returned. If the invoice is returned, the seller will be required to amend and resend the invoice as a new invoice, or nullify it. In both cases the existing Invoice will be effectively nullified, and the buyer's node will be informed of the timing the Invoice has been nullified either in the case of recreate, or trashed.

If the invoice is confirmed by the buyer, the invoice will be put in the state of Confirmed for the buyer, and Await Payment for the seller.

The seller will then have the option to return the Invoice back to the unconfirmed state, or make a payment on the invoice. A payment must be made with Ethereum, and will be reported back to the seller with the transaction hash to update the state to Paid for both parties.

After an Invoice has been marked as Paid, either party can move the Invoice to Archived independently of the other party which will indicate the seller or buyer has marked the Invoice as resolved, and only needs a read only copy for records.

For now we will describe this process as an exchange of presentations to update the status of a specific Invoice between Nodes. Potentially this could be better implement Baseline Protocol. More investigation into the source code, or documentation would be required to implement this correctly.

Data Structure

The closest status update schema we have is PGA Status Message.

  {
    "type": "PGAStatusMessage",
    "recordNo" : invoice no.,
    "entryNo" : not used,
    "entryLineSequence" : not used,
    "statusCode" : disputed / confirmed / unconfirmed / paid / nullified,
    "statusCodeDescription" : not used,
    "validCodeReason" : transaction id (if paid), new invoice no (if nullified and recreated),
    "validCodeReasonDescription" : not used
  }

With the case of invoices, we should try to adapt to the schemas are defined there. In the case of our invoice update message, it's niche enough that it would not cause conflict and we could provide our own enums and attribute names. We will map to an existing message type, and ivestigate the baseline protocol before opening a Pull Request on this front.

Disputing an Invoice

When a buyer has received an invoice, the two options they have are to Confirm it or Dispute it. Disputing the invoice effectively acts as a return to sender, for the seller to either amend or nullify the invoice.

Create Invoice - Return an Invoice

Confirming an Invoice

The other option is to confirm an invoice, where the buyer has confirmed the validity of the invoice and shows intent to make payment on the invoice.

Create Invoice - Return an Invoice(1)

Unconfirm Invoice

If an invoice has been confirmed, the buyer can choose to unconfirm the invoice in cases where an issue with the invoice was discovered before payment.

Create Invoice - Unconfirm Invoice(2)

Withdraw an Invoice

If a seller has recognized a mistake with their invoice, they can withdraw it on the condition that it has not yet been confirmed.

Create Invoice - Withdraw Invoice

Make Payment on an Invoice

The process for making a payment on an invoice is described in its own issue: https://github.com/WebServiceDevelopment/PrivateInvoice/issues/7

Archive an Invoice

Archiving an invoice happens independently of the other party. After an invoice has been paid, each party can leave it in their Paid tray until they have no need to actively reference the invoice, and move into the Archive folder on their respective node.

wsdOgawa commented 2 years ago

It looks like the last issue that has yet to be addressed in this one. If I can put a pending close tag on this issue, then I'll go back to all of the other issues and make sure that everything has been addressed before moving into documentation.

For the purposes of this issue, first want to test did authentication, which means sending an empty presentation to build modules needed for working with presentations. Then we can update the contacts module to use this approach. And then we can update the invoice and invoice updates to use presentations. Which means that once we've done this, this should be the first issue that we can definitively cross off as complete.

wsdOgawa commented 2 years ago

The next quest is how do we approach this. The first step is to identify the end points, what we need to send and what we expect to get back. The two that we expect to implement are both on the receiver side. On the sender's side we need to implement a module that will init this flow and take either null or a single verifiable credential to send to the remote server.

For /presentations/available, on the sender's side there's not much that we need to do. We can pretty much copy the example as-is, and then send it to the receiver. On the receiver's side of things we want two issues that need to address. First is the domain, this value looks like it's not really needed or used at all. Since it's the domain of the url which the sender is sending to anyways. So we can be lazy and put in the placeholder of "my-domain" to ignore this value because as far as I can can it's not doing anything.

The challenge is a slightly different story. We need to generate it, store it, and then either have it be consumed if it's used, or have it automatically be deleted after a certain number of seconds. The easy approach would be to do this in code, but I think it would be safer to do it with redis.

Edit: I'm getting trolled by redis, where the client always returns true even if the key doesn't exist in the store. So I'm going to do a simpler version of setting a global variable and checking against it.

wsdOgawa commented 2 years ago

The first pass of this was addressed with https://github.com/WebServiceDevelopment/PrivateInvoice/pull/14. The next steps will be move invoices and status messages over to the presentation end points as well.

wsdOgawa commented 2 years ago

Status messages were moved to presentations in https://github.com/WebServiceDevelopment/PrivateInvoice/pull/19. Remaining issues will be addressed in https://github.com/WebServiceDevelopment/PrivateInvoice/issues/15.