mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-01 11:06:50 +08:00
feat(core): accept gateway credentials in the request body in payments and refunds (#766)
This commit is contained in:
@ -9,6 +9,7 @@ impl PaymentIntents {
|
||||
pub fn server(state: routes::AppState) -> Scope {
|
||||
web::scope("/payment_intents")
|
||||
.app_data(web::Data::new(state))
|
||||
.service(payment_intents_retrieve_with_gateway_creds)
|
||||
.service(payment_intents_create)
|
||||
.service(payment_intents_retrieve)
|
||||
.service(payment_intents_update)
|
||||
|
||||
@ -75,6 +75,7 @@ pub async fn payment_intents_retrieve(
|
||||
force_sync: true,
|
||||
connector: None,
|
||||
param: None,
|
||||
merchant_connector_details: None,
|
||||
};
|
||||
|
||||
let (auth_type, auth_flow) = match auth::get_auth_type_and_flow(req.headers()) {
|
||||
@ -110,6 +111,64 @@ pub async fn payment_intents_retrieve(
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
#[post("/sync")]
|
||||
pub async fn payment_intents_retrieve_with_gateway_creds(
|
||||
state: web::Data<routes::AppState>,
|
||||
qs_config: web::Data<serde_qs::Config>,
|
||||
req: HttpRequest,
|
||||
form_payload: web::Bytes,
|
||||
) -> HttpResponse {
|
||||
let json_payload: payment_types::PaymentRetrieveBodyWithCredentials = match qs_config
|
||||
.deserialize_bytes(&form_payload)
|
||||
.map_err(|err| report!(errors::StripeErrorCode::from(err)))
|
||||
{
|
||||
Ok(p) => p,
|
||||
Err(err) => return api::log_and_return_error_response(err),
|
||||
};
|
||||
|
||||
let payload = payment_types::PaymentsRetrieveRequest {
|
||||
resource_id: payment_types::PaymentIdType::PaymentIntentId(
|
||||
json_payload.payment_id.to_string(),
|
||||
),
|
||||
merchant_id: json_payload.merchant_id.clone(),
|
||||
force_sync: json_payload.force_sync.unwrap_or(false),
|
||||
merchant_connector_details: json_payload.merchant_connector_details.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
let (auth_type, _auth_flow) = match auth::get_auth_type_and_flow(req.headers()) {
|
||||
Ok(auth) => auth,
|
||||
Err(err) => return api::log_and_return_error_response(report!(err)),
|
||||
};
|
||||
|
||||
wrap::compatibility_api_wrap::<
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
types::StripePaymentIntentResponse,
|
||||
errors::StripeErrorCode,
|
||||
>(
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
|state, merchant_account, req| {
|
||||
payments::payments_core::<api_types::PSync, payment_types::PaymentsResponse, _, _, _>(
|
||||
state,
|
||||
merchant_account,
|
||||
payments::PaymentStatus,
|
||||
req,
|
||||
api::AuthFlow::Merchant,
|
||||
payments::CallConnectorAction::Trigger,
|
||||
)
|
||||
},
|
||||
&*auth_type,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
#[post("/{payment_id}")]
|
||||
pub async fn payment_intents_update(
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
use api_models::{payments, refunds};
|
||||
use api_models::payments;
|
||||
use common_utils::{ext_traits::StringExt, pii as secret};
|
||||
use error_stack::ResultExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
compatibility::stripe::refunds::types as stripe_refunds,
|
||||
core::errors,
|
||||
pii::{self, PeekInterface},
|
||||
types::{
|
||||
api::enums as api_enums,
|
||||
api::{admin, enums as api_enums},
|
||||
transformers::{ForeignFrom, ForeignInto},
|
||||
},
|
||||
};
|
||||
@ -113,8 +114,10 @@ impl From<Shipping> for payments::Address {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(PartialEq, Eq, Deserialize, Clone)]
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct StripePaymentIntentRequest {
|
||||
pub id: Option<String>,
|
||||
pub amount: Option<i64>, //amount in cents, hence passed as integer
|
||||
pub connector: Option<Vec<api_enums::Connector>>,
|
||||
pub currency: Option<String>,
|
||||
@ -129,18 +132,19 @@ pub struct StripePaymentIntentRequest {
|
||||
pub return_url: Option<url::Url>,
|
||||
pub setup_future_usage: Option<api_enums::FutureUsage>,
|
||||
pub shipping: Option<Shipping>,
|
||||
pub billing_details: Option<StripeBillingDetails>,
|
||||
pub statement_descriptor: Option<String>,
|
||||
pub statement_descriptor_suffix: Option<String>,
|
||||
pub metadata: Option<api_models::payments::Metadata>,
|
||||
pub client_secret: Option<pii::Secret<String>>,
|
||||
pub payment_method_options: Option<StripePaymentMethodOptions>,
|
||||
pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
|
||||
}
|
||||
|
||||
impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
|
||||
type Error = error_stack::Report<errors::ApiErrorResponse>;
|
||||
fn try_from(item: StripePaymentIntentRequest) -> errors::RouterResult<Self> {
|
||||
Ok(Self {
|
||||
payment_id: item.id.map(payments::PaymentIdType::PaymentIntentId),
|
||||
amount: item.amount.map(|amount| amount.into()),
|
||||
connector: item.connector,
|
||||
currency: item
|
||||
@ -156,10 +160,6 @@ impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
|
||||
confirm: item.confirm,
|
||||
customer_id: item.customer,
|
||||
email: item.receipt_email,
|
||||
name: item
|
||||
.billing_details
|
||||
.as_ref()
|
||||
.and_then(|b| b.name.as_ref().map(|x| masking::Secret::new(x.to_owned()))),
|
||||
phone: item.shipping.as_ref().and_then(|s| s.phone.clone()),
|
||||
description: item.description,
|
||||
return_url: item.return_url,
|
||||
@ -177,9 +177,8 @@ impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
|
||||
.as_ref()
|
||||
.map(|s| payments::Address::from(s.to_owned())),
|
||||
billing: item
|
||||
.billing_details
|
||||
.as_ref()
|
||||
.map(|b| payments::Address::from(b.to_owned())),
|
||||
.payment_method_data
|
||||
.and_then(|pmd| pmd.billing_details.map(payments::Address::from)),
|
||||
statement_descriptor_name: item.statement_descriptor,
|
||||
statement_descriptor_suffix: item.statement_descriptor_suffix,
|
||||
metadata: item.metadata,
|
||||
@ -191,6 +190,7 @@ impl TryFrom<StripePaymentIntentRequest> for payments::PaymentsRequest {
|
||||
|
||||
request_three_d_secure.foreign_into()
|
||||
}),
|
||||
merchant_connector_details: item.merchant_connector_details,
|
||||
..Self::default()
|
||||
})
|
||||
}
|
||||
@ -274,7 +274,7 @@ pub struct StripePaymentIntentResponse {
|
||||
pub client_secret: Option<masking::Secret<String>>,
|
||||
pub created: Option<i64>,
|
||||
pub customer: Option<String>,
|
||||
pub refunds: Option<Vec<refunds::RefundResponse>>,
|
||||
pub refunds: Option<Vec<stripe_refunds::StripeRefundResponse>>,
|
||||
pub mandate_id: Option<String>,
|
||||
pub metadata: Option<secret::SecretSerdeValue>,
|
||||
pub charges: Charges,
|
||||
@ -283,7 +283,6 @@ pub struct StripePaymentIntentResponse {
|
||||
pub mandate_data: Option<payments::MandateData>,
|
||||
pub setup_future_usage: Option<api_models::enums::FutureUsage>,
|
||||
pub off_session: Option<bool>,
|
||||
|
||||
pub authentication_type: Option<api_models::enums::AuthenticationType>,
|
||||
pub next_action: Option<StripeNextAction>,
|
||||
pub cancellation_reason: Option<String>,
|
||||
@ -319,7 +318,9 @@ impl From<payments::PaymentsResponse> for StripePaymentIntentResponse {
|
||||
currency: resp.currency.to_lowercase(),
|
||||
customer: resp.customer_id,
|
||||
description: resp.description,
|
||||
refunds: resp.refunds,
|
||||
refunds: resp
|
||||
.refunds
|
||||
.map(|a| a.into_iter().map(Into::into).collect()),
|
||||
mandate_id: resp.mandate_id,
|
||||
mandate_data: resp.mandate_data,
|
||||
setup_future_usage: resp.setup_future_usage,
|
||||
|
||||
@ -1,13 +1,14 @@
|
||||
pub mod types;
|
||||
|
||||
use actix_web::{get, post, web, HttpRequest, HttpResponse};
|
||||
use error_stack::report;
|
||||
use router_env::{instrument, tracing};
|
||||
|
||||
use crate::{
|
||||
compatibility::{stripe::errors, wrap},
|
||||
core::refunds,
|
||||
routes,
|
||||
services::authentication as auth,
|
||||
services::{api, authentication as auth},
|
||||
types::api::refunds as refund_types,
|
||||
};
|
||||
|
||||
@ -15,10 +16,18 @@ use crate::{
|
||||
#[post("")]
|
||||
pub async fn refund_create(
|
||||
state: web::Data<routes::AppState>,
|
||||
qs_config: web::Data<serde_qs::Config>,
|
||||
req: HttpRequest,
|
||||
form_payload: web::Form<types::StripeCreateRefundRequest>,
|
||||
form_payload: web::Bytes,
|
||||
) -> HttpResponse {
|
||||
let payload = form_payload.into_inner();
|
||||
let payload: types::StripeCreateRefundRequest = match qs_config
|
||||
.deserialize_bytes(&form_payload)
|
||||
.map_err(|err| report!(errors::StripeErrorCode::from(err)))
|
||||
{
|
||||
Ok(p) => p,
|
||||
Err(err) => return api::log_and_return_error_response(err),
|
||||
};
|
||||
|
||||
let create_refund_req: refund_types::RefundRequest = payload.into();
|
||||
|
||||
wrap::compatibility_api_wrap::<
|
||||
@ -28,7 +37,7 @@ pub async fn refund_create(
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
types::StripeCreateRefundResponse,
|
||||
types::StripeRefundResponse,
|
||||
errors::StripeErrorCode,
|
||||
>(
|
||||
state.get_ref(),
|
||||
@ -47,7 +56,10 @@ pub async fn refund_retrieve(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let refund_id = path.into_inner();
|
||||
let refund_request = refund_types::RefundsRetrieveRequest {
|
||||
refund_id: path.into_inner(),
|
||||
merchant_connector_details: None,
|
||||
};
|
||||
wrap::compatibility_api_wrap::<
|
||||
_,
|
||||
_,
|
||||
@ -55,17 +67,17 @@ pub async fn refund_retrieve(
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
types::StripeCreateRefundResponse,
|
||||
types::StripeRefundResponse,
|
||||
errors::StripeErrorCode,
|
||||
>(
|
||||
state.get_ref(),
|
||||
&req,
|
||||
refund_id,
|
||||
|state, merchant_account, refund_id| {
|
||||
refund_request,
|
||||
|state, merchant_account, refund_request| {
|
||||
refunds::refund_response_wrapper(
|
||||
state,
|
||||
merchant_account,
|
||||
refund_id,
|
||||
refund_request,
|
||||
refunds::refund_retrieve_core,
|
||||
)
|
||||
},
|
||||
@ -93,7 +105,7 @@ pub async fn refund_update(
|
||||
_,
|
||||
_,
|
||||
_,
|
||||
types::StripeCreateRefundResponse,
|
||||
types::StripeRefundResponse,
|
||||
errors::StripeErrorCode,
|
||||
>(
|
||||
state.get_ref(),
|
||||
|
||||
@ -3,13 +3,16 @@ use std::{convert::From, default::Default};
|
||||
use common_utils::pii;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::types::api::refunds;
|
||||
use crate::types::api::{admin, refunds};
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct StripeCreateRefundRequest {
|
||||
pub refund_id: Option<String>,
|
||||
pub amount: Option<i64>,
|
||||
pub payment_intent: String,
|
||||
pub reason: Option<String>,
|
||||
pub metadata: Option<pii::SecretSerdeValue>,
|
||||
pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
|
||||
@ -18,7 +21,7 @@ pub struct StripeUpdateRefundRequest {
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, PartialEq, Eq)]
|
||||
pub struct StripeCreateRefundResponse {
|
||||
pub struct StripeRefundResponse {
|
||||
pub id: String,
|
||||
pub amount: i64,
|
||||
pub currency: String,
|
||||
@ -40,10 +43,13 @@ pub enum StripeRefundStatus {
|
||||
impl From<StripeCreateRefundRequest> for refunds::RefundRequest {
|
||||
fn from(req: StripeCreateRefundRequest) -> Self {
|
||||
Self {
|
||||
refund_id: req.refund_id,
|
||||
amount: req.amount,
|
||||
payment_id: req.payment_intent,
|
||||
reason: req.reason,
|
||||
refund_type: Some(refunds::RefundType::Instant),
|
||||
metadata: req.metadata,
|
||||
merchant_connector_details: req.merchant_connector_details,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
@ -69,7 +75,7 @@ impl From<refunds::RefundStatus> for StripeRefundStatus {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<refunds::RefundResponse> for StripeCreateRefundResponse {
|
||||
impl From<refunds::RefundResponse> for StripeRefundResponse {
|
||||
fn from(res: refunds::RefundResponse) -> Self {
|
||||
Self {
|
||||
id: res.refund_id,
|
||||
|
||||
@ -72,6 +72,7 @@ pub async fn setup_intents_retrieve(
|
||||
force_sync: true,
|
||||
connector: None,
|
||||
param: None,
|
||||
merchant_connector_details: None,
|
||||
};
|
||||
|
||||
let (auth_type, auth_flow) = match auth::get_auth_type_and_flow(req.headers()) {
|
||||
|
||||
@ -2,7 +2,7 @@ use api_models::webhooks::{self as api};
|
||||
use serde::Serialize;
|
||||
|
||||
use super::{
|
||||
payment_intents::types::StripePaymentIntentResponse, refunds::types::StripeCreateRefundResponse,
|
||||
payment_intents::types::StripePaymentIntentResponse, refunds::types::StripeRefundResponse,
|
||||
};
|
||||
|
||||
#[derive(Serialize)]
|
||||
@ -19,7 +19,7 @@ impl api::OutgoingWebhookType for StripeOutgoingWebhook {}
|
||||
#[serde(tag = "type", content = "object", rename_all = "snake_case")]
|
||||
pub enum StripeWebhookObject {
|
||||
PaymentIntent(StripePaymentIntentResponse),
|
||||
Refund(StripeCreateRefundResponse),
|
||||
Refund(StripeRefundResponse),
|
||||
}
|
||||
|
||||
impl From<api::OutgoingWebhook> for StripeOutgoingWebhook {
|
||||
|
||||
Reference in New Issue
Block a user