def test_cash_pay(self): activity = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, payment_type=Activity.PaymentType.CASH_PAY, title='no online pay', description='on need online pay', start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59', join_end="4000-01-01 22:59:59", max_members=10) url = self.JOIN_ACTIVITY.format(activity_id=activity.id) body = { "payment": TeamOrder.OrderPaymentMethod.WXPAY.value, "nickname": "Nick name" } self.auth_user = User.create(name='no need online pay') response = self.fetch(url, method='POST', body=json.dumps(body), params={'team_id': self.team.id}) result = json.loads(response.body.decode()) expect = { "status": "ok", "state": ActivityMember.ActivityMemberState.confirmed.value, "payment_state": TeamOrder.OrderState.WAIT_BUYER_PAY.value, "order_no": "" } self.assertDictEqual(expect, result, result) self.assertEqual(200, response.code, response.body) with self.assertRaises(TeamOrder.DoesNotExist): TeamOrder.get( user=self.auth_user, activity_id=activity.id, ) member = ActivityMember.get(activity=activity, user=self.auth_user) # 现在支付, 直接确认 self.assertEqual(ActivityMember.ActivityMemberState.confirmed.value, member.state, member.state)
def test_cash_free_activity(self): """ 参加免费活动不需要支付 线下支付活动的 ActivityMember.state 应该为 `确认` confirmed """ activity = self.create_free_activity( payment_type=Activity.PaymentType.CASH_PAY.value) url = self.JOIN_ACTIVITY.format(activity_id=activity.id) body = { "payment": TeamOrder.OrderPaymentMethod.WXPAY.value, "nickname": "Nick name" } self.auth_user = User.create(name='free activity') response = self.fetch(url, method='POST', body=json.dumps(body), params={'team_id': self.team.id}) self.assertEqual(200, response.code, response.body) result = json.loads(response.body.decode()) expect = { "status": "ok", "state": ActivityMember.ActivityMemberState.confirmed.value, "payment_state": TeamOrder.OrderState.TRADE_BUYER_PAID.value, "order_no": "" } self.assertDictEqual(expect, result, result) with self.assertRaises(TeamOrder.DoesNotExist): TeamOrder.get(user=self.auth_user, activity_id=activity.id) member = ActivityMember.get(activity=activity, user=self.auth_user) self.assertEqual(ActivityMember.ActivityMemberState.confirmed.value, member.state, member.state)
def leave(cls, user_id, match: Match, notify_url: str = None, insists=False, role: int = 1): """ 退出赛事 :param user_id: :param match: :param notify_url: 派队回调地址 :param insists: 强制退出 :param role: 退赛发起人, 1 用户, 2 赛事方 :return: """ logging.debug("notify_url: {0}, insists: {1}".format( notify_url, insists)) if not insists and notify_url is None: raise AssertionError("非强制退出 `insists=False` 操作需要提供退款回调" "地址 `notify_url`") if insists is False and not match.can_leave(): raise MatchException("赛事无法退出") # 退出赛事 member = MatchMember.get(user_id=user_id, match_id=match.id) # type: MatchMember with Match._meta.database.transaction(): if insists: match.leave(member) # Warning: 数据库事物中尝试远程 HTTP 调用, 需要修复 else: # match.leave_request(member) # 调用退款接口 pt = Parteam(app.settings["parteam_api_url"]) if member.order_id: # 有支付信息, 调用退款接口 order = TeamOrder.get( id=member.order_id) # type: TeamOrder refund_fee = int(order.payment_fee * 100) try: pt.order_refund(user_id=user_id, order_no=member.pt_order_no, refund_fee=refund_fee, notify_url=notify_url, role=role) except NotPaidError as e: logging.warning("调用派队退款接口发现订单未支付: {0}".format(str(e))) TeamOrder.update(state=TeamOrder.OrderState .TRADE_CLOSED_BY_USER.value) \ .where(TeamOrder.id == member.order_id) \ .execute() match.leave(member) except RefundError as e: raise MatchException(e) else: # 更新订单状态为 `退款`, 订单退款状态为 `全部退款` TeamOrder.update( state=TeamOrder.OrderState.TRADE_CLOSED.value, refund_state=TeamOrder.OrderRefundState.FULL_REFUNDED.value, refunded_time=datetime.now())\ .where(TeamOrder.id == member.order_id)\ .execute() match.leave(member) else: # 无支付信息直接退赛 match.leave(member)
def refund(order_no, refund_fee, is_retry=False): """ Args: order_no: int, 订单号 refund_fee: 退款金额 """ wxpay = WxPay(appid=current_app.settings["wxpay_appid"], mch_id=current_app.settings["wxpay_mchid"], secret_key=current_app.settings["wxpay_secret_key"], ca_certs=current_app.settings["wxpay_ca_certs"], client_cert=current_app.settings["wxpay_api_client_cert"], client_key=current_app.settings["wxpay_api_client_key"]) order = TeamOrder.get(order_no=order_no) if order.payment_method == order.OrderPaymentMethod.WXPAY.value and \ order.refund_state in ( TeamOrder.OrderRefundState.PARTIAL_REFUNDING.value, TeamOrder.OrderRefundState.PARTIAL_REFUNDED.value, TeamOrder.OrderRefundState.FULL_REFUNDING.value, TeamOrder.OrderRefundState.FULL_REFUNDED.value ): if is_retry: out_trade_no = 'J%s' % order.order_no else: out_trade_no = 'N%s' % order.order_no try: response = wxpay.refund(out_trade_no=out_trade_no, out_refund_no="R%s" % order.order_no, total_fee=order.total_fee, refund_fee=refund_fee, # transaction_id=order.gateway_trade_no, op_user_id=order.gateway_account) except Exception as e: logging.error("refund fail, order_no:{0} exception:{1}".format(out_trade_no, e)) response = None if response and response["result_code"] == "SUCCESS": logging.debug(response) TeamOrder.update( refund_state=TeamOrder.OrderRefundState.FULL_REFUNDED.value, refunded_fee=refund_fee, refunded_time=datetime.datetime.now(), state=TeamOrder.OrderState.TRADE_CLOSED, )\ .where(TeamOrder.order_no == order.order_no)\ .execute() # 换个订单号重试 elif not is_retry: refund(order_no, refund_fee, is_retry=True) else: # 标记退款失败 TeamOrder.update( refund_state=TeamOrder.OrderRefundState.FULL_REFUND_FAILED.value, ).where(TeamOrder.order_no == order.order_no)\ .execute() logging.error("refund fail,order_no:{0} response:{1}".format(order_no, response))