agentleFS
BrivaHamisiBrivaHamisi/laravel-shipkit/skills/paypal-checkout/SKILL.md

paypal-checkout

Skill0 starsChanged 49 days agoMITView on GitHub

Accept PayPal and card payments in Laravel with PayPal Orders v2 and Smart Buttons, where the server creates and captures every order so the amount can't be tampered with. Use when adding PayPal, PayPal buttons, card checkout through PayPal, donations, or when fixing PayPal capture, amount mismatch, duplicate order or sandbox/live issues.

  • Reads credentials

The file

We split this skill into the rules it gives an agent

5 rules. About 0 are common, 1 is distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈1

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Add require __DIR__.'/paypal.php'.

    line 30
  2. Very specific:

    Add these keys with empty values to .env.example.

    line 31
  3. Very specific:

    Don't read, print or copy the contents of .env.

    line 48
  4. Very specific:

    The client secret stays on the server: Only the client ID goes in the page.

    line 52
  5. Distinctive:

    Create a live app in the PayPal dashboard.

    line 61

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

PayPal checkout (Orders v2, server-side capture)

PayPal's Smart Buttons run in the browser, but here the server creates and captures every order. The browser can't change the amount, and a payment only counts when PayPal confirms the full amount in the right currency.

What you get

Copy each file in stubs/ to the same path in the app, dropping the .stub suffix.

FilePurpose
config/paypal.phpMode, client ID and secret, currency, amount limits
app/Support/Payments/PayPal.phpOAuth token caching, create order, capture (idempotent), paidInFull() check
app/Http/Controllers/PayPalCheckoutController.phpCreate, capture and cancel endpoints for the buttons
routes/paypal.phpThe three routes. require it from routes/web.php
app/Models/Payment.php, app/Enums/PaymentStatus.php, migration, factoryThe shared payments table (identical to the mpesa-stk-push skill's)
resources/js/paypal-checkout.jsrenderPayPalButtons(), wired to the endpoints
tests/Feature/PayPalCheckoutTest.php12 Pest tests with Http::fake()

Steps

  1. Copy the stubs. If app/Models/Payment.php already exists from mpesa-stk-push, keep it.
  2. Add require __DIR__.'/paypal.php'; to routes/web.php, then run php artisan migrate.
  3. Add these keys with empty values to .env.example. The owner fills in their own .env:
    PAYPAL_MODE=sandbox
    PAYPAL_CLIENT_ID=
    PAYPAL_CLIENT_SECRET=
    PAYPAL_CURRENCY=USD
    The owner creates the app at developer.paypal.com → Apps & Credentials. Sandbox and live have different credentials.
  4. Load the SDK on the checkout page with only the client ID: https://www.paypal.com/sdk/js?client-id=...&currency=USD&intent=capture&components=buttons
  5. Call renderPayPalButtons('#paypal-buttons', () => ({ amount }), onResult).
  6. Run php artisan test --filter=PayPal.

Agent safety

  • This skill writes integration code and tests. Never start a real payment or call the live API yourself: the tests use Http::fake(), and real charges only happen when a customer pays in the running app, in sandbox until the owner switches to live.
  • Never ask the user to paste keys into the chat, and never write key values into any file. Add the variable names with empty values to .env.example; the owner sets the real values in their own .env or the host's environment settings.
  • Don't read, print or copy the contents of .env.

Rules that matter

  • The client secret stays on the server. Only the client ID goes in the page. Never put the secret in a VITE_ variable: Vite compiles those into public JavaScript.
  • Verify the capture, not the button callback. onApprove only means the customer clicked. PayPal::paidInFull() checks that the capture status is COMPLETED, that the currency matches, and that the amount equals the payment's. A PENDING capture (under review) is not paid.
  • Idempotency: the PayPal-Request-Id header (the payment's UUID) stops retries from creating duplicate orders. Capturing an already-captured order returns ORDER_ALREADY_CAPTURED, and the client then fetches the order instead of failing.
  • Never trust the browser for prices. The stub takes amount from the request (donations). For orders, compute the amount server-side and link the payment through payable.
  • Cancel isn't failure. Closing the pop-up marks the payment abandoned. If PayPal later confirms it anyway, markCompleted() still records it.
  • shipping_preference: NO_SHIPPING hides the address step for donations and digital goods. Remove it if you ship things.

Going live

  1. Create a live app in the PayPal dashboard. It needs a verified business account.
  2. Set PAYPAL_MODE=live with the live client ID and secret. The client picks api-m.paypal.com automatically.
  3. The owner makes one small real payment themselves and refunds it from the PayPal dashboard.
  4. The owner rotates the credentials if they were ever pasted into chat, email or a commit. The secrets-scanner skill catches committed ones.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.