Skip to content

feat: add payment method type PixQr#1612

Open
bsayak03 wants to merge 1 commit into
mainfrom
pix_emv/to/pix_qr
Open

feat: add payment method type PixQr#1612
bsayak03 wants to merge 1 commit into
mainfrom
pix_emv/to/pix_qr

Conversation

@bsayak03

@bsayak03 bsayak03 commented Jun 16, 2026

Copy link
Copy Markdown

Type of Change

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

Description

Added support for a newly introduced Payment Method Type - PixQr in the sdk

How did you test it?

Payment Link Create

curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Accept-Language: en' \
--header 'locale: en' \
--header 'api-key: <API_KEY>' \
--data-raw '{
    "amount": 10,
    "currency": "BRL",
    "confirm": false,
    "payment_link": true,
    "session_expiry": 600000,
    "capture_method": "automatic",
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "state": "NL",
            "zip": "94122",
            "country": "BR",
            "first_name": "John",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "random@juspay.in"
    },
    "return_url": "https://www.example.com",
    "metadata": {
        "Field 1": "Additional Information1 from PSP-Receiver",
        "Field 2": "Additional Information2 from PSP-Receiver"
    },
    "billing_descriptor": {
        "statement_descriptor": "It'\''s my second payment request"
    },
    "description": "It'\''s my first payment request",
    "feature_metadata": {
        "pix_additional_details": {
            "scheduled": {
                "date": "2026-09-17"
            }
        }
    },
    "customer": {
        "id": "cus_eef0KnZEoPUxxdXpC06N",
        "document_details": {
            "name": "PERNALONGA E PATOLINO",
            "document_type": "cpf",
            "document_number": "44494387100"
        }
    }
}'

Response

{
    "payment_id": "pay_mNeo1q1xPKrZfbpCCsC2",
    "merchant_id": "merchant_1781597122",
    "status": "requires_payment_method",
    "amount": 10,
    "net_amount": 10,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": null,
    "processor_merchant_id": "merchant_1781597122",
    "initiator": null,
    "sdk_authorization": "cHJvZmlsZV9pZD1wcm9faUcxa1Y1SGVmZGxXOURTNlM2OEQscHVibGlzaGFibGVfa2V5PXBrX2Rldl8yOTBhYmVlZmNjYzY0ZjNkYmNhOTE1MzFjYmUyZmM1NixjbGllbnRfc2VjcmV0PXBheV9tTmVvMXExeFBLclpmYnBDQ3NDMl9zZWNyZXRfbkgyMk9iQlhNRFd5MlhOb3ZPa1QsY3VzdG9tZXJfaWQ9Y3VzX2VlZjBLblpFb1BVeHhkWHBDMDZOLGNsaWVudF9zZXNzaW9uX2lkPWNsaWVudF9zZXNzX0VBdFJkREs3aDloWXcwM2gyWXlSLHBheW1lbnRfaWQ9cGF5X21OZW8xcTF4UEtyWmZicENDc0My",
    "connector": null,
    "state_metadata": null,
    "client_secret": "pay_mNeo1q1xPKrZfbpCCsC2_secret_nH22ObBXMDWy2XNovOkT",
    "created": "2026-06-16T08:07:47.162Z",
    "modified_at": "2026-06-16T08:07:47.205Z",
    "connector_customer_id": null,
    "currency": "BRL",
    "customer_id": "cus_eef0KnZEoPUxxdXpC06N",
    "customer": {
        "id": "cus_eef0KnZEoPUxxdXpC06N",
        "name": null,
        "email": null,
        "phone": null,
        "phone_country_code": null,
        "customer_document_details": {
            "document_type": "cpf",
            "document_number": "44494387100"
        }
    },
    "description": "It's 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": null,
    "billing": {
        "address": {
            "city": null,
            "country": "BR",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "NL",
            "first_name": "John",
            "last_name": "Doe",
            "origin_zip": null
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "random@juspay.in"
    },
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": "https://www.example.com/",
    "authentication_type": null,
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "error_details": 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,
    "manual_retry_allowed": null,
    "connector_transaction_id": null,
    "frm_message": null,
    "metadata": {
        "Field 1": "Additional Information1 from PSP-Receiver",
        "Field 2": "Additional Information2 from PSP-Receiver"
    },
    "connector_metadata": null,
    "connector_response_metadata": null,
    "feature_metadata": {
        "redirect_response": null,
        "search_tags": null,
        "apple_pay_recurring_details": null,
        "pix_additional_details": {
            "scheduled": {
                "date": "2026-09-17",
                "validity_after_expiration": null,
                "pix_key": null
            }
        },
        "boleto_additional_details": null,
        "pix_automatico_additional_details": null,
        "finix_additional_details": null
    },
    "reference_id": null,
    "payment_link": {
        "link": "http://localhost:8080/payment_link/merchant_1781597122/pay_mNeo1q1xPKrZfbpCCsC2?locale=en",
        "secure_link": null,
        "payment_link_id": "plink_GZmUWpE6FOgq1fEWbUfs"
    },
    "profile_id": "pro_iG1kV5HefdlW9DS6S68D",
    "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": "2026-06-23T06:47:47.150Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_channel": null,
    "payment_method_id": null,
    "network_transaction_id": null,
    "network_transaction_link_id": null,
    "payment_method_status": null,
    "updated": "2026-06-16T08:07:47.205Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "extended_authorization_last_applied_at": null,
    "request_extended_authorization": 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,
    "enable_partial_authorization": null,
    "enable_overcapture": null,
    "is_overcapture_enabled": null,
    "network_details": null,
    "is_stored_credential": null,
    "mit_category": null,
    "billing_descriptor": {
        "name": null,
        "city": null,
        "phone": null,
        "statement_descriptor": "It's my second payment request",
        "statement_descriptor_suffix": null,
        "reference": null
    },
    "tokenization": null,
    "partner_merchant_identifier_details": null,
    "payment_method_tokenization_details": null,
    "installment_options": null,
    "installment_data": null,
    "sender_payment_instrument_id": null
}
Screenshot 2026-06-16 at 13 40 26 Screenshot 2026-06-16 at 13 40 16

Checklist

  • I ran npm run re:build
  • I reviewed submitted code
  • I added unit tests for my changes where possible

@semanticdiff-com

Copy link
Copy Markdown

Review changes with  SemanticDiff

@github-actions

Copy link
Copy Markdown
Contributor

🚫 Missing Linked Issue

Hi 👋 This pull request does not appear to be linked to any open issue yet.

Linking your PR to an issue helps keep the project tidy and ensures the issue is closed automatically.

✔️ How to fix this

  • Add a keyword like Fixes #123 or Closes #456 to your PR description or a commit message.
  • Or link it manually using the "Linked issues" panel in the PR sidebar.

Tip: You can link multiple issues.
🚫 Note: If only one issue is linked, it must be open for this check to pass.

Once linked, this check will pass automatically on your next push or when you re-run the workflow.

Thanks for helping maintainers! 🙌

@github-actions

Copy link
Copy Markdown
Contributor

🚫 Missing Linked Issue

Hi 👋 This pull request does not appear to be linked to any open issue yet.

Linking your PR to an issue helps keep the project tidy and ensures the issue is closed automatically.

✔️ How to fix this

  • Add a keyword like Fixes #123 or Closes #456 to your PR description or a commit message.
  • Or link it manually using the "Linked issues" panel in the PR sidebar.

Tip: You can link multiple issues.
🚫 Note: If only one issue is linked, it must be open for this check to pass.

Once linked, this check will pass automatically on your next push or when you re-run the workflow.

Thanks for helping maintainers! 🙌

@bsayak03 bsayak03 linked an issue Jun 16, 2026 that may be closed by this pull request
@XyneSpaces

Copy link
Copy Markdown

🔍 PR Review: PixQr Payment Method Support

Scenario: payment-method-addition
Files Changed: 20 locale files + PaymentMethodsRecord.res + DynamicFieldsUtils.res


✅ Review Summary

Clean implementation following existing patterns:

  1. Locale consistency: All 17 locale files updated with payment_methods_pix_qr_transfer key
  2. Type safety: Type definition added to LocaleStringTypes.res maintains ReScript type safety
  3. Payment method registration: Proper entry in getPaymentMethodsFields with:
    • InfoElement display (appropriate for QR-based methods)
    • Pix icon reuse (consistent branding)
    • Proper field sizing (26x40)
  4. Dynamic fields: Added to dynamicFieldsEnabledPaymentMethods list enabling proper form handling

✅ Tier 1 Checks Passed

  • ✅ No silent-null error handling changes
  • ✅ No card data logging concerns (locale strings only)
  • ✅ Endpoint routing: N/A (no new endpoints)
  • ✅ No 3DS-related changes
  • ✅ No amount/currency arithmetic
  • ✅ No pk_snd test/live isolation changes

💡 Suggestion — Icon Consistency

The PR reuses the "pix" icon for pix_qr_transfer. Confirm this is intentional — if PixQr has distinct branding requirements, a separate icon asset may be needed. If the existing pix icon is correct, no change needed.


💡 Suggestion — V1/V2 Parity Check

Since this is a new payment method type, verify if any corresponding changes are needed in:

  • PaymentBodyV2.res (if V2 payment methods differ)
  • Backend API contracts for PixQr

If the backend already supports PixQr and this is purely SDK exposure, no additional changes needed.


Verdict: ✅ Approve — Clean, consistent implementation following established patterns for adding new payment methods.

@XyneSpaces

Copy link
Copy Markdown

Review Summary

Status: ✅ No blocking issues found

Findings: 0

This PR adds pix_qr_transfer payment method support consistently across:

  • 18 locale files (Arabic, Catalan, Chinese, Deutsch, Dutch, EnglishGB, English, FrenchBelgium, French, Hebrew, Italian, Japanese, Polish, Portuguese, Russian, Spanish, Swedish, TraditionalChinese)
  • LocaleStringTypes.res — type definition
  • PaymentMethodsRecord.res — payment method configuration with icon and InfoElement field
  • DynamicFieldsUtils.res — dynamic fields enabled list

Checks passed:

  • Naming consistent with existing pix_transfer and pix_emv_transfer patterns
  • Icon reuses existing "pix" icon (appropriate for QR variant)
  • Uses InfoElement fields array matching other Pix variants
  • All locale strings added with appropriate translations

@XyneSpaces XyneSpaces left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Web SDK review completed. Clean implementation following existing patterns for Pix payment methods.

payment_methods_evoucher: `قسيمة إلكترونية`,
payment_methods_pix_transfer: `Pix`,
payment_methods_pix_emv_transfer: `PixEmv`,
payment_methods_pix_qr_transfer: `PixQr`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Non-English locale strings use English value

The Arabic locale uses PixQr as the translation, which may not be appropriate for Arabic-speaking users. While this is consistent with PixEmv, consider whether the Brazilian Portuguese original "Pix QR" should be preserved, or if a localized description is needed.

This is a minor nit since this payment method is primarily for the Brazilian market.

paymentMethodName: "pix_qr_transfer",
fields: [InfoElement],
icon: Some(icon("pix", ~size=26, ~width=40)),
displayName: localeString.payment_methods_pix_qr_transfer,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verify icon availability for pix_qr_transfer

The code reuses the pix icon for pix_qr_transfer. Verify that the same icon is appropriate for both payment method types, or if a distinct QR code variant should be added.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add payment method type PixQr

2 participants