Paypal payment integration
Skill findscripter/everything-skills/02-engineering/paypal-payment-integration
类书式 AI Agent 技能大典 · 精选/中文化/互见成网的 500+ 开源技能,可作为 Claude Code 插件市场一键安装。A curated, cross-referenced encyclopedia of 500+ open-source agent skills.
npx -y skills add findscripter/everything-skills --skill paypal-payment-integrationAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
当在后端接入 PayPal 收款、订阅或退款时使用;做 Orders v2 创建/捕获订单、IPN/Webhook 验签去重、Billing 订阅与退款的服务端落地;不适用于 Stripe/支付宝等其他支付渠道或纯前端按钮渲染;触发词:PayPal、Express Checkout、IPN、订阅扣费、退款
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
7.3 KB, as published. Nobody here has run it
何时使用
适用:在服务端接入 PayPal 作为支付方式,包括一次性收款(Express Checkout / Smart Buttons)、订阅与周期扣费、退款与争议处理、IPN/Webhook 异步通知验签、国际多币种支付。
不该用(负边界):
- 任务与 PayPal 无关,或目标是 Stripe、支付宝、微信支付等其他渠道。
- 只需前端渲染按钮、无服务端验证(前端回调不可信,必须服务端二次确认)。
- 缺少 client_id / client_secret、环境(sandbox/live)、币种或回调 URL 等必要输入时,先停下来澄清,不要硬编码假值。
步骤
- 明确目标与约束:收款场景(单次/订阅/退款)、环境(sandbox 还是 live)、币种、回调与 IPN/Webhook 地址。
- 用 client_credentials 换取 OAuth access_token(
/v1/oauth2/token)。 - 服务端创建订单
POST /v2/checkout/orders(intent=CAPTURE),前端用 Smart Buttons 拉起审批。 - 用户审批后,由服务端捕获
POST /v2/checkout/orders/{id}/capture,切勿仅信任前端onApprove。 - 配置异步通知(IPN 或 Webhook):收到后回传 PayPal 验签,再按
payment_status落库、去重、发货。 - 按需创建订阅计划/订阅、处理退款,并对所有 API 调用包裹统一错误处理。
- 全程先在 sandbox 用测试买卖家账号验证,再切 live。
指令
- 环境隔离:sandbox 用
https://api-m.sandbox.paypal.com,生产用https://api-m.paypal.com;IPN 验签 sandbox 用https://ipnpb.sandbox.paypal.com/cgi-bin/webscr。切勿混用凭据与 URL。 - IPN 验签:原样复制收到的表单字段,追加
cmd=_notify-validate回传 PayPal,仅当响应文本为VERIFIED才处理。 - 幂等去重:按
txn_id判断是否已处理,防止重复通知重复发货。 - 凭据与环境(mode/币种/回调 URL)全部走配置,不硬编码。
示例
前端 Smart Buttons(仅拉起 + 回传服务端,不在前端确认收款):
<div id="paypal-button-container"></div>
<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID¤cy=USD"></script>
<script>
paypal.Buttons({
createOrder: (data, actions) => actions.order.create({
purchase_units: [{ amount: { value: '25.00' } }]
}),
onApprove: (data, actions) =>
fetch('/api/paypal/capture', { // 交给服务端捕获/校验
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({ orderID: data.orderID })
})
}).render('#paypal-button-container');
</script>
服务端客户端(取 token / 建单 / 捕获):
import requests
class PayPalClient:
def __init__(self, client_id, client_secret, mode='sandbox'):
self.client_id, self.client_secret = client_id, client_secret
self.base_url = ('https://api-m.sandbox.paypal.com' if mode == 'sandbox'
else 'https://api-m.paypal.com')
self.access_token = self.get_access_token()
def get_access_token(self):
r = requests.post(f"{self.base_url}/v1/oauth2/token",
headers={"Accept": "application/json", "Accept-Language": "en_US"},
data={"grant_type": "client_credentials"},
auth=(self.client_id, self.client_secret))
return r.json()['access_token']
def create_order(self, amount, currency='USD'):
return requests.post(f"{self.base_url}/v2/checkout/orders",
headers={"Content-Type": "application/json",
"Authorization": f"Bearer {self.access_token}"},
json={"intent": "CAPTURE",
"purchase_units": [{"amount": {"currency_code": currency, "value": str(amount)}}]}
).json()
def capture_order(self, order_id):
return requests.post(f"{self.base_url}/v2/checkout/orders/{order_id}/capture",
headers={"Content-Type": "application/json",
"Authorization": f"Bearer {self.access_token}"}).json()
IPN 验签与分发(核心约束):
@app.route('/ipn', methods=['POST'])
def handle_ipn():
ipn = request.form.to_dict()
if not verify_ipn(ipn):
return 'IPN verification failed', 400
status = ipn.get('payment_status')
if status == 'Completed': handle_payment_completed(ipn) # 内部按 txn_id 去重
elif status == 'Refunded': handle_refund(ipn)
elif status == 'Reversed': handle_chargeback(ipn)
return 'IPN processed', 200
def verify_ipn(ipn):
data = ipn.copy(); data['cmd'] = '_notify-validate'
url = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr' # 生产换正式域名
return requests.post(url, data=data).text == 'VERIFIED'
退款(部分退款传 amount,否则全额):
# POST /v2/payments/captures/{capture_id}/refund
payload = {}
if amount: payload["amount"] = {"value": str(amount), "currency_code": "USD"}
if note: payload["note_to_payer"] = note
订阅:先 POST /v1/billing/plans 建计划(需先有 product_id),再 POST /v1/billing/subscriptions 建订阅,从返回 links 中取 rel == 'approve' 的审批 URL 引导用户。
注意事项
- 永远验签 IPN/Webhook,绝不直接信任未验证的通知。
- 幂等处理:按
txn_id去重,应对重复通知。 - 环境隔离:不要混用 sandbox 与 live 的 URL/凭据。
- 覆盖全部支付状态(Completed/Refunded/Reversed 等),不要漏处理回调。
- 别仅依赖前端回调;以服务端捕获 + 异步通知为准(双保险)。
- 显式指定币种;记录所有交易与错误日志;先在 sandbox 充分测试。
- 本技能不替代针对你环境的验证、测试与专家评审。
互见
- 源附带的参考资料(可在 vendor 目录查阅):
references/express-checkout.md、references/ipn-handling.md、references/refund-workflows.md、references/billing-agreements.md,以及assets/paypal-client.py、assets/ipn-processor.py、assets/recurring-billing.py。 - 同域可比对其他支付渠道集成技能(如 Stripe)。
采编自 sickn33/antigravity-awesome-skills(MIT License),适配重写而非逐字翻译。