ZHIWEI666 commited on
Commit
d9592d3
·
verified ·
1 Parent(s): 8072b08

更新支付宝付款

Browse files
Files changed (1) hide show
  1. router_wallet.py +97 -5
router_wallet.py CHANGED
@@ -175,18 +175,110 @@ async def purchase_item(req: PurchaseRequest, db: Session = Depends(get_db)):
175
  db.commit()
176
  return {"status": "success"}
177
 
178
- # =============== 以下为预留的充值/回调桩函数 ===============
 
179
  @router.post("/api/wallet/create_recharge_order")
180
  async def create_recharge_order(req: RechargeRequest, db: Session = Depends(get_db)):
 
 
 
 
181
  order_id = f"R_{int(time.time())}_{uuid.uuid4().hex[:6]}"
182
- # 由于缺少完整的支付宝业务逻辑代码,在此仅构建基础结构以防 import 崩溃
183
- # 实际项目中这里应通过 alipay.api_alipay_trade_precreate 返回二维码
184
- return {"status": "success", "order_id": order_id, "qr_code_url": "mock_qr_url"}
 
 
 
 
 
 
 
 
 
 
 
 
185
 
186
  @router.get("/api/wallet/check_order/{order_id}")
187
  async def check_order(order_id: str, db: Session = Depends(get_db)):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  return {"status": "PENDING"}
189
 
190
  @router.post("/api/wallet/alipay_notify")
191
  async def alipay_notify(request: Request, db: Session = Depends(get_db)):
192
- return {"status": "success"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  db.commit()
176
  return {"status": "success"}
177
 
178
+ # =============== 以下为真实支付宝充值回调逻辑 ===============
179
+
180
  @router.post("/api/wallet/create_recharge_order")
181
  async def create_recharge_order(req: RechargeRequest, db: Session = Depends(get_db)):
182
+ if not alipay:
183
+ raise HTTPException(status_code=500, detail="支付宝支付组件未配置或秘钥加载失败")
184
+
185
+ # 生成带时间戳和随机哈希的全局唯一订单号
186
  order_id = f"R_{int(time.time())}_{uuid.uuid4().hex[:6]}"
187
+
188
+ try:
189
+ # 调用支付宝当面付接口生成二维码链接 (1积分 = 1元)
190
+ result = alipay.api_alipay_trade_precreate(
191
+ subject=f"ComfyUI社区积分充值 - {req.account}",
192
+ out_trade_no=order_id,
193
+ total_amount=str(req.amount),
194
+ )
195
+
196
+ if result.get("code") == "10000":
197
+ return {"status": "success", "order_id": order_id, "qr_code_url": result.get("qr_code")}
198
+ else:
199
+ raise HTTPException(status_code=400, detail=result.get("msg", "创建支付宝订单失败"))
200
+ except Exception as e:
201
+ raise HTTPException(status_code=500, detail=f"支付网关异常: {str(e)}")
202
 
203
  @router.get("/api/wallet/check_order/{order_id}")
204
  async def check_order(order_id: str, db: Session = Depends(get_db)):
205
+ """前端轮询查单接口:主动向支付宝查询订单状态,防止异步回调延迟或丢失"""
206
+ if not alipay:
207
+ return {"status": "PENDING"}
208
+
209
+ try:
210
+ # 主动向支付宝发起查单请求
211
+ result = alipay.api_alipay_trade_query(out_trade_no=order_id)
212
+ if result.get("code") == "10000" and result.get("trade_status") == "TRADE_SUCCESS":
213
+
214
+ # 查单发现已支付,检查数据库防重复加钱
215
+ existing_tx = db.query(Transaction).filter(Transaction.tx_id == order_id).first()
216
+ if not existing_tx:
217
+ # 提取金额并加锁更新账户
218
+ amount = int(float(result.get("total_amount", 0)))
219
+ account = result.get("subject", "").split(" - ")[-1]
220
+
221
+ wallet = db.query(Wallet).filter(Wallet.account == account).with_for_update().first()
222
+ if not wallet:
223
+ wallet = Wallet(account=account)
224
+ db.add(wallet)
225
+
226
+ wallet.balance += amount
227
+
228
+ # 手动记录一条流水,tx_id 强制绑定为支付宝的 order_id 防止重复处理
229
+ last_tx = db.query(Transaction).filter(Transaction.account == account).order_by(Transaction.created_at.desc()).first()
230
+ prev_hash = last_tx.tx_hash if last_tx else "GENESIS_HASH"
231
+ tx_hash = calculate_tx_hash(order_id, account, "RECHARGE", amount, prev_hash)
232
+
233
+ new_tx = Transaction(
234
+ tx_id=order_id, account=account, tx_type="RECHARGE", amount=amount,
235
+ prev_hash=prev_hash, tx_hash=tx_hash
236
+ )
237
+ db.add(new_tx)
238
+ db.commit()
239
+
240
+ return {"status": "SUCCESS"}
241
+ except Exception:
242
+ pass
243
+
244
  return {"status": "PENDING"}
245
 
246
  @router.post("/api/wallet/alipay_notify")
247
  async def alipay_notify(request: Request, db: Session = Depends(get_db)):
248
+ """支付宝异步回调 Webhook (最高优先级的到账通知)"""
249
+ data = dict(await request.form())
250
+ signature = data.pop("sign", None)
251
+
252
+ # 核心风控:验证签名是否真的是支付宝发来的
253
+ if not alipay or not alipay.verify(data, signature):
254
+ return Response(content="fail", media_type="text/plain")
255
+
256
+ if data.get("trade_status") in ("TRADE_SUCCESS", "TRADE_FINISHED"):
257
+ order_id = data.get("out_trade_no")
258
+
259
+ # 检查是否已经被轮询查单处理过了
260
+ existing_tx = db.query(Transaction).filter(Transaction.tx_id == order_id).first()
261
+ if not existing_tx:
262
+ amount = int(float(data.get("total_amount", 0)))
263
+ account = data.get("subject", "").split(" - ")[-1]
264
+
265
+ wallet = db.query(Wallet).filter(Wallet.account == account).with_for_update().first()
266
+ if not wallet:
267
+ wallet = Wallet(account=account)
268
+ db.add(wallet)
269
+
270
+ wallet.balance += amount
271
+
272
+ last_tx = db.query(Transaction).filter(Transaction.account == account).order_by(Transaction.created_at.desc()).first()
273
+ prev_hash = last_tx.tx_hash if last_tx else "GENESIS_HASH"
274
+ tx_hash = calculate_tx_hash(order_id, account, "RECHARGE", amount, prev_hash)
275
+
276
+ new_tx = Transaction(
277
+ tx_id=order_id, account=account, tx_type="RECHARGE", amount=amount,
278
+ prev_hash=prev_hash, tx_hash=tx_hash
279
+ )
280
+ db.add(new_tx)
281
+ db.commit()
282
+
283
+ # 必须向支付宝返回 success,否则支付宝会按阶梯间隔持续重发请求
284
+ return Response(content="success", media_type="text/plain")