Skip to content

feat(connector): [facilitapay] fix refunds, add webhook and void support #8778

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

Merged
merged 7 commits into from
Jul 31, 2025

Conversation

pixincreate
Copy link
Member

@pixincreate pixincreate commented Jul 28, 2025

Type of Change

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

Description

This Facilitapay PR introudces 2 new features and a bug fix which is described below:

  • Add support for webhooks
    • Source verification supported
    • Payments
    • Refunds (It is only supported for pix payment when a third party makes a transaction instead of the actual user). The payload for both payments and refunds is exactly the same with 0 difference. It is kind of use less to have webhook for support for Refunds
  • Add support for voiding payments
    • At Facilita, refund means voiding a payment
    • This is a GET call with no request body
  • Fix a bug in Refunds (It was not testable until now)
    • At Facilita, refund_received_transaction means refunding a payment
    • This is a GET call with no request body
    • Does not support partial refunds

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

closes #8777

How did you test it?

Partial refunds
curl --location 'http://localhost:8080/refunds' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_FwRHVH9xL5cvYOsONW8YzIphnGhIibnEy9tCWuNCpDLwSnzR4Ilogl6sia26pcND' \
--data '{
    "payment_id": "pay_le5uOFoizxZPXFHPQuK1",
    "amount": 1000,
    "reason": "Customer returned product",
    "refund_type": "instant",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'
{
    "error": {
        "type": "invalid_request",
        "message": "Payment method type not supported",
        "code": "IR_19",
        "reason": "Partial refund not supported by Facilitapay is not supported by Facilitapay"
    }
}
Refunds
curl --location 'http://localhost:8080/refunds' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_FwRHVH9xL5cvYOsONW8YzIphnGhIibnEy9tCWuNCpDLwSnzR4Ilogl6sia26pcND' \
--data '{
    "payment_id": "pay_le5uOFoizxZPXFHPQuK1",
    "amount": 10400,
    "reason": "Customer returned product",
    "refund_type": "instant",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'
{
    "refund_id": "ref_bEMav88LA7llD0KS6Twk",
    "payment_id": "pay_le5uOFoizxZPXFHPQuK1",
    "amount": 10400,
    "currency": "BRL",
    "status": "succeeded",
    "reason": "Customer returned product",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "error_message": null,
    "error_code": null,
    "unified_code": null,
    "unified_message": null,
    "created_at": "2025-07-28T18:43:11.748Z",
    "updated_at": "2025-07-28T18:43:12.819Z",
    "connector": "facilitapay",
    "profile_id": "pro_ODZKRkH2uJIfAPClUy8B",
    "merchant_connector_id": "mca_A4Kpc6NUvBsN8RGvvJsm",
    "split_refunds": null,
    "issuer_error_code": null,
    "issuer_error_message": null
}

will introduce cypress in a separate pr

Void
curl --location 'https://pix-mbp.orthrus-monster.ts.net/payments/pay_XIq2h8snAnSp425StpHM/cancel' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_FwRHVH9xL5cvYOsONW8YzIphnGhIibnEy9tCWuNCpDLwSnzR4Ilogl6sia26pcND' \
--data '{"cancellation_reason":"requested_by_customer"}'
{
    "payment_id": "pay_XIq2h8snAnSp425StpHM",
    "merchant_id": "postman_merchant_GHAction_1753728068",
    "status": "cancelled",
    "amount": 10400,
    "net_amount": 10400,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": null,
    "client_secret": "pay_XIq2h8snAnSp425StpHM_secret_Za7LqUCCvag8LBMCyYBp",
    "created": "2025-07-28T18:44:39.081Z",
    "currency": "BRL",
    "customer_id": null,
    "customer": {
        "id": null,
        "name": null,
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "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": null,
    "payment_method_data": null,
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "BR",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": null
        },
        "phone": null,
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "BR",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": "THE"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": "https://duck.com/",
    "authentication_type": "three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": "requested_by_customer",
    "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": null,
    "manual_retry_allowed": false,
    "connector_transaction_id": null,
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_ODZKRkH2uJIfAPClUy8B",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": null,
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-07-28T18:59:39.081Z",
    "fingerprint": null,
    "browser_info": {
        "language": "en-GB",
        "time_zone": -330,
        "ip_address": "208.127.127.193",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
        "color_depth": 24,
        "java_enabled": true,
        "screen_width": 1280,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "screen_height": 720,
        "java_script_enabled": true
    },
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-07-28T18:44:43.912Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": null,
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": null
}
Webhook Setup
curl --location 'https://sandbox-api.facilitapay.com/api/v1/enable_webhooks' \
--header 'Authorization: Bearer <jwt_token>' \
--header 'Content-Type: application/json' \
--data '{
    "url": "https://baseUrl/webhooks/:merchant_id/facilitapay"
    
}'
{
    "data": {
        "secret": "1111"
    }
}
Payment Webhook

Source verification:

image

Incoming Webhook Logs:

image

Outgoing Webhook:

image
Refund Webhook

The payment_refunded webhook is only sent for a very specific use case - when a pix payment is automatically refunded because it was paid from a third-party account. for regular api-initiated refunds, facilitapay sends the same identified and wire_created webhooks as for payments, making it impossible to distinguish between payment and refund webhooks.

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by just clippy && just clippy_v2
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

@pixincreate pixincreate added this to the July 2025 Release milestone Jul 28, 2025
@pixincreate pixincreate self-assigned this Jul 28, 2025
@pixincreate pixincreate requested a review from a team as a code owner July 28, 2025 19:30
@pixincreate pixincreate added A-connector-integration Area: Connector integration C-bug Category: Bug C-feature Category: Feature request or enhancement S-waiting-on-review Status: This PR has been implemented and needs to be reviewed labels Jul 28, 2025
Copy link

semanticdiff-com bot commented Jul 28, 2025

@pixincreate pixincreate force-pushed the connector/facilitapay-webhooks branch from e0598bb to 5a48c90 Compare July 28, 2025 19:36
…acilitapay-webhooks

* 'main' of github.com:juspay/hyperswitch:
  fix(connector): [Worldpay] handle multiple ddc submission for CompleteAuthorize (#8741)
  feat(connector): [Adyen] receive incoming webhooks for pix expiry (#8720)
  feat(connector): [FISERV] Added GooglePay Payment Method - Connector Decryption Flow (#8658)
  feat(connector): [BLUECODE] Added Template Code (#8756)
  chore(version): 2025.07.29.0
@likhinbopanna likhinbopanna added this pull request to the merge queue Jul 31, 2025
Merged via the queue into main with commit c38ce38 Jul 31, 2025
19 of 24 checks passed
@likhinbopanna likhinbopanna deleted the connector/facilitapay-webhooks branch July 31, 2025 07:07
pixincreate added a commit that referenced this pull request Jul 31, 2025
…dd-xof-cybersource

* 'main' of github.com:juspay/hyperswitch:
  feat(authentication): added authentication sync api (#8596)
  feat(connector): [facilitapay] fix refunds, add webhook and void support (#8778)
  feat(connector): [payload] add recurring payments (#8597)
  chore(version): 2025.07.31.0
  feat(connector): [Flexiti]Add support for flexiti connector  (#8743)
  chore(router): events enhancement for kafka (#8780)
  ci(cypress): Making a mandate payment with large customer user agents (#8790)
pixincreate added a commit that referenced this pull request Aug 1, 2025
…rver

* 'main' of github.com:juspay/hyperswitch: (25 commits)
  chore: `xof` currency to cybersource cards (#8799)
  chore(version): 2025.08.01.0
  feat(core): Implement UCS based  upi for  paytm and phonepe (#8732)
  feat(connector): [katapult]add template code for katapult (#8783)
  feat(router): introduce `feature`  and `feature_data` to gsm (#7771)
  feat(connector): [cybersource] add changes for field CybersourceConsumerAuthInformation (#8768)
  feat(authentication): added authentication sync api (#8596)
  feat(connector): [facilitapay] fix refunds, add webhook and void support (#8778)
  feat(connector): [payload] add recurring payments (#8597)
  chore(version): 2025.07.31.0
  feat(connector): [Flexiti]Add support for flexiti connector  (#8743)
  chore(router): events enhancement for kafka (#8780)
  ci(cypress): Making a mandate payment with large customer user agents (#8790)
  fix(openapi): update create_platform endpoint in api-reference docs (#8782)
  chore(version): 2025.07.30.0
  fix(connector): [GLOBALPAY] Added Tokenization Flow for CITs (#8568)
  feat(routing): Add api-refs for new decision engine endpoints (#8709)
  fix: replace xtrim with xdel to support  older redis version (#8515)
  fix(connector): [Worldpay] handle multiple ddc submission for CompleteAuthorize (#8741)
  feat(connector): [Adyen] receive incoming webhooks for pix expiry (#8720)
  ...
@hyperswitch-bot hyperswitch-bot bot removed the S-waiting-on-review Status: This PR has been implemented and needs to be reviewed label Aug 5, 2025
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-bug Category: Bug C-feature Category: Feature request or enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FEAT] (CONNECTOR): Facilitapay webhook support
4 participants