PayPal Integration

Integrate PayPal payment processing with support for express checkout, subscriptions, and refund management.

You say
Buy it · $79 Read it before you buy $79 Written by rmyndharis · unverified publisher
Context cost
3.5k tokensestimated from the bundle, loaded when it triggers
Bundle
1 file · 13.9 kBtext throughout, nothing executable
Licence
MITpaid listing
Last change
no release on file
Servers it uses
Noneruns standalone

What it does

Integrate PayPal payment processing with support for express checkout, subscriptions, and refund management. Use when implementing PayPal payments, processing online transactions, or building e-commerce checkout flows.

Installed, it changes the agent in these ways.

What this skill changes about the agent is not written down here yet. The listing was collected from its source, and the description is in its own SKILL.md.

Workflow

Runs a procedure end to end.

e-commerce

The skill itself

This is the whole product. A skill is instructions the model reads, so there is nothing behind the listing you cannot see first — the front matter loads with every session, and the body below it loads when the skill triggers.

SKILL.md13.9 kB · 479 lines
--- name: paypal-integration description: Integrate PayPal payment processing with support for express checkout, subscriptions, and refund management. Use when implementing PayPal payments, processing online transactions, or building e-commerce checkout flows. ---
6# PayPal Integration
7
8Master PayPal payment integration including Express Checkout, IPN handling, recurring billing, and refund workflows.
9
10## Do not use this skill when
11
12- The task is unrelated to paypal integration
13- You need a different domain or tool outside this scope
14
15## Instructions
16
17- Clarify goals, constraints, and required inputs.
18- Apply relevant best practices and validate outcomes.
19- Provide actionable steps and verification.
20
21## Use this skill when
22
23- Integrating PayPal as a payment option
24- Implementing express checkout flows
25- Setting up recurring billing with PayPal
26- Processing refunds and payment disputes
27- Handling PayPal webhooks (IPN)
28- Supporting international payments
29- Implementing PayPal subscriptions
30
31## Core Concepts
32
33### 1. Payment Products
34**PayPal Checkout**
35- One-time payments
36- Express checkout experience
37- Guest and PayPal account payments
38
39**PayPal Subscriptions**
40- Recurring billing
41- Subscription plans
42- Automatic renewals
43
44**PayPal Payouts**
45- Send money to multiple recipients
46- Marketplace and platform payments
47
48### 2. Integration Methods
49**Client-Side (JavaScript SDK)**
50- Smart Payment Buttons
51- Hosted payment flow
52- Minimal backend code
53
54**Server-Side (REST API)**
55- Full control over payment flow
56- Custom checkout UI
57- Advanced features
58
59### 3. IPN (Instant Payment Notification)
60- Webhook-like payment notifications
61- Asynchronous payment updates
62- Verification required
63
64## Quick Start
65
66```javascript
67// Frontend - PayPal Smart Buttons
68<div id="paypal-button-container"></div>
69
70<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&currency=USD"></script>
71<script>
72 paypal.Buttons({
73 createOrder: function(data, actions) {
74 return actions.order.create({
75 purchase_units: [{
76 amount: {
77 value: '25.00'
78 }
79 }]
80 });
81 },
82 onApprove: function(data, actions) {
83 return actions.order.capture().then(function(details) {
84 // Payment successful
85 console.log('Transaction completed by ' + details.payer.name.given_name);
86
87 // Send to backend for verification
88 fetch('/api/paypal/capture', {
89 method: 'POST',
90 headers: {'Content-Type': 'application/json'},
91 body: JSON.stringify({orderID: data.orderID})
92 });
93 });
94 }
95 }).render('#paypal-button-container');
96</script>
97```
98
99```python
100# Backend - Verify and capture order
101from paypalrestsdk import Payment
102import paypalrestsdk
103
104paypalrestsdk.configure({
105 "mode": "sandbox", # or "live"
106 "client_id": "YOUR_CLIENT_ID",
107 "client_secret": "YOUR_CLIENT_SECRET"
108})
109
110def capture_paypal_order(order_id):
111 """Capture a PayPal order."""
112 payment = Payment.find(order_id)
113
114 if payment.execute({"payer_id": payment.payer.payer_info.payer_id}):
115 # Payment successful
116 return {
117 'status': 'success',
118 'transaction_id': payment.id,
119 'amount': payment.transactions[0].amount.total
120 }
121 else:
122 # Payment failed
123 return {
124 'status': 'failed',
125 'error': payment.error
126 }
127```
128
129## Express Checkout Implementation
130
131### Server-Side Order Creation
132```python
133import requests
134import json
135
136class PayPalClient:
137 def __init__(self, client_id, client_secret, mode='sandbox'):
138 self.client_id = client_id
139 self.client_secret = client_secret
140 self.base_url = 'https://api-m.sandbox.paypal.com' if mode == 'sandbox' else 'https://api-m.paypal.com'
141 self.access_token = self.get_access_token()
142
143 def get_access_token(self):
144 """Get OAuth access token."""
145 url = f"{self.base_url}/v1/oauth2/token"
146 headers = {"Accept": "application/json", "Accept-Language": "en_US"}
147
148 response = requests.post(
149 url,
150 headers=headers,
151 data={"grant_type": "client_credentials"},
152 auth=(self.client_id, self.client_secret)
153 )
154
155 return response.json()['access_token']
156
157 def create_order(self, amount, currency='USD'):
158 """Create a PayPal order."""
159 url = f"{self.base_url}/v2/checkout/orders"
160 headers = {
161 "Content-Type": "application/json",
162 "Authorization": f"Bearer {self.access_token}"
163 }
164
165 payload = {
166 "intent": "CAPTURE",
167 "purchase_units": [{
168 "amount": {
169 "currency_code": currency,
170 "value": str(amount)
171 }
172 }]
173 }
174
175 response = requests.post(url, headers=headers, json=payload)
176 return response.json()
177
178 def capture_order(self, order_id):
179 """Capture payment for an order."""
180 url = f"{self.base_url}/v2/checkout/orders/{order_id}/capture"
181 headers = {
182 "Content-Type": "application/json",
183 "Authorization": f"Bearer {self.access_token}"
184 }
185
186 response = requests.post(url, headers=headers)
187 return response.json()
188
189 def get_order_details(self, order_id):
190 """Get order details."""
191 url = f"{self.base_url}/v2/checkout/orders/{order_id}"
192 headers = {
193 "Authorization": f"Bearer {self.access_token}"
194 }
195
196 response = requests.get(url, headers=headers)
197 return response.json()
198```
199
200## IPN (Instant Payment Notification) Handling
201
202### IPN Verification and Processing
203```python
204from flask import Flask, request
205import requests
206from urllib.parse import parse_qs
207
208app = Flask(__name__)
209
210@app.route('/ipn', methods=['POST'])
211def handle_ipn():
212 """Handle PayPal IPN notifications."""
213 # Get IPN message
214 ipn_data = request.form.to_dict()
215
216 # Verify IPN with PayPal
217 if not verify_ipn(ipn_data):
218 return 'IPN verification failed', 400
219
220 # Process IPN based on transaction type
221 payment_status = ipn_data.get('payment_status')
222 txn_type = ipn_data.get('txn_type')
223
224 if payment_status == 'Completed':
225 handle_payment_completed(ipn_data)
226 elif payment_status == 'Refunded':
227 handle_refund(ipn_data)
228 elif payment_status == 'Reversed':
229 handle_chargeback(ipn_data)
230
231 return 'IPN processed', 200
232
233def verify_ipn(ipn_data):
234 """Verify IPN message authenticity."""
235 # Add 'cmd' parameter
236 verify_data = ipn_data.copy()
237 verify_data['cmd'] = '_notify-validate'
238
239 # Send back to PayPal for verification
240 paypal_url = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr' # or production URL
241
242 response = requests.post(paypal_url, data=verify_data)
243
244 return response.text == 'VERIFIED'
245
246def handle_payment_completed(ipn_data):
247 """Process completed payment."""
248 txn_id = ipn_data.get('txn_id')
249 payer_email = ipn_data.get('payer_email')
250 mc_gross = ipn_data.get('mc_gross')
251 item_name = ipn_data.get('item_name')
252
253 # Check if already processed (prevent duplicates)
254 if is_transaction_processed(txn_id):
255 return
256
257 # Update database
258 # Send confirmation email
259 # Fulfill order
260 print(f"Payment completed: {txn_id}, Amount: ${mc_gross}")
261
262def handle_refund(ipn_data):
263 """Handle refund."""
264 parent_txn_id = ipn_data.get('parent_txn_id')
265 mc_gross = ipn_data.get('mc_gross')
266
267 # Process refund in your system
268 print(f"Refund processed: {parent_txn_id}, Amount: ${mc_gross}")
269
270def handle_chargeback(ipn_data):
271 """Handle payment reversal/chargeback."""
272 txn_id = ipn_data.get('txn_id')
273 reason_code = ipn_data.get('reason_code')
274
275 # Handle chargeback
276 print(f"Chargeback: {txn_id}, Reason: {reason_code}")
277```
278
279## Subscription/Recurring Billing
280
281### Create Subscription Plan
282```python
283def create_subscription_plan(name, amount, interval='MONTH'):
284 """Create a subscription plan."""
285 client = PayPalClient(CLIENT_ID, CLIENT_SECRET)
286
287 url = f"{client.base_url}/v1/billing/plans"
288 headers = {
289 "Content-Type": "application/json",
290 "Authorization": f"Bearer {client.access_token}"
291 }
292
293 payload = {
294 "product_id": "PRODUCT_ID", # Create product first
295 "name": name,
296 "billing_cycles": [{
297 "frequency": {
298 "interval_unit": interval,
299 "interval_count": 1
300 },
301 "tenure_type": "REGULAR",
302 "sequence": 1,
303 "total_cycles": 0, # Infinite
304 "pricing_scheme": {
305 "fixed_price": {
306 "value": str(amount),
307 "currency_code": "USD"
308 }
309 }
310 }],
311 "payment_preferences": {
312 "auto_bill_outstanding": True,
313 "setup_fee": {
314 "value": "0",
315 "currency_code": "USD"
316 },
317 "setup_fee_failure_action": "CONTINUE",
318 "payment_failure_threshold": 3
319 }
320 }
321
322 response = requests.post(url, headers=headers, json=payload)
323 return response.json()
324
325def create_subscription(plan_id, subscriber_email):
326 """Create a subscription for a customer."""
327 client = PayPalClient(CLIENT_ID, CLIENT_SECRET)
328
329 url = f"{client.base_url}/v1/billing/subscriptions"
330 headers = {
331 "Content-Type": "application/json",
332 "Authorization": f"Bearer {client.access_token}"
333 }
334
335 payload = {
336 "plan_id": plan_id,
337 "subscriber": {
338 "email_address": subscriber_email
339 },
340 "application_context": {
341 "return_url": "https://yourdomain.com/subscription/success",
342 "cancel_url": "https://yourdomain.com/subscription/cancel"
343 }
344 }
345
346 response = requests.post(url, headers=headers, json=payload)
347 subscription = response.json()
348
349 # Get approval URL
350 for link in subscription.get('links', []):
351 if link['rel'] == 'approve':
352 return {
353 'subscription_id': subscription['id'],
354 'approval_url': link['href']
355 }
356```
357
358## Refund Workflows
359
360```python
361def create_refund(capture_id, amount=None, note=None):
362 """Create a refund for a captured payment."""
363 client = PayPalClient(CLIENT_ID, CLIENT_SECRET)
364
365 url = f"{client.base_url}/v2/payments/captures/{capture_id}/refund"
366 headers = {
367 "Content-Type": "application/json",
368 "Authorization": f"Bearer {client.access_token}"
369 }
370
371 payload = {}
372 if amount:
373 payload["amount"] = {
374 "value": str(amount),
375 "currency_code": "USD"
376 }
377
378 if note:
379 payload["note_to_payer"] = note
380
381 response = requests.post(url, headers=headers, json=payload)
382 return response.json()
383
384def get_refund_details(refund_id):
385 """Get refund details."""
386 client = PayPalClient(CLIENT_ID, CLIENT_SECRET)
387
388 url = f"{client.base_url}/v2/payments/refunds/{refund_id}"
389 headers = {
390 "Authorization": f"Bearer {client.access_token}"
391 }
392
393 response = requests.get(url, headers=headers)
394 return response.json()
395```
396
397## Error Handling
398
399```python
400class PayPalError(Exception):
401 """Custom PayPal error."""
402 pass
403
404def handle_paypal_api_call(api_function):
405 """Wrapper for PayPal API calls with error handling."""
406 try:
407 result = api_function()
408 return result
409 except requests.exceptions.RequestException as e:
410 # Network error
411 raise PayPalError(f"Network error: {str(e)}")
412 except Exception as e:
413 # Other errors
414 raise PayPalError(f"PayPal API error: {str(e)}")
415
416# Usage
417try:
418 order = handle_paypal_api_call(lambda: client.create_order(25.00))
419except PayPalError as e:
420 # Handle error appropriately
421 log_error(e)
422```
423
424## Testing
425
426```python
427# Use sandbox credentials
428SANDBOX_CLIENT_ID = "..."
429SANDBOX_SECRET = "..."
430
431# Test accounts
432# Create test buyer and seller accounts at developer.paypal.com
433
434def test_payment_flow():
435 """Test complete payment flow."""
436 client = PayPalClient(SANDBOX_CLIENT_ID, SANDBOX_SECRET, mode='sandbox')
437
438 # Create order
439 order = client.create_order(10.00)
440 assert 'id' in order
441
442 # Get approval URL
443 approval_url = next((link['href'] for link in order['links'] if link['rel'] == 'approve'), None)
444 assert approval_url is not None
445
446 # After approval (manual step with test account)
447 # Capture order
448 # captured = client.capture_order(order['id'])
449 # assert captured['status'] == 'COMPLETED'
450```
451
452## Resources
453
454- **references/express-checkout.md**: Express Checkout implementation guide
455- **references/ipn-handling.md**: IPN verification and processing
456- **references/refund-workflows.md**: Refund handling patterns
457- **references/billing-agreements.md**: Recurring billing setup
458- **assets/paypal-client.py**: Production PayPal client
459- **assets/ipn-processor.py**: IPN webhook processor
460- **assets/recurring-billing.py**: Subscription management
461
462## Best Practices
463
4641. **Always Verify IPN**: Never trust IPN without verification
4652. **Idempotent Processing**: Handle duplicate IPN notifications
4663. **Error Handling**: Implement robust error handling
4674. **Logging**: Log all transactions and errors
4685. **Test Thoroughly**: Use sandbox extensively
4696. **Webhook Backup**: Don't rely solely on client-side callbacks
4707. **Currency Handling**: Always specify currency explicitly
471
472## Common Pitfalls
473
474- **Not Verifying IPN**: Accepting IPN without verification
475- **Duplicate Processing**: Not checking for duplicate transactions
476- **Wrong Environment**: Mixing sandbox and production URLs/credentials
477- **Missing Webhooks**: Not handling all payment states
478- **Hardcoded Values**: Not making configurable for different environments
479
In the file
SKILL.md1,272 words
Files1
LicenceMIT
Why you can read it

Nothing in a skill executes. The client loads the text and the model follows it, so a skill can be audited the way a runbook is — by reading it.

What it costs in context

Skills are not billed by the call. They are paid for in context: every token the instructions occupy is a token your code, your diff and your conversation cannot use. Here is what this one takes and when it takes it.

≈70
always loaded
The name and description, so the model knows the skill exists and when to reach for it.
3,405
on trigger
The instruction body, read only when the skill fires.
1.7%
of a 200k window
Ten skills this size would take about 17% of the window before you open a file.
050k100k150k200k context window

3.5k tokens, estimated from the bundle at four bytes to the token, held for the rest of the session once it triggers. Middling. Fine to keep on in a project where you use it weekly, worth unloading in one where you never do.

Servers bill, skills cost

A server charges by the month. A skill charges once per session, in context, and then keeps charging it for as long as the session lives.

Before and after

The same question, put to the same model twice: once as it comes, and once with these instructions loaded.

No worked example has been published for this skill yet.

Adoption
Installsnone yet
Ratingno reviews yet

The procedure it runs

The procedure has not been published here. It is in the skill’s own SKILL.md, which its author has not sent to the marketplace yet.

Prose, not code

These steps are written for a model to follow, not executed by a runtime. It can still be told to skip one, and it will say so when it does.

Servers it uses

None. This skill calls no MCP servers at all.

Everything it needs is in the instructions, so it works in a project with nothing connected — the model reads the file and changes how it works with what it can already reach.

It writes no files and reaches no network. All it changes is how the model reasons and writes.

What it asks for
Writes filesno
Network accessno

Read from the allowed-tools line of this skill’s own SKILL.md. A skill grants no permissions of its own — it can only ask for tools your client already has.

What it will not do

Every skill is narrow, and the useful ones say where they stop. These are the jobs this one is the wrong tool for.

What this skill is not for has not been published here. Nothing is implied by that: it is a section the author has not filled in.

What is in the bundle

1 file, 13.9 kB on disk. A bundle is text throughout: the instructions the model reads, plus the templates it fills in.

  • SKILL.md13.9 kB
What is not in it

No dependencies and nothing executable: a skill is text the agent reads, so the bundle is 1 file you can review in full before installing. The MIT licence covers the templates and examples as well as the instructions.

Install

Installing copies the bundle into your project. Nothing runs at install time — the files sit on disk until the model reads them.

$79 once
PayPal Integration · MIT · rmyndharis
one-time
Price$79 once
LicenceMIT — the author’s, unchanged by this purchase
Paid throughStripe, once, on the card you add at the checkout
Keeps workingfor good — the files are yours once they are on disk
Updatesevery update its author ships, delivered through this account

You can read the whole bundle before paying — the SKILL.md above is the product, not a preview of it. What the money buys is the delivery: the folder packaged and handed to your machine by key, every update its author ships, and our support if it does not do what this listing says. The terms of use are MIT, set by the author and unchanged by buying it here.

Payment runs through Stripe, on a page like this one rather than a redirect. Once there is an account it joins the same mcprush invoice as everything else you run, so there is never a second card to enter.

Which clients pick it up on their own

A skill is a folder of text. A client with a skills folder reads it without being told; everywhere else the same text works, it is just handed to the model rather than found.

Claude Code.claude/skills/
Claude Desktop
ChatGPT
Cursor.cursor/skills/
VS Code.github/skills/
Codex CLI.agents/skills/
Gemini CLI.gemini/skills/
Grok.grok/skills/
Zed.agents/skills/
Windsurf.windsurf/skills/
Agent SDK.claude/skills/
HTTP / API
This release
Versionnot versioned
Publishedno release date on file
Price$79
Referencermyndharis/paypal-integration

Versions

Its author publishes no version number, so there is nothing here to pin to: what you install is the folder as it stands today. Instructions change more often than APIs do — a skill can be rewritten entirely without anything it depends on moving.

v
  • No earlier releases have been published to the marketplace.
Pinning

Nothing to pin to: this skill carries no version number of its own. What you install is what the folder holds on the day you install it.

Reviews

no reviews yet · no installs yet

Nobody has reviewed this skill yet. The rating is the mean of the reviews written here, so there is none until somebody writes the first.

Who can post

Only accounts that have had the skill installed for fourteen days, so a review is written after living with it rather than after reading it. Publishers may reply once.

Who wrote it

RM
rmyndharis

Publishes on mcprush.

0 servers listed1 skill listednot claimed
Profile
Publisher
Servers0