Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"repo": "PaymobAccept/Paymob-AI-Integration-Skill"
},
"description": "Build and verify secure Paymob payment flows across Egypt, UAE, KSA, and Oman.",
"version": "3.4.0"
"version": "3.4.1"
}
]
}
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "paymob-integration",
"description": "Expert, workflow-driven guidance for integrating the Paymob payment gateway across Egypt, UAE, KSA, and Oman. Routes by platform (Shopify apps / prebuilt e-commerce plugins vs custom build), onboarding, web/API (Intention API + Unified Checkout + Pixel SDK), and native Mobile SDKs. Covers all 3 HMAC types (transaction, card token, subscription), transaction inquiry/reconciliation, subscriptions, saved cards (CIT/MIT), Auth/Capture, refunds/void, split features, and convenience fees, and ships corrected ready-to-use code for Node.js, Python, PHP, .NET, Ruby, and frontend. Bundles Paymob's official MCP server for live account actions. Covers post-integration management too: go-live readiness, Dashboard operations, monitoring and reconciliation, diagnostics with the Paymob Integration Wizard (Code Lab, HMAC Signature Troubleshooter, Store Check, Mobe), and redacted support tickets. Includes /paymob-test-cards, /paymob-explain-error, /paymob-check-hmac, /paymob-go-live-check, and /paymob-support-ticket slash commands. Triggers even when no provider is named for a regional payment request.",
"version": "3.4.0",
"version": "3.4.1",
"author": {
"name": "Paymob Support",
"email": "mohamedragab@paymob.com"
Expand Down
2 changes: 1 addition & 1 deletion .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "paymob-integration",
"version": "3.4.0",
"version": "3.4.1",
"description": "Integrate, verify, and operate Paymob payments across Egypt, UAE, KSA, and Oman: secure checkout, webhooks, reconciliation, go-live, diagnostics, support tickets, and optional live account tools.",
"author": {
"name": "Paymob Support",
Expand Down
4 changes: 4 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ This repository is a portable **skill** that makes any AI coding agent an expert

For broad integrations or audits, delegate independent read-only tasks such as codebase mapping, current-doc verification, and security review. Subagents receive no Paymob credentials, do not use authenticated Paymob tools, and return findings only with file/line references. Keep one primary agent responsible for requirements, final edits, tests, and every live action. If edits must be delegated, give agents exclusive non-overlapping paths and merge through the primary agent.

## Replit and other hosted builders

For Replit, read `skills/paymob-integration/references/replit.md` (or `references/replit.md` relative to the installed skill). Verify the skill import separately from payment connector availability. A missing connector alone does not establish an API prohibition; inspect the backend and enforced host restrictions. Use Replit Secrets, verify test/production `APP_URL` origins and public webhook reachability, and keep MCP optional. Preserve the user's provider choice and existing project rules, including the project-root `replit.md`; explain an enforced host restriction without trying to bypass it. Missing credentials permit scaffolding and local mocked tests, not authenticated API calls or a claim that payments work.

## Non-negotiable rules

1. **Intention API only.** Create payments with `POST {base_url}/v1/intention/`. Never use or suggest the legacy 3-step flow (auth token → order → payment key).
Expand Down
107 changes: 82 additions & 25 deletions README.md

Large diffs are not rendered by default.

28 changes: 21 additions & 7 deletions scripts/package_skill.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@ def source_files() -> list[Path]:
return sorted(path for path in SKILL_DIR.rglob("*") if path.is_file())


def archive_sources() -> dict[str, Path]:
"""Map package paths to canonical sources, including the MIT notice."""
entries = {
PurePosixPath(ARCHIVE_ROOT, *path.relative_to(SKILL_DIR).parts).as_posix(): path
for path in source_files()
}
license_path = ROOT / "LICENSE"
if not license_path.is_file():
raise ValueError("Repository LICENSE is required for standalone distribution")
entries[f"{ARCHIVE_ROOT}/LICENSE"] = license_path
return entries


def build_archive(output: Path) -> None:
"""Create a deterministic ZIP with one top-level skill folder."""
output = output.resolve()
Expand All @@ -28,9 +41,7 @@ def build_archive(output: Path) -> None:

output.parent.mkdir(parents=True, exist_ok=True)
with zipfile.ZipFile(output, "w", compression=zipfile.ZIP_DEFLATED) as archive:
for source in source_files():
relative = source.relative_to(SKILL_DIR)
archive_name = PurePosixPath(ARCHIVE_ROOT, *relative.parts).as_posix()
for archive_name, source in sorted(archive_sources().items()):
info = zipfile.ZipInfo(archive_name, FIXED_TIMESTAMP)
info.compress_type = zipfile.ZIP_DEFLATED
info.create_system = 3
Expand All @@ -41,14 +52,17 @@ def build_archive(output: Path) -> None:
def archive_errors(archive_path: Path) -> list[str]:
"""Return structural or content errors for an upload archive."""
errors: list[str] = []
expected = {
PurePosixPath(ARCHIVE_ROOT, *path.relative_to(SKILL_DIR).parts).as_posix()
for path in source_files()
}
sources = archive_sources()
expected = set(sources)
try:
with zipfile.ZipFile(archive_path) as archive:
names = {name for name in archive.namelist() if not name.endswith("/")}
bad_entries = archive.testzip()
if len(archive.namelist()) != len(set(archive.namelist())):
errors.append("Archive contains duplicate entries")
for name in sorted(names & expected):
if archive.read(name) != sources[name].read_bytes():
errors.append(f"Archive content differs from its canonical source: {name}")
except (FileNotFoundError, zipfile.BadZipFile) as exc:
return [f"Cannot read archive: {exc}"]

Expand Down
6 changes: 5 additions & 1 deletion scripts/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,10 @@ def validate_install_docs(version: str, errors: list[str]) -> None:
"Settings → Skills",
"choose the **ZIP** tab",
"/paymob-integration",
"### Replit",
"Preview skills",
".agents/skills/paymob-integration/",
"references/replit.md",
)
for command in required:
if command not in readme:
Expand Down Expand Up @@ -634,4 +638,4 @@ def main() -> int:


if __name__ == "__main__":
sys.exit(main())
sys.exit(main())
13 changes: 11 additions & 2 deletions skills/paymob-integration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ After a successful first integration or test payment, end with **one line** of r

## Step -1 — Check the platform first

**Running in Replit?** Read `references/replit.md` first. Verify the skill was imported and its references are readable; inspect the existing app backend and host restrictions before choosing an integration route. A missing payment connector is not by itself proof that a custom Paymob API integration is prohibited. Respect an enforced host restriction, explain the exact blocker, and never substitute another provider without the user's choice.

**Resolve references from the installed skill folder.** A folder-only install includes this file and `references/`, but not the repository-root `AGENTS.md`, Claude commands, or MCP registration. If a referenced file is missing, fetch that specific file from `https://raw.githubusercontent.com/PaymobAccept/Paymob-AI-Integration-Skill/main/skills/paymob-integration/references/`. If retrieval is unavailable, name the missing file and stop the affected task rather than inventing API details or declaring Paymob unsupported. Prefer a complete skill import to relying on remote fallback.

Before anything else, find out **what the store is built on**. If it's not already obvious from context, ask:

> "Is your store on Shopify or another e-commerce platform (WooCommerce, Magento, Odoo, …), is this a custom-built site/app, or do you just want to share payment links without a website?"
Expand Down Expand Up @@ -116,7 +120,7 @@ Route based on the answer:
| Not registered with Paymob, or registered but verification/business docs incomplete | **Phase 1: Onboarding** (below) |
| Already registered, has credentials and Integration ID(s) | Skip to **Step 0.5** (below) |

Do not proceed to writing integration code until Phase 1 is confirmed complete (see exit criteria below) — the agent will not have a Secret Key or Integration ID to use otherwise.
Until Phase 1 is complete, allow scaffolding, environment-variable placeholders, and local mocked tests. Do not make authenticated Paymob API requests or claim a working end-to-end integration without the required test credentials and Integration IDs.

---

Expand Down Expand Up @@ -151,9 +155,12 @@ Do not proceed to writing integration code until Phase 1 is confirmed complete (
PAYMOB_API_KEY=
PAYMOB_HMAC_SECRET=
PAYMOB_INTEGRATION_ID_CARD=
PAYMOB_BASE_URL=
APP_URL=
# add one var per enabled payment method (wallet, kiosk, etc.)
```
(`PAYMOB_API_KEY` is only needed for the Transaction Inquiry / reconciliation flow — see `references/transaction-inquiry.md`.)
`APP_URL` is the merchant app's externally reachable HTTPS origin, used to build callback and redirect URLs; it is not the Paymob regional base URL. Verify test and production origins separately. On hosted platforms, use their environment-variable/Secrets facility instead of requiring a local `.env` file.

**Exit criteria for Phase 1:** merchant has Secret Key, Public Key, HMAC Secret, and at least one Integration ID (Test mode is enough to proceed). Then continue below.

Expand Down Expand Up @@ -290,6 +297,8 @@ Rules for this phase:

## Reference files

- `references/replit.md` — Replit install verification, skill/connector/MCP separation, host restrictions, Secrets, callback URLs, and test checkpoint; read first when running in Replit

**Integration paths & security (current as of 2026-06; post-integration checked 2026-09):**
- `references/shopify-apps.md` — Paymob's Shopify apps (on-site, off-site, Sympl, valU), install links, which to recommend when
- `references/intention-api.md` — Create Intention endpoint, request/response fields, Unified Checkout redirect, common errors
Expand All @@ -299,7 +308,7 @@ Rules for this phase:
- `references/test-credentials.md` — Sandbox test cards, wallet numbers, OTPs
- `references/testing-guide.md` — Test checkpoint, which test details to show per payment method, and how to test each integration type (custom web, Pixel, mobile, Shopify, plugins, Payment Links)

**Ready-to-use code (corrected, copy-ready):**
**Stack-specific adaptation templates:** Retain the merchant's framework bootstrap and implement the required durable persistence adapters; these snippets are not standalone runnable apps.
- `references/code-nodejs.md` — Node.js / TypeScript / Express / NestJS
- `references/code-python.md` — Python / Django / Flask / FastAPI
- `references/code-php.md` — PHP / Laravel
Expand Down
2 changes: 1 addition & 1 deletion skills/paymob-integration/references/intention-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ Paymob's servers POST to `notification_url` from the internet, so the URL must b
| Goal | Use as `notification_url` | Notes |
|---|---|---|
| **See the raw callback** (payload shape, `hmac` query param, redirect params) | `https://hooks.paymob.com/<your-id>` — Paymob's own webhook inspector | The user opens `https://hooks.paymob.com`, copies the unique Hook URL it shows, and pastes it back to the agent (the agent cannot generate one). It shows POST, GET, and PUT requests live, so it also works as `redirection_url`. **No retention** — keep the page open while the test payment runs, or the request is not seen. Paste the captured payload into the Integration Wizard's HMAC Signature Troubleshooter (`https://wizard.paymob.com/`) to confirm the HMAC logic. |
| **Test the merchant's own webhook handler end to end** | A tunnel to the local server (e.g. `ngrok http 3000`, `cloudflared tunnel --url http://localhost:3000`) or a deployed preview URL | Hosted builders (Replit, Lovable, Vercel/Netlify previews) already expose a public HTTPS URL — use it. Tunnel URLs usually change on restart; update `notification_url` when they do. |
| **Test the merchant's own webhook handler end to end** | A tunnel to the local server (e.g. `ngrok http 3000`, `cloudflared tunnel --url http://localhost:3000`) or an externally reachable test deployment | Hosted builders may supply a preview HTTPS URL, but verify an external POST reaches the actual handler without login, an access interstitial, or a frontend HTML fallback. A preview may sleep, stop, or change URL; prefer a stable test deployment. Update `notification_url` and `APP_URL` whenever the origin changes. For Replit, read `replit.md`. |
| **Live** | The merchant's own production HTTPS endpoint | Never leave a hooks.paymob.com or tunnel URL in live config. |

hooks.paymob.com **only displays** requests — it does not forward them to the merchant's server, so their HMAC verification and order-update code never runs. Seeing a callback there proves Paymob sends it; it does **not** complete Phase 3 testing, which needs the merchant's own handler to receive, verify, and process the callback.
12 changes: 12 additions & 0 deletions skills/paymob-integration/references/mcp-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ Add to the project's `.mcp.json` (or the client's MCP config):

Add the same object to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global).

### Replit — connect separately from skill import

[Add Paymob MCP to Replit](https://replit.com/integrations?mcp=eyJkaXNwbGF5TmFtZSI6IlBheW1vYiIsImJhc2VVcmwiOiJodHRwczovL21jcC5wYXltb2IuY29tL21jcCJ9)

This link uses Replit's documented install-link format and contains only the server name and public endpoint. It does not install the Paymob skill, supply credentials, or prove account access. Confirm the connection in Replit; its security scanner and workspace permissions still apply.

For manual setup: open Replit Integrations, find the MCP Servers settings, select **+ Add MCP server**, enter display name **Paymob** and URL `https://mcp.paymob.com/mcp`, then select **Test & save**. Do not assume Replit reads the repository-root `.mcp.json` when importing a skill. Read `replit.md` for the combined skill/MCP setup request.

After connection, verify tool discovery and read the server's current help without account credentials. Only then authenticate a test account through a host-supported secure input/runtime mechanism. Never put API keys in the install URL, a committed file, or ordinary chat. If the credential-setup tool cannot receive keys securely in this host, report that limitation; server registration alone is not authenticated account readiness. Replit connection/authentication behavior with this Paymob server has not been tested here.

Sources: [Replit Connect via MCP](https://docs.replit.com/build/connect-via-mcp), [Replit MCP install-link format](https://docs.replit.com/features/mcp/overview).

---

## Authenticating (per session)
Expand Down
Loading
Loading