mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 17:19:15 +08:00
feat: update surcharge_amount and tax_amount in update_trackers of payment_confirm (#2603)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit is contained in:
@ -311,7 +311,9 @@ pub struct PaymentsRequest {
|
||||
pub payment_type: Option<api_enums::PaymentType>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize, Copy, ToSchema)]
|
||||
#[derive(
|
||||
Default, Debug, Clone, serde::Serialize, serde::Deserialize, Copy, ToSchema, PartialEq,
|
||||
)]
|
||||
pub struct RequestSurchargeDetails {
|
||||
pub surcharge_amount: i64,
|
||||
pub tax_amount: Option<i64>,
|
||||
@ -2096,6 +2098,9 @@ pub struct PaymentsResponse {
|
||||
/// The business profile that is associated with this payment
|
||||
pub profile_id: Option<String>,
|
||||
|
||||
/// details of surcharge applied on this payment
|
||||
pub surcharge_details: Option<RequestSurchargeDetails>,
|
||||
|
||||
/// total number of attempts associated with this payment
|
||||
pub attempt_count: i16,
|
||||
|
||||
|
||||
@ -250,6 +250,8 @@ pub enum PaymentAttemptUpdate {
|
||||
error_code: Option<Option<String>>,
|
||||
error_message: Option<Option<String>>,
|
||||
amount_capturable: Option<i64>,
|
||||
surcharge_amount: Option<i64>,
|
||||
tax_amount: Option<i64>,
|
||||
updated_by: String,
|
||||
},
|
||||
RejectUpdate {
|
||||
@ -307,11 +309,6 @@ pub enum PaymentAttemptUpdate {
|
||||
multiple_capture_count: i16,
|
||||
updated_by: String,
|
||||
},
|
||||
SurchargeAmountUpdate {
|
||||
surcharge_amount: Option<i64>,
|
||||
tax_amount: Option<i64>,
|
||||
updated_by: String,
|
||||
},
|
||||
AmountToCaptureUpdate {
|
||||
status: storage_enums::AttemptStatus,
|
||||
amount_capturable: i64,
|
||||
|
||||
@ -166,6 +166,8 @@ pub enum PaymentAttemptUpdate {
|
||||
error_code: Option<Option<String>>,
|
||||
error_message: Option<Option<String>>,
|
||||
amount_capturable: Option<i64>,
|
||||
surcharge_amount: Option<i64>,
|
||||
tax_amount: Option<i64>,
|
||||
updated_by: String,
|
||||
},
|
||||
VoidUpdate {
|
||||
@ -228,11 +230,6 @@ pub enum PaymentAttemptUpdate {
|
||||
amount_capturable: i64,
|
||||
updated_by: String,
|
||||
},
|
||||
SurchargeAmountUpdate {
|
||||
surcharge_amount: Option<i64>,
|
||||
tax_amount: Option<i64>,
|
||||
updated_by: String,
|
||||
},
|
||||
PreprocessingUpdate {
|
||||
status: storage_enums::AttemptStatus,
|
||||
payment_method_id: Option<Option<String>>,
|
||||
@ -378,6 +375,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
||||
error_code,
|
||||
error_message,
|
||||
amount_capturable,
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
} => Self {
|
||||
amount: Some(amount),
|
||||
@ -397,6 +396,8 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
||||
error_code,
|
||||
error_message,
|
||||
amount_capturable,
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
..Default::default()
|
||||
},
|
||||
@ -561,16 +562,6 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
||||
updated_by,
|
||||
..Default::default()
|
||||
},
|
||||
PaymentAttemptUpdate::SurchargeAmountUpdate {
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
} => Self {
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
..Default::default()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,6 +216,10 @@ impl ConnectorValidation for Paypal {
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_if_surcharge_implemented(&self) -> CustomResult<(), errors::ConnectorError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
|
||||
@ -148,7 +148,11 @@ impl ConnectorCommon for Trustpay {
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectorValidation for Trustpay {}
|
||||
impl ConnectorValidation for Trustpay {
|
||||
fn validate_if_surcharge_implemented(&self) -> CustomResult<(), errors::ConnectorError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl api::Payment for Trustpay {}
|
||||
|
||||
|
||||
@ -73,6 +73,12 @@ impl Feature<api::Authorize, types::PaymentsAuthorizeData> for types::PaymentsAu
|
||||
.connector
|
||||
.validate_capture_method(self.request.capture_method)
|
||||
.to_payment_failed_response()?;
|
||||
if self.request.surcharge_details.is_some() {
|
||||
connector
|
||||
.connector
|
||||
.validate_if_surcharge_implemented()
|
||||
.to_payment_failed_response()?;
|
||||
}
|
||||
|
||||
if self.should_proceed_with_authorize() {
|
||||
self.decide_authentication_type();
|
||||
|
||||
@ -82,7 +82,10 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
|
||||
helpers::validate_status_with_capture_method(payment_intent.status, capture_method)?;
|
||||
|
||||
helpers::validate_amount_to_capture(payment_intent.amount, request.amount_to_capture)?;
|
||||
helpers::validate_amount_to_capture(
|
||||
payment_attempt.amount_capturable,
|
||||
request.amount_to_capture,
|
||||
)?;
|
||||
|
||||
helpers::validate_capture_method(capture_method)?;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use api_models::enums::FrmSuggestion;
|
||||
use api_models::{enums::FrmSuggestion, payment_methods};
|
||||
use async_trait::async_trait;
|
||||
use common_utils::ext_traits::{AsyncExt, Encode};
|
||||
use error_stack::ResultExt;
|
||||
@ -335,6 +335,19 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
sm
|
||||
});
|
||||
|
||||
// populate payment_data.surcharge_details from request
|
||||
let surcharge_details = request.surcharge_details.map(|surcharge_details| {
|
||||
payment_methods::SurchargeDetailsResponse {
|
||||
surcharge: payment_methods::Surcharge::Fixed(surcharge_details.surcharge_amount),
|
||||
tax_on_surcharge: None,
|
||||
surcharge_amount: surcharge_details.surcharge_amount,
|
||||
tax_on_surcharge_amount: surcharge_details.tax_amount.unwrap_or(0),
|
||||
final_amount: payment_attempt.amount
|
||||
+ surcharge_details.surcharge_amount
|
||||
+ surcharge_details.tax_amount.unwrap_or(0),
|
||||
}
|
||||
});
|
||||
|
||||
Ok((
|
||||
Box::new(self),
|
||||
PaymentData {
|
||||
@ -368,7 +381,7 @@ impl<F: Send + Clone, Ctx: PaymentMethodRetrieve>
|
||||
ephemeral_key: None,
|
||||
multiple_capture_data: None,
|
||||
redirect_response: None,
|
||||
surcharge_details: None,
|
||||
surcharge_details,
|
||||
frm_message: None,
|
||||
payment_link_data: None,
|
||||
},
|
||||
@ -543,7 +556,19 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
|
||||
.take();
|
||||
let order_details = payment_data.payment_intent.order_details.clone();
|
||||
let metadata = payment_data.payment_intent.metadata.clone();
|
||||
let authorized_amount = payment_data.payment_attempt.amount;
|
||||
let surcharge_amount = payment_data
|
||||
.surcharge_details
|
||||
.as_ref()
|
||||
.map(|surcharge_details| surcharge_details.surcharge_amount);
|
||||
let tax_amount = payment_data
|
||||
.surcharge_details
|
||||
.as_ref()
|
||||
.map(|surcharge_details| surcharge_details.tax_on_surcharge_amount);
|
||||
let authorized_amount = payment_data
|
||||
.surcharge_details
|
||||
.as_ref()
|
||||
.map(|surcharge_details| surcharge_details.final_amount)
|
||||
.unwrap_or(payment_data.payment_attempt.amount);
|
||||
let payment_attempt_fut = db
|
||||
.update_payment_attempt_with_attempt_id(
|
||||
payment_data.payment_attempt,
|
||||
@ -564,6 +589,8 @@ impl<F: Clone, Ctx: PaymentMethodRetrieve>
|
||||
error_code,
|
||||
error_message,
|
||||
amount_capturable: Some(authorized_amount),
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by: storage_scheme.to_string(),
|
||||
},
|
||||
storage_scheme,
|
||||
|
||||
@ -559,7 +559,7 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
|
||||
|
||||
payment_attempt_update = Some(storage::PaymentAttemptUpdate::AmountToCaptureUpdate {
|
||||
status: multiple_capture_data.get_attempt_status(authorized_amount),
|
||||
amount_capturable: payment_data.payment_attempt.amount
|
||||
amount_capturable: authorized_amount
|
||||
- multiple_capture_data.get_total_blocked_amount(),
|
||||
updated_by: storage_scheme.to_string(),
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::{fmt::Debug, marker::PhantomData, str::FromStr};
|
||||
|
||||
use api_models::payments::FrmMessage;
|
||||
use api_models::payments::{FrmMessage, RequestSurchargeDetails};
|
||||
use common_utils::{consts::X_HS_LATENCY, fp_utils};
|
||||
use diesel_models::ephemeral_key;
|
||||
use error_stack::{IntoReport, ResultExt};
|
||||
@ -424,7 +424,13 @@ where
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||
field_name: "payment_method_data",
|
||||
})?;
|
||||
|
||||
let surcharge_details =
|
||||
payment_attempt
|
||||
.surcharge_amount
|
||||
.map(|surcharge_amount| RequestSurchargeDetails {
|
||||
surcharge_amount,
|
||||
tax_amount: payment_attempt.tax_amount,
|
||||
});
|
||||
let merchant_decision = payment_intent.merchant_decision.to_owned();
|
||||
let frm_message = payment_data.frm_message.map(FrmMessage::foreign_from);
|
||||
|
||||
@ -557,6 +563,7 @@ where
|
||||
.set_amount(payment_attempt.amount)
|
||||
.set_amount_capturable(Some(payment_attempt.amount_capturable))
|
||||
.set_amount_received(payment_intent.amount_captured)
|
||||
.set_surcharge_details(surcharge_details)
|
||||
.set_connector(routed_through)
|
||||
.set_client_secret(payment_intent.client_secret.map(masking::Secret::new))
|
||||
.set_created(Some(payment_intent.created_at))
|
||||
@ -743,6 +750,7 @@ where
|
||||
reference_id: payment_attempt.connector_response_reference_id,
|
||||
attempt_count: payment_intent.attempt_count,
|
||||
payment_link: payment_link_data,
|
||||
surcharge_details,
|
||||
..Default::default()
|
||||
},
|
||||
headers,
|
||||
|
||||
@ -96,6 +96,14 @@ pub trait ConnectorValidation: ConnectorCommon {
|
||||
fn is_webhook_source_verification_mandatory(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn validate_if_surcharge_implemented(&self) -> CustomResult<(), errors::ConnectorError> {
|
||||
Err(errors::ConnectorError::NotImplemented(format!(
|
||||
"Surcharge not implemented for {}",
|
||||
self.id()
|
||||
))
|
||||
.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
|
||||
@ -1181,6 +1181,8 @@ impl DataModelExt for PaymentAttemptUpdate {
|
||||
error_code,
|
||||
error_message,
|
||||
amount_capturable,
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
} => DieselPaymentAttemptUpdate::ConfirmUpdate {
|
||||
amount,
|
||||
@ -1199,6 +1201,8 @@ impl DataModelExt for PaymentAttemptUpdate {
|
||||
error_code,
|
||||
error_message,
|
||||
amount_capturable,
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
},
|
||||
Self::VoidUpdate {
|
||||
@ -1333,15 +1337,6 @@ impl DataModelExt for PaymentAttemptUpdate {
|
||||
surcharge_metadata,
|
||||
updated_by,
|
||||
},
|
||||
Self::SurchargeAmountUpdate {
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
} => DieselPaymentAttemptUpdate::SurchargeAmountUpdate {
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -1413,6 +1408,8 @@ impl DataModelExt for PaymentAttemptUpdate {
|
||||
error_code,
|
||||
error_message,
|
||||
amount_capturable,
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
} => Self::ConfirmUpdate {
|
||||
amount,
|
||||
@ -1431,6 +1428,8 @@ impl DataModelExt for PaymentAttemptUpdate {
|
||||
error_code,
|
||||
error_message,
|
||||
amount_capturable,
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
},
|
||||
DieselPaymentAttemptUpdate::VoidUpdate {
|
||||
@ -1565,15 +1564,6 @@ impl DataModelExt for PaymentAttemptUpdate {
|
||||
surcharge_metadata,
|
||||
updated_by,
|
||||
},
|
||||
DieselPaymentAttemptUpdate::SurchargeAmountUpdate {
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
} => Self::SurchargeAmountUpdate {
|
||||
surcharge_amount,
|
||||
tax_amount,
|
||||
updated_by,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -9738,6 +9738,14 @@
|
||||
"description": "The business profile that is associated with this payment",
|
||||
"nullable": true
|
||||
},
|
||||
"surcharge_details": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/RequestSurchargeDetails"
|
||||
}
|
||||
],
|
||||
"nullable": true
|
||||
},
|
||||
"attempt_count": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
{
|
||||
"childrenOrder": [
|
||||
"Payments - Create",
|
||||
"Payments - Confirm",
|
||||
"Payments - Capture",
|
||||
"Payments - Retrieve"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"eventOrder": ["event.test.js"]
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
// Validate status 2xx
|
||||
pm.test("[POST]::/payments/:id/capture - Status code is 2xx", function () {
|
||||
pm.response.to.be.success;
|
||||
});
|
||||
|
||||
// Validate if response header has matching content-type
|
||||
pm.test(
|
||||
"[POST]::/payments/:id/capture - Content-Type is application/json",
|
||||
function () {
|
||||
pm.expect(pm.response.headers.get("Content-Type")).to.include(
|
||||
"application/json",
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// Validate if response has JSON Body
|
||||
pm.test("[POST]::/payments/:id/capture - Response has JSON Body", function () {
|
||||
pm.response.to.have.jsonBody();
|
||||
});
|
||||
|
||||
// Set response object as internal variable
|
||||
let jsonData = {};
|
||||
try {
|
||||
jsonData = pm.response.json();
|
||||
} catch (e) {}
|
||||
|
||||
// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
|
||||
if (jsonData?.payment_id) {
|
||||
pm.collectionVariables.set("payment_id", jsonData.payment_id);
|
||||
console.log(
|
||||
"- use {{payment_id}} as collection variable for value",
|
||||
jsonData.payment_id,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
|
||||
if (jsonData?.mandate_id) {
|
||||
pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
|
||||
console.log(
|
||||
"- use {{mandate_id}} as collection variable for value",
|
||||
jsonData.mandate_id,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
|
||||
if (jsonData?.client_secret) {
|
||||
pm.collectionVariables.set("client_secret", jsonData.client_secret);
|
||||
console.log(
|
||||
"- use {{client_secret}} as collection variable for value",
|
||||
jsonData.client_secret,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "processing" for "status"
|
||||
if (jsonData?.status) {
|
||||
pm.test(
|
||||
"[POST]:://payments/:id/capture - Content check if value for 'status' matches 'processing'",
|
||||
function () {
|
||||
pm.expect(jsonData.status).to.eql("processing");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Validate the connector
|
||||
pm.test("[POST]::/payments - connector", function () {
|
||||
pm.expect(jsonData.connector).to.eql("paypal");
|
||||
});
|
||||
|
||||
// Response body should have value "6540" for "amount"
|
||||
if (jsonData?.amount) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount).to.eql(6540);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "6000" for "amount_received"
|
||||
if (jsonData?.amount_received) {
|
||||
pm.test(
|
||||
"[POST]::/payments:id/capture - Content check if value for 'amount_received' matches '6000'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount_received).to.eql(6000);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "6540" for "amount_capturable"
|
||||
if (jsonData?.amount_capturable) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount_capturable' matches 0",
|
||||
function () {
|
||||
pm.expect(jsonData.amount_capturable).to.eql(0);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have a valid surcharge_details field"
|
||||
pm.test("Check if valid 'surcharge_details' is present in the response", function () {
|
||||
pm.response.to.have.jsonBody('surcharge_details');
|
||||
pm.expect(jsonData.surcharge_details.surcharge_amount).to.eql(5);
|
||||
pm.expect(jsonData.surcharge_details.tax_amount).to.eql(5);
|
||||
});
|
||||
@ -0,0 +1,39 @@
|
||||
{
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Accept",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
},
|
||||
"raw_json_formatted": {
|
||||
"amount_to_capture": 6000,
|
||||
"statement_descriptor_name": "Joseph",
|
||||
"statement_descriptor_suffix": "JS"
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/payments/:id/capture",
|
||||
"host": ["{{baseUrl}}"],
|
||||
"path": ["payments", ":id", "capture"],
|
||||
"variable": [
|
||||
{
|
||||
"key": "id",
|
||||
"value": "{{payment_id}}",
|
||||
"description": "(Required) unique payment id"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "To capture the funds for an uncaptured payment"
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"eventOrder": ["event.test.js"]
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
// Validate status 2xx
|
||||
pm.test("[POST]::/payments/:id/confirm - Status code is 2xx", function () {
|
||||
pm.response.to.be.success;
|
||||
});
|
||||
|
||||
// Validate if response header has matching content-type
|
||||
pm.test(
|
||||
"[POST]::/payments/:id/confirm - Content-Type is application/json",
|
||||
function () {
|
||||
pm.expect(pm.response.headers.get("Content-Type")).to.include(
|
||||
"application/json",
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// Validate if response has JSON Body
|
||||
pm.test("[POST]::/payments/:id/confirm - Response has JSON Body", function () {
|
||||
pm.response.to.have.jsonBody();
|
||||
});
|
||||
|
||||
// Set response object as internal variable
|
||||
let jsonData = {};
|
||||
try {
|
||||
jsonData = pm.response.json();
|
||||
} catch (e) {}
|
||||
|
||||
// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
|
||||
if (jsonData?.payment_id) {
|
||||
pm.collectionVariables.set("payment_id", jsonData.payment_id);
|
||||
console.log(
|
||||
"- use {{payment_id}} as collection variable for value",
|
||||
jsonData.payment_id,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
|
||||
if (jsonData?.mandate_id) {
|
||||
pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
|
||||
console.log(
|
||||
"- use {{mandate_id}} as collection variable for value",
|
||||
jsonData.mandate_id,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
|
||||
if (jsonData?.client_secret) {
|
||||
pm.collectionVariables.set("client_secret", jsonData.client_secret);
|
||||
console.log(
|
||||
"- use {{client_secret}} as collection variable for value",
|
||||
jsonData.client_secret,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// Validate the connector
|
||||
pm.test("[POST]::/payments - connector", function () {
|
||||
pm.expect(jsonData.connector).to.eql("paypal");
|
||||
});
|
||||
|
||||
// Response body should have value "requires_capture" for "status"
|
||||
if (jsonData?.status) {
|
||||
pm.test(
|
||||
"[POST]::/payments - Content check if value for 'status' matches 'requires_capture'",
|
||||
function () {
|
||||
pm.expect(jsonData.status).to.eql("requires_capture");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "6540" for "amount"
|
||||
if (jsonData?.amount) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount).to.eql(6540);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "null" for "amount_received"
|
||||
if (jsonData?.amount_received) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount_received' matches 'null'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount_received).to.eql(null);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "6540" for "amount_capturable"
|
||||
if (jsonData?.amount_capturable) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount_capturable' matches 'amount - 0'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount_capturable).to.eql(6550);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have a valid surcharge_details field"
|
||||
pm.test("Check if valid 'surcharge_details' is present in the response", function () {
|
||||
pm.response.to.have.jsonBody('surcharge_details');
|
||||
pm.expect(jsonData.surcharge_details.surcharge_amount).to.eql(5);
|
||||
pm.expect(jsonData.surcharge_details.tax_amount).to.eql(5);
|
||||
});
|
||||
@ -0,0 +1,60 @@
|
||||
{
|
||||
"auth": {
|
||||
"type": "apikey",
|
||||
"apikey": [
|
||||
{
|
||||
"key": "value",
|
||||
"value": "{{publishable_key}}",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "key",
|
||||
"value": "api-key",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "in",
|
||||
"value": "header",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Accept",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
},
|
||||
"raw_json_formatted": {
|
||||
"client_secret": "{{client_secret}}",
|
||||
"surcharge_details": {
|
||||
"surcharge_amount": 5,
|
||||
"tax_amount": 5
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/payments/:id/confirm",
|
||||
"host": ["{{baseUrl}}"],
|
||||
"path": ["payments", ":id", "confirm"],
|
||||
"variable": [
|
||||
{
|
||||
"key": "id",
|
||||
"value": "{{payment_id}}"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"eventOrder": ["event.test.js"]
|
||||
}
|
||||
@ -0,0 +1,101 @@
|
||||
// Validate status 2xx
|
||||
pm.test("[POST]::/payments - Status code is 2xx", function () {
|
||||
pm.response.to.be.success;
|
||||
});
|
||||
|
||||
// Validate if response header has matching content-type
|
||||
pm.test("[POST]::/payments - Content-Type is application/json", function () {
|
||||
pm.expect(pm.response.headers.get("Content-Type")).to.include(
|
||||
"application/json",
|
||||
);
|
||||
});
|
||||
|
||||
// Validate if response has JSON Body
|
||||
pm.test("[POST]::/payments - Response has JSON Body", function () {
|
||||
pm.response.to.have.jsonBody();
|
||||
});
|
||||
|
||||
// Set response object as internal variable
|
||||
let jsonData = {};
|
||||
try {
|
||||
jsonData = pm.response.json();
|
||||
} catch (e) {}
|
||||
|
||||
// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
|
||||
if (jsonData?.payment_id) {
|
||||
pm.collectionVariables.set("payment_id", jsonData.payment_id);
|
||||
console.log(
|
||||
"- use {{payment_id}} as collection variable for value",
|
||||
jsonData.payment_id,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
|
||||
if (jsonData?.mandate_id) {
|
||||
pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
|
||||
console.log(
|
||||
"- use {{mandate_id}} as collection variable for value",
|
||||
jsonData.mandate_id,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
|
||||
if (jsonData?.client_secret) {
|
||||
pm.collectionVariables.set("client_secret", jsonData.client_secret);
|
||||
console.log(
|
||||
"- use {{client_secret}} as collection variable for value",
|
||||
jsonData.client_secret,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "requires_confirmation" for "status"
|
||||
if (jsonData?.status) {
|
||||
pm.test(
|
||||
"[POST]::/payments - Content check if value for 'status' matches 'requires_capture'",
|
||||
function () {
|
||||
pm.expect(jsonData.status).to.eql("requires_confirmation");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "6540" for "amount"
|
||||
if (jsonData?.amount) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount).to.eql(6540);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "null" for "amount_received"
|
||||
if (jsonData?.amount_received) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount_received' matches 'null'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount_received).to.eql(null);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "6540" for "amount_capturable"
|
||||
if (jsonData?.amount_capturable) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount_capturable' matches 'amount - 6540'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount_capturable).to.eql(6540);
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
{
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Accept",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
},
|
||||
"raw_json_formatted": {
|
||||
"amount": 6540,
|
||||
"currency": "USD",
|
||||
"confirm": false,
|
||||
"capture_method": "manual",
|
||||
"capture_on": "2022-09-10T10:11:12Z",
|
||||
"customer_id": "StripeCustomer",
|
||||
"email": "guest@example.com",
|
||||
"name": "John Doe",
|
||||
"phone": "999999999",
|
||||
"phone_country_code": "+1",
|
||||
"description": "Its my first payment request",
|
||||
"authentication_type": "no_three_ds",
|
||||
"return_url": "https://duck.com",
|
||||
"payment_method": "card",
|
||||
"payment_method_data": {
|
||||
"card": {
|
||||
"card_number": "4005519200000004",
|
||||
"card_exp_month": "10",
|
||||
"card_exp_year": "25",
|
||||
"card_holder_name": "joseph Doe",
|
||||
"card_cvc": "123"
|
||||
}
|
||||
},
|
||||
"billing": {
|
||||
"address": {
|
||||
"line1": "1467",
|
||||
"line2": "Harrison Street",
|
||||
"line3": "Harrison Street",
|
||||
"city": "San Fransico",
|
||||
"state": "California",
|
||||
"zip": "94122",
|
||||
"country": "US",
|
||||
"first_name": "PiX"
|
||||
}
|
||||
},
|
||||
"shipping": {
|
||||
"address": {
|
||||
"line1": "1467",
|
||||
"line2": "Harrison Street",
|
||||
"line3": "Harrison Street",
|
||||
"city": "San Fransico",
|
||||
"state": "California",
|
||||
"zip": "94122",
|
||||
"country": "US",
|
||||
"first_name": "PiX"
|
||||
}
|
||||
},
|
||||
"statement_descriptor_name": "joseph",
|
||||
"statement_descriptor_suffix": "JS",
|
||||
"metadata": {
|
||||
"udf1": "value1",
|
||||
"new_customer": "true",
|
||||
"login_date": "2019-09-10T10:11:12Z"
|
||||
},
|
||||
"routing": {
|
||||
"type": "single",
|
||||
"data": "paypal"
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/payments",
|
||||
"host": ["{{baseUrl}}"],
|
||||
"path": ["payments"]
|
||||
},
|
||||
"description": "To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture"
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"eventOrder": ["event.test.js"]
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
// Validate status 2xx
|
||||
pm.test("[GET]::/payments/:id - Status code is 2xx", function () {
|
||||
pm.response.to.be.success;
|
||||
});
|
||||
|
||||
// Validate if response header has matching content-type
|
||||
pm.test("[GET]::/payments/:id - Content-Type is application/json", function () {
|
||||
pm.expect(pm.response.headers.get("Content-Type")).to.include(
|
||||
"application/json",
|
||||
);
|
||||
});
|
||||
|
||||
// Validate if response has JSON Body
|
||||
pm.test("[GET]::/payments/:id - Response has JSON Body", function () {
|
||||
pm.response.to.have.jsonBody();
|
||||
});
|
||||
|
||||
// Set response object as internal variable
|
||||
let jsonData = {};
|
||||
try {
|
||||
jsonData = pm.response.json();
|
||||
} catch (e) {}
|
||||
|
||||
// pm.collectionVariables - Set payment_id as variable for jsonData.payment_id
|
||||
if (jsonData?.payment_id) {
|
||||
pm.collectionVariables.set("payment_id", jsonData.payment_id);
|
||||
console.log(
|
||||
"- use {{payment_id}} as collection variable for value",
|
||||
jsonData.payment_id,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{payment_id}}, as jsonData.payment_id is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// pm.collectionVariables - Set mandate_id as variable for jsonData.mandate_id
|
||||
if (jsonData?.mandate_id) {
|
||||
pm.collectionVariables.set("mandate_id", jsonData.mandate_id);
|
||||
console.log(
|
||||
"- use {{mandate_id}} as collection variable for value",
|
||||
jsonData.mandate_id,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{mandate_id}}, as jsonData.mandate_id is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// pm.collectionVariables - Set client_secret as variable for jsonData.client_secret
|
||||
if (jsonData?.client_secret) {
|
||||
pm.collectionVariables.set("client_secret", jsonData.client_secret);
|
||||
console.log(
|
||||
"- use {{client_secret}} as collection variable for value",
|
||||
jsonData.client_secret,
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
"INFO - Unable to assign variable {{client_secret}}, as jsonData.client_secret is undefined.",
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "processing" for "status"
|
||||
if (jsonData?.status) {
|
||||
pm.test(
|
||||
"[POST]::/payments - Content check if value for 'status' matches 'processing'",
|
||||
function () {
|
||||
pm.expect(jsonData.status).to.eql("processing");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Validate the connector
|
||||
pm.test("[POST]::/payments - connector", function () {
|
||||
pm.expect(jsonData.connector).to.eql("paypal");
|
||||
});
|
||||
|
||||
// Response body should have value "6540" for "amount"
|
||||
if (jsonData?.amount) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount' matches '6540'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount).to.eql(6540);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "6000" for "amount_received"
|
||||
if (jsonData?.amount_received) {
|
||||
pm.test(
|
||||
"[POST]::/payments:id/capture - Content check if value for 'amount_received' matches '6000'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount_received).to.eql(6000);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have value "6540" for "amount_capturable"
|
||||
if (jsonData?.amount_capturable) {
|
||||
pm.test(
|
||||
"[post]:://payments/:id/capture - Content check if value for 'amount_capturable' matches 'amount - 540'",
|
||||
function () {
|
||||
pm.expect(jsonData.amount_capturable).to.eql(540);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Response body should have a valid surcharge_details field"
|
||||
pm.test("Check if valid 'surcharge_details' is present in the response", function () {
|
||||
pm.response.to.have.jsonBody('surcharge_details');
|
||||
pm.expect(jsonData.surcharge_details.surcharge_amount).to.eql(5);
|
||||
pm.expect(jsonData.surcharge_details.tax_amount).to.eql(5);
|
||||
});
|
||||
@ -0,0 +1,28 @@
|
||||
{
|
||||
"method": "GET",
|
||||
"header": [
|
||||
{
|
||||
"key": "Accept",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/payments/:id?force_sync=true",
|
||||
"host": ["{{baseUrl}}"],
|
||||
"path": ["payments", ":id"],
|
||||
"query": [
|
||||
{
|
||||
"key": "force_sync",
|
||||
"value": "true"
|
||||
}
|
||||
],
|
||||
"variable": [
|
||||
{
|
||||
"key": "id",
|
||||
"value": "{{payment_id}}",
|
||||
"description": "(Required) unique payment id"
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment"
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
[]
|
||||
@ -79,6 +79,10 @@
|
||||
"metadata": {
|
||||
"city": "NY",
|
||||
"unit": "245"
|
||||
},
|
||||
"routing_algorithm": {
|
||||
"type": "single",
|
||||
"data": "paypal"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user