hyperswitch
hyperswitch copied to clipboard
feat(connector): [NMI] External 3DS flow for Cards
Type of Change
- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD
Description
External 3DS is done through ThreeDSecure.io for Card payment in NMI
Additional Changes
- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables
Motivation and Context
How did you test it?
Tested through Postman:
- Create a MCA(NMI):
curl --location 'http://localhost:8080/account/{{merchant_id}}/connectors' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: {{admin_api_key}}' \
--data '{
"connector_type": "payment_processor",
"connector_name": "nmi",
"connector_account_details": {
"auth_type": "BodyKey",
"api_key": "{{api_key}}",
"key1": "{{key1}}"
},
"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": "voucher",
"payment_method_types": [
{
"payment_method_type": "boleto",
"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",
"acquirer_bin": "{{acquirer_bin}}",
"acquirer_merchant_id": "{{acquirer_merchant_id}}"
},
"connector_webhook_details": {
"merchant_secret": "{{merchant_secret}}"
},
"business_country": "US",
"business_label": "default"
}'
- Create External ThreeDS MCA:
curl --location 'http://localhost:8080/account/{{merchant_id}}/connectors' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: {{admin_api_key}}' \
--data '{
"connector_type": "authentication_processor",
"connector_name": "threedsecureio",
"connector_account_details": {
"auth_type": "HeaderKey",
"api_key":"{{api_key}}"
},
"test_mode": true,
"disabled": false,
"metadata": {
"mcc": "5411",
"merchant_country_code": "840",
"merchant_name": "Dummy Merchant"
}
}'
- Update Business Profile:
curl --location 'http://localhost:8080/account/{{merchant_id}}/business_profile/{{profile_id}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: {{admin_api_key}}' \
--data '{
"authentication_connector_details": {
"authentication_connectors": ["threedsecureio"],
"three_ds_requestor_url": "https://google.com"
}
}'
- Create a External 3DS request:
{
"amount": 254,
"currency": "USD",
"confirm": true,
"amount_to_capture": 254,
"capture_method": "automatic",
"capture_on": "2022-09-10T10:11:12Z",
"customer_id": "StripeCustomer",
"email": "[email protected]",
"name": "John Doe",
"phone": "999999999",
"request_external_three_ds_authentication": true,
"phone_country_code": "+65",
"description": "Its my first payment request",
"authentication_type": "three_ds",
"return_url": "https://google.com",
"setup_future_usage": "on_session",
"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"
}
},
"routing": {
"type": "single",
"data": "nmi"
},
"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": "4000000000002503",
"card_exp_month": "08",
"card_exp_year": "25",
"card_holder_name": "joseph Doe",
"card_cvc": "999"
}
},
"billing": {
"address": {
"line1": "1467",
"line2": "Harrison Street",
"line3": "Harrison Street",
"city": "San Fransico",
"state": "California",
"zip": "94122",
"country": "US",
"first_name": "John",
"last_name": "Doe"
}
}
}
- Collect the
three_ds_method_datafrom the response: - Simulate Device Data Collection: Fill the threeDSMethodData field with collected three_ds_method_data
curl --location 'https://acs40.sandbox.3dsecure.io/3dsmethod' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'api-key: {{api_key}}' \
--data-urlencode 'threeDSMethodData={{threeDSMethodData}}'
- Create a Challenge request:
curl --location 'http://localhost:8080/payments/{{payment_id}}/3ds/authentication' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: {{api_key}}' \
--data '{
"client_secret": "{{client_secret}}",
"device_channel": "BRW",
"threeds_method_comp_ind": "Y"
}'
- Authorize the Payment:
curl --location --request POST 'http://localhost:8080/payments/{{payment_id}}/{{merchant_id}}/authorize/checkout' \
--header 'api-key: {{api_key}}'
- Do a Payment Sync:
curl --location 'http://localhost:8080/payments/{{payment_id}}?force_sync=true' \
--header 'Accept: application/json' \
--header 'api-key: {{api_key}}'
- Status should be
succeeded
Checklist
- [x] I formatted the code
cargo +nightly fmt --all - [x] I addressed lints thrown by
cargo clippy - [x] I reviewed the submitted code
- [ ] I added unit tests for my changes where possible
- [ ] I added a CHANGELOG entry if applicable