mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 17:19:15 +08:00
feat(connector): [Stripe] Add support for WeChat Pay and Qr code support in next action (#1555)
Co-authored-by: AkshayaFoiger <akshaya.shankar@juspay.in> Co-authored-by: chikke srujan <121822803+srujanchikke@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
ca4e242d20
commit
a15a77dea3
@ -687,6 +687,9 @@ pub enum StripeNextAction {
|
||||
ThirdPartySdkSessionToken {
|
||||
session_token: Option<payments::SessionToken>,
|
||||
},
|
||||
QrCodeInformation {
|
||||
image_data_url: url::Url,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) fn into_stripe_next_action(
|
||||
@ -710,5 +713,8 @@ pub(crate) fn into_stripe_next_action(
|
||||
payments::NextActionData::ThirdPartySdkSessionToken { session_token } => {
|
||||
StripeNextAction::ThirdPartySdkSessionToken { session_token }
|
||||
}
|
||||
payments::NextActionData::QrCodeInformation { image_data_url } => {
|
||||
StripeNextAction::QrCodeInformation { image_data_url }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -345,6 +345,9 @@ pub enum StripeNextAction {
|
||||
ThirdPartySdkSessionToken {
|
||||
session_token: Option<payments::SessionToken>,
|
||||
},
|
||||
QrCodeInformation {
|
||||
image_data_url: url::Url,
|
||||
},
|
||||
}
|
||||
|
||||
pub(crate) fn into_stripe_next_action(
|
||||
@ -368,6 +371,9 @@ pub(crate) fn into_stripe_next_action(
|
||||
payments::NextActionData::ThirdPartySdkSessionToken { session_token } => {
|
||||
StripeNextAction::ThirdPartySdkSessionToken { session_token }
|
||||
}
|
||||
payments::NextActionData::QrCodeInformation { image_data_url } => {
|
||||
StripeNextAction::QrCodeInformation { image_data_url }
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -1060,8 +1060,7 @@ fn create_stripe_payment_method(
|
||||
StripePaymentMethodType::ApplePay,
|
||||
StripeBillingAddress::default(),
|
||||
)),
|
||||
|
||||
payments::WalletData::WeChatPayRedirect(_) => Ok((
|
||||
payments::WalletData::WeChatPay(_) => Ok((
|
||||
StripePaymentMethodData::Wallet(StripeWallet::WechatpayPayment(WechatpayPayment {
|
||||
client: WechatClient::Web,
|
||||
payment_method_types: StripePaymentMethodType::Wechatpay,
|
||||
@ -1515,6 +1514,12 @@ pub struct SepaAndBacsBankTransferInstructions {
|
||||
pub receiver: SepaAndBacsReceiver,
|
||||
}
|
||||
|
||||
#[serde_with::skip_serializing_none]
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct WechatPayNextInstructions {
|
||||
pub image_data_url: Url,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct SepaAndBacsReceiver {
|
||||
pub amount_received: i64,
|
||||
@ -1699,26 +1704,47 @@ pub fn get_connector_metadata(
|
||||
amount: i64,
|
||||
) -> CustomResult<Option<serde_json::Value>, errors::ConnectorError> {
|
||||
let next_action_response = next_action
|
||||
.and_then(|next_action_response| match next_action_response {
|
||||
StripeNextActionResponse::DisplayBankTransferInstructions(response) => {
|
||||
Some(SepaAndBacsBankTransferInstructions {
|
||||
sepa_bank_instructions: response.financial_addresses[0].iban.to_owned(),
|
||||
bacs_bank_instructions: response.financial_addresses[0]
|
||||
.sort_code
|
||||
.to_owned(),
|
||||
receiver: SepaAndBacsReceiver {
|
||||
amount_received: amount - response.amount_remaining,
|
||||
amount_remaining: response.amount_remaining,
|
||||
},
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
}).map(|response| {
|
||||
common_utils::ext_traits::Encode::<SepaAndBacsBankTransferInstructions>::encode_to_value(
|
||||
&response,
|
||||
)
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}).transpose()?;
|
||||
.and_then(|next_action_response| match next_action_response {
|
||||
StripeNextActionResponse::DisplayBankTransferInstructions(response) => {
|
||||
let bank_instructions = response.financial_addresses.get(0);
|
||||
let (sepa_bank_instructions, bacs_bank_instructions) =
|
||||
bank_instructions.map_or((None, None), |financial_address| {
|
||||
(
|
||||
financial_address.iban.to_owned(),
|
||||
financial_address.sort_code.to_owned(),
|
||||
)
|
||||
});
|
||||
|
||||
let bank_transfer_instructions = SepaAndBacsBankTransferInstructions {
|
||||
sepa_bank_instructions,
|
||||
bacs_bank_instructions,
|
||||
receiver: SepaAndBacsReceiver {
|
||||
amount_received: amount - response.amount_remaining,
|
||||
amount_remaining: response.amount_remaining,
|
||||
},
|
||||
};
|
||||
|
||||
Some(common_utils::ext_traits::Encode::<
|
||||
SepaAndBacsBankTransferInstructions,
|
||||
>::encode_to_value(
|
||||
&bank_transfer_instructions
|
||||
))
|
||||
}
|
||||
StripeNextActionResponse::WechatPayDisplayQrCode(response) => {
|
||||
let wechat_pay_instructions = WechatPayNextInstructions {
|
||||
image_data_url: response.image_data_url.to_owned(),
|
||||
};
|
||||
|
||||
Some(
|
||||
common_utils::ext_traits::Encode::<WechatPayNextInstructions>::encode_to_value(
|
||||
&wechat_pay_instructions,
|
||||
),
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.transpose()
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)?;
|
||||
Ok(next_action_response)
|
||||
}
|
||||
|
||||
@ -1848,7 +1874,7 @@ impl StripeNextActionResponse {
|
||||
Self::RedirectToUrl(redirect_to_url) | Self::AlipayHandleRedirect(redirect_to_url) => {
|
||||
Some(redirect_to_url.url.to_owned())
|
||||
}
|
||||
Self::WechatPayDisplayQrCode(redirect_to_url) => Some(redirect_to_url.data.to_owned()),
|
||||
Self::WechatPayDisplayQrCode(_) => None,
|
||||
Self::VerifyWithMicrodeposits(verify_with_microdeposits) => {
|
||||
Some(verify_with_microdeposits.hosted_verification_url.to_owned())
|
||||
}
|
||||
@ -1885,7 +1911,11 @@ pub struct StripeRedirectToUrlResponse {
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct StripeRedirectToQr {
|
||||
// This data contains url, it should be converted to QR code.
|
||||
// Note: The url in this data is not redirection url
|
||||
data: Url,
|
||||
// This is the image source, this image_data_url can directly be used by sdk to show the QR code
|
||||
image_data_url: Url,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Deserialize)]
|
||||
|
||||
@ -431,7 +431,8 @@ impl PaymentRedirectFlow for PaymentRedirectCompleteAuthorize {
|
||||
.and_then(|next_action_data| match next_action_data {
|
||||
api_models::payments::NextActionData::RedirectToUrl { redirect_to_url } => Some(redirect_to_url),
|
||||
api_models::payments::NextActionData::DisplayBankTransferInformation { .. } => None,
|
||||
api_models::payments::NextActionData::ThirdPartySdkSessionToken { .. } => None
|
||||
api_models::payments::NextActionData::ThirdPartySdkSessionToken { .. } => None,
|
||||
api_models::payments::NextActionData::QrCodeInformation{..} => None
|
||||
})
|
||||
.ok_or(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
|
||||
@ -322,6 +322,9 @@ where
|
||||
let bank_transfer_next_steps =
|
||||
bank_transfer_next_steps_check(payment_attempt.clone())?;
|
||||
|
||||
let next_action_containing_qr_code =
|
||||
qr_code_next_steps_check(payment_attempt.clone())?;
|
||||
|
||||
if payment_intent.status == enums::IntentStatus::RequiresCustomerAction
|
||||
|| bank_transfer_next_steps.is_some()
|
||||
{
|
||||
@ -331,6 +334,11 @@ where
|
||||
bank_transfer_steps_and_charges_details: bank_transfer,
|
||||
}
|
||||
})
|
||||
.or(next_action_containing_qr_code.map(|qr_code_data| {
|
||||
api_models::payments::NextActionData::QrCodeInformation {
|
||||
image_data_url: qr_code_data.image_data_url,
|
||||
}
|
||||
}))
|
||||
.or(Some(api_models::payments::NextActionData::RedirectToUrl {
|
||||
redirect_to_url: helpers::create_startpay_url(
|
||||
server,
|
||||
@ -554,6 +562,18 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn qr_code_next_steps_check(
|
||||
payment_attempt: storage::PaymentAttempt,
|
||||
) -> RouterResult<Option<api_models::payments::QrCodeNextStepsInstruction>> {
|
||||
let qr_code_steps: Option<Result<api_models::payments::QrCodeNextStepsInstruction, _>> =
|
||||
payment_attempt
|
||||
.connector_metadata
|
||||
.map(|metadata| metadata.parse_value("QrCodeNextStepsInstruction"));
|
||||
|
||||
let qr_code_instructions = qr_code_steps.transpose().ok().flatten();
|
||||
Ok(qr_code_instructions)
|
||||
}
|
||||
|
||||
impl ForeignFrom<(storage::PaymentIntent, storage::PaymentAttempt)> for api::PaymentsResponse {
|
||||
fn foreign_from(item: (storage::PaymentIntent, storage::PaymentAttempt)) -> Self {
|
||||
let pi = item.0;
|
||||
|
||||
@ -233,6 +233,7 @@ Never share your secret api keys. Keep them guarded and secure.
|
||||
api_models::payments::SdkNextAction,
|
||||
api_models::payments::NextActionCall,
|
||||
api_models::payments::SamsungPayWalletData,
|
||||
api_models::payments::WeChatPay,
|
||||
api_models::payments::GpayTokenizationData,
|
||||
api_models::payments::GooglePayPaymentMethodInfo,
|
||||
api_models::payments::ApplePayWalletData,
|
||||
|
||||
Reference in New Issue
Block a user