Payment Integration
aiskillstore/marketplace
Integrate Stripe, PayPal, and payment processors. An agent skill from aiskillstore/marketplace.
Test payment and checkout flows end to end against PSP sandboxes — Stripe first, with the general pattern for Adyen/Braintree/PayPal.
$ npx skills add petrkindlmann/qa-skills --skill payment-testing -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install petrkindlmann/qa-skills payment-testing --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/payment-testing .claude/skills/payment-testing && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "payment-testing" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/payment-testing into .claude/skills/payment-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "payment-testing", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/petrkindlmann/qa-skills/tree/main/skills/payment-testingType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add petrkindlmann/qa-skills --skill payment-testing -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install petrkindlmann/qa-skills payment-testing --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/payment-testing .agents/skills/payment-testing && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "payment-testing" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/payment-testing into .agents/skills/payment-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "payment-testing", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add petrkindlmann/qa-skills --skill payment-testing -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install petrkindlmann/qa-skills payment-testing --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/payment-testing .cursor/skills/payment-testing && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "payment-testing" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/payment-testing into .cursor/skills/payment-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "payment-testing", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/petrkindlmann/qa-skills.git --path skills/payment-testing--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add petrkindlmann/qa-skills --skill payment-testing -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install petrkindlmann/qa-skills payment-testing --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/payment-testing .gemini/skills/payment-testing && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "payment-testing" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/payment-testing into .gemini/skills/payment-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "payment-testing", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install petrkindlmann/qa-skills payment-testingInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add petrkindlmann/qa-skills --skill payment-testing -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/payment-testing .github/skills/payment-testing && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "payment-testing" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/payment-testing into .github/skills/payment-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "payment-testing", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add petrkindlmann/qa-skills --skill payment-testing -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install petrkindlmann/qa-skills payment-testing --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/petrkindlmann/qa-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/payment-testing .opencode/skills/payment-testing && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "payment-testing" agent skill from https://github.com/petrkindlmann/qa-skills/tree/main/skills/payment-testing into .opencode/skills/payment-testing/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "payment-testing", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
payment-testingTest payment and checkout flows end to end against PSP sandboxes — Stripe first, with the general pattern for Adyen/Braintree/PayPal.
Payment Testing is an agent skill from petrkindlmann/qa-skills. Test payment and checkout flows end to end against PSP sandboxes — Stripe first, with the general pattern for Adyen/Braintree/PayPal. Covers Stripe test-mode card numbers and their decline codes, the 3DS/SCA challenge flow and its nested-iframe handling in Playwright, test clocks for subscription/billing-cycle simulation, webhook testing (stripe listen/trigger, signature verification, idempotency), failed/retried payments and refunds, and never using real cards. Use when: "test Stripe checkout," "payment test,"…
Its SKILL.md is about 4.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 5 other files, including reference files (for example `references/multi-psp.md`, `references/playwright-3ds.md` and `references/stripe-test-cards.md`).
It sits in Testing & QA, covering Webhooks, End-to-end testing and Payments and billing. It works with Stripe, Playwright and PayPal. The repository describes itself as: 50 QA and test-automation skills for Claude Code, Codex, Cursor, and any Agent Skills Standard runtime. The licence is MIT.
11 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit b3bb61b. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
stripeFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
STRIPE_WEBHOOK_SECRETSTRIPE_SECRET_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Payment Testing loads about 4.9k tokens when it runs, and up to ~9.9k if it reads all its reference files. Until then it costs about 227 tokens; SKILL.md has 2,048 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from petrkindlmann/qa-skills at commit b3bb61b, republished under its MIT licence (© petrkindlmann). 2,048 words, ~4,881 tokens.
.claude/skills/payment-testing/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.<objective>
Payment flows fail in ways generic E2E tests miss: a card field in a cross-origin iframe
that `page.locator` silently never reaches, a renewal that won't trigger for a year, a
webhook handler that "works" until Stripe retries and fulfills an order twice, an order
marked paid on a redirect that the browser forged. This skill makes you test payments the
way they actually break — against PSP sandboxes, with the real test cards, the nested 3DS
challenge, server-side test clocks, signature-verified webhooks, and idempotent
fulfillment. Never a real PAN, never a live key.
</objective>
| You need to test… | Go to | Reference |
|---|---|---|
| Success / decline / insufficient-funds outcomes | Test cards | references/stripe-test-cards.md |
| A 3DS/SCA challenge that pops a modal | 3DS challenge | references/playwright-3ds.md |
| A subscription renewal months/years out | Test clocks | references/webhooks-and-clocks.md |
| Webhooks reaching localhost + signatures | Webhooks | references/webhooks-and-clocks.md |
| A failed renewal then a refund | Failed payments | references/webhooks-and-clocks.md |
| Fulfillment only after real payment | Reconciliation | references/webhooks-and-clocks.md |
| Adyen / PayPal / Braintree sandboxes | Multi-PSP | references/multi-psp.md |
First, check .agents/qa-project-context.md in the project root and skip anything it
already answers (PSP, stack, test framework, existing fixtures). Then clarify:
invoice.* lifecycle; one-time payments don't.return_url, that's the bug to test for — fulfillment must wait for the verified webhook.stripe listen) vs a deployed
preview env changes how you deliver events.Never touch a real card or a live key — and this is non-negotiable, not a preference.
Real PANs in any environment violate Stripe's Services Agreement and drag your repo into
PCI scope. Test mode (pk_test_/sk_test_) with Stripe's published test cards is the
only correct answer. Masking or encrypting a real number does not fix it; removing it
does.
Money is confirmed server-side, never client-side. A redirect, an onApprove
callback, or a ?status=success query param can be premature, replayed, or forged.
Fulfill an order only after a signature-verified payment_intent.succeeded webhook,
re-confirmed with an API retrieve.
Verify the signature before you parse the body. Parsing JSON first destroys the raw
bytes constructEvent needs. The webhook route gets the raw body; everything else can
parse JSON.
Time is a server-side construct for billing. Stripe's billing engine runs on Stripe's servers. Faking the clock in your test process changes nothing. Use test clocks.
Assume every webhook is delivered more than once. Stripe retries. Idempotency keyed
on event.id in durable storage is mandatory; an in-memory set is not idempotency.
Drive each outcome with the card that deterministically produces it. The four you need most:
| PAN | Outcome | Code |
|---|---|---|
4242424242424242 | Succeeds | — |
4000000000000002 | Declined | card_declined (generic_decline) |
4000000000009995 | Declined | insufficient_funds |
4000000000003220 | 3DS always challenges | — |
4000000000000341 | Attaches, then fails on charge | card_declined |
Use test keys (pk_test_…/sk_test_…) in the app under test and assert that in setup.
Do not use 4111111111111111 — that is a generic Braintree/PayPal-era Luhn number,
not a Stripe test card, and it does not deterministically decline.
The card field is in a cross-origin Stripe iframe, so fill it through frameLocator, never
page.locator directly. Assert outcomes on UI copy for a smoke test, or more robustly on
the server-side last_payment_error.decline_code from paymentIntents.retrieve. Full
Playwright tests for success / card_declined / insufficient_funds:
references/stripe-test-cards.md.
This is the hardest part to get right. The Stripe 3DS challenge is a frame nested inside
the Stripe modal frame — a single frameLocator cannot reach it. Chain
frameLocator outer → inner, then click Complete authentication.
What fails, and why:
page.locator('#card') → the input is cross-origin; the locator matches nothing.page.frames()[1] → frame index shifts when Stripe adds/reorders frames. Never select
frames by index.await page.waitForTimeout(5000) → guessing the challenge duration. Wait on the element.The correct shape (full test, including the fail-authentication variant, in
references/playwright-3ds.md):
// 3DS-required card so the challenge always appears.
await card.getByPlaceholder('Card number').fill('4000000000003220');
await page.getByRole('button', { name: /pay/i }).click();
// Nested: outer Stripe challenge frame → inner ACS frame. One frameLocator is not enough.
const inner = page
.frameLocator('iframe[name^="__privateStripeFrame"]')
.frameLocator('iframe#challengeFrame, iframe[name="acsFrame"]');
await inner.getByRole('button', { name: /complete authentication|complete|authorize/i }).click();
await expect(page).toHaveURL(/\/success/); // assert the succeeded state
await expect(page.getByText(/payment succeeded/i)).toBeVisible();4000002760003184 is the alternative SCA card for setup-intent / first-use flows; the eval
and docs accept it where a one-time-payment 3DS card is wanted.
To test an annual renewal without waiting a year, use a Stripe test clock — a
server-side construct. Client-side fakes (jest.useFakeTimers, sinon, mocking Date) do
nothing to Stripe's billing engine.
Rules that bite if missed:
frozen_time, then attach the customer at creation with
test_clock: clock.id. You cannot attach an existing customer to a clock afterward.testHelpers.testClocks.advance moves time forward only — you cannot rewind. Advance
at most two billing cycles per call.ready, then assert the renewal invoice and webhooks.const clock = await stripe.testHelpers.testClocks.create({
frozen_time: Math.floor(Date.now() / 1000), name: 'annual-renewal',
});
const customer = await stripe.customers.create({ test_clock: clock.id /* … */ });
// …create subscription, then advance ~12 months forward:
await stripe.testHelpers.testClocks.advance(clock.id, { frozen_time: oneYearLater });Full create/advance/assert flow: references/webhooks-and-clocks.md (section 4).
Local delivery. Do not expose your endpoint with ngrok and do not poll the API for
status. stripe listen tunnels test events to localhost natively; stripe trigger fires
them on demand:
stripe listen --forward-to localhost:3000/webhooks # prints whsec_… ONCE at startup
stripe trigger payment_intent.succeededCopy that whsec_… into STRIPE_WEBHOOK_SECRET. It is the signing secret, a different
value from STRIPE_SECRET_KEY (sk_test_…) — do not conflate them.
Signature verification. Mount express.raw on the webhook route before any global
express.json(), so constructEvent gets the raw body. A forged or tampered event must be
rejected with 400; never hand-roll a === signature string comparison.
app.post('/webhooks', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['stripe-signature'] as string;
try {
const event = stripe.webhooks.constructEvent(req.body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
return handleEvent(event, res);
} catch (err) {
return res.status(400).send(`Webhook Error: ${(err as Error).message}`); // SignatureVerificationError
}
});
app.use(express.json()); // everything else, after the webhook routeIdempotency. Stripe retries delivery, so the same event.id arrives twice. Request-side
idempotency keys (for outbound API calls) do not dedup inbound webhooks. Store event.id
with a UNIQUE constraint and short-circuit on conflict; an in-memory set is lost on
restart and useless across instances. The handler returns 200 for a duplicate so Stripe
stops retrying, and fulfillment runs exactly once.
const inserted = await db.query(
`INSERT INTO processed_events (id) VALUES ($1) ON CONFLICT (id) DO NOTHING RETURNING id`, [event.id]);
if (inserted.rowCount === 0) return res.status(200).send('duplicate ignored');The signature test (valid accepted, forged → 400) and the "deliver the same event twice,
assert fulfilled once" idempotency test are in references/webhooks-and-clocks.md
(sections 2–3).
To test a failed recurring charge end to end, subscribe with 4000000000000341 (SDK token
pm_card_chargeCustomerFail) — it attaches to the customer but fails on the later
charge, which is what the renewal needs. Cards that decline at attach time can't be saved,
so they can't model a renewal failure.
Drive the lifecycle with a test clock:
advance the clock past the renewal date → Stripe attempts the charge.invoice.payment_failed and the subscription goes
past_due. Assert both.refunds.create (fires charge.refunded) — do
not "fix" it by deleting the subscription.Full driver in references/webhooks-and-clocks.md (section 5).
Mark an order paid only after a signature-verified payment_intent.succeeded webhook,
re-confirmed against the API — never on the return_url redirect or a client-side success
flag, and never by polling with a sleep.
if (event.type === 'payment_intent.succeeded') {
const verified = await stripe.paymentIntents.retrieve(event.data.object.id);
if (verified.status === 'succeeded' && verified.amount_received === expected) {
await markOrderPaid(verified.metadata.orderId); // fulfillment happens HERE
}
}The reconciliation test asserts the order is still pending after the redirect and only
paid after the verified webhook: references/webhooks-and-clocks.md (section 6).
Stripe test cards do not work on other PSPs. Each has its own sandbox cards and sandbox buyer accounts. Port the structure of your Stripe tests; swap in the PSP's sandbox values. Never reuse Stripe PANs or live/production keys.
4212345678910014 for 3DS2); many declines are driven by
the transaction amount (.13 refused, .51 referral), not the card. Events arrive as
HMAC-signed notifications.onApprove.What stays the same: separate test/sandbox credentials, no real card, and fulfillment on the
verified server-side event/notification. Details: references/multi-psp.md.
4111111111111111That Luhn-valid number is a Braintree/PayPal-era generic PAN, not a Stripe test card. Use
4242424242424242 for success and the specific decline cards (4000000000000002,
4000000000009995).
page.locator('#card-number') silently matches nothing because the field is in a
cross-origin iframe. Use frameLocator.
page.frames()[1] breaks the instant Stripe reorders frames. Match the frame by a stable
name prefix (iframe[name^="__privateStripeFrame"]) and chain frameLocator for the nested
3DS challenge.
waitForTimeout to "wait for the challenge"Flaky on slow CI, wasteful on fast CI. Wait on the element (expect(...).toBeVisible() /
auto-waiting locator actions), never the clock.
jest.useFakeTimers / sinon / mocking Date cannot move Stripe's server-side billing.
Use a test clock.
stripe listen --forward-to localhost:3000/webhooks tunnels events natively; stripe trigger fires them. No public tunnel, no status polling.
A global express.json() ahead of the webhook route destroys the raw body
constructEvent needs, so verification can never pass. Mount express.raw on the webhook
route first.
Outbound idempotency keys don't dedup inbound webhooks; an in-memory Set dies on restart.
Persist event.id with a UNIQUE constraint.
The return_url can be premature, replayed, or forged. Fulfill only on the verified
payment_intent.succeeded webhook.
The correct resolution is a refund via refunds.create, leaving the dunning lifecycle
(invoice.payment_failed → past_due) intact and testable.
A hardcoded real PAN is a PCI/compliance violation regardless of environment. The fix is a test card in test mode — plus removing the secret from the repo and git history and rotating any exposed key. Masking or encrypting it does not make it acceptable.
stripe listen --forward-to localhost:3000/webhooks prints a whsec_… and shows events
arriving when you run stripe trigger payment_intent.succeeded.4000000000003220 reaches and clicks the Complete
authentication button (the test fails loudly, not silently, if the nested frame isn't
found).Stripe-Signature returns 400; a header from
generateTestHeaderString returns 200.event.id twice fulfills once.grep -rE 'pk_live|sk_live|4111111111111111' over the test suite returns nothing.4242424242424242), card_declined
(4000000000000002), and insufficient_funds (4000000000009995), each asserting the
matching outcome, using pk_test_/sk_test_ keys.4000000000003220, reaches the nested challenge frame via chained
frameLocator, clicks Complete authentication, and asserts the succeeded state — no
frames()[index], no waitForTimeout.testHelpers.testClocks.create +
advance, forward-only, customer attached at creation) instead of any client-side time mock.stripe listen --forward-to / stripe trigger, with the
whsec_… wired into STRIPE_WEBHOOK_SECRET (distinct from STRIPE_SECRET_KEY).constructEvent on the raw body
before parsing, returns 400 on a forged event, and a test proves it.event.id with a UNIQUE constraint; a duplicate
delivery returns 200 and fulfills exactly once, proven by a test.invoice.payment_failed → past_due → refunds.create via
a test clock and the attach-then-fail card 4000000000000341.paid only after the verified
payment_intent.succeeded webhook (re-checked with paymentIntents.retrieve), not on the
redirect.grep -rE 'pk_live|sk_live|4111111111111111' finds no live key or banned PAN in the test
suite. (A bare [0-9]{16} scan would false-positive on every legitimate test card —
match live-key prefixes and the banned 4111… number, not all 16-digit strings.)references/)stripe listen/trigger, raw-body signature verification,
idempotency by event.id, test clocks, failed-renewal dunning + refunds, and
reconciliation.© petrkindlmann, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 4 other files (references) in skills/payment-testing of petrkindlmann/qa-skills.
Open the folder on GitHubat commit b3bb61b
Payment Testing next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Payment Testing this skillpetrkindlmann/qa-skills | 163 | — | ~4.9k | Automated safety check: Pass | MIT | |
| Payment Integrationaiskillstore/marketplace | 430 | 8 repos | ~916 | Automated safety check: Pass | None | |
| Privacy Pagamenticcplugins/awesome-claude-code-plugins | 967 | — | ~845 | Automated safety check: Pass | Apache-2.0 | |
| Common Tasksidavidov13/agentic-playwright | 223 | — | ~2.5k | Automated safety check: Pass | MIT | |
| Data Strategyidavidov13/agentic-playwright | 223 | — | ~3.4k | Automated safety check: Pass | MIT | |
| Proxy Setupasmyshlyaev177/test-proxy-recorder | 112 | — | ~4.3k | Automated safety check: Pass | MIT |
aiskillstore/marketplace
Integrate Stripe, PayPal, and payment processors. An agent skill from aiskillstore/marketplace.
ccplugins/awesome-claude-code-plugins
Protegge dati di pagamento e abbonamenti quando un sito/app gestisce checkout, carte, subscription o fatturazione.
idavidov13/agentic-playwright
Copy-paste AI prompt templates for common Playwright scaffold development tasks — adding page objects, functional/E2E/API tests, Zod schemas, factories, fixtures, and components.
idavidov13/agentic-playwright
Test data strategy for the Playwright scaffold — Faker + Zod factories for dynamic happy-path data, static TS files (.ts with as const exports — never .json) for domain-specific curated invalid…
asmyshlyaev177/test-proxy-recorder
Set up test-proxy-recorder for any Playwright project. An agent skill from asmyshlyaev177/test-proxy-recorder.
fugazi/test-automation-skills-agents
Author and maintain versioned Playwright (@playwright/test) TypeScript UI specs for browser user flows.
petrkindlmann/qa-skills
Test for WCAG 2.2 AA compliance with axe-core + Playwright, keyboard navigation audits, screen reader testing, ARIA pattern validation, and legal compliance mapping (ADA, EAA, Section 508).
petrkindlmann/qa-skills
Goal-driven E2E testing where a browser agent (Playwright MCP / computer-use) reads a natural-language goal and explores the app via the accessibility tree to assert outcomes — no pre-written script.
petrkindlmann/qa-skills
Use AI to write NEW test code from specs, PRDs, user stories, code diffs, bug reports, or OpenAPI specs.
petrkindlmann/qa-skills
Test REST and GraphQL APIs with Playwright APIRequestContext, Supertest, or standalone HTTP clients.
petrkindlmann/qa-skills
Design CI/CD pipelines that run test suites. An agent skill from petrkindlmann/qa-skills.
petrkindlmann/qa-skills
Test for regulatory compliance: GDPR/CMP consent verification, Google Consent Mode v2, Global Privacy Control (GPC), CCPA/US state opt-out, EU AI Act Article 50 transparency, Better Ads Standards…
Works with
Categories
Test payment and checkout flows end to end against PSP sandboxes — Stripe first, with the general pattern for Adyen/Braintree/PayPal. Payment Testing is an agent skill from petrkindlmann/qa-skills. Test payment and checkout flows end to end against PSP sandboxes — Stripe first, with the general pattern for Adyen/Braintree/PayPal.
Payment Testing fits situations like: : test Stripe checkout; test webhook signature; test subscription renewal; decline card test.
Run `npx skills add petrkindlmann/qa-skills --skill payment-testing -a claude-code`. Or copy the skill folder (skills/payment-testing in petrkindlmann/qa-skills) into .claude/skills/payment-testing in your project. Claude Code loads it when a task matches its description.
Run `npx skills add petrkindlmann/qa-skills --skill payment-testing -a codex`. Or copy the skill folder (skills/payment-testing in petrkindlmann/qa-skills) into .agents/skills/payment-testing in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add petrkindlmann/qa-skills --skill payment-testing -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/payment-testing, .gemini/skills/payment-testing, .github/skills/payment-testing and .opencode/skills/payment-testing in your project.
Going by SKILL.md and its folder, Payment Testing needs the command-line tools its instructions call (stripe) and credentials named STRIPE_WEBHOOK_SECRET and STRIPE_SECRET_KEY. Our summary lists: A credential in STRIPE_WEBHOOK_SECRET; A credential in STRIPE_SECRET_KEY.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Payment Testing is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 4.9k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 5k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Payment Testing: Payment Integration (aiskillstore/marketplace, 430 stars), Privacy Pagamenti (ccplugins/awesome-claude-code-plugins, 967 stars), Common Tasks (idavidov13/agentic-playwright, 223 stars) and Data Strategy (idavidov13/agentic-playwright, 223 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
petrkindlmann (a GitHub user) maintains it in petrkindlmann/qa-skills, which has 163 GitHub stars. The repository holds 45 skills in this directory. The repository was last updated on June 10, 2026.
Source: petrkindlmann/qa-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.