Skip to content
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

refactor: [Checkout] change payment and webhooks API contract #4023

Merged
merged 7 commits into from
Mar 12, 2024

Conversation

swangi-kumari
Copy link
Contributor

@swangi-kumari swangi-kumari commented Mar 8, 2024

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

Resolves 4486

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?

Create a Card Non 3ds and 3ds payment and do refund for the same. Also configure webhooks and check for all the events.

On Checkout dashboard you can configure Webhooks from Developer -> Webhooks -> New Webhook
Under events enable Disputes and Gateway Events

Payment Create for card no 3ds

{
    "amount": 100000,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 100000,
    "customer_id": "StripeCustomer",
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://duck.com",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
      "card_number": "5385308360135181",
      "card_exp_month": "10",
      "card_exp_year": "25",
      "card_holder_name": "Joseph Doe",
      "card_cvc": "123" 
    }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "PiX"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "PiX"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}

Paymnet Response for Card No 3ds

{
    "payment_id": "pay_EhIzTPz73pEcipFaVHvH",
    "merchant_id": "merchant_1709891938",
    "status": "processing",
    "amount": 100000,
    "net_amount": 100000,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "checkout",
    "client_secret": "pay_EhIzTPz73pEcipFaVHvH_secret_nRSE9HFvr1xsJ1MFI9I9",
    "created": "2024-03-08T11:36:02.581Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "5181",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "538530",
            "card_extended_bin": "53853083",
            "card_exp_month": "10",
            "card_exp_year": "25",
            "card_holder_name": "Joseph Doe"
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": null
        },
        "phone": {
            "number": null,
            "country_code": null
        },
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": null
        },
        "phone": {
            "number": null,
            "country_code": null
        },
        "email": null
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://duck.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": null,
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "StripeCustomer",
        "created_at": 1709897762,
        "expires": 1709901362,
        "secret": "epk_7641d4ed9d3b472db8e20f865730b54a"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "pay_tnmq7gnqtmaehlt2u5xaxn6wey",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_EhIzTPz73pEcipFaVHvH_1",
    "payment_link": null,
    "profile_id": "pro_be1gUpysocx6W37SPG4t",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_Pn5Xfkl0OhRYI8v8hwkf",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "request_external_3ds_authentication": null,
    "expires_on": "2024-03-08T11:51:02.581Z",
    "fingerprint": null
}

Do Payment Retrieve for the same Payment ID , status should be "succeeded"

Paymnet Request For Card 3ds

{
  "amount": 10000,
  "currency": "USD",
  "confirm": true,
  "capture_method": "automatic",
  "capture_on": "2022-09-10T10:11:12Z",
  "customer_id": "StripeCustomer",
  "email": "[email protected]",
  "name": "John Doe",
  "phone": "999999999",
  "phone_country_code": "+65",
  "description": "Its my first payment request",
  "authentication_type": "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_data": {
    "card": {
      "card_number": "5385308360135181",
      "card_exp_month": "10",
      "card_exp_year": "25",
      "card_holder_name": "Joseph Doe",
      "card_cvc": "123"
    }
  }
}

Payment Response for Card 3ds

{
    "payment_id": "pay_z8U0xwgUnYD2BTDKHLaz",
    "merchant_id": "merchant_1709891938",
    "status": "requires_customer_action",
    "amount": 10000,
    "net_amount": 10000,
    "amount_capturable": 10000,
    "amount_received": null,
    "connector": "checkout",
    "client_secret": "pay_z8U0xwgUnYD2BTDKHLaz_secret_c1BdGVuoXDPiHC1juzfO",
    "created": "2024-03-08T11:41:58.987Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": "off_session",
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "5181",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "538530",
            "card_extended_bin": "53853083",
            "card_exp_month": "10",
            "card_exp_year": "25",
            "card_holder_name": "Joseph Doe"
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "John",
            "last_name": "Doe"
        },
        "phone": {
            "number": null,
            "country_code": null
        },
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": null,
            "last_name": null
        },
        "phone": {
            "number": null,
            "country_code": null
        },
        "email": null
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://google.com/",
    "authentication_type": "three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": {
        "type": "redirect_to_url",
        "redirect_to_url": "http://localhost:8080/payments/redirect/pay_z8U0xwgUnYD2BTDKHLaz/merchant_1709891938/pay_z8U0xwgUnYD2BTDKHLaz_1"
    },
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": null,
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "StripeCustomer",
        "created_at": 1709898118,
        "expires": 1709901718,
        "secret": "epk_b5fbfc761c114252bfbe35f0d7072cf6"
    },
    "manual_retry_allowed": null,
    "connector_transaction_id": "pay_tpmddusbl3hulmsrkzyzlbb3xa",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_z8U0xwgUnYD2BTDKHLaz_1",
    "payment_link": null,
    "profile_id": "pro_be1gUpysocx6W37SPG4t",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_Pn5Xfkl0OhRYI8v8hwkf",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "request_external_3ds_authentication": null,
    "expires_on": "2024-03-08T11:56:58.987Z",
    "fingerprint": null
}

Do Payment Retrieve for the same Payment ID, status should be "succeeded"

Do Refund for same Payment ID

{
    "payment_id": "{{payment_id}}",
    "amount": 100,
    "reason": "Customer returned product",
    "refund_type": "instant",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible
  • I added a CHANGELOG entry if applicable

@swangi-kumari swangi-kumari added A-connector-integration Area: Connector integration C-refactor Category: Refactor labels Mar 8, 2024
@swangi-kumari swangi-kumari self-assigned this Mar 8, 2024
@swangi-kumari swangi-kumari requested a review from a team as a code owner March 8, 2024 13:37
ArjunKarthik
ArjunKarthik previously approved these changes Mar 9, 2024
};

return Ok(api_models::webhooks::ObjectReferenceId::RefundId(
refund_reference,
));
}
Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to handle with Hyperswitch reference attempt_id first, if it is not provided use checkout's connector transaction id

Comment on lines 462 to 463
| CheckoutWebhookEventType::PaymentCanceled
| CheckoutWebhookEventType::PaymentVoided
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle these status in Psync then map it here

SamraatBansal
SamraatBansal previously approved these changes Mar 11, 2024
@@ -450,6 +453,16 @@ pub enum CheckoutPaymentStatus {
CardVerified,
Declined,
Captured,
#[serde(rename = "Retry Scheduled")]
RetryScheduled,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please raise this with connector and get clarity on when do we get this status?

CheckoutPaymentStatus::CardVerified | CheckoutPaymentStatus::RetryScheduled => {
Self::Pending
}
CheckoutPaymentStatus::Voided | CheckoutPaymentStatus::Canceled => Self::Voided,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When do we get this Canceled status? if this is during authentication then should be mapped to payment failure

CheckoutPaymentStatus::CardVerified | CheckoutPaymentStatus::RetryScheduled => {
Self::Pending
}
CheckoutPaymentStatus::Voided | CheckoutPaymentStatus::Canceled => Self::Voided,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When do we get this Canceled status? if this is during authentication then should be mapped to payment failure

CheckoutPaymentStatus::CardVerified | CheckoutPaymentStatus::RetryScheduled => {
Self::Pending
}
CheckoutPaymentStatus::Voided | CheckoutPaymentStatus::Canceled => Self::Voided,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When do we get this Canceled status? if this is during authentication then should be mapped to payment failure

CheckoutWebhookEventType::PaymentApproved => Self::EventNotSupported,
CheckoutWebhookEventType::PaymentCaptured => Self::PaymentIntentSuccess,
CheckoutWebhookEventType::PaymentDeclined => Self::PaymentIntentFailure,
CheckoutWebhookEventType::PaymentRefunded => Self::RefundSuccess,
CheckoutWebhookEventType::PaymentRefundDeclined => Self::RefundFailure,
CheckoutWebhookEventType::PaymentCanceled => Self::PaymentIntentCancelled,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When do we get this Canceled status? if this is during authentication then should be mapped to payment failure

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Occurs when the customer has canceled the payment via a provider's platform.

@likhinbopanna likhinbopanna added this pull request to the merge queue Mar 12, 2024
Merged via the queue into main with commit 733a560 Mar 12, 2024
10 of 12 checks passed
@likhinbopanna likhinbopanna deleted the checkout-refactor branch March 12, 2024 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-connector-integration Area: Connector integration C-refactor Category: Refactor
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants