diff --git a/server/p2p_payment_destination.go b/server/p2p_payment_destination.go index ee413fa..a763335 100644 --- a/server/p2p_payment_destination.go +++ b/server/p2p_payment_destination.go @@ -1,8 +1,8 @@ package server import ( + "encoding/json" "net/http" - "strconv" "github.com/bitcoin-sv/go-paymail" "github.com/julienschmidt/httprouter" @@ -14,15 +14,15 @@ Incoming Data Object Example: "satoshis": 1000100, } */ +type p2pDestinationRequestBody struct { + Satoshis uint64 `json:"satoshis,omitempty"` +} // p2pDestination will return an output script(s) for a destination (used with SendP2PTransaction) // // Specs: https://docs.moneybutton.com/docs/paymail-07-p2p-payment-destination.html -func (c *Configuration) p2pDestination(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { - - // Get the params & paymail address submitted via URL request - params := req.URL.Query() - incomingPaymail := params.Get("paymailAddress") +func (c *Configuration) p2pDestination(w http.ResponseWriter, req *http.Request, p httprouter.Params) { + incomingPaymail := p.ByName("paymailAddress") // Parse, sanitize and basic validation alias, domain, paymailAddress := paymail.SanitizePaymail(incomingPaymail) @@ -33,16 +33,16 @@ func (c *Configuration) p2pDestination(w http.ResponseWriter, req *http.Request, ErrorResponse(w, ErrorUnknownDomain, "domain unknown: "+domain, http.StatusBadRequest) return } - - satoshis, err := strconv.ParseUint(params.Get("satoshis"), 10, 64) - if err != nil { - ErrorResponse(w, ErrorInvalidParameter, "invalid satoshis: "+params.Get("satoshis"), http.StatusBadRequest) + var b p2pDestinationRequestBody + err := json.NewDecoder(req.Body).Decode(&b) + if err != nil { + ErrorResponse(w, ErrorInvalidParameter, "invalid satoshis: ", http.StatusBadRequest) return - } + } // Start the PaymentRequest paymentRequest := &paymail.PaymentRequest{ - Satoshis: satoshis, + Satoshis: b.Satoshis, } // Did we get some satoshis? diff --git a/server/p2p_receive_transaction.go b/server/p2p_receive_transaction.go index dcb18a6..88fa1b6 100644 --- a/server/p2p_receive_transaction.go +++ b/server/p2p_receive_transaction.go @@ -31,10 +31,10 @@ Incoming Data Object Example: // p2pReceiveTx will receive a P2P transaction (from previous request: P2P Payment Destination) // // Specs: https://docs.moneybutton.com/docs/paymail-06-p2p-transactions.html -func (c *Configuration) p2pReceiveTx(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { +func (c *Configuration) p2pReceiveTx(w http.ResponseWriter, req *http.Request, p httprouter.Params) { p2pFormat := basicP2pPayload - requestPayload, _, md, vErr := processP2pReceiveTxRequest(c, req, p2pFormat) + requestPayload, _, md, vErr := processP2pReceiveTxRequest(c, req, p, p2pFormat) if vErr != nil { ErrorResponse(w, vErr.code, vErr.msg, vErr.httpResponseCode) return @@ -70,10 +70,10 @@ Incoming Data Object Example: } */ // p2pReceiveBeefTx will receive a P2P transaction in BEEF format -func (c *Configuration) p2pReceiveBeefTx(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { +func (c *Configuration) p2pReceiveBeefTx(w http.ResponseWriter, req *http.Request, p httprouter.Params) { p2pFormat := beefP2pPayload - requestPayload, beefData, md, vErr := processP2pReceiveTxRequest(c, req, p2pFormat) + requestPayload, beefData, md, vErr := processP2pReceiveTxRequest(c, req, p, p2pFormat) if vErr != nil { ErrorResponse(w, vErr.code, vErr.msg, vErr.httpResponseCode) return diff --git a/server/p2p_receive_transaction_request_parser.go b/server/p2p_receive_transaction_request_parser.go index 88ce15d..2cffda9 100644 --- a/server/p2p_receive_transaction_request_parser.go +++ b/server/p2p_receive_transaction_request_parser.go @@ -2,17 +2,18 @@ package server import ( "encoding/json" - "net/url" + "net/http" "github.com/bitcoin-sv/go-paymail" + "github.com/julienschmidt/httprouter" ) type parseError struct { code, msg string } -func parseP2pReceiveTxRequest(c *Configuration, parms url.Values, format p2pPayloadFormat) (*p2pReceiveTxReqPayload, *parseError) { - incomingPaymail := parms.Get("paymailAddress") +func parseP2pReceiveTxRequest(c *Configuration, req *http.Request, params httprouter.Params, format p2pPayloadFormat) (*p2pReceiveTxReqPayload, *parseError) { + incomingPaymail := params.ByName("paymailAddress") alias, domain, paymailAddress := paymail.SanitizePaymail(incomingPaymail) if len(paymailAddress) == 0 { @@ -27,46 +28,33 @@ func parseP2pReceiveTxRequest(c *Configuration, parms url.Values, format p2pPayl incomingPaymailDomain: domain, } - requestTx := paymail.P2PTransaction{} - - requestTx.Reference = parms.Get("reference") - if len(requestTx.Reference) == 0 { + var p2pTransaction paymail.P2PTransaction + err := json.NewDecoder(req.Body).Decode(&p2pTransaction) + if err != nil { + return nil, &parseError{ErrorInvalidParameter, "invalid request"} + } + if len(p2pTransaction.Reference) == 0 { return nil, &parseError{ErrorMissingField, "missing parameter: reference"} } - if format == basicP2pPayload { - requestTx.Hex = parms.Get("hex") - if len(requestTx.Hex) == 0 { + if len(p2pTransaction.Hex) == 0 { return nil, &parseError{ErrorMissingField, "missing parameter: hex"} } } else if format == beefP2pPayload { - requestTx.Beef = parms.Get("beef") - if len(requestTx.Beef) == 0 { + if len(p2pTransaction.Beef) == 0 { return nil, &parseError{ErrorMissingField, "missing parameter: beef"} } } - - requestTx.MetaData = parseMetadata(parms.Get("metadata")) - vErr := validateMetadata(c, requestTx.MetaData) + vErr := validateMetadata(c, p2pTransaction.MetaData) if vErr != nil { return nil, vErr } - requestData.P2PTransaction = &requestTx + requestData.P2PTransaction = &p2pTransaction return &requestData, nil } -func parseMetadata(metadata string) *paymail.P2PMetaData { - result := paymail.P2PMetaData{} - - if len(metadata) > 0 { - _ = json.Unmarshal([]byte(metadata), &result) // ignore metadata deserialization errors - } - - return &result -} - func validateMetadata(c *Configuration, metadata *paymail.P2PMetaData) *parseError { // Check signature if: 1) sender validation enabled or 2) a signature was given (optional) if c.SenderValidationEnabled || len(metadata.Signature) > 0 { diff --git a/server/p2p_receive_transaction_request_processor.go b/server/p2p_receive_transaction_request_processor.go index e4861d6..6de7fda 100644 --- a/server/p2p_receive_transaction_request_processor.go +++ b/server/p2p_receive_transaction_request_processor.go @@ -6,6 +6,7 @@ import ( "github.com/bitcoin-sv/go-paymail" "github.com/bitcoinschema/go-bitcoin/v2" + "github.com/julienschmidt/httprouter" "github.com/libsv/go-bt/v2" "github.com/libsv/go-bt/v2/bscript" ) @@ -20,10 +21,10 @@ type processingError struct { httpResponseCode int } -func processP2pReceiveTxRequest(c *Configuration, req *http.Request, format p2pPayloadFormat) ( +func processP2pReceiveTxRequest(c *Configuration, req *http.Request, p httprouter.Params, format p2pPayloadFormat) ( *p2pReceiveTxReqPayload, *paymail.DecodedBEEF, *RequestMetadata, *processingError, ) { - payload, vErr := parseP2pReceiveTxRequest(c, req.URL.Query(), format) + payload, vErr := parseP2pReceiveTxRequest(c, req, p, format) if vErr != nil { return returnError(&processingError{vErr, http.StatusBadRequest}) } diff --git a/server/pki.go b/server/pki.go index 8d272e8..018d87a 100644 --- a/server/pki.go +++ b/server/pki.go @@ -10,11 +10,9 @@ import ( // showPKI will return the public key information for the corresponding paymail address // // Specs: http://bsvalias.org/03-public-key-infrastructure.html -func (c *Configuration) showPKI(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { +func (c *Configuration) showPKI(w http.ResponseWriter, req *http.Request, p httprouter.Params) { - // Get the params & paymail address submitted via URL request - params := req.URL.Query() - incomingPaymail := params.Get("paymailAddress") + incomingPaymail := p.ByName("paymailAddress") // Parse, sanitize and basic validation alias, domain, address := paymail.SanitizePaymail(incomingPaymail) diff --git a/server/public_profile.go b/server/public_profile.go index 5cb49b6..c112bf1 100644 --- a/server/public_profile.go +++ b/server/public_profile.go @@ -10,11 +10,8 @@ import ( // publicProfile will return the public profile for the corresponding paymail address // // Specs: https://github.com/bitcoin-sv-specs/brfc-paymail/pull/7/files -func (c *Configuration) publicProfile(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { - - // Get the params & paymail address submitted via URL request - params := req.URL.Query() - incomingPaymail := params.Get("paymailAddress") +func (c *Configuration) publicProfile(w http.ResponseWriter, req *http.Request, p httprouter.Params) { + incomingPaymail := p.ByName("paymailAddress") // Parse, sanitize and basic validation alias, domain, address := paymail.SanitizePaymail(incomingPaymail) diff --git a/server/resolve_address.go b/server/resolve_address.go index 7111770..29b5f2e 100644 --- a/server/resolve_address.go +++ b/server/resolve_address.go @@ -1,9 +1,9 @@ package server import ( + "encoding/json" "net" "net/http" - "strconv" "time" "github.com/bitcoin-sv/go-paymail" @@ -28,11 +28,8 @@ Incoming Data Object Example: // resolveAddress will return the payment destination (bitcoin address) for the corresponding paymail address // // Specs: http://bsvalias.org/04-01-basic-address-resolution.html -func (c *Configuration) resolveAddress(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { - - // Get the params & paymail address submitted via URL request - params := req.URL.Query() - incomingPaymail := params.Get("paymailAddress") +func (c *Configuration) resolveAddress(w http.ResponseWriter, req *http.Request, p httprouter.Params) { + incomingPaymail := p.ByName("paymailAddress") // Parse, sanitize and basic validation alias, domain, paymailAddress := paymail.SanitizePaymail(incomingPaymail) @@ -44,22 +41,13 @@ func (c *Configuration) resolveAddress(w http.ResponseWriter, req *http.Request, return } - amount, err := strconv.ParseUint(params.Get("amount"), 10, 64) + var senderRequest paymail.SenderRequest + err := json.NewDecoder(req.Body).Decode(&senderRequest) if err != nil { - ErrorResponse(w, ErrorInvalidParameter, "invalid amount: "+err.Error(), http.StatusBadRequest) + ErrorResponse(w, ErrorInvalidParameter, "invalid request body", http.StatusBadRequest) return } - // Start the SenderRequest - senderRequest := &paymail.SenderRequest{ - Amount: amount, - Dt: params.Get("dt"), - Purpose: params.Get("purpose"), - SenderHandle: params.Get("senderHandle"), - SenderName: params.Get("senderName"), - Signature: params.Get("signature"), - } - // Check for required fields if len(senderRequest.SenderHandle) == 0 { ErrorResponse(w, ErrorInvalidSenderHandle, "senderHandle is empty", http.StatusBadRequest) @@ -113,7 +101,7 @@ func (c *Configuration) resolveAddress(w http.ResponseWriter, req *http.Request, // Create the metadata struct md := CreateMetadata(req, alias, domain, "") - md.ResolveAddress = senderRequest + md.ResolveAddress = &senderRequest // Get from the data layer foundPaymail, err := c.actions.GetPaymailByAlias(req.Context(), alias, domain, md) diff --git a/server/verify.go b/server/verify.go index 8bb0877..412effe 100644 --- a/server/verify.go +++ b/server/verify.go @@ -11,12 +11,9 @@ import ( // verifyPubKey will return a response if the pubkey matches the paymail given // // Specs: https://bsvalias.org/05-verify-public-key-owner.html -func (c *Configuration) verifyPubKey(w http.ResponseWriter, req *http.Request, _ httprouter.Params) { - - // Get the params submitted via URL request - params := req.URL.Query() - incomingPaymail := params.Get("paymailAddress") - incomingPubKey := params.Get("pubKey") +func (c *Configuration) verifyPubKey(w http.ResponseWriter, req *http.Request, p httprouter.Params) { + incomingPaymail := p.ByName("paymailAddress") + incomingPubKey := p.ByName("pubKey") // Parse, sanitize and basic validation alias, domain, address := paymail.SanitizePaymail(incomingPaymail)