hyperswitch
hyperswitch copied to clipboard
feat(payment_methods_v2): single use token implementation
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
Changed Files
| File | Status |
|---|---|