mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 09:07:09 +08:00
feat(docs): add multiple examples support and webhook schema (#1864)
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
use common_utils::custom_serde;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use time::PrimitiveDateTime;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::{disputes, enums as api_enums, payments, refunds};
|
||||
|
||||
@ -81,20 +82,33 @@ pub struct IncomingWebhookDetails {
|
||||
pub resource_object: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[derive(Debug, Clone, Serialize, ToSchema)]
|
||||
pub struct OutgoingWebhook {
|
||||
/// The merchant id of the merchant
|
||||
pub merchant_id: String,
|
||||
|
||||
/// The unique event id for each webhook
|
||||
pub event_id: String,
|
||||
|
||||
/// The type of event this webhook corresponds to.
|
||||
#[schema(value_type = EventType)]
|
||||
pub event_type: api_enums::EventType,
|
||||
|
||||
/// This is specific to the flow, for ex: it will be `PaymentsResponse` for payments flow
|
||||
pub content: OutgoingWebhookContent,
|
||||
#[serde(default, with = "custom_serde::iso8601")]
|
||||
|
||||
/// The time at which webhook was sent
|
||||
pub timestamp: PrimitiveDateTime,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
#[derive(Debug, Clone, Serialize, ToSchema)]
|
||||
#[serde(tag = "type", content = "object", rename_all = "snake_case")]
|
||||
pub enum OutgoingWebhookContent {
|
||||
#[schema(value_type = PaymentsResponse)]
|
||||
PaymentDetails(payments::PaymentsResponse),
|
||||
#[schema(value_type = RefundResponse)]
|
||||
RefundDetails(refunds::RefundResponse),
|
||||
#[schema(value_type = DisputeResponse)]
|
||||
DisputeDetails(Box<disputes::DisputeResponse>),
|
||||
}
|
||||
|
||||
@ -736,6 +736,7 @@ impl Currency {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
ToSchema,
|
||||
)]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
|
||||
@ -17,7 +17,6 @@ pub mod routes;
|
||||
pub mod scheduler;
|
||||
|
||||
pub mod middleware;
|
||||
#[cfg(feature = "openapi")]
|
||||
pub mod openapi;
|
||||
pub mod services;
|
||||
pub mod types;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
#[cfg(feature = "openapi")]
|
||||
#[derive(utoipa::OpenApi)]
|
||||
#[openapi(
|
||||
info(
|
||||
@ -318,6 +319,9 @@ Never share your secret api keys. Keep them guarded and secure.
|
||||
api_models::enums::PayoutStatus,
|
||||
api_models::enums::PayoutType,
|
||||
api_models::payments::FrmMessage,
|
||||
api_models::webhooks::OutgoingWebhook,
|
||||
api_models::webhooks::OutgoingWebhookContent,
|
||||
api_models::enums::EventType,
|
||||
crate::types::api::admin::MerchantAccountResponse,
|
||||
crate::types::api::admin::MerchantConnectorId,
|
||||
crate::types::api::admin::MerchantDetails,
|
||||
@ -377,3 +381,107 @@ impl utoipa::Modify for SecurityAddon {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod examples {
|
||||
/// Creating the payment with minimal fields
|
||||
pub const PAYMENTS_CREATE_MINIMUM_FIELDS: &str = r#"{
|
||||
"amount": 6540,
|
||||
"currency": "USD",
|
||||
}"#;
|
||||
|
||||
/// Creating a manual capture payment
|
||||
pub const PAYMENTS_CREATE_WITH_MANUAL_CAPTURE: &str = r#"{
|
||||
"amount": 6540,
|
||||
"currency": "USD",
|
||||
"capture_method":"manual"
|
||||
}"#;
|
||||
|
||||
/// Creating a payment with billing and shipping address
|
||||
pub const PAYMENTS_CREATE_WITH_ADDRESS: &str = r#"{
|
||||
"amount": 6540,
|
||||
"currency": "USD",
|
||||
"customer": {
|
||||
"id" : "cus_abcdefgh"
|
||||
},
|
||||
"billing": {
|
||||
"address": {
|
||||
"line1": "1467",
|
||||
"line2": "Harrison Street",
|
||||
"line3": "Harrison Street",
|
||||
"city": "San Fransico",
|
||||
"state": "California",
|
||||
"zip": "94122",
|
||||
"country": "US",
|
||||
"first_name": "joseph",
|
||||
"last_name": "Doe"
|
||||
},
|
||||
"phone": {
|
||||
"number": "8056594427",
|
||||
"country_code": "+91"
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
|
||||
/// Creating a payment with customer details
|
||||
pub const PAYMENTS_CREATE_WITH_CUSTOMER_DATA: &str = r#"{
|
||||
"amount": 6540,
|
||||
"currency": "USD",
|
||||
"customer": {
|
||||
"id":"cus_abcdefgh",
|
||||
"name":"John Dough",
|
||||
"phone":"9999999999",
|
||||
"email":"john@example.com"
|
||||
}
|
||||
}"#;
|
||||
|
||||
/// 3DS force payment
|
||||
pub const PAYMENTS_CREATE_WITH_FORCED_3DS: &str = r#"{
|
||||
"amount": 6540,
|
||||
"currency": "USD",
|
||||
"authentication_type" : "three_ds"
|
||||
}"#;
|
||||
|
||||
/// A payment with other fields
|
||||
pub const PAYMENTS_CREATE: &str = r#"{
|
||||
"amount": 6540,
|
||||
"currency": "USD",
|
||||
"payment_id": "abcdefghijklmnopqrstuvwxyz",
|
||||
"customer": {
|
||||
"id":"cus_abcdefgh",
|
||||
"name":"John Dough",
|
||||
"phone":"9999999999",
|
||||
"email":"john@example.com"
|
||||
},
|
||||
"description": "Its my first payment request",
|
||||
"statement_descriptor_name": "joseph",
|
||||
"statement_descriptor_suffix": "JS",
|
||||
"metadata": {
|
||||
"udf1": "some-value",
|
||||
"udf2": "some-value"
|
||||
}
|
||||
}"#;
|
||||
|
||||
/// Creating the payment with order details
|
||||
pub const PAYMENTS_CREATE_WITH_ORDER_DETAILS: &str = r#"{
|
||||
"amount": 6540,
|
||||
"currency": "USD",
|
||||
"order_details": [
|
||||
{
|
||||
"product_name": "Apple iPhone 15",
|
||||
"quantity": 1,
|
||||
"amount" : 6540
|
||||
}
|
||||
]
|
||||
}"#;
|
||||
|
||||
/// Creating the payment with connector metadata for noon
|
||||
pub const PAYMENTS_CREATE_WITH_NOON_ORDER_CATETORY: &str = r#"{
|
||||
"amount": 6540,
|
||||
"currency": "USD",
|
||||
"connector_metadata": {
|
||||
"noon": {
|
||||
"order_category":"shoes"
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
}
|
||||
|
||||
@ -10,6 +10,12 @@ use crate::{
|
||||
errors::http_not_implemented,
|
||||
payments::{self, PaymentRedirectFlow},
|
||||
},
|
||||
openapi::examples::{
|
||||
PAYMENTS_CREATE, PAYMENTS_CREATE_MINIMUM_FIELDS, PAYMENTS_CREATE_WITH_ADDRESS,
|
||||
PAYMENTS_CREATE_WITH_CUSTOMER_DATA, PAYMENTS_CREATE_WITH_FORCED_3DS,
|
||||
PAYMENTS_CREATE_WITH_MANUAL_CAPTURE, PAYMENTS_CREATE_WITH_NOON_ORDER_CATETORY,
|
||||
PAYMENTS_CREATE_WITH_ORDER_DETAILS,
|
||||
},
|
||||
services::{api, authentication as auth},
|
||||
types::{
|
||||
api::{self as api_types, enums as api_enums, payments as payment_types},
|
||||
@ -23,17 +29,59 @@ use crate::{
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/payments",
|
||||
request_body=PaymentsCreateRequest,
|
||||
request_body(
|
||||
content = PaymentsCreateRequest,
|
||||
examples(
|
||||
(
|
||||
"Create a payment with minimul fields" = (
|
||||
value = json!(PAYMENTS_CREATE_MINIMUM_FIELDS)
|
||||
)
|
||||
),
|
||||
(
|
||||
"Create a manual capture payment" = (
|
||||
value = json!(PAYMENTS_CREATE_WITH_MANUAL_CAPTURE)
|
||||
)
|
||||
),
|
||||
(
|
||||
"Create a payment with address" = (
|
||||
value = json!(PAYMENTS_CREATE_WITH_ADDRESS)
|
||||
)
|
||||
),
|
||||
(
|
||||
"Create a payment with customer details" = (
|
||||
value = json!(PAYMENTS_CREATE_WITH_CUSTOMER_DATA)
|
||||
)
|
||||
),
|
||||
(
|
||||
"Create a 3DS payment" = (
|
||||
value = json!(PAYMENTS_CREATE_WITH_FORCED_3DS)
|
||||
)
|
||||
),
|
||||
(
|
||||
"Create a payment" = (
|
||||
value = json!(PAYMENTS_CREATE)
|
||||
)
|
||||
),
|
||||
(
|
||||
"Create a payment with order details" = (
|
||||
value = json!(PAYMENTS_CREATE_WITH_ORDER_DETAILS)
|
||||
)
|
||||
),
|
||||
(
|
||||
"Create a payment with order category for noon" = (
|
||||
value = json!(PAYMENTS_CREATE_WITH_NOON_ORDER_CATETORY)
|
||||
)
|
||||
),
|
||||
)),
|
||||
responses(
|
||||
(status = 200, description = "Payment created", body = PaymentsResponse),
|
||||
(status = 400, description = "Missing Mandatory fields")
|
||||
),
|
||||
tag = "Payments",
|
||||
operation_id = "Create a Payment",
|
||||
security(("api_key" = []))
|
||||
security(("api_key" = [])),
|
||||
)]
|
||||
#[instrument(skip_all, fields(flow = ?Flow::PaymentsCreate))]
|
||||
// #[post("")]
|
||||
pub async fn payments_create(
|
||||
state: web::Data<app::AppState>,
|
||||
req: actix_web::HttpRequest,
|
||||
|
||||
@ -976,6 +976,32 @@
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/PaymentsCreateRequest"
|
||||
},
|
||||
"examples": {
|
||||
"Create a 3DS payment": {
|
||||
"value": "{\n \"amount\": 6540,\n \"currency\": \"USD\",\n \"authentication_type\" : \"three_ds\"\n }"
|
||||
},
|
||||
"Create a manual capture payment": {
|
||||
"value": "{\n \"amount\": 6540,\n \"currency\": \"USD\",\n \"capture_method\":\"manual\"\n }"
|
||||
},
|
||||
"Create a payment": {
|
||||
"value": "{\n \"amount\": 6540,\n \"currency\": \"USD\",\n \"payment_id\": \"abcdefghijklmnopqrstuvwxyz\",\n \"customer\": {\n \"id\":\"cus_abcdefgh\",\n \"name\":\"John Dough\",\n \"phone\":\"9999999999\",\n \"email\":\"john@example.com\"\n },\n \"description\": \"Its my first payment request\",\n \"statement_descriptor_name\": \"joseph\",\n \"statement_descriptor_suffix\": \"JS\",\n \"metadata\": {\n \"udf1\": \"some-value\",\n \"udf2\": \"some-value\"\n }\n }"
|
||||
},
|
||||
"Create a payment with address": {
|
||||
"value": "{\n \"amount\": 6540,\n \"currency\": \"USD\",\n \"customer\": {\n \"id\" : \"cus_abcdefgh\"\n },\n \"billing\": {\n \"address\": {\n \"line1\": \"1467\",\n \"line2\": \"Harrison Street\",\n \"line3\": \"Harrison Street\",\n \"city\": \"San Fransico\",\n \"state\": \"California\",\n \"zip\": \"94122\",\n \"country\": \"US\",\n \"first_name\": \"joseph\",\n \"last_name\": \"Doe\"\n },\n \"phone\": {\n \"number\": \"8056594427\",\n \"country_code\": \"+91\"\n }\n }\n }"
|
||||
},
|
||||
"Create a payment with customer details": {
|
||||
"value": "{\n \"amount\": 6540,\n \"currency\": \"USD\",\n \"customer\": {\n \"id\":\"cus_abcdefgh\",\n \"name\":\"John Dough\",\n \"phone\":\"9999999999\",\n \"email\":\"john@example.com\"\n }\n }"
|
||||
},
|
||||
"Create a payment with minimul fields": {
|
||||
"value": "{\n \"amount\": 6540,\n \"currency\": \"USD\",\n }"
|
||||
},
|
||||
"Create a payment with order category for noon": {
|
||||
"value": "{\n \"amount\": 6540,\n \"currency\": \"USD\",\n \"connector_metadata\": {\n \"noon\": {\n \"order_category\":\"shoes\"\n }\n }\n }"
|
||||
},
|
||||
"Create a payment with order details": {
|
||||
"value": "{\n \"amount\": 6540,\n \"currency\": \"USD\",\n \"order_details\": [\n {\n \"product_name\": \"Apple iPhone 15\",\n \"quantity\": 1,\n \"amount\" : 6540\n }\n ]\n }"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -4853,6 +4879,24 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"EventType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"payment_succeeded",
|
||||
"payment_failed",
|
||||
"payment_processing",
|
||||
"action_required",
|
||||
"refund_succeeded",
|
||||
"refund_failed",
|
||||
"dispute_opened",
|
||||
"dispute_expired",
|
||||
"dispute_accepted",
|
||||
"dispute_cancelled",
|
||||
"dispute_challenged",
|
||||
"dispute_won",
|
||||
"dispute_lost"
|
||||
]
|
||||
},
|
||||
"FeatureMetadata": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -6986,6 +7030,97 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"OutgoingWebhook": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"merchant_id",
|
||||
"event_id",
|
||||
"event_type",
|
||||
"content"
|
||||
],
|
||||
"properties": {
|
||||
"merchant_id": {
|
||||
"type": "string",
|
||||
"description": "The merchant id of the merchant"
|
||||
},
|
||||
"event_id": {
|
||||
"type": "string",
|
||||
"description": "The unique event id for each webhook"
|
||||
},
|
||||
"event_type": {
|
||||
"$ref": "#/components/schemas/EventType"
|
||||
},
|
||||
"content": {
|
||||
"$ref": "#/components/schemas/OutgoingWebhookContent"
|
||||
},
|
||||
"timestamp": {
|
||||
"type": "string",
|
||||
"format": "date-time",
|
||||
"description": "The time at which webhook was sent"
|
||||
}
|
||||
}
|
||||
},
|
||||
"OutgoingWebhookContent": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"object"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"payment_details"
|
||||
]
|
||||
},
|
||||
"object": {
|
||||
"$ref": "#/components/schemas/PaymentsResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"object"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"refund_details"
|
||||
]
|
||||
},
|
||||
"object": {
|
||||
"$ref": "#/components/schemas/RefundResponse"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"object"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"dispute_details"
|
||||
]
|
||||
},
|
||||
"object": {
|
||||
"$ref": "#/components/schemas/DisputeResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"discriminator": {
|
||||
"propertyName": "type"
|
||||
}
|
||||
},
|
||||
"PayLaterData": {
|
||||
"oneOf": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user