From 500405d78938772e0e9f8e3ce4f930d782c670fa Mon Sep 17 00:00:00 2001 From: Prasunna Soppa <70575890+prasunna09@users.noreply.github.com> Date: Fri, 13 Oct 2023 19:14:55 +0530 Subject: [PATCH] feat(connector): [Paypal] use connector request reference id as reference for paypal (#2577) --- crates/router/src/connector/paypal.rs | 2 +- .../src/connector/paypal/transformers.rs | 85 ++++++++++++++----- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/crates/router/src/connector/paypal.rs b/crates/router/src/connector/paypal.rs index 1f872868a00..fd104ac4aa5 100644 --- a/crates/router/src/connector/paypal.rs +++ b/crates/router/src/connector/paypal.rs @@ -1091,7 +1091,7 @@ impl api::IncomingWebhook for Paypal { resource .purchase_units .first() - .map(|unit| unit.reference_id.clone()) + .and_then(|unit| unit.invoice_id.clone().or(unit.reference_id.clone())) .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?, ), )) diff --git a/crates/router/src/connector/paypal/transformers.rs b/crates/router/src/connector/paypal/transformers.rs index 78bd75efe14..72dccaed733 100644 --- a/crates/router/src/connector/paypal/transformers.rs +++ b/crates/router/src/connector/paypal/transformers.rs @@ -73,7 +73,9 @@ pub struct OrderAmount { #[derive(Default, Debug, Serialize, Eq, PartialEq)] pub struct PurchaseUnitRequest { - reference_id: String, + reference_id: Option, //reference for an item in purchase_units + invoice_id: Option, //The API caller-provided external invoice number for this order. Appears in both the payer's transaction history and the emails that the payer receives. + custom_id: Option, //Used to reconcile client transactions with PayPal transactions. amount: OrderAmount, } @@ -260,10 +262,13 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP currency_code: item.router_data.request.currency, value: item.amount.to_owned(), }; - let reference_id = item.router_data.attempt_id.clone(); + let connector_request_reference_id = + item.router_data.connector_request_reference_id.clone(); let purchase_units = vec![PurchaseUnitRequest { - reference_id, + reference_id: Some(connector_request_reference_id.clone()), + custom_id: Some(connector_request_reference_id.clone()), + invoice_id: Some(connector_request_reference_id), amount, }]; let card = item.router_data.request.get_card()?; @@ -304,9 +309,14 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP currency_code: item.router_data.request.currency, value: item.amount.to_owned(), }; - let reference_id = item.router_data.attempt_id.clone(); + + let connector_req_reference_id = + item.router_data.connector_request_reference_id.clone(); + let purchase_units = vec![PurchaseUnitRequest { - reference_id, + reference_id: Some(connector_req_reference_id.clone()), + custom_id: Some(connector_req_reference_id.clone()), + invoice_id: Some(connector_req_reference_id), amount, }]; let payment_source = @@ -367,9 +377,13 @@ impl TryFrom<&PaypalRouterData<&types::PaymentsAuthorizeRouterData>> for PaypalP currency_code: item.router_data.request.currency, value: item.amount.to_owned(), }; - let reference_id = item.router_data.attempt_id.clone(); + let connector_req_reference_id = + item.router_data.connector_request_reference_id.clone(); + let purchase_units = vec![PurchaseUnitRequest { - reference_id, + reference_id: Some(connector_req_reference_id.clone()), + custom_id: Some(connector_req_reference_id.clone()), + invoice_id: Some(connector_req_reference_id), amount, }]; let payment_source = @@ -655,7 +669,8 @@ pub struct PaymentsCollection { #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct PurchaseUnitItem { - pub reference_id: String, + pub reference_id: Option, + pub invoice_id: Option, pub payments: PaymentsCollection, } @@ -680,11 +695,17 @@ pub struct PaypalLinks { rel: String, } +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct RedirectPurchaseUnitItem { + pub invoice_id: String, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PaypalRedirectResponse { id: String, intent: PaypalPaymentIntent, status: PaypalOrderStatus, + purchase_units: Vec, links: Vec, } @@ -712,6 +733,7 @@ pub struct PaypalPaymentsSyncResponse { id: String, status: PaypalPaymentStatus, amount: OrderAmount, + invoice_id: Option, supplementary_data: PaypalSupplementaryData, } @@ -792,7 +814,7 @@ impl capture_id: Some(id), psync_flow: item.response.intent.clone() }), - types::ResponseId::ConnectorTransactionId(item.response.id), + types::ResponseId::ConnectorTransactionId(item.response.id.clone()), ), PaypalPaymentIntent::Authorize => ( @@ -801,7 +823,7 @@ impl capture_id: None, psync_flow: item.response.intent.clone() }), - types::ResponseId::ConnectorTransactionId(item.response.id), + types::ResponseId::ConnectorTransactionId(item.response.id.clone()), ), PaypalPaymentIntent::Authenticate => { @@ -836,7 +858,10 @@ impl mandate_reference: None, connector_metadata: Some(connector_meta), network_txn_id: None, - connector_response_reference_id: None, + connector_response_reference_id: purchase_units + .invoice_id + .clone() + .or(Some(item.response.id)), }), ..item.data }) @@ -925,11 +950,12 @@ impl capture_id: None, psync_flow: item.response.intent }); + let purchase_units = item.response.purchase_units.first(); Ok(Self { status, response: Ok(types::PaymentsResponseData::TransactionResponse { - resource_id: types::ResponseId::ConnectorTransactionId(item.response.id), + resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()), redirection_data: Some(services::RedirectForm::from(( link.ok_or(errors::ConnectorError::ResponseDeserializationFailed)?, services::Method::Get, @@ -937,7 +963,9 @@ impl mandate_reference: None, connector_metadata: Some(connector_meta), network_txn_id: None, - connector_response_reference_id: None, + connector_response_reference_id: Some( + purchase_units.map_or(item.response.id, |item| item.invoice_id.clone()), + ), }), ..item.data }) @@ -1075,13 +1103,21 @@ impl status: storage_enums::AttemptStatus::from(item.response.status), response: Ok(types::PaymentsResponseData::TransactionResponse { resource_id: types::ResponseId::ConnectorTransactionId( - item.response.supplementary_data.related_ids.order_id, + item.response + .supplementary_data + .related_ids + .order_id + .clone(), ), redirection_data: None, mandate_reference: None, connector_metadata: None, network_txn_id: None, - connector_response_reference_id: None, + connector_response_reference_id: item + .response + .invoice_id + .clone() + .or(Some(item.response.supplementary_data.related_ids.order_id)), }), ..item.data }) @@ -1133,6 +1169,7 @@ pub struct PaypalCaptureResponse { id: String, status: PaypalPaymentStatus, amount: Option, + invoice_id: Option, final_capture: bool, } @@ -1174,11 +1211,14 @@ impl TryFrom> mandate_reference: None, connector_metadata: Some(serde_json::json!(PaypalMeta { authorize_id: connector_payment_id.authorize_id, - capture_id: Some(item.response.id), + capture_id: Some(item.response.id.clone()), psync_flow: PaypalPaymentIntent::Capture })), network_txn_id: None, - connector_response_reference_id: None, + connector_response_reference_id: item + .response + .invoice_id + .or(Some(item.response.id)), }), amount_captured: Some(amount_captured), ..item.data @@ -1193,11 +1233,11 @@ pub enum PaypalCancelStatus { } #[derive(Debug, Serialize, Deserialize, PartialEq)] -#[serde(rename_all = "camelCase")] pub struct PaypalPaymentsCancelResponse { id: String, status: PaypalCancelStatus, amount: Option, + invoice_id: Option, } impl @@ -1220,12 +1260,15 @@ impl Ok(Self { status, response: Ok(types::PaymentsResponseData::TransactionResponse { - resource_id: types::ResponseId::ConnectorTransactionId(item.response.id), + resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()), redirection_data: None, mandate_reference: None, connector_metadata: None, network_txn_id: None, - connector_response_reference_id: None, + connector_response_reference_id: item + .response + .invoice_id + .or(Some(item.response.id)), }), ..item.data }) @@ -1408,6 +1451,7 @@ pub struct PaypalSellerPayableBreakdown { pub struct PaypalCardWebhooks { pub supplementary_data: PaypalSupplementaryData, pub amount: OrderAmount, + pub invoice_id: Option, } #[derive(Deserialize, Debug, Serialize)] @@ -1528,6 +1572,7 @@ impl TryFrom<(PaypalCardWebhooks, PaypalWebhookEventType)> for PaypalPaymentsSyn status: PaypalPaymentStatus::try_from(webhook_event)?, amount: webhook_body.amount, supplementary_data: webhook_body.supplementary_data, + invoice_id: webhook_body.invoice_id, }) } }