Sin Descripción

views.py 12KB

    # -*- coding: utf-8 -*- from django.conf import settings from django.db import transaction from django.shortcuts import HttpResponse from django_logit import logit from django_response import response from paginator import pagination from pywe_exception import WeChatPayException from pywe_pay import WeChatPay from pywe_pay_notify import check_pay_notify from pywe_response import WXPAY_NOTIFY_FAIL, WXPAY_NOTIFY_SUCCESS from pywe_sign import check_signature from TimeConvert import TimeConvert as tc from account.models import UserIncomeExpensesInfo, UserInfo from group.models import GroupPhotoInfo, GroupPhotoOrderInfo from pay.models import OrderInfo from photo.models import PhotosInfo from utils.error.errno_utils import (GroupPhotoStatusCode, OrderStatusCode, UserStatusCode, WechatStatusCode, WithdrawStatusCode) from utils.price_utils import get_group_photo_price from utils.redis.rbrief import set_brief_info from utils.redis.rorder import set_lensman_order_record from utils.wx_utils import get_trade_type, get_user_openid WECHAT = settings.WECHAT @logit @transaction.atomic def wx_order_create_api(request): """ 订单创建 """ group_id = request.POST.get('group_id', '') user_id = request.POST.get('user_id', '') photo_id = request.POST.get('photo_id', '') photo_type = request.POST.get('photo_type', 'nomark') # nomark for 去除水印, origin for 获取高清图 photo_type_int = OrderInfo.ORIGIN if photo_type == 'origin' else OrderInfo.NOMARK # 用户校验 try: user = UserInfo.objects.get(user_id=user_id) except UserInfo.DoesNotExist: return response(UserStatusCode.USER_NOT_FOUND) # 群组照片校验 try: group_photo = GroupPhotoInfo.objects.get(photo_id=photo_id, status=True) except GroupPhotoInfo.DoesNotExist: return response(GroupPhotoStatusCode.GROUP_PHOTO_NOT_FOUND) # 判断是否重复购买 if OrderInfo.objects.filter(photo_id=photo_id, photo_type=photo_type_int, from_uid=user_id, pay_status=OrderInfo.PAID, status=True).exists(): return response(OrderStatusCode.WX_ORDER_PAID_ALREADY_EXISTS) body = request.POST.get('body', '') # 商品描述 total_fee = int(request.POST.get('total_fee', 0)) # 总金额,单位分 # 金额校验 if get_group_photo_price(group_photo, photo_type) != total_fee: return response(OrderStatusCode.FEE_CHECK_FAIL) # 获取 from_uid, to_uid from_uid = user_id to_uid = group_photo.lensman_id or group_photo.user_id # JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里 trade_type = request.POST.get('trade_type', '') # 根据 trade_type 获取 wechat 配置 wxcfg = WECHAT.get(trade_type, {}) # WeChatPay 初始化 wxpay = WeChatPay(wxcfg.get('appID'), wxcfg.get('apiKey'), wxcfg.get('mchID')) # 生成订单 order = OrderInfo.objects.create( group_id=group_id, photo_id=photo_id, lensman_photo_id=group_photo.lensman_photo_id, photo_type=photo_type_int, from_uid=from_uid, to_uid=to_uid, session_id=group_photo.session_id, total_fee=total_fee, trade_type=trade_type, ) try: prepay_data = wxpay.order.create( body=body, notify_url=settings.API_DOMAIN + '/wx/notify_url', out_trade_no=order.order_id, total_fee=total_fee, trade_type=get_trade_type(trade_type), openid=get_user_openid(user, trade_type), # 可选,用户在商户appid下的唯一标识。trade_type=JSAPI,此参数必传 ) except WeChatPayException as e: order.unifiedorder_result = e.message order.save() return response(OrderStatusCode.WX_UNIFIED_ORDER_FAIL) prepay_id = prepay_data.get('prepay_id', '') order.prepay_id = prepay_id order.save() if trade_type == 'JSAPI' or trade_type == 'MINIAPP': wxpay_params = wxpay.jsapi.get_jsapi_params(prepay_id) elif trade_type == 'APP': wxpay_params = wxpay.order.get_appapi_params(prepay_id) return response(200, 'Order Create Success', u'订单创建成功', { 'order_id': order.order_id, 'prepay_id': prepay_id, 'wxpay_params': wxpay_params, }) def order_paid_success(order): if order.pay_status == OrderInfo.PAID: return if order.photo_type == OrderInfo.NOMARK: order.photo_status = OrderInfo.FETCHED order.pay_status = OrderInfo.PAID order.paid_at = tc.utc_datetime() order.save() porder, created = GroupPhotoOrderInfo.objects.select_for_update().get_or_create( group_id=order.group_id, session_id=order.session_id, user_id=order.from_uid, photo_id=order.photo_id, lensman_photo_id=order.lensman_photo_id, ) photo = PhotosInfo.objects.get( lensman_id=order.to_uid, session_id=order.session_id, photo_id=order.lensman_photo_id, ) if order.photo_type == OrderInfo.NOMARK: porder.m_photo_path = photo.m_photo_path elif order.photo_type == OrderInfo.ORIGIN: porder.r_photo_path = photo.r_photo_path porder.save() set_lensman_order_record(porder) to_uid = order.to_uid total_fee = order.total_fee try: user = UserInfo.objects.select_for_update().get(user_id=to_uid) except UserInfo.DoesNotExist: return if order.photo_type == OrderInfo.NOMARK: # 余额增加 amount, freeze_income_amount = total_fee, 0 user.balance += amount # Redis 数值更新 set_brief_info(to_uid, order.photo_type, total_fee) # 余额记录 UserIncomeExpensesInfo.objects.create( user_id=to_uid, photo_id=order.photo_id, type=UserIncomeExpensesInfo.INCOME, amount=amount, balance=user.balance, freeze_income_amount=freeze_income_amount, freeze_income_balance=user.freeze_income_balance, remark=u'图片购买', ) elif order.photo_type == OrderInfo.ORIGIN: amount, freeze_income_amount = 0, total_fee user.freeze_income_balance += freeze_income_amount user.save() def order_paid_fail(order): if order.pay_status == OrderInfo.FAIL: return order.pay_status = OrderInfo.FAIL order.save() @logit @transaction.atomic def wx_order_query_api(request): """ 订单查询 """ order_id = request.POST.get('order_id', '') transaction_id = request.POST.get('transaction_id', '') try: order = OrderInfo.objects.select_for_update().get(order_id=order_id, status=True) except OrderInfo.DoesNotExist: return response(OrderStatusCode.WX_ORDER_NOT_FOUND) if order.pay_status == OrderInfo.PAID: return response(200, 'Order Pay Success', u'订单支付成功') elif order.pay_status == OrderInfo.FAIL: return response(OrderStatusCode.WX_ORDER_PAY_FAIL) # 根据 trade_type 获取 wechat 配置 wxcfg = WECHAT.get(order.trade_type, {}) # WeChatPay 初始化 wxpay = WeChatPay(wxcfg.get('appID'), wxcfg.get('apiKey'), wxcfg.get('mchID')) # 订单查询 query_data = wxpay.order.query(transaction_id, order_id) # 签名校验 if not check_signature(query_data, wxcfg.get('apiKey')): return response(OrderStatusCode.SIGN_CHECK_FAIL) order.notify_msg = query_data order.transaction_id = query_data.get('transaction_id', '') order.save() # 交易状态 trade_state = query_data.get('trade_state') # 订单状态判断更新 if trade_state == 'SUCCESS': # 订单支付成功 order_paid_success(order) return response(200, 'Order Pay Success', u'订单支付成功') elif trade_state == 'NOTPAY': # 订单未支付 return response(OrderStatusCode.WX_ORDER_NOT_PAY) elif trade_state == 'USERPAYING': # 订单支付中 return response(OrderStatusCode.WX_ORDER_PAYING) else: # 订单支付失败 order_paid_fail(order) return response(OrderStatusCode.WX_ORDER_PAY_FAIL) @logit @transaction.atomic def wx_order_list_api(request): """ 订单列表 """ user_id = request.POST.get('user_id', '') page = int(request.POST.get('page', 1)) num = int(request.POST.get('num', settings.ORDER_NUM_PER_PAGE)) orders = OrderInfo.objects.filter(from_uid=user_id, pay_status=OrderInfo.PAID, status=True).order_by('-pk') orders, left = pagination(orders, page, num) orders = [order.data(user_id) for order in orders] return response(200, 'Get Order List Success', u'获取订单列表成功', { 'orders': orders, 'left': left, }) @logit @transaction.atomic def wx_order_detail_api(request): """ 订单详情 """ user_id = request.POST.get('user_id', '') order_id = request.POST.get('order_id', '') try: order = OrderInfo.objects.get(order_id=order_id, status=True) except OrderInfo.DoesNotExist: return response(OrderStatusCode.WX_ORDER_NOT_FOUND) if user_id not in [order.from_uid, order.to_uid]: return response(OrderStatusCode.NO_DETAIL_PERMISSION) return response(200, 'Get Order Detail Success', u'获取订单详情成功', order.data(user_id)) @logit @transaction.atomic def wx_notify_url_api(request): """ 支付异步通知回调地址 """ notify_data, success = check_pay_notify(request.body, wx_configs=settings.WECHAT) if not success: return HttpResponse(WXPAY_NOTIFY_FAIL) try: order = OrderInfo.objects.select_for_update().get(order_id=notify_data.get('out_trade_no', ''), status=True) except OrderInfo.DoesNotExist: return HttpResponse(WXPAY_NOTIFY_FAIL) order.notify_msg = request.body order.transaction_id = notify_data.get('transaction_id', '') order.save() result_code = notify_data.get('result_code', '') if result_code == 'SUCCESS': order_paid_success(order) else: order_paid_fail(order) return HttpResponse(WXPAY_NOTIFY_SUCCESS) @logit @transaction.atomic def wx_balance_withdraw_api(request): user_id = request.POST.get('user_id', '') # 用户校验 try: user = UserInfo.objects.select_for_update().get(user_id=user_id) except UserInfo.DoesNotExist: return response(UserStatusCode.USER_NOT_FOUND) # JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里 trade_type = request.POST.get('trade_type', '') # TRANSFER--企业付款、PACKET--现金红包, 余额提现接口withdraw_type的传参可参考这里 withdraw_type = request.POST.get('withdraw_type', 'TRANSFER') amount = int(request.POST.get('amount', 0)) if not user.openid: return response(WechatStatusCode.OPENID_NOT_FOUND) if user.balance < amount: return response(WithdrawStatusCode.BALANCE_NOT_ENOUGH) # 根据 trade_type 获取 wechat 配置 wxcfg = WECHAT.get(trade_type, {}) # WeChatPay 初始化 wxpay = WeChatPay(wxcfg.get('appID'), wxcfg.get('apiKey'), wxcfg.get('mchID'), mch_cert=wxcfg.get('mch_cert'), mch_key=wxcfg.get('mch_key')) if withdraw_type == 'TRANSFER': ret_data = wxpay.transfer.transfer(user.openid, amount, u'摄影师余额提现,企业付款', check_name='NO_CHECK') elif withdraw_type == 'PACKET': wxrpk = wxcfg.get('redpack', {}) ret_data = wxpay.redpack.send( user.openid, amount, send_name=wxrpk.get('SEND_NAME'), nick_name=wxrpk.get('NICK_NAME'), act_name=wxrpk.get('ACT_NAME'), wishing=wxrpk.get('WISHING'), remark=wxrpk.get('REMARK'), ) # 根据 ret_data 判断是否提现成功, 成功则减余额, 失败则提示 user.balance -= amount user.save() return response(200, 'Withdraw Success', u'提现成功', {})