diff --git a/docs/developers/apis/apple-native-payment.api.mdx b/docs/developers/apis/apple-native-payment.api.mdx index 7e9290e..f02c7ed 100644 --- a/docs/developers/apis/apple-native-payment.api.mdx +++ b/docs/developers/apis/apple-native-payment.api.mdx @@ -5,7 +5,7 @@ description: "Allows merchants to submit an Apple Pay payment directly via serve sidebar_label: "Native Payment API(Apple Pay)" hide_title: true hide_table_of_contents: true -api: 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 +api: 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 sidebar_class_name: "post api-method" info_path: developers/apis/ottu-api custom_edit_url: null @@ -48,6 +48,8 @@ Typical use case: The merchant collects the Apple Pay token on their frontend an | [Basic Auth](/developers/getting-started/authentication/#basic-auth) | `Can add payment requests` or `Can add e-commerce payments` | +
{"curl --location 'https://sandbox.ottu.net/b/pbl/v2/payment/apple-pay/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n  \"payload\": {\n    \"paymentData\": {\n      \"version\": \"string\",\n      \"data\": \"string\",\n      \"signature\": \"string\",\n      \"header\": {\n        \"ephemeralPublicKey\": \"string\",\n        \"wrappedKey\": \"string\",\n        \"publicKeyHash\": \"string\",\n        \"transactionId\": \"string\"\n      }\n    },\n    \"paymentMethod\": {\n      \"displayName\": \"string\",\n      \"network\": \"string\",\n      \"type\": \"string\"\n    },\n    \"transactionIdentifier\": \"string\"\n  },\n  \"pg_code\": \"string\",\n  \"session_id\": \"string\"\n}'"}
+ {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/payment/auto-debit/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"session_id\": \"string\",\n \"token\": \"string\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/auto-debit/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"session_id\": \"string\",\n \"token\": \"string\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/payment/cash/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"session_id\": \"string\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/cash-payment/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"session_id\": \"string\"\n}'"} + **Gateway permission**: `Can use pg_code` for the target [payment gateway](/developers/payments/payment-methods/) +
{"curl --location 'https://sandbox.ottu.net/b/invoice/v1/invoice/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n  \"type\": \"payment_request\",\n  \"invoice_number\": \"INV-001\",\n  \"due_date\": \"2030-12-31\",\n  \"currency_code\": \"KWD\",\n  \"pg_codes\": [\n    \"knet\"\n  ],\n  \"invoice_items\": [\n    {\n      \"sku\": \"ITEM-001\",\n      \"description\": \"Product description\",\n      \"unit_price\": \"10.000\",\n      \"quantity\": \"1\"\n    }\n  ]\n}'"}
+ {"curl --location 'https://sandbox.ottu.net/b/checkout/v1/pymt-txn/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"type\": \"e_commerce\",\n \"amount\": \"10.000\",\n \"currency_code\": \"KWD\",\n \"pg_codes\": [\n \"knet\"\n ]\n}'"} + {"curl --location --globoff --request DELETE 'https://sandbox.ottu.net/b/pbl/v2/card/{token}/?customer_id={customer_id}&type={type}' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY'"} + {"curl --location --globoff 'https://sandbox.ottu.net/b/api/v1/reports/files/{token}/download/' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY'"} + {"curl --location --globoff --request PUT 'https://sandbox.ottu.net/b/checkout/v1/pymt-txn/{session_id}/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data-raw '{\n \"amount\": \"string\",\n \"currency_code\": \"string\",\n \"pg_codes\": [\n \"string\"\n ],\n \"type\": \"e_commerce\",\n \"billing_address\": {\n \"line1\": \"string\",\n \"line2\": \"string\",\n \"city\": \"string\",\n \"state\": \"string\",\n \"country\": \"AF\",\n \"postal_code\": \"string\"\n },\n \"branding_options\": {\n \"payment_methods\": {}\n },\n \"loyalty\": {\n \"enabled\": true,\n \"reference\": \"string\",\n \"metadata\": {}\n },\n \"shipping_address\": {\n \"line1\": \"string\",\n \"line2\": \"string\",\n \"city\": \"string\",\n \"state\": \"string\",\n \"country\": \"AF\",\n \"postal_code\": \"string\",\n \"first_name\": \"string\",\n \"last_name\": \"string\",\n \"email\": \"user@example.com\",\n \"phone\": \"string\"\n },\n \"agreement\": {\n \"id\": \"string\",\n \"amount_variability\": \"fixed\",\n \"start_date\": \"2024-07-29\",\n \"expiry_date\": \"2024-07-29\",\n \"max_amount_per_cycle\": \"string\",\n \"cycle_interval_days\": 0,\n \"total_cycles\": 0,\n \"frequency\": \"irregular\",\n \"type\": \"recurring\",\n \"seller\": {\n \"name\": \"string\",\n \"short_name\": \"string\",\n \"category_code\": \"string\"\n }\n },\n \"attachment\": \"string\",\n \"attachment_upload_url\": \"string\",\n \"card_acceptance_criteria\": {\n \"min_expiry_time\": 0\n },\n \"customer_birthdate\": \"2024-07-29\",\n \"customer_email\": \"user@example.com\",\n \"customer_first_name\": \"string\",\n \"customer_id\": \"string\",\n \"customer_last_name\": \"string\",\n \"customer_phone\": \"string\",\n \"customer_phone_2\": \"string\",\n \"due_datetime\": \"2024-07-29T15:51:28.071Z\",\n \"email_recipients\": [\n \"user@example.com\"\n ],\n \"expiration_time\": \"string\",\n \"generate_qr_code\": false,\n \"include_sdk_setup_preload\": false,\n \"initiator_id\": 0,\n \"language\": \"en\",\n \"notifications\": {\n \"email\": [\n \"created\"\n ],\n \"sms\": [\n \"created\"\n ],\n \"whatsapp\": [\n \"created\"\n ]\n },\n \"order_no\": \"string\",\n \"payment_instrument\": {\n \"instrument_type\": \"apple_pay\",\n \"payload\": {\n \"paymentData\": {\n \"version\": \"string\",\n \"data\": \"string\",\n \"signature\": \"string\",\n \"header\": {\n \"ephemeralPublicKey\": \"string\",\n \"publicKeyHash\": \"string\",\n \"transactionId\": \"string\"\n }\n },\n \"paymentMethod\": {\n \"displayName\": \"string\",\n \"network\": \"string\",\n \"type\": \"string\"\n },\n \"transactionIdentifier\": \"string\"\n }\n },\n \"payment_type\": \"one_off\",\n \"preload_checkout_page\": false,\n \"product_type\": \"string\",\n \"redirect_url\": \"string\",\n \"shortify_attachment_url\": false,\n \"shortify_checkout_url\": false,\n \"unit_code\": \"string\",\n \"vendor_name\": \"string\",\n \"webhook_url\": \"string\"\n}'"} + **Gateway permission**: `Can use pg_code` — grants access to the specific [payment gateway](/developers/payments/payment-methods/) (e.g., "Can use Credit Card") +
{"curl --location 'https://sandbox.ottu.net/b/pbl/v2/payment-methods/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n  \"plugin\": \"payment_request\",\n  \"operation\": \"purchase\",\n  \"currencies\": [\n    \"KWD\"\n  ],\n  \"type\": \"sandbox\",\n  \"tags\": [\n    \"demo\"\n  ]\n}'"}
+ {"curl --location --globoff 'https://sandbox.ottu.net/b/checkout/api/sdk/v1/pre-payment-option-check/{session_id}/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"pg_code\": \"string\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/card/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"type\": \"sandbox\",\n \"customer_id\": \"sandbox\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/payment/google-pay/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data-raw '{\n \"payload\": {\n \"apiVersion\": 0,\n \"apiVersionMinor\": 0,\n \"paymentMethodData\": {\n \"type\": \"string\",\n \"description\": \"string\",\n \"info\": {},\n \"tokenizationData\": {}\n },\n \"email\": \"user@example.com\",\n \"shippingAddress\": {}\n },\n \"pg_code\": \"string\",\n \"session_id\": \"string\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/inquiry/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"order_no\": \"string\",\n \"session_id\": \"string\"\n}'"} + {"curl --location --globoff 'https://sandbox.ottu.net/b/api/v1/reports/files/?created_after={created_after}&created_before={created_before}&interval={interval}&limit={limit}&offset={offset}&source={source}' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/message-notification/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"session_id\": \"string\",\n \"order_no\": \"string\",\n \"channels\": [\n \"sms\",\n \"email\"\n ]\n}'"} + {"curl --location --globoff --request PATCH 'https://sandbox.ottu.net/b/checkout/v1/pymt-txn/{session_id}/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data-raw '{\n \"amount\": \"string\",\n \"currency_code\": \"string\",\n \"pg_codes\": [\n \"string\"\n ],\n \"type\": \"e_commerce\",\n \"billing_address\": {\n \"line1\": \"string\",\n \"line2\": \"string\",\n \"city\": \"string\",\n \"state\": \"string\",\n \"country\": \"AF\",\n \"postal_code\": \"string\"\n },\n \"branding_options\": {\n \"payment_methods\": {}\n },\n \"loyalty\": {\n \"enabled\": true,\n \"reference\": \"string\",\n \"metadata\": {}\n },\n \"shipping_address\": {\n \"line1\": \"string\",\n \"line2\": \"string\",\n \"city\": \"string\",\n \"state\": \"string\",\n \"country\": \"AF\",\n \"postal_code\": \"string\",\n \"first_name\": \"string\",\n \"last_name\": \"string\",\n \"email\": \"user@example.com\",\n \"phone\": \"string\"\n },\n \"agreement\": {\n \"id\": \"string\",\n \"amount_variability\": \"fixed\",\n \"start_date\": \"2024-07-29\",\n \"expiry_date\": \"2024-07-29\",\n \"max_amount_per_cycle\": \"string\",\n \"cycle_interval_days\": 0,\n \"total_cycles\": 0,\n \"frequency\": \"irregular\",\n \"type\": \"recurring\",\n \"seller\": {\n \"name\": \"string\",\n \"short_name\": \"string\",\n \"category_code\": \"string\"\n }\n },\n \"attachment\": \"string\",\n \"attachment_upload_url\": \"string\",\n \"card_acceptance_criteria\": {\n \"min_expiry_time\": 0\n },\n \"customer_birthdate\": \"2024-07-29\",\n \"customer_email\": \"user@example.com\",\n \"customer_first_name\": \"string\",\n \"customer_id\": \"string\",\n \"customer_last_name\": \"string\",\n \"customer_phone\": \"string\",\n \"customer_phone_2\": \"string\",\n \"due_datetime\": \"2024-07-29T15:51:28.071Z\",\n \"email_recipients\": [\n \"user@example.com\"\n ],\n \"expiration_time\": \"string\",\n \"generate_qr_code\": false,\n \"include_sdk_setup_preload\": false,\n \"initiator_id\": 0,\n \"language\": \"en\",\n \"notifications\": {\n \"email\": [\n \"created\"\n ],\n \"sms\": [\n \"created\"\n ],\n \"whatsapp\": [\n \"created\"\n ]\n },\n \"order_no\": \"string\",\n \"payment_instrument\": {\n \"instrument_type\": \"apple_pay\",\n \"payload\": {\n \"paymentData\": {\n \"version\": \"string\",\n \"data\": \"string\",\n \"signature\": \"string\",\n \"header\": {\n \"ephemeralPublicKey\": \"string\",\n \"publicKeyHash\": \"string\",\n \"transactionId\": \"string\"\n }\n },\n \"paymentMethod\": {\n \"displayName\": \"string\",\n \"network\": \"string\",\n \"type\": \"string\"\n },\n \"transactionIdentifier\": \"string\"\n }\n },\n \"payment_type\": \"one_off\",\n \"preload_checkout_page\": false,\n \"product_type\": \"string\",\n \"redirect_url\": \"string\",\n \"shortify_attachment_url\": false,\n \"shortify_checkout_url\": false,\n \"unit_code\": \"string\",\n \"vendor_name\": \"string\",\n \"webhook_url\": \"string\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/operation/' \\\n--header 'Tracking-Key: Tracking-Key: your_operation_tracking_key' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"order_no\": \"string\",\n \"session_id\": \"string\",\n \"operation\": \"delete\",\n \"amount\": \"string\",\n \"extra\": {},\n \"destination\": \"pg\"\n}'"} + {"curl --location --globoff 'https://sandbox.ottu.net/b/checkout/v1/pymt-txn/{session_id}/' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/send-notification/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data-raw '{\n \"channel\": \"email\",\n \"template_id\": \"payment-request-mail\",\n \"to\": \"customer@example.com\"\n}'"} + {"curl --location --globoff 'https://sandbox.ottu.net/b/pbl/v2/notifications/send/{channel}/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data-raw '{\n \"template_id\": \"payment-request-mail\",\n \"to\": \"customer@example.com\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/checkout/v1/upload-attachment/' \\\n--header 'Content-Type: multipart/form-data' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--form 'file=@\"/path/to/file\"' \\\n--form 'shortify_attachment_url=\"false\"' \\\n--form 'order_no=\"\"' \\\n--form 'session_id=\"\"'"} + {"curl --location 'https://sandbox.ottu.net/b/wallet/ottu/v1/accounts/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"customer_id\": \"sandbox-usd\",\n \"currency\": \"USD\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/wallet/ottu/v1/entries/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"customer_id\": \"sandbox-usd\",\n \"currency\": \"USD\"\n}'"} + {"curl --location --globoff 'https://sandbox.ottu.net/b/checkout/v1/wallet/payment-sessions/{session_id}/finalization-status/' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY'"} + {"curl --location 'https://sandbox.ottu.net/b/pbl/v2/payment/wallet/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"payload\": {},\n \"pg_code\": \"string\",\n \"session_id\": \"string\"\n}'"} + {"curl --location 'https://sandbox.ottu.net/b/wallet/ottu/v1/operations/' \\\n--header 'Content-Type: application/json' \\\n--header 'Accept: application/json' \\\n--header 'Authorization: Api-Key YOUR_API_KEY' \\\n--data '{\n \"operation_id\": 0\n}'"} + .ottu.net/b/checkout/v1/pymt-txn/ There are no separate sandbox and production URLs. The **MID (Merchant Identification Number)** configuration in the Ottu admin panel determines whether a payment gateway runs in sandbox or production mode. You can test with: - **Your own instance** — configure a MID as sandbox in the admin panel. Recommended for testing your specific gateway configuration. -- **Shared sandbox** — `ksa.ottu.dev` has all payment gateways active in sandbox mode. Useful for quick tests without configuring your own instance. +- **Shared sandbox** — `sandbox.ottu.net` has all payment gateways active in sandbox mode. Useful for quick tests without configuring your own instance. ::: ## API Endpoints @@ -197,7 +197,7 @@ When you exceed the limit, the API returns `429 Too Many Requests`. Implement ex | Option | URL | Best for | |--------|-----|----------| -| **Shared sandbox** | `ksa.ottu.dev` | Quick tests — all gateways active, public credentials available | +| **Shared sandbox** | `sandbox.ottu.net` | Quick tests — all gateways active, public credentials available | | **Your own instance** | `.ottu.net` | Integration testing — verify your specific MID and gateway configuration | **Recommended workflow:** Start with the shared sandbox for rapid prototyping, then switch to your own instance to test with your actual gateway configuration before going live. diff --git a/docs/developers/payments/checkout-sdk/web.mdx b/docs/developers/payments/checkout-sdk/web.mdx index 2113432..2052925 100644 --- a/docs/developers/payments/checkout-sdk/web.mdx +++ b/docs/developers/payments/checkout-sdk/web.mdx @@ -251,7 +251,7 @@ Checkout.init({ ```javascript Checkout.init({ selector: "checkout", - merchant_id: 'ksa.ottu.dev', // use your merchant id + merchant_id: 'sandbox.ottu.net', // use your merchant id session_id: 'session_id', apiKey: 'apiKey', theme: { @@ -338,7 +338,7 @@ Checkout.init({ ```javascript Checkout.init({ selector: "checkout", - merchant_id: "ksa.ottu.dev", // use your merchant id + merchant_id: "sandbox.ottu.net", // use your merchant id session_id: "session_id", apiKey: "apiKey", theme: { @@ -379,7 +379,7 @@ Checkout.init({ ```javascript Checkout.init({ selector: "checkout", - merchant_id: "ksa.ottu.dev", // use your merchant id + merchant_id: "sandbox.ottu.net", // use your merchant id session_id: "session_id", apiKey: "apiKey", googlePayInit: { @@ -447,7 +447,7 @@ Checkout.init({ ```javascript Checkout.init({ selector: "checkout", - merchant_id: "ksa.ottu.dev", // use your merchant id + merchant_id: "sandbox.ottu.net", // use your merchant id session_id: "session_id", apiKey: "apiKey", theme: { @@ -480,7 +480,7 @@ However, Google Pay supports an additional property `buttonSizeMode` property, w ```javascript Checkout.init({ selector: "checkout", - merchant_id: "ksa.ottu.dev", // use your merchant id + merchant_id: "sandbox.ottu.net", // use your merchant id session_id: "session_id", apiKey: "apiKey", theme: { @@ -559,7 +559,7 @@ However, `stcPay` and `urPay` can supported any `css` collor in `buttonColor.` ```javascript Checkout.init({ selector: "checkout", - merchant_id: "ksa.ottu.dev", // use your merchant id + merchant_id: "sandbox.ottu.net", // use your merchant id session_id: "session_id", apiKey: "apiKey", lang: "en", @@ -617,7 +617,7 @@ In addition to above properties, users have the capability to customize the Appl ```javascript Checkout.init({ selector: "checkout", - merchant_id: 'ksa.ottu.dev', // use your merchant id + merchant_id: 'sandbox.ottu.net', // use your merchant id session_id: 'session_id', apiKey: 'apiKey', // Default values configured for Apple Pay @@ -958,7 +958,7 @@ Onsite Checkout is loaded when `'jazz'` is part of the [`formsOfPayment`](#forms ```javascript Checkout.init({ selector: "checkout", - merchant_id: "ksa.ottu.dev", // use your merchant id + merchant_id: "sandbox.ottu.net", // use your merchant id apiKey: "", session_id: "", formsOfPayment: ["jazz", "tokenPay", "applePay"], @@ -1238,7 +1238,7 @@ window.successCallback = (data) => { }; Checkout.init({ selector: "checkout", - merchant_id: "ksa.ottu.dev", // use your merchant id + merchant_id: "sandbox.ottu.net", // use your merchant id session_id: "session_id", apiKey: "apiKey", }); @@ -1588,7 +1588,7 @@ function unfreezeBasket() { Checkout.init({ selector: "checkout", - merchant_id: "ksa.ottu.dev", // use your merchant id + merchant_id: "sandbox.ottu.net", // use your merchant id session_id: "session_id", apiKey: "apiKey", lang: "en", @@ -1694,7 +1694,7 @@ Checkout init function ```javascript Checkout.init({ selector: "checkout", - merchant_id: "ksa.ottu.dev", // use your merchant id + merchant_id: "sandbox.ottu.net", // use your merchant id session_id: "session_id", apiKey: "apiKey", lang: "en", // en or ar default en diff --git a/mcp-server/config.mjs b/mcp-server/config.mjs index 71bae50..1aeeba1 100644 --- a/mcp-server/config.mjs +++ b/mcp-server/config.mjs @@ -17,3 +17,20 @@ export const KSA_OTTU_DEV = { clientSecretEnvVar: "KSA_KEYCLOAK_CLIENT_SECRET", }, }; + +// Active docs merchant — the WalletDemo seeds wallet credit here. Shares the +// wallet service + Keycloak host with KSA; only the realm, merchant id, and +// secret differ. Confirmed in Keycloak (auth.ottu.dev): realm +// `sandbox.ottu.net`, client `backend` (Client Id and Secret authenticator). +export const SANDBOX_OTTU_NET = { + merchantId: "sandbox.ottu.net", + walletUrl: "https://wallet.ottu.dev", + keycloak: { + url: "https://auth.ottu.dev", + realm: "sandbox.ottu.net", + clientId: "backend", + // Client secret resolved from process.env.SANDBOX_KEYCLOAK_CLIENT_SECRET + // at the call site (mcp-server/server.mjs handleSeedWallet). + clientSecretEnvVar: "SANDBOX_KEYCLOAK_CLIENT_SECRET", + }, +}; diff --git a/mcp-server/server.mjs b/mcp-server/server.mjs index e96d703..36e6acc 100644 --- a/mcp-server/server.mjs +++ b/mcp-server/server.mjs @@ -3,7 +3,7 @@ import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; import { McpDocsServer } from "docusaurus-plugin-mcp-server"; -import { KSA_OTTU_DEV } from "./config.mjs"; +import { SANDBOX_OTTU_NET } from "./config.mjs"; import { getKeycloakToken } from "./keycloak.mjs"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -142,7 +142,7 @@ async function handleSeedWallet(req, res) { return; } - const merchant = KSA_OTTU_DEV; + const merchant = SANDBOX_OTTU_NET; let token; try { token = await getKeycloakToken({ diff --git a/package-lock.json b/package-lock.json index 20fd7fd..f0aca98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,12 +25,16 @@ "sass": "^1.98.0" }, "devDependencies": { + "@apidevtools/json-schema-ref-parser": "^15.3.5", "@docusaurus/module-type-aliases": "^3.10.0", "@docusaurus/tsconfig": "^3.10.0", "@docusaurus/types": "^3.10.0", "@types/js-yaml": "^4.0.9", "docusaurus-plugin-openapi-docs": "^5.0.0", "docusaurus-theme-openapi-docs": "^5.0.0", + "openapi-to-postmanv2": "^6.0.0", + "postman-code-generators": "^2.1.0", + "postman-collection": "^5.2.0", "tsx": "^4.21.0", "typescript": "^6.0.2" }, diff --git a/package.json b/package.json index d72cd44..221921b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "fetch-api": "tsx scripts/fetch-api-schema.ts", "enrich-api": "tsx scripts/enrich-api-spec.ts", "extract-schemas": "tsx scripts/extract-schema.ts SchemaWebhook PaymentOperationResponses", - "gen-api": "npm run enrich-api && npx docusaurus clean-api-docs ottuApi && npx docusaurus gen-api-docs ottuApi && npm run extract-schemas", + "inject-mcp-hints": "tsx scripts/inject-mcp-hints.ts", + "gen-api": "npm run enrich-api && npx docusaurus clean-api-docs ottuApi && npx docusaurus gen-api-docs ottuApi && npm run extract-schemas && npm run inject-mcp-hints", "update-api": "npm run fetch-api && npm run gen-api", "start": "docusaurus start", "build": "docusaurus build && cp -r build/mcp build/_mcp-data", @@ -38,12 +39,16 @@ "sass": "^1.98.0" }, "devDependencies": { + "@apidevtools/json-schema-ref-parser": "^15.3.5", "@docusaurus/module-type-aliases": "^3.10.0", "@docusaurus/tsconfig": "^3.10.0", "@docusaurus/types": "^3.10.0", "@types/js-yaml": "^4.0.9", "docusaurus-plugin-openapi-docs": "^5.0.0", "docusaurus-theme-openapi-docs": "^5.0.0", + "openapi-to-postmanv2": "^6.0.0", + "postman-code-generators": "^2.1.0", + "postman-collection": "^5.2.0", "tsx": "^4.21.0", "typescript": "^6.0.2" }, diff --git a/scripts/enrich-api-spec.ts b/scripts/enrich-api-spec.ts index bcb6b55..ef23d13 100644 --- a/scripts/enrich-api-spec.ts +++ b/scripts/enrich-api-spec.ts @@ -620,6 +620,14 @@ function processSource(name: string, config: SourceConfig): void { info("Resolving template variables..."); const enrichedSpec = resolveVariablesDeep(spec, variables); + // 9b. Point the API-explorer "Base URL" at the docs sandbox host. The raw + // spec's servers come from Ottu core (e.g. ksa.ottu.dev); override them here + // so the value is controlled by `sandboxUrl` in _variables.yaml and survives + // a re-fetch of the raw spec. + if (variables.sandboxUrl) { + enrichedSpec.servers = [{ url: variables.sandboxUrl }]; + } + // 10. Write output info("Writing enriched spec..."); const output = yaml.dump(enrichedSpec, { diff --git a/scripts/inject-mcp-hints.ts b/scripts/inject-mcp-hints.ts new file mode 100644 index 0000000..032a5a8 --- /dev/null +++ b/scripts/inject-mcp-hints.ts @@ -0,0 +1,297 @@ +/** + * MCP Curl Example Injector + * + * Auto-generates a runnable curl example for every API operation in the + * enriched OpenAPI spec — using the same conversion and snippet-generation + * pipeline the interactive ApiExplorer uses under the hood (openapi-to-postmanv2 + * to build a Postman collection, postman-code-generators to render the curl, + * and the openapi-docs plugin's own sampleRequestFromSchema for body examples) + * — and injects each one as a visually-hidden into the matching + * generated .api.mdx file. + * + * The ApiExplorer already renders an interactive curl example for human + * readers, so this hidden copy exists purely so the MCP server's static-HTML + * indexer can return a usable request example via docs_fetch, without + * duplicating it visibly on the page. + * + * Runs after docusaurus gen-api-docs as part of npm run gen-api. + * Reads from: static/Ottu_API_enriched.yaml (written by npm run enrich-api) + * Patches: docs/developers/apis/*.api.mdx (written by docusaurus gen-api-docs) + */ + +import * as fs from "node:fs"; +import * as path from "node:path"; +import * as yaml from "js-yaml"; +import RefParser from "@apidevtools/json-schema-ref-parser"; +import openapiToPostman from "openapi-to-postmanv2"; +// @ts-expect-error — no published type declarations +import sdk from "postman-collection"; +// @ts-expect-error — no published type declarations +import codegen from "postman-code-generators"; +import { sampleRequestFromSchema } from "docusaurus-plugin-openapi-docs/lib/openapi/createRequestExample.js"; + +const ROOT = path.resolve(__dirname, ".."); +const SOURCES_FILE = path.join(ROOT, "static", "api-sources.yaml"); +const API_DOCS_DIR = path.join(ROOT, "docs", "developers", "apis"); + +// Whitespace/indentation-agnostic: matches `; +} + +interface OperationMatcher { + operationId: string; + method: string; + pathRegex: RegExp; + operation: any; +} + +function operationIdToFilename(operationId: string): string { + return operationId.replace(/_/g, "-") + ".api.mdx"; +} + +// Same templating as the openapi-docs plugin's bindCollectionToApiItems — +// turns "/foo/{id}/bar" into a regex that matches "/foo//bar". +function pathTemplateToRegex(pathTemplate: string): RegExp { + const withTokens = pathTemplate.replace(/\{[^}]+\}/g, "__OPENAPI_PATH_PARAM__"); + const escaped = withTokens.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const pattern = escaped.replace(/__OPENAPI_PATH_PARAM__/g, "[^/]+"); + return new RegExp(`^${pattern}$`); +} + +function buildOperationMatchers(spec: any): OperationMatcher[] { + const matchers: OperationMatcher[] = []; + for (const [pathTemplate, pathItem] of Object.entries(spec.paths || {})) { + for (const method of HTTP_METHODS) { + const operation = pathItem[method]; + if (operation?.operationId) { + matchers.push({ + operationId: operation.operationId, + method, + pathRegex: pathTemplateToRegex(pathTemplate), + operation, + }); + } + } + } + return matchers; +} + +// Mirrors the openapi-docs plugin's createPostmanCollection: strip servers +// (they break the conversion) and run the spec through openapi-to-postmanv2. +async function buildPostmanCollection(spec: any): Promise { + const data = JSON.parse(JSON.stringify(spec)); + delete data.servers; + for (const pathItem of Object.values(data.paths || {})) { + delete pathItem.servers; + for (const method of HTTP_METHODS) delete pathItem[method]?.servers; + } + return new Promise((resolve, reject) => { + const schemaPack = new openapiToPostman.SchemaPack({ type: "json", data }, { schemaFaker: false }); + schemaPack.convert((err: any, result: any) => { + if (err || !result?.result) return reject(err || result?.reason); + resolve(new sdk.Collection(result.output[0].data)); + }); + }); +} + +function collectionItems(collection: any): any[] { + const items: any[] = []; + collection.forEachItem((item: any) => items.push(item)); + return items; +} + +// Point the request at the real sandbox host, turn placeholder path/query +// values into readable {param} templates, and attach the API key header — +// the same masked-credential placeholder shape the ApiExplorer shows. +function applyServerAndAuth(request: any, baseUrl: string): void { + const parsed = new URL(`https://${baseUrl.replace(/^https?:\/\//, "")}`); + request.url.protocol = parsed.protocol.replace(":", ""); + request.url.host = parsed.hostname.split("."); + request.url.variables.each((variable: any) => { + variable.value = `{${variable.key}}`; + }); + request.url.query.each((param: any) => { + param.value = `{${param.key}}`; + }); + request.headers.add({ key: "Authorization", value: "Api-Key YOUR_API_KEY" }); +} + +// Reuse the plugin's own example generator so the body in the curl matches +// the example shown in the page's request schema — only handles JSON bodies, +// which covers every write endpoint that matters for an MCP example. +function applyJsonBody(request: any, operation: any): void { + const jsonContent = operation.requestBody?.content?.["application/json"]; + if (!jsonContent?.schema) return; + const example = sampleRequestFromSchema(jsonContent.schema); + if (example === undefined) return; + request.body = new sdk.RequestBody({ + mode: "raw", + raw: JSON.stringify(example, null, 2), + options: { raw: { language: "json" } }, + }); + request.headers.upsert({ key: "Content-Type", value: "application/json" }); +} + +function generateCurl(request: any): Promise { + return new Promise((resolve, reject) => { + codegen.convert("curl", "cURL", request, CURL_OPTIONS, (err: any, snippet: string) => { + if (err) return reject(err); + resolve(snippet); + }); + }); +} + +function injectSpan(mdxContent: string, curl: string): string | null { + // Curl text contains literal `{`/`}` (path templates, JSON bodies), which + // MDX would otherwise try to parse as JS expressions in raw text. Wrapping + // it as a JS string expression — {"..."} — sidesteps that entirely. + // + //
, not : the MCP plugin converts page HTML to Markdown via
+  // rehype-remark/remark-stringify, which escapes `_` and `:` in plain text
+  // nodes (CommonMark rules) — turning `session_id` and `https://` into
+  // `session\_id` and `https\://` in the docs_fetch output. Code blocks are
+  // emitted verbatim, so 
 keeps the curl copy-paste-safe.
+  const span = `${INJECTED_MARKER}{${JSON.stringify(curl)}}
\n\n`; + const match = INJECTION_ANCHOR.exec(mdxContent); + if (!match) return null; + return mdxContent.slice(0, match.index) + span + mdxContent.slice(match.index); +} + +interface SourceResult { + injected: number; + failures: string[]; + // Set when the whole source couldn't be processed at all — distinct from + // `failures`, which are per-operation. One bad source means every + // operation in it was skipped, not "N operations failed." + error?: string; +} + +async function processSource(enrichedSpecPath: string): Promise { + if (!fs.existsSync(enrichedSpecPath)) { + console.error(` ERROR: Enriched spec not found: ${enrichedSpecPath}`); + console.error(` Run "npm run enrich-api" first.`); + process.exit(1); + } + + const spec = yaml.load(fs.readFileSync(enrichedSpecPath, "utf-8")) as any; + const baseUrl = spec.servers?.[0]?.url; + if (!baseUrl) { + return { injected: 0, failures: [], error: "Spec has no servers[0].url — skipping curl generation for all operations" }; + } + + // Dereferenced copy: operation matching and body example generation both + // need resolved $refs (sampleRequestFromSchema can't fake a bare $ref). + const dereferenced = await RefParser.dereference(JSON.parse(JSON.stringify(spec)), { + mutateInputSchema: false, + }); + const matchers = buildOperationMatchers(dereferenced); + const collection = await buildPostmanCollection(spec); + + let injected = 0; + const failures: string[] = []; + + for (const item of collectionItems(collection)) { + const request = item.request; + const method = request.method.toLowerCase(); + const requestPath = request.url.getPath({ unresolved: true }); + const matcher = matchers.find((m) => m.method === method && m.pathRegex.test(requestPath)); + if (!matcher) continue; + + applyServerAndAuth(request, baseUrl); + applyJsonBody(request, matcher.operation); + + let curl: string; + try { + curl = await generateCurl(request); + } catch (err) { + failures.push(`Failed to generate curl for ${matcher.operationId}: ${err}`); + continue; + } + + const filename = operationIdToFilename(matcher.operationId); + const mdxPath = path.join(API_DOCS_DIR, filename); + if (!fs.existsSync(mdxPath)) { + failures.push(`No .api.mdx found for ${matcher.operationId} (expected ${filename})`); + continue; + } + + const original = fs.readFileSync(mdxPath, "utf-8"); + if (original.includes(INJECTED_MARKER)) continue; + + const patched = injectSpan(original, curl); + if (patched === null) { + failures.push(`Injection anchor not found in ${filename}`); + continue; + } + + fs.writeFileSync(mdxPath, patched, "utf-8"); + console.log(` Injected curl example into ${filename}`); + injected++; + } + + return { injected, failures }; +} + +async function main(): Promise { + console.log("\nMCP Curl Example Injector"); + + const config = yaml.load(fs.readFileSync(SOURCES_FILE, "utf-8")) as ApiSourcesConfig; + let total = 0; + const failures: string[] = []; + const sourceErrors: string[] = []; + + for (const [name, source] of Object.entries(config.sources)) { + console.log(`\n ── ${name} ──`); + const enrichedSpecPath = path.resolve(ROOT, source.enrichedOutput); + const result = await processSource(enrichedSpecPath); + total += result.injected; + failures.push(...result.failures); + if (result.error) sourceErrors.push(`${name}: ${result.error}`); + } + + if (sourceErrors.length > 0) { + console.error(`\n ${sourceErrors.length} source(s) could not be processed:`); + for (const error of sourceErrors) console.error(` - ${error}`); + } + + if (failures.length > 0) { + console.error(`\n ${failures.length} curl example(s) failed to inject:`); + for (const failure of failures) console.error(` - ${failure}`); + } + + if (sourceErrors.length > 0 || failures.length > 0) { + process.exit(1); + } + + console.log(`\n Done — ${total} file(s) patched\n`); +} + +main(); diff --git a/src/components/WalletDemo/WalletDemoInner.tsx b/src/components/WalletDemo/WalletDemoInner.tsx index 8711e94..5396ef5 100644 --- a/src/components/WalletDemo/WalletDemoInner.tsx +++ b/src/components/WalletDemo/WalletDemoInner.tsx @@ -111,7 +111,7 @@ export default function WalletDemoInner() { if (pgCodes.length === 0) { dispatch({ type: "ERROR", - message: `No wallet-capable gateways for ${WALLET_DEMO.currency} on the active merchant. Enable a PG with payment_services: ["wallet"] tagged "docs".`, + message: `No wallet-capable gateways for ${WALLET_DEMO.currency} on the active merchant. Enable a PG with payment_services: ["wallet"] tagged "demo".`, }); return; } diff --git a/src/constants/api.ts b/src/constants/api.ts index 2fe1b15..b7494b5 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -1,7 +1,6 @@ -// Base URL for all API code samples and interactive demos. -// Points at Ottu's KSA dev environment (`ksa.ottu.dev`), which currently -// hosts the full public API surface including wallet endpoints. -export const OTTU_CONNECT_BASE_URL = "https://ksa.ottu.dev"; +// Base URL shown in all API code samples — the host developers copy. +// docs.ottu.com advertises the public sandbox `sandbox.ottu.net` only. +export const OTTU_CONNECT_BASE_URL = "https://sandbox.ottu.net"; // Backwards-compatible alias. Historically `OTTU_DEV_BASE_URL` pointed at // `ksa.ottu.dev` for APIs not yet on the public sandbox; both constants now diff --git a/src/theme/ApiExplorer/Authorization/index.tsx b/src/theme/ApiExplorer/Authorization/index.tsx index 86776a2..1a8d8ce 100644 --- a/src/theme/ApiExplorer/Authorization/index.tsx +++ b/src/theme/ApiExplorer/Authorization/index.tsx @@ -9,12 +9,13 @@ import FormTextInput from "@theme/ApiExplorer/FormTextInput"; import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks"; import { OPENAPI_AUTH } from "@theme/translationIds"; import React, { Fragment, useEffect } from "react"; +import { ACTIVE_CONNECT } from "@site/src/utils/sandbox"; const DEFAULT_USERNAME = "demo_user"; const DEFAULT_PASSWORD = "WY4Q9I1d5kHH3nJ"; -// Public demo key on ksa.ottu.dev. Bare key only — the explorer prepends -// the "Api-Key " prefix when it builds the Authorization header. -const DEFAULT_API_KEY = "uUjUqczM.P5PqlXx8zyuFUQVk19PLxfHBZu8rG4Uy"; +// Public sandbox demo key — tracks ACTIVE_CONNECT (sandbox.ottu.net). Bare key +// only; the explorer prepends the "Api-Key " prefix for the Authorization header. +const DEFAULT_API_KEY = ACTIVE_CONNECT.connectApiKey; export default function Authorization(): React.JSX.Element | null { const data = useTypedSelector((state: any) => state.auth.data); diff --git a/src/utils/sandbox.ts b/src/utils/sandbox.ts index d2bf9ef..19fe084 100644 --- a/src/utils/sandbox.ts +++ b/src/utils/sandbox.ts @@ -30,17 +30,13 @@ export const KSA: ConnectEnv = { sdkApiKey: "88a460b42a0f8bec4011da23ce1d547bd04e8afc", }; -// ⬇️ THE GLOBAL SWITCH — change this one line to retarget every demo on the site. -// Both branches (dev → docs.ottu.dev, main → docs.ottu.com) currently use KSA: -// it is the only environment that hosts the full public API surface + wallet, -// so every demo and every code sample (via OTTU_CONNECT_BASE_URL) resolves the -// host through here. -// -// Do NOT point main at SANDBOX — sandbox.ottu.net has no wallet PG, so the -// WalletDemo and every wallet code sample would break in production. Move to a -// per-branch ConnectEnv (or a build-time env override) only once a -// production-grade sandbox also hosts wallet. -export const ACTIVE_CONNECT: ConnectEnv = KSA; +// ⬇️ THE GLOBAL SWITCH for the LIVE interactive demos (Checkout / Recurring / +// PaymentJourney / Wallet) + the API-explorer "try it". docs.ottu.com +// advertises only sandbox.ottu.net, so everything runs on SANDBOX. +// The wallet gateway is live on sandbox.ottu.net for USD only — PG +// `ottu-sandbox-usd`, payment_services `ottu-wallet`, tagged `demo` — so the +// WalletDemo seeds and charges in USD (see walletDemoConfig.ts). +export const ACTIVE_CONNECT: ConnectEnv = SANDBOX; export interface CreateSessionOptions { pg_codes: string[]; diff --git a/src/utils/walletDemoConfig.ts b/src/utils/walletDemoConfig.ts index c977e7c..f28524a 100644 --- a/src/utils/walletDemoConfig.ts +++ b/src/utils/walletDemoConfig.ts @@ -7,9 +7,10 @@ * in `./sandbox` — flip that one global to retarget every demo on the site. */ export const WALLET_DEMO = { - currency: "KWD", - seedAmount: "10.000", - sessionAmount: "8.000", + // Wallet on sandbox.ottu.net is enabled for USD only (PG `ottu-sandbox-usd`). + currency: "USD", + seedAmount: "10.00", + sessionAmount: "8.00", pgFilter: { plugin: "e_commerce", type: "sandbox", diff --git a/static/Ottu_API.yaml b/static/Ottu_API.yaml index d4a4d7a..64c7dd0 100644 --- a/static/Ottu_API.yaml +++ b/static/Ottu_API.yaml @@ -9885,4 +9885,4 @@ components: name: Authorization description: Token-based authentication with required prefix "Token" servers: - - url: https://ksa.ottu.dev + - url: https://sandbox.ottu.net diff --git a/static/api-enrichments/_variables.yaml b/static/api-enrichments/_variables.yaml index f8e2275..7d1da06 100644 --- a/static/api-enrichments/_variables.yaml +++ b/static/api-enrichments/_variables.yaml @@ -6,4 +6,4 @@ apiBaseUrl: "/developers" glossaryUrl: "/glossary" -sandboxUrl: "https://ksa.ottu.dev" +sandboxUrl: "https://sandbox.ottu.net"