-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(connector): [NMI] Implement webhook for Payments and Refunds #3164
Conversation
) -> CustomResult<Box<dyn masking::ErasedMaskSerialize>, errors::ConnectorError> { | ||
Err(errors::ConnectorError::WebhooksNotImplemented).into_report() | ||
let webhook_body: nmi::NmiWebhookBody = request |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since, this object will be consumed by PSync handle_response, let's have try_from webhook response object to PSync response object for payments and in case of refund return the object as it is. This will ensure that any changes in PSync will not break the incoming webhook flow
| NmiWebhookEventType::AuthSuccess | ||
| NmiWebhookEventType::AuthFailure | ||
| NmiWebhookEventType::AuthProcessing | ||
| NmiWebhookEventType::VoidSuccess |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VoidSuccess can be mapped to PaymentIntentCancelled
#[serde(rename = "transaction.auth.failure")] | ||
AuthFailure, | ||
#[serde(rename = "transaction.auth.unknown")] | ||
AuthProcessing, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is unknown status, Let's use AuthUnknown.
#[serde(rename = "transaction.sale.failure")] | ||
PaymentIntentFailure, | ||
#[serde(rename = "transaction.sale.unknown")] | ||
PaymentIntentProcessing, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is unknown status, Let's use SaleUnknown.
#[derive(Debug, Deserialize, Serialize)] | ||
pub enum NmiWebhookEventType { | ||
#[serde(rename = "transaction.sale.success")] | ||
PaymentIntentSuccess, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of PaymentIntent in the enum naming, let's use SaleSuccess, SaleFailure, SaleUnknown
#[serde(rename = "transaction.capture.failure")] | ||
CaptureFailure, | ||
#[serde(rename = "transaction.capture.unknown")] | ||
CaptureProcessing, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is unknown status, Let's use CaptureUnknown.
#[serde(rename = "transaction.void.failure")] | ||
VoidFailure, | ||
#[serde(rename = "transaction.void.unknown")] | ||
VoidProcessing, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is unknown status, Let's use VoidUnknown.
crates/router/src/connector/nmi.rs
Outdated
.parse_struct("nmi NmiWebhookBody") | ||
.change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?; | ||
|
||
if let nmi::NmiActionType::Sale = webhook_body.event_body.action.action_type { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add all payment events
https://github.com/juspay/hyperswitch/tree/feat_nmi_webhooks I had previously implemented webhooks for this connector when we did not had proper access to their dashboard. |
Type of Change
Description
Additional Changes
Motivation and Context
How did you test it?
Create a merchant account:
{ "merchant_id": "merchant_{{$timestamp}}", "locker_id": "m0010", "merchant_name": "NewAge Retailer", "merchant_details": { "primary_contact_person": "John Test", "primary_email": "JohnTest@test.com", "primary_phone": "sunt laborum", "secondary_contact_person": "John Test2", "secondary_email": "JohnTest2@test.com", "secondary_phone": "cillum do dolor id", "website": "www.example.com", "about_business": "Online Retail with a wide selection of organic products for North America", "address": { "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "city": "San Fransico", "state": "California", "zip": "94122", "country": "US" } }, "return_url": "https://google.com/success", "webhook_details": { "webhook_version": "1.0.1", "webhook_username": "ekart_retail", "webhook_password": "password_ekart@123", "payment_created_enabled": true, "payment_succeeded_enabled": true, "payment_failed_enabled": true }, "routing_algorithm": { "type": "single", "data": "nmi" }, "sub_merchants_enabled": false, "metadata": { "city": "NY", "unit": "245" }, "primary_business_details": [ { "country": "US", "business": "default" } ] }
Update the merchant account:
{ "merchant_id": "{{merchant_id}}", "webhook_details": { "webhook_version": "1.0.1", "webhook_username": "ekart_retail", "webhook_password": "password_ekart@123", "payment_created_enabled": true, "payment_succeeded_enabled": true, "payment_failed_enabled": true, "webhook_url": "{{webhook_url}}" } }
Create a Payment Connector(NMI):
{ "connector_type": "fiz_operations", "connector_name": "nmi", "connector_account_details": { "auth_type": "BodyKey", "api_key": "{{api_Key}}", "key1": "{{public_key}}" }, "test_mode": false, "disabled": false, "payment_methods_enabled": [ { "payment_method": "card", "payment_method_types": [ { "payment_method_type": "credit", "card_networks": [ "Visa", "Mastercard" ], "minimum_amount": 1, "maximum_amount": 68607706, "recurring_enabled": true, "installment_payment_enabled": true }, { "payment_method_type": "debit", "card_networks": [ "Visa", "Mastercard" ], "minimum_amount": 1, "maximum_amount": 68607706, "recurring_enabled": true, "installment_payment_enabled": true } ] }, { "payment_method": "pay_later", "payment_method_types": [ { "payment_method_type": "klarna", "payment_experience": "redirect_to_url", "minimum_amount": 1, "maximum_amount": 68607706, "recurring_enabled": true, "installment_payment_enabled": true }, { "payment_method_type": "affirm", "payment_experience": "redirect_to_url", "minimum_amount": 1, "maximum_amount": 68607706, "recurring_enabled": true, "installment_payment_enabled": true }, { "payment_method_type": "afterpay_clearpay", "payment_experience": "redirect_to_url", "minimum_amount": 1, "maximum_amount": 68607706, "recurring_enabled": true, "installment_payment_enabled": true } ] } ], "metadata": { "city": "NY", "unit": "245" }, "business_country": "US", "business_label": "default" }
Update the payment connector:
{ "connector_type": "fiz_operations", "connector_webhook_details": { "merchant_secret": "{{webhook_secret_key}}" } }
Create a non 3ds payment with NMI:
{ "amount": 18000, "currency": "USD", "confirm": true, "capture_method": "automatic", "capture_on": "2022-09-10T10:11:12Z", "customer_id": "StripeCustomer", "email": "abcdef123@gmail.com", "name": "John Doe", "phone": "999999999", "phone_country_code": "+65", "description": "Its my first payment request", "authentication_type": "no_three_ds", "return_url": "https://google.com", "setup_future_usage": "off_session", "billing": { "address": { "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "city": "San Fransico", "state": "California", "zip": "94122", "country": "US" } }, "browser_info": { "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36", "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "language": "nl-NL", "color_depth": 24, "screen_height": 723, "screen_width": 1536, "time_zone": 0, "java_enabled": true, "java_script_enabled": true, "ip_address": "127.0.0.1" }, "shipping": { "address": { "line1": "1467", "line2": "Harrison Street", "line3": "Harrison Street", "city": "San Fransico", "state": "California", "zip": "94122", "country": "US", "first_name": "John", "last_name": "Doe" } }, "statement_descriptor_name": "joseph", "statement_descriptor_suffix": "JS", "metadata": { "udf1": "value1", "new_customer": "true", "login_date": "2019-09-10T10:11:12Z" }, "payment_method": "card", "payment_method_type": "credit", "payment_method_data": { "card": { "card_number": "4111111111111111", "card_exp_month": "10", "card_exp_year": "25", "card_holder_name": "joseph Doe", "card_cvc": "999" } } }
Checklist
cargo +nightly fmt --all
cargo clippy