mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
refactor(connector): airwallex convert init payment to preprocessing (#4842)
This commit is contained in:
@ -249,6 +249,9 @@ impl Connector {
|
||||
Self::Checkout | Self::Nmi| Self::Cybersource => true,
|
||||
}
|
||||
}
|
||||
pub fn is_pre_processing_required_before_authorize(&self) -> bool {
|
||||
matches!(self, Self::Airwallex)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(
|
||||
|
||||
@ -18,7 +18,7 @@ use crate::{
|
||||
payments,
|
||||
},
|
||||
events::connector_api_logs::ConnectorEvent,
|
||||
headers, logger, routes,
|
||||
headers, logger,
|
||||
services::{
|
||||
self,
|
||||
request::{self, Mask},
|
||||
@ -27,7 +27,6 @@ use crate::{
|
||||
types::{
|
||||
self,
|
||||
api::{self, ConnectorCommon, ConnectorCommonExt},
|
||||
transformers::ForeignFrom,
|
||||
ErrorResponse, Response, RouterData,
|
||||
},
|
||||
utils::{crypto, BytesExt},
|
||||
@ -123,6 +122,7 @@ impl ConnectorValidation for Airwallex {
|
||||
}
|
||||
|
||||
impl api::Payment for Airwallex {}
|
||||
impl api::PaymentsPreProcessing for Airwallex {}
|
||||
impl api::PaymentsCompleteAuthorize for Airwallex {}
|
||||
impl api::MandateSetup for Airwallex {}
|
||||
impl
|
||||
@ -242,14 +242,14 @@ impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, t
|
||||
|
||||
impl
|
||||
ConnectorIntegration<
|
||||
api::InitPayment,
|
||||
types::PaymentsAuthorizeData,
|
||||
api::PreProcessing,
|
||||
types::PaymentsPreProcessingData,
|
||||
types::PaymentsResponseData,
|
||||
> for Airwallex
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsInitRouterData,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
@ -261,7 +261,7 @@ impl
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
_req: &types::PaymentsInitRouterData,
|
||||
_req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!(
|
||||
@ -273,7 +273,7 @@ impl
|
||||
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::PaymentsInitRouterData,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||
let req_obj = airwallex::AirwallexIntentRequest::try_from(req)?;
|
||||
@ -282,16 +282,20 @@ impl
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsInitRouterData,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsInitType::get_url(self, req, connectors)?)
|
||||
.url(&types::PaymentsPreProcessingType::get_url(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.attach_default_headers()
|
||||
.headers(types::PaymentsInitType::get_headers(self, req, connectors)?)
|
||||
.set_body(types::PaymentsInitType::get_request_body(
|
||||
.headers(types::PaymentsPreProcessingType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.set_body(types::PaymentsPreProcessingType::get_request_body(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.build(),
|
||||
@ -300,10 +304,10 @@ impl
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsInitRouterData,
|
||||
data: &types::PaymentsPreProcessingRouterData,
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsInitRouterData, errors::ConnectorError> {
|
||||
) -> CustomResult<types::PaymentsPreProcessingRouterData, errors::ConnectorError> {
|
||||
let response: airwallex::AirwallexPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("airwallex AirwallexPaymentsResponse")
|
||||
@ -335,36 +339,6 @@ impl api::PaymentAuthorize for Airwallex {}
|
||||
impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
|
||||
for Airwallex
|
||||
{
|
||||
async fn execute_pretasks(
|
||||
&self,
|
||||
router_data: &mut types::PaymentsAuthorizeRouterData,
|
||||
app_state: &routes::AppState,
|
||||
) -> CustomResult<(), errors::ConnectorError> {
|
||||
let integ: Box<
|
||||
&(dyn ConnectorIntegration<
|
||||
api::InitPayment,
|
||||
types::PaymentsAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
> + Send
|
||||
+ Sync
|
||||
+ 'static),
|
||||
> = Box::new(&Self);
|
||||
let authorize_data = &types::PaymentsInitRouterData::foreign_from((
|
||||
&router_data.to_owned(),
|
||||
router_data.request.clone(),
|
||||
));
|
||||
let resp = services::execute_connector_processing_step(
|
||||
app_state,
|
||||
integ,
|
||||
authorize_data,
|
||||
payments::CallConnectorAction::Trigger,
|
||||
None,
|
||||
)
|
||||
.await?;
|
||||
router_data.reference_id = resp.reference_id;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsAuthorizeRouterData,
|
||||
|
||||
@ -41,13 +41,26 @@ pub struct AirwallexIntentRequest {
|
||||
//ID created in merchant's order system that corresponds to this PaymentIntent.
|
||||
merchant_order_id: String,
|
||||
}
|
||||
impl TryFrom<&types::PaymentsInitRouterData> for AirwallexIntentRequest {
|
||||
impl TryFrom<&types::PaymentsPreProcessingRouterData> for AirwallexIntentRequest {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(item: &types::PaymentsInitRouterData) -> Result<Self, Self::Error> {
|
||||
fn try_from(item: &types::PaymentsPreProcessingRouterData) -> Result<Self, Self::Error> {
|
||||
// amount and currency will always be Some since PaymentsPreProcessingData is constructed using PaymentsAuthorizeData
|
||||
let amount = item
|
||||
.request
|
||||
.amount
|
||||
.ok_or(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "amount",
|
||||
})?;
|
||||
let currency =
|
||||
item.request
|
||||
.currency
|
||||
.ok_or(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "currency",
|
||||
})?;
|
||||
Ok(Self {
|
||||
request_id: Uuid::new_v4().to_string(),
|
||||
amount: utils::to_currency_base_unit(item.request.amount, item.request.currency)?,
|
||||
currency: item.request.currency,
|
||||
amount: utils::to_currency_base_unit(amount, currency)?,
|
||||
currency,
|
||||
merchant_order_id: item.connector_request_reference_id.clone(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -1885,6 +1885,14 @@ where
|
||||
dyn api::Connector:
|
||||
services::api::ConnectorIntegration<F, Req, router_types::PaymentsResponseData>,
|
||||
{
|
||||
if !is_operation_complete_authorize(&operation)
|
||||
&& connector
|
||||
.connector_name
|
||||
.is_pre_processing_required_before_authorize()
|
||||
{
|
||||
router_data = router_data.preprocessing_steps(state, connector).await?;
|
||||
return Ok((router_data, should_continue_payment));
|
||||
}
|
||||
//TODO: For ACH transfers, if preprocessing_step is not required for connectors encountered in future, add the check
|
||||
let router_data_and_should_continue_payment = match payment_data.payment_method_data.clone() {
|
||||
Some(api_models::payments::PaymentMethodData::BankTransfer(data)) => match data.deref() {
|
||||
|
||||
@ -928,7 +928,6 @@ impl<const T: u8>
|
||||
|
||||
default_imp_for_pre_processing_steps!(
|
||||
connector::Aci,
|
||||
connector::Airwallex,
|
||||
connector::Authorizedotnet,
|
||||
connector::Bambora,
|
||||
connector::Billwerk,
|
||||
|
||||
@ -322,13 +322,14 @@ pub async fn authorize_preprocessing_steps<F: Clone>(
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
let authorize_router_data = helpers::router_data_type_conversion::<_, F, _, _, _, _>(
|
||||
let mut authorize_router_data = helpers::router_data_type_conversion::<_, F, _, _, _, _>(
|
||||
resp.clone(),
|
||||
router_data.request.to_owned(),
|
||||
resp.response,
|
||||
);
|
||||
|
||||
if connector.connector_name == api_models::enums::Connector::Airwallex {
|
||||
authorize_router_data.reference_id = resp.reference_id;
|
||||
}
|
||||
Ok(authorize_router_data)
|
||||
} else {
|
||||
Ok(router_data.clone())
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
{
|
||||
"childrenOrder": [
|
||||
"Payments - Create",
|
||||
"Payments - Capture",
|
||||
"Payments - Retrieve"
|
||||
]
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
{
|
||||
"eventOrder": ["event.test.js"]
|
||||
}
|
||||
@ -0,0 +1,94 @@
|
||||
// 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 "succeeded" for "status"
|
||||
if (jsonData?.status) {
|
||||
pm.test(
|
||||
"[POST]:://payments/:id/capture - Content check if value for 'status' matches 'partially_captured'",
|
||||
function () {
|
||||
pm.expect(jsonData.status).to.eql("partially_captured");
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// 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);
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -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,71 @@
|
||||
// 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_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");
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,84 @@
|
||||
{
|
||||
"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": true,
|
||||
"capture_method": "manual",
|
||||
"capture_on": "2022-09-10T10:11:12Z",
|
||||
"amount_to_capture": 6540,
|
||||
"customer_id": "AirwallexCustomer",
|
||||
"email": "guest@example.com",
|
||||
"name": "John Doe",
|
||||
"phone": "999999999",
|
||||
"phone_country_code": "+65",
|
||||
"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": "4035501000000008",
|
||||
"card_exp_month": "10",
|
||||
"card_exp_year": "2025",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
},
|
||||
"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,71 @@
|
||||
// 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 "succeeded" for "status"
|
||||
if (jsonData?.status) {
|
||||
pm.test(
|
||||
"[POST]::/payments - Content check if value for 'status' matches 'partially_captured'",
|
||||
function () {
|
||||
pm.expect(jsonData.status).to.eql("partially_captured");
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -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 @@
|
||||
[]
|
||||
@ -88,7 +88,7 @@ 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);
|
||||
pm.expect(jsonData.amount_received).to.eql(6540);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
}
|
||||
},
|
||||
"raw_json_formatted": {
|
||||
"amount_to_capture": 6000,
|
||||
"amount_to_capture": 6540,
|
||||
"statement_descriptor_name": "Joseph",
|
||||
"statement_descriptor_suffix": "JS"
|
||||
}
|
||||
|
||||
@ -806,6 +806,398 @@
|
||||
{
|
||||
"name": "Happy Cases",
|
||||
"item": [
|
||||
{
|
||||
"name": "Scenario11-Create payment with Manual Partial capture",
|
||||
"item": [
|
||||
{
|
||||
"name": "Payments - Create",
|
||||
"event": [
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"exec": [
|
||||
"// 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_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\");",
|
||||
" },",
|
||||
" );",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"type": "text/javascript"
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Accept",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
},
|
||||
"raw": "{\"amount\":6540,\"currency\":\"USD\",\"confirm\":true,\"capture_method\":\"manual\",\"capture_on\":\"2022-09-10T10:11:12Z\",\"amount_to_capture\":6540,\"customer_id\":\"AirwallexCustomer\",\"email\":\"guest@example.com\",\"name\":\"John Doe\",\"phone\":\"999999999\",\"phone_country_code\":\"+65\",\"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\":\"4035501000000008\",\"card_exp_month\":\"10\",\"card_exp_year\":\"2025\",\"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\"}}"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Payments - Capture",
|
||||
"event": [
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"exec": [
|
||||
"// 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 \"succeeded\" for \"status\"",
|
||||
"if (jsonData?.status) {",
|
||||
" pm.test(",
|
||||
" \"[POST]:://payments/:id/capture - Content check if value for 'status' matches 'partially_captured'\",",
|
||||
" function () {",
|
||||
" pm.expect(jsonData.status).to.eql(\"partially_captured\");",
|
||||
" },",
|
||||
" );",
|
||||
"}",
|
||||
"",
|
||||
"// 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);",
|
||||
" },",
|
||||
" );",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"type": "text/javascript"
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
},
|
||||
{
|
||||
"key": "Accept",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"options": {
|
||||
"raw": {
|
||||
"language": "json"
|
||||
}
|
||||
},
|
||||
"raw": "{\"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"
|
||||
},
|
||||
"response": []
|
||||
},
|
||||
{
|
||||
"name": "Payments - Retrieve",
|
||||
"event": [
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"exec": [
|
||||
"// 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 \"succeeded\" for \"status\"",
|
||||
"if (jsonData?.status) {",
|
||||
" pm.test(",
|
||||
" \"[POST]::/payments - Content check if value for 'status' matches 'partially_captured'\",",
|
||||
" function () {",
|
||||
" pm.expect(jsonData.status).to.eql(\"partially_captured\");",
|
||||
" },",
|
||||
" );",
|
||||
"}",
|
||||
""
|
||||
],
|
||||
"type": "text/javascript"
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"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"
|
||||
},
|
||||
"response": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Scenario1-Create payment with confirm true",
|
||||
"item": [
|
||||
@ -2050,7 +2442,7 @@
|
||||
" pm.test(",
|
||||
" \"[POST]::/payments:id/capture - Content check if value for 'amount_received' matches '6000'\",",
|
||||
" function () {",
|
||||
" pm.expect(jsonData.amount_received).to.eql(6000);",
|
||||
" pm.expect(jsonData.amount_received).to.eql(6540);",
|
||||
" },",
|
||||
" );",
|
||||
"}",
|
||||
@ -2079,7 +2471,7 @@
|
||||
"language": "json"
|
||||
}
|
||||
},
|
||||
"raw": "{\"amount_to_capture\":6000,\"statement_descriptor_name\":\"Joseph\",\"statement_descriptor_suffix\":\"JS\"}"
|
||||
"raw": "{\"amount_to_capture\":6540,\"statement_descriptor_name\":\"Joseph\",\"statement_descriptor_suffix\":\"JS\"}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/payments/:id/capture",
|
||||
|
||||
Reference in New Issue
Block a user