Skip to content

Commit

Permalink
Dip 158 remove ready for settlement (#189)
Browse files Browse the repository at this point in the history
* Include only Charge payment type in DIP-158.
Removed all items and updated the relevant descriptions.

* Minor phrasing changes following Dahlia's comments.

* Minor updates

* Added "(optional) Recipient Signature" which was missed

* Updated typo

* QR Scan flow

* Removed ReadyForSettlement

* Update dip-158.md
  • Loading branch information
YinonFirstDAG authored Jun 16, 2021
1 parent 5007017 commit debb0ca
Showing 1 changed file with 71 additions and 53 deletions.
124 changes: 71 additions & 53 deletions dips/dip-158.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ status: Draft
type: Standard
created: 03/15/2021
updated: 05/23/2021
requires: DIP-1, DIP-5, DIP-161
requires: DIP-1, DIP-5, DIP-10, DIP-161
---

# Summary
Expand All @@ -18,10 +18,12 @@ This DIP does NOT include payment flows which require funds pull pre-approval su

This DIP makes use of the `result` field added to the `CommandResponseObject` as described in [DIP-161](https://github.com/diem/dip/blob/main/dips/dip-161.md)

This DIP makes use of the `PaymentMetadata` enum as described in [DIP-10](https://github.com/diem/dip/blob/main/dips/dip-10.md#on-chain-transaction-settlement)

---
# Abstract / Motivation
This DIP is an extension of the Off-Chain Protocol to support more advanced payment functionality - particularly eCommerce P2M Charge payment.
Charge payment stipulates an immediate capture of funds. This means that a successful off-chain negotiation for such payment will result in funds being captured (and submit a corresponding transaction on-chain and actually transfer the funds).
Charge payment stipulates an immediate capture of funds. This means that a successful off-chain negotiation for such payment will result in funds being captured and the existence of a corresponding transaction on-chain.

## How P2M Payments Differ from P2P Transfers
There are several key differences between the process of paying a merchant (P2M) and a simple P2P transfer:
Expand Down Expand Up @@ -56,21 +58,23 @@ Content:
* [Request / Response Payload](#request--response-payload)
* [Structures](#new-structures)
* [Appendix A: Sharing Common Payment Identifier and Address](#appendix-a---prerequisite-sharing-common-payment-identifier-and-address)
* [Appendix B: Include Reference ID in the On-Chain Transaction](#appendix-b---include-reference-id-in-the-on-chain-transaction)
---
## High-Level Flow and Payment Types
---
The high-level flow of an eCommerce P2M payment is:
1. On the merchant's checkout page the customer chooses to pay with Diem
2. The merchant transmits the payment details to its VASP (receiver VASP) so the latter can generate a payment request with Diem
3. The the receiver VASP generates a payment request with all details needed to identify this payment later in the process, provides it to the merchant and makes it available to the customer's Diem wallet (the customer's VASP or sender)
4. The sender VASP parses the payment request (e.g. by scanning the payment request QR) and uses the provided payment identifier to get the payment details. This is the first step of the off-chain protocol
5. The wallet then presents the requested payment details to the customer so the customer can review the payment
6. The customer approves the payment request in the wallet
7. The wallet initializes the payment protocol (off-chain) which will end (if successful) with the funds being charged. Successful completion implies that the receiving VASP was satisfied with the payer information provided and the sender VASP was satisfied with the merchant information provided. **Note** that if the payment amount exceeds the amount that requires a dual attestation signature to be submitted to the blockchain, it must be part of the on-chain transaction submitted
3. The receiver VASP generates a payment request with all details needed and provides it to the merchant, so the latter can display the Diem payment details in the checkout page
4. The customer triggers the payment by performing the required actions in the checkout page, e.g. by scanning a QR code
5. The sender VASP parses the payment request (e.g. parse the information encoded in the QR code) and uses the provided payment identifier to get the payment details. This is the first step of the off-chain protocol
6. The wallet then presents the requested payment details to the customer so the customer can review the payment
7. The customer approves the payment request in the wallet
8. The wallet initializes the payment protocol (off-chain) which will end (if successful) with the funds being charged and a corresponsing transaction was put on-chain. Successful completion implies that the receiving VASP was satisfied with the payer information provided and the sender VASP was satisfied with the merchant information provided. **Note** that if the payment amount exceeds the amount that requires a dual attestation signature (i.e. above Travel Rule threshold), the receipient signature must be provided to the sender, so the latter can include it in the on-chain transaction submitted.

### **Charge Payment Type**
Charge payment stipulates an immediate capture of funds. This means that a successful off-chain negotiation for such payment will result in funds being captured.
As soon as the funds are captured, i.e. the sender agreed to the payment terms, the sender VASP is expected to submit a corresponding transaction on-chain and actually transfer the funds.
As soon as the funds are captured, i.e. the sender and receiver agreed to the payment terms, the sender VASP is expected to submit a corresponding transaction on-chain and actually transfer the funds.

### **Other Payment Types (future)**
Protocols supporting other eCommerce payments flows will require additional payment types which will be be defined in future DIPs.
Expand All @@ -85,18 +89,16 @@ Some examples for such flows are:
This section describes a set of functionalities / activities that should be made available by a Sender and Receiver VASPs in order to support P2M Charge flow based on this DIP. Each functionality can be conceptually compared to an API endpoint. Similar to API documentation, it includes the expected input and output for each functionality.

## Command Types
The following is a list of new values for the `command_type` field of the `CommandRequestObject`. Each command type denotes a step in the off-chain negotiations and specifies the data of the requests and the response
The following is a list of new values for the `command_type` field of the `CommandRequestObject`. Each command type denotes a step in the off-chain negotiations and specifies the data of the request and response
* `GetPaymentInfo` - Allows obtaining payment information based on reference id
* `InitChargePayment` - Initializes a payment process of type `charge`
* `ReadyForSettlementNotification` - Notifies the payment is ready for settlement on-chain
* `InitChargePayment` - Initializes a payment process of type `charge`. Triggering this command by the wallet means the customer approved to proceed with the payment and that the wallet is satisified with the business infromation provided. Successful response from the receiver means that the receiver is satisfied with the payer data provided by the wallet
* `AbortPayment` - Aborts a payment

| Command Type |Direction| Description | Request Data | Response Data |
|-|-|-|-|-|
|[GetPaymentInfo](#getpaymentinfo)|Sender > Receiver|By providing the object reference id the wallet can retrieve the object information from the receiving VASP. In most cases, this would be the first command sent by the wallet. The wallet is not expected to provide any payer data at this stage|Reference ID|Payment Details ; Business Data|
|[InitChargePayment](#initchargepayment)|Sender > Receiver|This functionality allows the wallet to init the payment process based on the payment details. For example, this may occur after the customer approved the payment request|Reference ID ; Payer Data|(optional) Recipient Signature|
|[ReadyForSettlementNotification](#readyforsettlementnotification)|Sender > Receiver|This functionality allows the wallet to indicate the payment is ready for settlement. The wallet is expected to submit a transaction on-chain immediately before or after declaring it is ready|Reference ID||
|[AbortPayment](#abortpayment)|Sender > Receiver / Receiver > Sender|This functionality allows both parties to abort the payment. For example, the receiver may want to abort the payment following failed risk checks|Reference ID||
|[InitChargePayment](#initchargepayment)|Sender > Receiver|This functionality allows the wallet to init the payment process based on the payment details. This is likely to occur after the customer approved the payment request and the wallet verified the business data|Reference ID ; Payer Data|(optional) Recipient Signature|
|[AbortPayment](#abortpayment)|Sender > Receiver / Receiver > Sender|This functionality allows both parties to abort the payment outside the standard flow of the protocol|Reference ID||

---
## Payment Sequences
Expand All @@ -111,35 +113,50 @@ Each scenario is expressed using a sequence of Sender / Receiver functionality.
|-|-|-|-|
|1|GetPaymentInfo|Sender|The wallet requests payment details using the reference id provided. The receiver will respond with the payment details and merchant data. The wallet will display the payment details so the customer can approve or reject|
|2|InitChargePayment|Sender|Following customer approval the wallet initializes the payment process and sends the payer data|
|3|ReadyForSettlementNotification|Sender|The wallet indicates the payment is ready for settlement. The wallet is expected to submit a transaction on-chain immediately before or after this step|
|3|Put transaction on-chain|Sender|Following a successful response from the receiver (to the InitChargePayment in the previous step), the wallet must put a corresponding transaction on-chain and include the Reference ID as part of the metadata. See [appendix B](#appendix-b---include-reference-id-in-the-on-chain-transaction). If the payment is over the travel rule threshold, the sender must verify the recipient provided its signature as part of the InitChargePayment response|

**Note** that following the completion of the Charge sequence, the receiver should start looking for the transaction put by the sender on the blockchain

#### Charge Sequence Diagram
![Charge Sequence Diagram](https://static.swimlanes.io/13ec145db305a3c02323bb3288db52a3.png)
TBD

### Risk Checks Failed (Init Payment Error)
| Step |Command Type| Triggered by | Description |
|-|-|-|-|
|1|GetPaymentInfo|Sender|The wallet requests payment details using the reference id provided. The receiver will respond with the payment details and merchant data. The wallet will display the payment details so the customer can approve or reject|
|2|InitChargePayment|Sender|Following customer approval the wallet initializes the payment process and sends the payer data. Risk checks failed. Receiver will respond with PaymentCommandErrorObject where the error_code is `risk_checks_failed`|

### Invalid Command Type (Premature Settlement Error)
### Abort Sequence - Customer Rejected the Payment Request
| Step |Command Type| Triggered by | Description |
|-|-|-|-|
|1|GetPaymentInfo|Sender|The wallet requests payment details using the reference id provided. The receiver will respond with the payment details and merchant data. The wallet will display the payment details so the customer can approve or reject|
|2|ReadyForSettlementNotification|Sender|Instead of initializing the payment, the wallet wrongly notifies that the payment is ready for settlement. Receiver will respond with PaymentCommandErrorObject where the error_code is `invalid_command_type`|
|2|AbortPayment|Sender|Customer decided not to approve the payment based on the information displayed. The abort_code is `customer_declined`. It is recommended to include a descriptive abort_message|

### Abort Sequence - Customer Rejected the Payment Request
### Abort Sequence - Merchant Data Checks (performed by the Sender) Failed
| Step |Command Type| Triggered by | Description |
|-|-|-|-|
|1|GetPaymentInfo|Sender|The wallet requests payment details using the reference id provided. The receiver will respond with the payment details and merchant data|
|2|AbortPayment|Sender|Sender decided to abort. Can happen if the sender does not approve merchant data provided by the receiver. The abort_code is `business_not_verified`. It is recommended to include a descriptive abort_message|

### Abort Sequence - Insufficient Funds
| Step |Command Type| Triggered by | Description |
|-|-|-|-|
|1|GetPaymentInfo|Sender|The wallet requests payment details using the reference id provided. The receiver will respond with the payment details and merchant data|
|2|AbortPayment|Sender|After getting the payments details from the receiver, the wallet verifies the customer has sufficient funds to complete the payment. If not (and the customer cannot/does not top up the account balance), the wallet should respond with AbortPayment. The abort_code is `insufficient_funds`. It is recommended to include a descriptive abort_message|

### Abort Sequence - Missing Recipient Signature
| Step |Command Type| Triggered by | Description |
|-|-|-|-|
|1|GetPaymentInfo|Sender|The wallet requests payment details using the reference id provided. The receiver will respond with the payment details and merchant data. The wallet will display the payment details so the customer can approve or reject|
|2|AbortPayment|Sender|Customer decided not to approve the payment based on the information displayed. It is recommended to include a descriptive abort_message|
|2|InitChargePayment|Sender|Following customer approval the wallet initializes the payment process and sends the payer data. Since the payment is over the travel rule threshold, the wallet expects a recipient signature as part of the response|
|3|AbortPayment|Sender|After getting the payments details from the receiver, the wallet verifies the recipient signature exists. If not, the wallet should respond with AbortPayment. The abort_code is `missing_recipient_signature`. It is recommended to include a descriptive abort_message|

### Abort Sequence - Merchant Data Checks (performed by the Sender) Failed
### Abort Sequence - Could Not Put Transaction On-Chain
| Step |Command Type| Triggered by | Description |
|-|-|-|-|
|1|GetPaymentInfo|Sender|The wallet requests payment details using the reference id provided. The receiver will respond with the payment details and merchant data. The wallet will display the payment details so the customer can approve or reject|
|2|InitChargePayment|Sender|Following customer approval the wallet initializes the payment process and sends the payer data|
|3|AbortPayment|Sender|Sender decided to abort. Can happen if the sender does not approve merchant data provided by the receiver|
|3|AbortPayment|Sender|After getting the payments details from the receiver, for some reason, the wallet is not able to put the transaction on-chain. The wallet should respond with AbortPayment. The abort_code is `could_not_put_transaction`. It is recommended to include a descriptive abort_message|

### Abort Sequence - Insufficient Funds
| Step |Command Type| Triggered by | Description |
Expand Down Expand Up @@ -216,7 +233,7 @@ Field|Type|Required?|Description|
### InitChargePayment
| Command Type |Direction| Description | Request Data | Response Data |
|-|-|-|-|-|
|InitChargePayment|Sender > Receiver|This functionality allows the wallet to init the payment process for payments of type `charge` based on the payment details. For example, this may occur after the customer approved the payment request|Reference ID ; Payer Data|(optional) Recipient Signature|
|InitChargePayment|Sender > Receiver|This functionality allows the wallet to init the payment process for payments of type `charge` based on the payment details. This is likely to occur after the customer approved the payment request and the wallet verified the business data. Successful response from the receiver means that the receiver is willing to accept the funds and the wallet is expected to put a transaction on-chain|Reference ID ; Payer Data|(optional) Recipient Signature|

#### InitChargePayment Request
Field|Type|Required?|Description|
Expand Down Expand Up @@ -273,45 +290,18 @@ Field|Type|Required?|Description|
}
```
### ReadyForSettlementNotification
| Command Type |Direction| Description | Request Data | Response Data |
|-|-|-|-|-|
|ReadyForSettlementNotification|Sender > Receiver|This functionality allows the wallet to indicate the payment is ready for settlement. The wallet is expected to submit a transaction on-chain immediately before or after declaring it is ready|Reference ID||

#### ReadyForSettlementNotification Request
Field|Type|Required?|Description|
|-|-|-|-|
|reference_id|str|Y|Unique reference ID of this payment. This value should be globally unique|
```
{
"_ObjectType": "CommandRequestObject",
"command_type": "ReadyForSettlementNotification",
"cid": "3185027f-0574-6f55-2668-3a38fdb5de98",
"command": {
"_ObjectType": "ReadyForSettlementNotification",
"reference_id": "4185027f-0574-6f55-2668-3a38fdb5de98"
}
}

```
#### ReadyForSettlementNotification Response
```
{
"_ObjectType": "CommandResponseObject",
"status": "success",
"cid": "12ce83f6-6d18-0d6e-08b6-c00fdbbf085a"
}
```
### AbortPayment
| Command Type |Direction| Description | Request Data | Response Data |
|-|-|-|-|-|
|AbortPayment|Sender > Receiver / Receiver > Sender|This functionality allows both parties to abort the payment. For example, the receiver may want to abort the payment following failed risk checks|Reference ID||
|AbortPayment|Sender > Receiver / Receiver > Sender|This functionality allows both parties to abort the payment outside the standard flow of the protocol|Reference ID||


#### AbortPayment Request
Field|Type|Required?|Description|
|-|-|-|-|
|reference_id|str|Y|Unique reference ID of this payment. This value should be globally unique|
|abort_code |[AbortCode enum](#abortcode-enum)|N| This field is used to specify the reason for the abort|
|abort_message|str|N|Additional information about the reason for aborting this payment|
```
{
Expand All @@ -321,6 +311,7 @@ Field|Type|Required?|Description|
"command": {
"_ObjectType": "AbortPayment",
"reference_id": "4185027f-0574-6f55-2668-3a38fdb5de98",
"abort_code": "customer_declined",
"abort_message": "abort message"
}
}
Expand Down Expand Up @@ -385,7 +376,7 @@ A PaymentSenderObject represents the person in the payment. In P2M scenarios it

|Field|Type|Required?|Description|
|-|-|-|-|
| account_address | str | Y | Address of the receiver account. The addresses are encoded using bech32|
| account_address | str | Y | Address of the sender account. The addresses are encoded using bech32|
|payer_data|[PayerDataObject](#payerdataobject)|Y|The details of the payer|

```
Expand Down Expand Up @@ -535,6 +526,18 @@ For example, a response of GetPaymentInfo in which the refernce_id provided was
* `invalid_command_type`
* `unspecified_error`

Note that the list of error codes above is non exhaustive. A VASP may choose to use values not specified in this list.

### AbortCode Enum
* `insufficient_funds`
* `customer_declined`
* `business_not_verified`
* `missing_recipient_signature`
* `could_not_put_transaction`
* `unspecified_error`

Note that the list of error codes above is non exhaustive. A VASP may choose to use values not specified in this list.

---
# Appendix A - Prerequisite: Sharing Common Payment Identifier and Address

Expand Down Expand Up @@ -596,3 +599,18 @@ The deeplink represented by QR code would be (the domain and path are examples -
`diem://some-diem-wallet.com/pay?vasp_address=dm1pgxah7pxhzljvp3p4m9g0m3tm0qqqqqqqqqqqqqqgyftgh&reference_id=ad8d888a-1791-4b63-98e5-6f1d6ddb4411`

After scanning the QR code, the wallet can request the payment details from the receiving VASP and display them to the customer to review and approve.

---
# Appendix B - Include Reference ID in the On-Chain Transaction

In order for the receiver VASP to be able to correlate the on-chain transaction to the off-chain payment, the sender VASP must include the Reference ID in the on-chain transaction metadata.
Using the Reference ID for correlation, the receiver VASP can, for example, verify that the amount in the on-chain transaction matches the off-chain payment amount.

The Reference ID must be added to the PaymentMetadata element defined in [DIP-10](https://github.com/diem/dip/blob/main/dips/dip-10.md#on-chain-transaction-settlement).
```
enum PaymentMetadata {
PaymentMetadataV0(ReferenceId),
}
type ReferenceId = [u8, 16];
```

0 comments on commit debb0ca

Please sign in to comment.