Esteban Ordano
10 years ago
1 changed files with 179 additions and 0 deletions
@ -0,0 +1,179 @@ |
|||
# Payment Protocol |
|||
|
|||
`PaymentProtocol` and associated functions and methods will serialize, deserialize, sign and verify payment protocol messages both in Node.js and web browsers. Both X.509 and [bitcoin identity protocol](https://en.bitcoin.it/wiki/Identity_protocol_v1) are supported. For detailed technical information, please view [BIP70](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki). |
|||
|
|||
```javascript |
|||
var bitcore = require('bitcore'); |
|||
var PaymentProtocol = bitcore.PaymentProtocol; |
|||
``` |
|||
|
|||
## Make Payment Details |
|||
|
|||
Here the merchant's server will construct the payment details message: |
|||
|
|||
```javascript |
|||
var now = Date.now() / 1000 | 0; |
|||
|
|||
// construct the payment details |
|||
var details = new PaymentProtocol().makePaymentDetails(); |
|||
details.set('network', 'test'); |
|||
details.set('outputs', outputs); |
|||
details.set('time', now); |
|||
details.set('expires', now + 60 * 60 * 24); |
|||
details.set('memo', 'A payment request from the merchant.'); |
|||
details.set('payment_url', 'https://localhost/-/pay'); |
|||
details.set('merchant_data', new Buffer({size: 7})); // identify the request |
|||
|
|||
``` |
|||
|
|||
For more information about these fields please visit [BIP70](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki#paymentdetailspaymentrequest) |
|||
|
|||
|
|||
## Sign a Payment Request |
|||
|
|||
The merchant's server will then construct a payment request and send it to the customer: |
|||
|
|||
```javascript |
|||
// load the X509 certificate |
|||
var certificates = new PaymentProtocol().makeX509Certificates(); |
|||
certificates.set('certificate', [<file_of_x509_der_cert>]); |
|||
|
|||
// form the request |
|||
var request = new PaymentRequest().makePaymentRequest(); |
|||
request.set('payment_details_version', 1); |
|||
request.set('pki_type', 'x509+sha256'); |
|||
request.set('pki_data', certificates.serialize()); |
|||
request.set('serialized_payment_details', details.serialize()); |
|||
request.sign(<file_of_x509_private_key>); |
|||
|
|||
// serialize the request |
|||
var rawbody = request.serialize(); |
|||
|
|||
// Example HTTP Response Headers: |
|||
// Content-Type: PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE |
|||
// Content-Length: request.length |
|||
// Content-Transfer-Encoding: 'binary' |
|||
|
|||
``` |
|||
|
|||
## Verify a Payment Request |
|||
|
|||
The customers wallet would then verify the payment request as follows (after asking for the payment request message): |
|||
|
|||
```javascript |
|||
|
|||
// Example HTTP Request Headers: |
|||
// Method: GET |
|||
// Accept: PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE, PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE |
|||
// Content-Type: 'application/octet-stream' |
|||
// Content-Length: 0 |
|||
|
|||
var body = PaymentProtocol.PaymentRequest.decode(rawbody); |
|||
var request = new PaymentProtocol().makePaymentRequest(body); |
|||
|
|||
var version = pr.get('payment_details_version'); |
|||
var pki_type = pr.get('pki_type'); |
|||
var pki_data = pr.get('pki_data'); |
|||
var serializedDetails = pr.get('serialized_payment_details'); |
|||
var signature = pr.get('signature'); |
|||
|
|||
// Verify the signature |
|||
var verified = request.verify(); |
|||
|
|||
// Get the payment details |
|||
var decodedDetails = PaymentProtocol.PaymentDetails.decode(serializedDetails); |
|||
var details = new PaymentProtocol().makePaymentDetails(decodedDetails); |
|||
var network = details.get('network'); |
|||
var outputs = details.get('outputs'); |
|||
var time = details.get('time'); |
|||
var expires = details.get('expires'); |
|||
var memo = details.get('memo'); |
|||
var payment_url = details.get('payment_url'); |
|||
var merchant_data = details.get('merchant_data'); |
|||
|
|||
``` |
|||
|
|||
## Send a Payment |
|||
|
|||
After the request is verified a payment can be sent to the merchant, from the customer's wallet: |
|||
|
|||
```javascript |
|||
|
|||
// send the payment transaction |
|||
var payment = new PaymentProtocol().makePayment(); |
|||
payment.set('merchant_data', merchant_data); |
|||
payment.set('transactions', [<transaction_with_outputs>]); // as from payment details |
|||
|
|||
// define the refund outputs |
|||
var refund_outputs = []; |
|||
var outputs = new PaymentProtocol().makeOutput(); |
|||
outputs.set('amount', 0); |
|||
outputs.set('script', script.toBuffer()); // an instance of script |
|||
refund_outputs.push(outputs.message); |
|||
|
|||
payment.set('refund_to', refund_outputs); |
|||
payment.set('memo', 'Here is a payment'); |
|||
|
|||
// serialize and send |
|||
var rawbody = pay.serialize(); |
|||
|
|||
// Example Request Headers: |
|||
// Method: 'POST', |
|||
// Accept: PaymentProtocol.PAYMENT_REQUEST_CONTENT_TYPE, PaymentPrococl.PAYMENT_ACK_CONTENT_TYPE |
|||
// Content-Type: PaymentProtocol.PAYMENT_CONTENT_TYPE |
|||
// Content-Length: payment.length |
|||
// Content-Transfer-Encoding: 'binary' |
|||
|
|||
``` |
|||
|
|||
## Receive a Payment |
|||
|
|||
The merchant would then receive the payment as follows: |
|||
|
|||
```javascript |
|||
|
|||
var body = PaymentProtocol.Payment.decode(rawbody); |
|||
var payment = new PaymentProtocol().makePayment(body); |
|||
var merchant_data = payment.get('merchant_data'); |
|||
var transactions = payment.get('transactions'); |
|||
var refund_to = payment.get('refund_to'); |
|||
var memo = payment.get('memo'); |
|||
|
|||
// send the transaction to the bitcoin network |
|||
|
|||
``` |
|||
|
|||
## Send a Payment Acknowledgement |
|||
|
|||
After the payment has been broadcasted, a payment acknowledgement can be sent in response: |
|||
|
|||
```javascript |
|||
|
|||
// make a payment acknowledgement |
|||
var ack = new PaymentProtocol().makePaymentACK(); |
|||
ack.set('payment', payment.message); |
|||
ack.set('memo', 'Thank you for your payment!'); |
|||
var rawbody = ack.serialize(); |
|||
|
|||
// Example Response Headers: |
|||
// Content-Type: PaymentProtocol.PAYMENT_ACK_CONTENT_TYPE |
|||
// Content-Length: ack.length |
|||
// Content-Transfer-Encoding: 'binary' |
|||
|
|||
``` |
|||
|
|||
## Receive an Acknowledgement |
|||
|
|||
The customer's wallet can then receive an acknowledgement of payment as follows: |
|||
|
|||
```javascript |
|||
var body = PaymentProtocol.PaymentACK.decode(rawbody); |
|||
var ack = new PaymentProtocol().makePaymentACK(body); |
|||
var serializedPayment = ack.get('payment'); |
|||
var memo = ack.get('memo'); |
|||
var decodedPayment = PaymentProtocol.Payment.decode(serializedPayment); |
|||
var payment = new PaymentProtocol().makePayment(decodedPayment); |
|||
var tx = payment.message.transactions[0]; |
|||
``` |
|||
|
|||
For detailed diagram of the exchange of messages, please see the [Protocol section of BIP70](https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki#protocol). |
Loading…
Reference in new issue