Skip to content

feat(connector): GrabPay connector integration - #2063

Open
peeyushshukla-juspay wants to merge 85 commits into
mainfrom
Grabpay_Connector_Integration
Open

feat(connector): GrabPay connector integration#2063
peeyushshukla-juspay wants to merge 85 commits into
mainfrom
Grabpay_Connector_Integration

Conversation

@peeyushshukla-juspay

@peeyushshukla-juspay peeyushshukla-juspay commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Description

Adds the GrabPay one-time-charge redirect wallet connector with Create Order, OAuth authorization, redirect verification, payment sync, refund, and refund sync support.

Flows Implemented

Flow Service Method Status
Create Order / Authorize types.CompositePaymentService/Authorize Creates the GrabPay charge and returns the OAuth redirect URL
Verify Redirect Response types.CompositePaymentService/VerifyRedirectResponse Exchanges the OAuth code and completes the charge
PSync types.CompositePaymentService/Get Queries the payment status
Refund types.CompositePaymentService/Refund Processes full and partial refunds
RSync types.CompositeRefundService/Get Queries the refund status
Webhook types.EventService/HandleEvent GrabPay webhook handler

Additional Changes

  • This PR modifies the API contract by adding the GrabPay connector, GRAB_PAY payment method type, and grabpayRedirect wallet data.
  • This PR modifies connector configuration by adding GrabPay credentials and base URL configuration.
  • Redirect connector feature data is propagated through the composite flow to preserve PKCE, transaction, currency, and access-token context.

Testing

1. Authorize - Redirect Pending
grpcurl -plaintext \
  -H 'x-connector: grabpay' \
  -H 'x-connector-config: {"config":{"Grabpay":{"partner_id":"<REDACTED>","partner_secret":"<REDACTED>","client_id":"<REDACTED>","client_secret":"<REDACTED>","merchant_id":"<REDACTED>","base_url":"https://partner-api.grab.com/grabpay/partner/v2"}}}' \
  -d '{
    "merchantTransactionId": "<REDACTED_TRANSACTION_ID>",
    "merchantOrderId": "<REDACTED_TRANSACTION_ID>",
    "amount": {
      "minorAmount": 1,
      "currency": "PHP"
    },
    "paymentMethod": {
      "grabpayRedirect": {}
    },
    "captureMethod": "AUTOMATIC",
    "authType": "NO_THREE_DS",
    "returnUrl": "https://example.com/payment/response",
    "webhookUrl": "https://example.com/webhook",
    "description": "GrabPay test payment",
    "address": {
      "billingAddress": {
        "countryAlpha2Code": "PH"
      }
    },
    "testMode": false
  }' \
  localhost:8000 \
  types.CompositePaymentService/Authorize

Response:

{
  "authorizeResponse": {
    "connectorTransactionId": "<REDACTED_TRANSACTION_ID>",
    "status": "AUTHENTICATION_PENDING",
    "statusCode": 302,
    "redirectionData": {
      "uri": {
        "uri": "https://partner-api.grab.com/grabid/v1/oauth2/authorize?<REDACTED>"
      }
    },
    "connectorFeatureData": {
      "value": "{\"state\":\"<REDACTED>\",\"nonce\":\"<REDACTED>\",\"code_verifier\":\"<REDACTED>\",\"redirect_uri\":\"https://example.com/payment/response\",\"partner_tx_id\":\"<REDACTED_TRANSACTION_ID>\",\"currency\":\"PHP\",\"request_code\":\"<REDACTED>\"}"
    }
  },
  "createOrderResponse": {
    "connectorOrderId": "<REDACTED_REQUEST_CODE>",
    "status": "PENDING",
    "statusCode": 200
  },
  "compositeStatus": "COMPLETED"
}
2. Verify Redirect Response - Charge Success
grpcurl -plaintext \
  -H 'x-connector: grabpay' \
  -H 'x-connector-config: {"config":{"Grabpay":{"partner_id":"<REDACTED>","partner_secret":"<REDACTED>","client_id":"<REDACTED>","client_secret":"<REDACTED>","merchant_id":"<REDACTED>","base_url":"https://partner-api.grab.com/grabpay/partner/v2"}}}' \
  -d '{
    "merchantTransactionId": "<REDACTED_TRANSACTION_ID>",
    "merchantOrderId": "<REDACTED_TRANSACTION_ID>",
    "connectorOrderId": "<REDACTED_REQUEST_CODE>",
    "requestDetails": {
      "queryParams": "code=<REDACTED>&state=<REDACTED>"
    },
    "connectorFeatureData": {
      "value": "{\"state\":\"<REDACTED>\",\"nonce\":\"<REDACTED>\",\"code_verifier\":\"<REDACTED>\",\"redirect_uri\":\"https://example.com/payment/response\",\"partner_tx_id\":\"<REDACTED_TRANSACTION_ID>\",\"currency\":\"PHP\",\"request_code\":\"<REDACTED>\"}"
    },
    "amount": {
      "minorAmount": 1,
      "currency": "PHP"
    },
    "paymentMethod": {
      "grabpayRedirect": {}
    },
    "captureMethod": "AUTOMATIC",
    "address": {
      "billingAddress": {
        "countryAlpha2Code": "PH"
      }
    },
    "returnUrl": "https://example.com/payment/response",
    "testMode": false
  }' \
  localhost:8000 \
  types.CompositePaymentService/VerifyRedirectResponse

Response:

{
  "verifyRedirectResponse": {
    "rawConnectorResponse": {
      "value": "{\"code\":\"<REDACTED>\",\"state\":\"<REDACTED>\",\"error\":null}"
    },
    "connectorFeatureData": {
      "value": "<REDACTED_CONNECTOR_FEATURE_DATA>"
    }
  },
  "accessTokenResponse": {
    "accessToken": {
      "value": "<REDACTED_ACCESS_TOKEN>"
    },
    "tokenType": "Bearer",
    "expiresInSeconds": "31535999",
    "status": "OPERATION_STATUS_SUCCESS",
    "statusCode": 200
  },
  "authorizeResponse": {
    "connectorTransactionId": "<REDACTED_CONNECTOR_TRANSACTION_ID>",
    "status": "CHARGED",
    "statusCode": 200,
    "connectorFeatureData": {
      "value": "{\"txID\":\"<REDACTED_CONNECTOR_TRANSACTION_ID>\",\"status\":\"success\",\"paymentMethod\":\"GPWALLET\",\"description\":\"\",\"reason\":\"\"}"
    }
  }
}
3. Payment Sync - Success
grpcurl -plaintext \
  -H 'x-connector: grabpay' \
  -H 'x-connector-config: {"config":{"Grabpay":{"partner_id":"<REDACTED>","partner_secret":"<REDACTED>","client_id":"<REDACTED>","client_secret":"<REDACTED>","merchant_id":"<REDACTED>","base_url":"https://partner-api.grab.com/grabpay/partner/v2"}}}' \
  -d '{
    "connectorTransactionId": "<REDACTED_CONNECTOR_TRANSACTION_ID>",
    "merchantTransactionId": "<REDACTED_TRANSACTION_ID>",
    "state": {
      "accessToken": {
        "token": {
          "value": "<REDACTED_ACCESS_TOKEN>"
        },
        "expiresInSeconds": "31535999",
        "tokenType": "Bearer"
      }
    },
    "amount": {
      "minorAmount": 1,
      "currency": "PHP"
    },
    "paymentMethod": {
      "grabpayRedirect": {}
    },
    "paymentMethodType": "GRAB_PAY",
    "testMode": false
  }' \
  localhost:8000 \
  types.CompositePaymentService/Get

Response:

{
  "getResponse": {
    "connectorTransactionId": "<REDACTED_CONNECTOR_TRANSACTION_ID>",
    "status": "CHARGED",
    "statusCode": 200,
    "amount": {
      "minorAmount": "1",
      "currency": "PHP"
    },
    "connectorFeatureData": {
      "value": "{\"txID\":\"<REDACTED_CONNECTOR_TRANSACTION_ID>\",\"status\":\"success\",\"paymentMethod\":\"GPWALLET\",\"description\":\"\",\"txStatus\":\"success\",\"reason\":\"\"}"
    }
  }
}
4. Refund - Success
grpcurl -plaintext \
  -H 'x-connector: grabpay' \
  -H 'x-connector-config: {"config":{"Grabpay":{"partner_id":"<REDACTED>","partner_secret":"<REDACTED>","client_id":"<REDACTED>","client_secret":"<REDACTED>","merchant_id":"<REDACTED>","base_url":"https://partner-api.grab.com/grabpay/partner/v2"}}}' \
  -d '{
    "merchantRefundId": "<REDACTED_REFUND_ID>",
    "connectorTransactionId": "<REDACTED_TRANSACTION_ID>",
    "connectorOrderId": "<REDACTED_CONNECTOR_TRANSACTION_ID>",
    "paymentAmount": 100,
    "refundAmount": {
      "minorAmount": 1,
      "currency": "PHP"
    },
    "reason": "GrabPay test refund",
    "state": {
      "accessToken": {
        "token": {
          "value": "<REDACTED_ACCESS_TOKEN>"
        },
        "expiresInSeconds": "31535999",
        "tokenType": "Bearer"
      }
    },
    "paymentMethodType": "GRAB_PAY",
    "paymentMethod": {
      "grabpayRedirect": {}
    },
    "testMode": false
  }' \
  localhost:8000 \
  types.CompositePaymentService/Refund

Response:

{
  "refundResponse": {
    "connectorRefundId": "<REDACTED_REFUND_ID>",
    "status": "REFUND_SUCCESS",
    "statusCode": 200,
    "connectorTransactionId": "<REDACTED_TRANSACTION_ID>",
    "rawConnectorResponse": {
      "value": "{\"txID\":\"<REDACTED_CONNECTOR_REFUND_TRANSACTION_ID>\",\"status\":\"success\",\"paymentMethod\":\"GPWALLET\",\"description\":\"\",\"txStatus\":\"success\",\"reason\":\"\",\"echo\":null}"
    }
  }
}
5. Refund Sync - Success
grpcurl -plaintext \
  -H 'x-connector: grabpay' \
  -H 'x-connector-config: {"config":{"Grabpay":{"partner_id":"<REDACTED>","partner_secret":"<REDACTED>","client_id":"<REDACTED>","client_secret":"<REDACTED>","merchant_id":"<REDACTED>","base_url":"https://partner-api.grab.com/grabpay/partner/v2"}}}' \
  -d '{
    "connectorTransactionId": "<REDACTED_TRANSACTION_ID>",
    "refundId": "<REDACTED_REFUND_ID>",
    "connectorRefundId": "<REDACTED_REFUND_ID>",
    "refundAmount": {
      "minorAmount": 1,
      "currency": "PHP"
    },
    "state": {
      "accessToken": {
        "token": {
          "value": "<REDACTED_ACCESS_TOKEN>"
        },
        "expiresInSeconds": "31535999",
        "tokenType": "Bearer"
      }
    },
    "paymentMethodType": "GRAB_PAY",
    "paymentMethod": {
      "grabpayRedirect": {}
    },
    "testMode": false
  }' \
  localhost:8000 \
  types.CompositeRefundService/Get

Response:

{
  "refundResponse": {
    "merchantRefundId": "<REDACTED_REFUND_ID>",
    "connectorRefundId": "<REDACTED_REFUND_ID>",
    "status": "REFUND_SUCCESS",
    "statusCode": 200,
    "connectorTransactionId": "<REDACTED_TRANSACTION_ID>",
    "rawConnectorResponse": {
      "value": "{\"txID\":\"<REDACTED_CONNECTOR_REFUND_TRANSACTION_ID>\",\"status\":\"success\",\"paymentMethod\":\"GPWALLET\",\"description\":\"\",\"txStatus\":\"success\",\"reason\":\"\",\"echo\":null}"
    }
  }
}

Validation

  • cargo fmt --check
  • cargo test -p connector-integration -- grabpay
  • cargo check -p connector-integration -p composite-service -p grpc-server

@peeyushshukla-juspay
peeyushshukla-juspay requested review from a team as code owners August 5, 2026 07:27
peeyushshukla-juspay and others added 25 commits August 5, 2026 13:49
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
kanikachaudhary199 and others added 4 commits August 7, 2026 19:20
Clippy with -D warnings (CI) rejected the fully-qualified
hyperswitch_masking::Secret in should_do_session_token; Secret is already
imported.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…egration

# Conflicts:
#	config/development.toml
#	config/production.toml
#	config/sandbox.toml
#	crates/integrations/connector-integration/src/connectors/stripe/transformers.rs
#	crates/types-traits/domain_types/src/connector_types.rs
#	crates/types-traits/grpc-api-types/proto/payment.proto
#	sdk/javascript/src/payments/_generated_grpc_client.ts
…payload

Follow the same pattern as the initial authorize flow: fold the verify-redirect
response's connector_feature_data (which carries the redirect callback, e.g. the
OAuth code) into the payload once, then pass the payload straight to the
access/session token steps — instead of cloning + mutating a per-call payload
inside authorize_post_redirect.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Comment thread crates/integrations/connector-integration/src/connectors/grabpay.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay/transformers.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay/transformers.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay/transformers.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay/transformers.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay/transformers.rs Outdated
hyperswitch-bot Bot and others added 11 commits August 7, 2026 14:40
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Comment thread crates/integrations/connector-integration/src/connectors/grabpay/transformers.rs Outdated
@kanikac199

kanikac199 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

request_code field (line 202) and its request_code: None init (line 1295) are unused, please drop them.

kanikac199
kanikac199 previously approved these changes Aug 7, 2026
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
Comment thread crates/internal/composite-service/src/payments.rs Outdated
Comment on lines +340 to +352
fn session_token_from_connector_feature_data(
connector_feature_data: Option<&common_utils::pii::SecretSerdeValue>,
) -> Option<String> {
let metadata =
utils::to_connector_meta_from_secret::<serde_json::Value>(connector_feature_data.cloned())
.ok()?;

metadata
.get("session_token")
.or_else(|| metadata.get("access_token"))
.and_then(serde_json::Value::as_str)
.map(ToOwned::to_owned)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

please raise an issue to revert this once Euler side changes for session token is done

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

already created a ticket 👍

Comment thread crates/integrations/connector-integration/src/connectors/grabpay.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay.rs Outdated
Comment thread crates/integrations/connector-integration/src/connectors/grabpay/transformers.rs Outdated
peeyushshukla-juspay and others added 3 commits August 8, 2026 13:16
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
kanikac199
kanikac199 previously approved these changes Aug 8, 2026
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
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.

5 participants