hyperswitch icon indicating copy to clipboard operation
hyperswitch copied to clipboard

feat(payment_methods_v2): single use token implementation

Open su-shivanshmathur opened this issue 9 months ago • 1 comments

Type of Change

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

Description

Add single use token implementation for Payment Method Service

The feature would help to provide a single use PSP token for creating payment

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 Payment Method Session

Request

curl --location 'http://localhost:8080/v2/payment-methods-session' \
--header 'x-profile-id: pro_2A1cEgnP0mOT4rqUqLtt' \
--header 'Authorization: api-key=dev_KVJIPqLBqYEGWUSse6Bggow5xL2PkaWLMYcpgTGcvr334sCVwagyUNbrBOTRnESf' \
--header 'Content-Type: application/json' \
--data-raw '{
    "customer_id": "12345_cus_0195ab1d3f807a80bd6611b1b71cd1d0",
     "billing": {
        "address": {
            "first_name": "John",
            "last_name": "Dough"
        },
        "email": "[email protected]"
    },"psp_tokenization": {
        "tokenization_type": "single_use",
        "connector_id": "mca_lWefajNQ9HaKiJUhvAZo"
    }
}'

Response

{
    "id": "12345_pms_0195ab1d677970a3bf12c0c019d42f6b",
    "customer_id": "12345_cus_0195ab1d3f807a80bd6611b1b71cd1d0",
    "billing": {
        "address": {
            "city": null,
            "country": null,
            "line1": null,
            "line2": null,
            "line3": null,
            "zip": null,
            "state": null,
            "first_name": "John",
            "last_name": "Dough"
        },
        "phone": null,
        "email": "[email protected]"
    },
    "psp_tokenization": {
        "tokenization_type": "single_use",
        "connector_id": "mca_lWefajNQ9HaKiJUhvAZo"
    },
    "network_tokenization": null,
    "expires_at": "2025-03-18T21:31:25.850Z",
    "client_secret": "cs_0195ab1d677a73c2a9b18b77354ad4ae",
    "return_url": null,
    "next_action": null,
    "authentication_details": null,
    "associated_payment_methods": null
}

Confirm call for the Payment method session with tokenization_type as single_use under psp_tokenization in the request

Request

curl --location 'http://localhost:8080/v2/payment-methods-session/12345_pms_0195ab1d677970a3bf12c0c019d42f6b/confirm' \
--header 'x-profile-id: pro_2A1cEgnP0mOT4rqUqLtt' \
--header 'Authorization: publishable-key=pk_dev_427ac8f9e07d403a9dc21d71be6725cb,client-secret=cs_0195ab1d677a73c2a9b18b77354ad4ae' \
--header 'Content-Type: application/json' \
--header 'api-key: dev_KVJIPqLBqYEGWUSse6Bggow5xL2PkaWLMYcpgTGcvr334sCVwagyUNbrBOTRnESf' \
--data '{
    "payment_method_data": {
        "card": {
            "card_number": "4242424242424242",
            "card_exp_month": "04",
            "card_exp_year": "40",
            "card_holder_name": "John Doe",
            "card_cvc": "100"
        }
    },
    "payment_method_type": "card",
    "payment_method_subtype": "credit",
    "psp_tokenization": {
        "tokenization_type": "single_use",
        "connector_id": "mca_wmwOLCiB3NoMv8YwyxcE"
    }
}'

Response

{
    "id": "12345_pms_0195ab1d677970a3bf12c0c019d42f6b",
    "customer_id": "12345_cus_0195ab1d3f807a80bd6611b1b71cd1d0",
    "billing": {
        "address": {
            "city": null,
            "country": null,
            "line1": null,
            "line2": null,
            "line3": null,
            "zip": null,
            "state": null,
            "first_name": "John",
            "last_name": "Dough"
        },
        "phone": null,
        "email": "[email protected]"
    },
    "psp_tokenization": {
        "tokenization_type": "single_use",
        "connector_id": "mca_lWefajNQ9HaKiJUhvAZo"
    },
    "network_tokenization": null,
    "expires_at": "2025-03-18T21:31:25.850Z",
    "client_secret": "CLIENT_SECRET_REDACTED",
    "return_url": null,
    "next_action": null,
    "authentication_details": null,
    "associated_payment_methods": null
}

The way the same is stored in the Storage ( Redis )

127.0.0.1:6379> get single_use_token_12345_pm_0195d26b9d2b71f094ba39e9fd131ca8
"{\"token\":\"tok_1R6t2xD5R7gDAGffQLz0D4fj\",\"merchant_connector_id\":\"mca_lWefajNQ9HaKiJUhvAZo\"}"

Retrieve API for the payment method created

Request

curl --location 'http://localhost:8080/v2/payment-methods/12345_pm_0195d26b9d2b71f094ba39e9fd131ca8' \
--header 'Content-Type: application/json' \
--header 'x-profile-id: pro_2A1cEgnP0mOT4rqUqLtt' \
--header 'api-key: dev_KVJIPqLBqYEGWUSse6Bggow5xL2PkaWLMYcpgTGcvr334sCVwagyUNbrBOTRnESf' \
--header 'Authorization: publishable-key=pk_dev_427ac8f9e07d403a9dc21d71be6725cb, api-key=dev_KVJIPqLBqYEGWUSse6Bggow5xL2PkaWLMYcpgTGcvr334sCVwagyUNbrBOTRnESf'

Response

{
  "id": "12345_pm_0195d26b9d2b71f094ba39e9fd131ca8",
  "merchant_id": "apka_apna_test_gvHKZJ8EatRCipXedizy",
  "customer_id": "12345_cus_0195ab1d3f807a80bd6611b1b71cd1d0",
  "payment_method_type": "card",
  "payment_method_subtype": "credit",
  "recurring_enabled": false,
  "created": "2025-03-26T12:27:02.827Z",
  "last_used_at": "2025-03-26T12:27:02.827Z",
  "payment_method_data": {
    "card": {
      "issuer_country": null,
      "last4_digits": "4242",
      "expiry_month": "04",
      "expiry_year": "28",
      "card_holder_name": "John Doe",
      "card_fingerprint": null,
      "nick_name": null,
      "card_network": null,
      "card_isin": null,
      "card_issuer": null,
      "card_type": null,
      "saved_to_locker": true
    }
  },
  "connector_tokens": [
    {
      "connector_id": "mca_lWefajNQ9HaKiJUhvAZo",
      "token_type": "single_use",
      "status": "active",
      "connector_token_request_reference_id": null,
      "original_payment_authorized_amount": null,
      "original_payment_authorized_currency": null,
      "metadata": null,
      "token": "tok_1R6t2xD5R7gDAGffQLz0D4fj"
    }
  ],
  "network_token": null
}

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

su-shivanshmathur avatar Mar 11 '25 19:03 su-shivanshmathur