diff --git a/products/views/chongzhi_payment.py b/products/views/chongzhi_payment.py index 7509c74..4cacfaa 100644 --- a/products/views/chongzhi_payment.py +++ b/products/views/chongzhi_payment.py @@ -423,60 +423,21 @@ class ShangjiaHuitiao(View): return self.wechat_response('SUCCESS', 'OK') # 6. 验证金额(微信返回的是分,需要转换) - wechat_amount_yuan = Decimal(str(total_fee)) / Decimal('100') # 转换为元 - order_amount_yuan = Decimal(str(order.jine)) # 订单金额(元) + wechat_amount_yuan = total_fee / 100 # 转换为元 + order_amount_yuan = float(order.jine) # 订单金额(元) - # 允许1分钱的误差 - if abs(wechat_amount_yuan - order_amount_yuan) > Decimal('0.01'): + # 允许1分钱的误差(浮点数比较) + if abs(wechat_amount_yuan - order_amount_yuan) > 0.01: logger.error(f"商家订单金额不一致: 订单金额{order_amount_yuan}元, 支付金额{wechat_amount_yuan}元") return self.wechat_response('FAIL', '金额不一致') - # ===== 在这里添加收支记录更新代码 ===== - # 更新收支记录表 + # 7. 调用统一履约函数(事务 + 行锁 + 幂等 + 收支记录) + from jituan.services.czjilu_fulfill import fulfill_shangjia, CzjiluFulfillError try: - jine_decimal = Decimal(str(order.jine)) if not isinstance(order.jine, Decimal) else order.jine - from jituan.services.szjilu_accounting import repair_wechat_income_if_missing - repair_wechat_income_if_missing( - jine_decimal, - getattr(order, 'club_id', None), - biz_ref=f'cz:{order.dingdan_id}', - ) - - logger.info(f"收支记录更新成功: 订单{order.dingdan_id}, 金额{jine_decimal}元") - - except Exception as e: - # 收支记录更新失败不影响主流程,只记录日志 - logger.error(f"更新收支记录失败: {str(e)}", exc_info=True) - # ===== 添加结束 ===== - - - - # 7. 使用事务更新订单状态和商家余额 - with transaction.atomic(): - # 更新订单状态为已支付(3) - order.zhuangtai = 3 - order.save(update_fields=['zhuangtai']) - logger.info(f"商家订单状态更新成功: {order.dingdan_id} -> 3") - - # 更新商家余额 - try: - # 通过用户ID查找商家(高效查询) - shangjia = UserShangjia.query.get(user__UserUID=order.yonghuid) - - # 增加余额 - shangjia.yue += order_amount_yuan - shangjia.save(update_fields=['yue']) - - logger.info(f"商家余额更新成功: 商家{shangjia.nicheng}, 增加{order_amount_yuan}元, 新余额{shangjia.yue}") - - except UserShangjia.DoesNotExist: - # 如果找不到商家,记录错误,但依然返回成功(避免微信重复回调) - logger.error(f"商家信息不存在: 用户{order.yonghuid}") - return self.wechat_response('SUCCESS', 'OK') - except Exception as e: - logger.error(f"更新商家余额失败: {str(e)}", exc_info=True) - # 回滚事务 - raise + fulfill_shangjia(out_trade_no, paid_amount_yuan=wechat_amount_yuan) + except CzjiluFulfillError as exc: + logger.error('商家充值回调履约失败 %s: %s', out_trade_no, exc) + return self.wechat_response('FAIL', str(exc)) # 8. 返回成功响应给微信 logger.info(f"商家支付回调处理完成: {out_trade_no}") diff --git a/users/views/pay.py b/users/views/pay.py index f4b92fd..452073f 100644 --- a/users/views/pay.py +++ b/users/views/pay.py @@ -397,58 +397,15 @@ class FaKuanHuitiaoView(View): logger.error(f"金额不一致: 订单金额{order_amount_yuan}元, 支付金额{wechat_amount_yuan}元") return self.wechat_response('FAIL', '金额不一致') - # 7. 更新订单状态为已支付(3) - order.zhuangtai = 3 - order.save(update_fields=['zhuangtai']) - logger.info(f"订单状态更新成功: {order.dingdan_id} -> 3") - - # 8. 更新罚单状态为已缴纳(2) + # 7. 调用统一履约函数(事务 + 行锁 + 幂等 + 罚单状态 + 分红 + 收支记录) + from jituan.services.czjilu_fulfill import fulfill_fakuan, CzjiluFulfillError try: - fadan = None - m = re.search(r'#fadan:(\d+)', order.shuoming or '') - if m: - fadan = Penalty.query.filter( - id=int(m.group(1)), - PenalizedUserID=order.yonghuid, - Status__in=[1, 3], - ).first() - if not fadan: - fadan = Penalty.query.filter( - PenalizedUserID=order.yonghuid, - FineAmount=order.jine, - Status__in=[1, 3], - ).order_by('-CreateTime').first() - if fadan: - fadan.Status = 2 # 已缴纳 - fadan.save(update_fields=['Status']) - logger.info(f"罚单 {fadan.id} 已自动标记为已缴纳") + fulfill_fakuan(out_trade_no, paid_amount_yuan=wechat_amount_yuan) + except CzjiluFulfillError as exc: + logger.error('罚款回调履约失败 %s: %s', out_trade_no, exc) + return self.wechat_response('FAIL', str(exc)) - success, msg = process_fadan_fenhong(fadan.id) - if not success: - logger.error(f"罚单 {fadan.id} 分红处理失败: {msg}") - else: - logger.info(f"罚单 {fadan.id} 分红处理完成: {msg}") - - except Exception as e: - logger.error(f"更新罚单状态失败: {str(e)}", exc_info=True) - - # 9. 更新收支记录表 - try: - jine_decimal = Decimal(str(order.jine)) if not isinstance(order.jine, Decimal) else order.jine - from jituan.services.szjilu_accounting import repair_wechat_income_if_missing - repair_wechat_income_if_missing( - jine_decimal, - getattr(order, 'club_id', None), - biz_ref=f'cz:{order.dingdan_id}', - ) - - logger.info(f"收支记录更新成功: 订单{order.dingdan_id}, 金额{jine_decimal}元") - - except Exception as e: - # 收支记录更新失败不影响主流程,只记录日志 - logger.error(f"更新收支记录失败: {str(e)}", exc_info=True) - - # 10. 返回成功响应给微信 + # 8. 返回成功响应给微信 logger.info(f"罚款支付回调处理完成: {out_trade_no}") return self.wechat_response('SUCCESS', 'OK') @@ -975,59 +932,13 @@ class KaohePayCallbackView(View): return self.wechat_response('FAIL', '金额不一致') logger.info(f"金额验证通过: {wechat_yuan}元") - # 更新订单状态为已支付 - order.zhuangtai = 3 - order.save(update_fields=['zhuangtai']) - logger.info(f"订单状态更新为已支付: {out_trade_no}") - - # 从临时表获取业务参数并创建审核记录 + # 调用统一履约函数(事务 + 行锁 + 幂等 + 审核记录 + 收支记录) + from jituan.services.czjilu_fulfill import fulfill_kaohe, CzjiluFulfillError try: - temp = KaohePayTemp.query.get(dingdan_id=out_trade_no, yonghuid=order.yonghuid) - logger.info(f"找到临时表记录: {out_trade_no}, 用户ID: {order.yonghuid}") - - user = User.query.get(UserUID=order.yonghuid) - logger.info(f"获取用户信息成功: {user.UserUID}") - - success, msg, record = create_shenhe_jilu_from_temp(user, temp) - if success: - logger.info(f"创建审核记录成功: jilu_id={record.jilu_id}, 订单号: {out_trade_no}") - else: - logger.error(f"创建审核记录失败: {msg}, 订单号: {out_trade_no}") - # 订单已支付但记录创建失败,需要标记订单异常,人工介入 - order.zhuangtai = 10 # 10表示支付成功但业务处理失败 - order.save(update_fields=['zhuangtai']) - logger.error(f"订单状态标记为异常(10): {out_trade_no}") - - except KaohePayTemp.DoesNotExist: - logger.error(f"临时表无记录,订单号: {out_trade_no}, 用户ID: {order.yonghuid}") - # 尝试从attach解析(兼容旧数据) - attach_element = root.find('attach') - if attach_element is not None and attach_element.text: - try: - attach_data = json.loads(attach_element.text) - logger.info(f"从attach解析数据成功: {attach_data}") - # 这里可以保留旧逻辑,但建议只记录日志 - except Exception as e: - logger.error(f"解析attach失败: {str(e)}") - except Exception as e: - logger.error(f"处理临时表或创建审核记录异常: {str(e)}", exc_info=True) - # 标记订单异常 - order.zhuangtai = 10 - order.save(update_fields=['zhuangtai']) - logger.error(f"订单状态标记为异常(10): {out_trade_no}") - - # 更新收支记录 - try: - jine_decimal = Decimal(str(order.jine)) - from jituan.services.szjilu_accounting import repair_wechat_income_if_missing - repair_wechat_income_if_missing( - jine_decimal, - getattr(order, 'club_id', None), - biz_ref=f'cz:{order.dingdan_id}', - ) - logger.info(f"更新收支记录成功: {jine_decimal}元") - except Exception as e: - logger.error(f"更新收支记录失败: {str(e)}", exc_info=True) + fulfill_kaohe(out_trade_no, paid_amount_yuan=wechat_yuan) + except CzjiluFulfillError as exc: + logger.error('考核回调履约失败 %s: %s', out_trade_no, exc) + return self.wechat_response('FAIL', str(exc)) logger.info(f"考核支付回调处理完成,订单号: {out_trade_no}") return self.wechat_response('SUCCESS', 'OK')