diff --git a/payjoin-cli/src/app/v2.rs b/payjoin-cli/src/app/v2.rs index 8beb504c..942d7db5 100644 --- a/payjoin-cli/src/app/v2.rs +++ b/payjoin-cli/src/app/v2.rs @@ -7,7 +7,7 @@ use payjoin::bitcoin::consensus::encode::serialize_hex; use payjoin::bitcoin::psbt::Psbt; use payjoin::bitcoin::Amount; use payjoin::receive::v2::ActiveSession; -use payjoin::send::RequestContext; +use payjoin::send::{RequestContext, ResponseError}; use payjoin::{bitcoin, Error, Uri}; use tokio::signal; use tokio::sync::watch; @@ -213,6 +213,7 @@ impl App { } async fn long_poll_post(&self, req_ctx: &mut payjoin::send::RequestContext) -> Result { + use payjoin::send::WellKnownError; loop { let (req, ctx) = req_ctx.extract_v2(self.config.ohttp_relay.clone())?; println!("Polling send request..."); @@ -232,6 +233,28 @@ impl App { println!("No response yet."); tokio::time::sleep(std::time::Duration::from_secs(5)).await; } + Err(ResponseError::WellKnown(WellKnownError::VersionUnsupported { + message, + supported, + })) => { + if supported.contains(&1) { + let (req, ctx) = req_ctx.clone().extract_v1()?; + println!("Polling send request..."); + let http = http_agent()?; + let response = http + .post(req.url) + .header("Content-Type", "text/plain") + .body(req.body) + .send() + .await + .map_err(map_reqwest_err)?; + + return Ok( + ctx.process_response(&mut response.bytes().await?.to_vec().as_slice())? + ); + } + return Err(anyhow!("Response error: {}", message)); + } Err(re) => { println!("{}", re); log::debug!("{:?}", re); diff --git a/payjoin/src/send/mod.rs b/payjoin/src/send/mod.rs index 175b3dce..36dc0136 100644 --- a/payjoin/src/send/mod.rs +++ b/payjoin/src/send/mod.rs @@ -32,7 +32,7 @@ use bitcoin::secp256k1::rand; #[cfg(feature = "v2")] use bitcoin::secp256k1::PublicKey; use bitcoin::{FeeRate, Script, ScriptBuf, Sequence, TxOut, Weight}; -pub use error::{CreateRequestError, ResponseError, ValidationError}; +pub use error::{CreateRequestError, ResponseError, ValidationError, WellKnownError}; pub(crate) use error::{InternalCreateRequestError, InternalValidationError}; #[cfg(feature = "v2")] use serde::{ @@ -557,6 +557,7 @@ impl ContextV2 { let mut body = match response.status() { http::StatusCode::OK => response.body().to_vec(), http::StatusCode::ACCEPTED => return Ok(None), + http::StatusCode::BAD_REQUEST => return Ok(None), // TODO return properl _ => return Err(InternalValidationError::UnexpectedStatusCode)?, }; let psbt = crate::v2::decrypt_message_b(&mut body, self.e)