kboss/b/pub/get_baidu_orderlist.dspy
2025-07-16 14:27:17 +08:00

396 lines
19 KiB
Plaintext

async def user_action_record(ns={}):
ns_dic = {
'id': uuid(),
'source': '百度智能云',
'orderid': ns.get('orderid'),
'ordertype': ns.get('ordertype'),
'userid': ns.get('userid'),
'reason': ns.get('reason')
}
db = DBPools()
async with db.sqlorContext('kboss') as sor:
await sor.C('user_action', ns_dic)
async def time_convert(resoucetime=None):
if not resoucetime:
return
utc_time = datetime.datetime.strptime(resoucetime, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=datetime.timezone.utc)
beijing_time = utc_time.astimezone(datetime.timezone(datetime.timedelta(hours=8)))
return beijing_time.strftime("%Y-%m-%d %H:%M:%S")
async def cal_expire_time(history_time=None, chargeduration=None, unit=None):
chargeduration = int(chargeduration)
# 当前时间
# now = datetime.datetime.now()
now = datetime.datetime.strptime(history_time, '%Y-%m-%d %H:%M:%S')
if unit == 'MONTH':
expire_time = now + dateutil.relativedelta.relativedelta(months=chargeduration)
elif unit == 'YEAR':
expire_time = now + dateutil.relativedelta.relativedelta(years=chargeduration)
else:
expire_time = None
if expire_time:
return str(expire_time)
else:
return None
async def affirmbz_order(ns={}):
"""确认支付"""
order_type = ns.get('order_type')
sor = ns['sor']
orgid = await sor.R('bz_order', {'id': ns['orderid']})
servicename = orgid[0]['servicename']
product_url = None
if ('BCC' in servicename) or ('GPU' in servicename):
product_url = 'https://console.vcp.baidu.com/bcc/#/bcc/instance/list'
date = await get_business_date(sor=None)
await sor.U('bz_order',{'id':ns['orderid'],'order_date': date})
count = await getCustomerBalance(sor, orgid[0]['customerid'])
if count == None:
count = 0
if count - float(orgid[0]['amount']) < 0:
pricedifference = count - round(orgid[0]['amount'],2)
return {'status': False, 'msg': '账户余额不足','pricedifference': round(pricedifference,2)}
await order2bill(ns['orderid'], sor)
bills = await sor.R('bill', {'orderid': ns['orderid'], 'del_flg': '0'})
try:
# 需要加事务
for i in bills:
ba = BillAccounting(i)
r = await ba.accounting(sor)
dates = datetime.datetime.now()
await sor.U('bz_order', {'id': ns['orderid'], 'order_status': '1','create_at':dates})
await sor.U('bill', {'id': ns['orderid'], 'bill_state': '1'})
order_goods = await sor.R('order_goods', {'orderid': ns['orderid']})
for j in order_goods:
# 处理续费逻辑
if order_type == 'RENEW':
# 找到资源并更新时间
resource_find_sql = """select id from customer_goods where resourceid = '%s' and del_flg = '0';""" % j['resourceids']
resource_find_li = await sor.sqlExe(resource_find_sql, {})
resource_find_id = resource_find_li[0]['id']
await sor.U('customer_goods', {'id': resource_find_id, 'start_date': j['resourcestarttime'], 'expire_date': j['resourceendtime']})
# 处理购买逻辑
else:
product = await sor.R('product', {'id': j['productid']})
nss = {}
nss['id'] = uuid()
# nss['id'] = UUID()
nss['providerrid'] = product[0]['providerid']
nss['productname'] = product[0]['name']
nss['productdesc'] = product[0]['description']
nss['customerid'] = orgid[0]['customerid']
nss['productid'] = product[0]['id']
nss['specdataid'] = j['spec_id']
nss['orderid'] = orgid[0]['id']
nss['start_date'] = j['resourcestarttime']
nss['expire_date'] = j['resourceendtime']
nss['resourceid'] = j['resourceids']
if product_url:
nss['product_url'] = product_url
else:
spec = json.loads(product[0]['spec_note']) if isinstance(product[0]['spec_note'], str) else product[0]['spec_note']
spec_list_url = [item['value'] for item in spec if item['configName'] == 'listUrl']
nss['product_url'] = spec_list_url[0] if spec_list_url else 'https://console.vcp.baidu.com/bcc/#/bcc/instance/list'
await sor.C('customer_goods', nss)
return {'status': True, 'msg': '支付成功'}
except Exception as error:
raise error
async def get_baidu_orderlist(ns={}):
"""
百度支付
1、获取订单
2、算出购买的产品折扣
3、比对账号余额
"""
# ns = {
# 'order_id': 'f0551a743b0a491d8ac05e3159c4e8e9', # RENEW
# # 'order_id': '00ccb91d6cdb45c1be07653ba268e7d0', # NEW
# 'userid': 'KsKhCUPizQyGiw3L1WVRy'
# }
db = DBPools()
async with db.sqlorContext('kboss') as sor:
baidu_users = await sor.R('baidu_users', {'user_id': ns.get('userid'),'del_flg':'0'})
user = await sor.R('users', {'id': ns.get('userid')})
orgid = await sor.R('organization', {'id': user[0]['orgid']})
nss = {'uuids': [ns.get('order_id')], 'queryAccountId': baidu_users[0]['baidu_id']}
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
url = 'https://billing.baidubce.com/v1/order/getByUuid?%s' % ns_format
method = 'POST'
header = {
"Host": "billing.baidubce.com",
"ContentType": "application/json;charset=UTF-8"
}
header = await get_auth_header(method=method, url=url, header=header)
async with aiohttp_client.request(
method=method,
url=url,
headers=header,
json=nss) as res:
data_ = await res.json()
orders = data_['orders']
serviceType = orders[0]['orderItems']
# 判断订单item中productType是否有后付费的产品
for item in orders:
order_items = item['orderItems']
for order_info in order_items:
if order_info['productType'] == 'postpay' and order_info['itemFee']['price'] != 0:
return {
'status': False,
'msg': '暂不支持后付费按量购买, 请联系后台开通'
}
# 实付价格
total_price = 0
productType = ''
# 买/续/退 字段映射
order_type = orders[0]['type']
if order_type == 'NEW':
business_op = 'BUY'
elif order_type == 'RENEW':
business_op = 'RENEW'
elif order_type == 'REFUND':
business_op = 'BUY_REVERSE'
else:
ns_record = {
'orderid': ns.get('order_id'),
'ordertype': orders[0]['type'],
'userid': ns.get('userid'),
'reason': '支付形式目前只包含NEW,RENEW,BUY_REVERSE'
}
await user_action_record(ns_record)
return {
'status': False,
'msg': '线上暂不支持, 请联系售后'
}
try:
# 生成本地订单
bz_ns = {}
bz_ns['id'] = uuid()
bz_ns['order_status'] = '0'
bz_ns['business_op'] = business_op
bz_ns['userid'] = ns.get('userid')
bz_ns['customerid'] = orgid[0]['id']
bz_ns['order_date'] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
bz_ns['thirdparty_order'] = ns.get('order_id')
bz_ns['source'] = '百度智能云'
bz_ns['originalprice'] = orders[0]['price']
bz_ns['provider_orderid'] = ns.get('order_id')
bz_ns['ordertype'] = orders[0]['productType']
bz_ns['servicename'] = orders[0]['serviceType']
bz_ns['autoreneworder'] = '1' if orders[0]['autoRenewOrder'] else '0'
if ns.get('specdataid'):
bz_ns['specdataid'] = ns['specdataid']
await sor.C('bz_order', bz_ns)
for i in serviceType:
if i['productType'] == 'prepay':
# 预付费
productType = 'prepay'
# financePrice = 0
# 获取产品id
product = await sor.R('product', {'providerpid': 'baidu_' + i['serviceType'], 'del_flg': '0'})
# 获取协议
saleprotocol = await sor.R('saleprotocol',
{'bid_orgid': orgid[0]['id'], 'offer_orgid': orgid[0]['parentid'],
'del_flg': '0'})
if saleprotocol == []:
# 等于空就代表这个客户没有特殊折扣,就要找到买方为*的协议
saleprotocol = await sor.R('saleprotocol', {'bid_orgid': '*', 'offer_orgid': orgid[0]['parentid'],
'del_flg': '0', 'salemode': '0'})
product_salemode = await sor.R('product_salemode',
{'protocolid': saleprotocol[0]['id'], 'productid': product[0]['id'],
'del_flg': '0'})
supply_price = i['itemFee']['price'] if i.get('itemFee') else i['financePrice']
financePrice = supply_price * product_salemode[0]['discount']
total_price += financePrice
# 添加订单子表
nss = {}
nss['id'] = uuid()
nss['orderid'] = bz_ns['id']
nss['productid'] = product[0]['id']
nss['providerid'] = product[0]['providerid']
if i['count'] > 1:
nss['list_price'] = i['realCatalogPrice'] / i['count']
else:
nss['list_price'] = i['realCatalogPrice']
nss['discount'] = product_salemode[0]['discount']
nss['quantity'] = i['count']
nss['price'] = round(nss['list_price'] * product_salemode[0]['discount'], 2)
# 计算总价
# nss['amount'] = round(total_price, 2)
nss['amount'] = round(nss['price'] * nss['quantity'], 2)
nss['chargemode'] = i.get('productType')
nss['servicename'] = i.get('serviceType')
nss['chargeduration'] = i.get('time')
nss['unit'] = i.get('timeUnit')
nss['resourceids'] = ','.join(i['shortIds']) if i.get('shortIds') else ''
# 如果是续费订单 由于没有返回日期, 重新计算日期
if order_type == 'RENEW':
history_time_sql = "select resourcestarttime, resourceendtime from order_goods where resourceids = '%s' order by resourceendtime desc;" % \
nss['resourceids']
history_time = await sor.sqlExe(history_time_sql, {})
new_end_time = await cal_expire_time(history_time=history_time[0]['resourceendtime'],
chargeduration=nss['chargeduration'], unit=nss['unit'])
# 开始日期不变 更新到期日期
nss['resourcestarttime'] = history_time[0]['resourcestarttime']
nss['resourceendtime'] = new_end_time
else:
nss['resourcestarttime'] = await time_convert(i.get('resourceStartTime')) if i.get(
'resourceStartTime') else None
nss['resourceendtime'] = await time_convert(i.get('resourceEndTime')) if i.get(
'resourceEndTime') else None
await sor.C('order_goods', nss)
# 循环后更新订单中总价
await sor.U('bz_order', {'id': bz_ns['id'], 'amount': round(total_price, 2)})
except Exception as e:
ns_record = {
'orderid': ns.get('order_id'),
'ordertype': orders[0]['type'],
'userid': ns.get('userid'),
'reason': '发生错误, %s' % str(e)[:100]
}
await user_action_record(ns_record)
import traceback
with open('baiducloud_err.txt', 'w') as f:
f.write(str(e)+ traceback.format_exc())
traceback.print_exc()
# 判断用户账户余额是否足够支付
try:
count = await getCustomerBalance(sor, orgid[0]['id'])
if round(total_price,2) <= count:
#判断预付费或者后付费
if productType == 'prepay':
# 调用扣费接口
affirmbz_order_ns = {
'sor': sor,
'orderid': bz_ns['id'],
'order_type': order_type
}
affirmbz_order_res = await affirmbz_order(affirmbz_order_ns)
if not affirmbz_order_res['status']:
# if True:
await sor.rollback()
ns_record = {
'orderid': ns.get('order_id'),
'ordertype': orders[0]['type'],
'userid': ns.get('userid'),
'reason': '支付错误, 请联系售后'
}
await user_action_record(ns_record)
return {
'status': False,
'msg': '支付错误, 请联系售后'
}
# 调用支付订单接口
paydata = {'queryAccountId':baidu_users[0]['baidu_id'],'orderId':ns.get('order_id')}
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
url = 'https://billing.baidubce.com/v1/order/pay?%s' % ns_format
method = 'POST'
header = {
"Host": "billing.baidubce.com"
}
header = await get_auth_header(method=method, url=url, header=header)
async with aiohttp_client.request(
method=method,
url=url,
headers=header,
json=paydata) as res:
data_ = await res.json()
if data_ == {'success': True}:
# if True:
ns_record = {
'orderid': ns.get('order_id'),
'ordertype': orders[0]['type'],
'userid': ns.get('userid'),
'reason': '购买成功'
}
await user_action_record(ns_record)
return {
'status': True,
'orderid': bz_ns['id']
}
else:
await sor.rollback()
ns_record = {
'orderid': ns.get('order_id'),
'ordertype': orders[0]['type'],
'userid': ns.get('userid'),
'reason': '支付成功后, order_pay接口错误, 回滚, %s' % str(data_)[:400]
}
await user_action_record(ns_record)
return {
'status': False,
'msg': '产品分配排队中, 请联系售后详询'
}
else:
# 取消订单
await sor.rollback()
paydata = {'queryAccountId': baidu_users[0]['baidu_id'], 'orderIds': [ns.get('order_id')]}
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format
method = 'POST'
header = {
"Host": "billing.baidubce.com"
}
header = await get_auth_header(method=method, url=url, header=header)
async with aiohttp_client.request(
method=method,
url=url,
headers=header,
json=paydata) as res:
await res.json()
ns_record = {
'orderid': ns.get('order_id'),
'ordertype': orders[0]['type'],
'userid': ns.get('userid'),
'reason': '无法购买后付费产品'
}
await user_action_record(ns_record)
return {'status': False, 'msg': '无法购买后付费产品'}
else:
#取消订单
await sor.rollback()
paydata = {'queryAccountId':baidu_users[0]['baidu_id'],'orderIds':[ns.get('order_id')]}
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
url = 'https://billing.baidubce.com/v1/order/cancel?%s' % ns_format
method = 'POST'
header = {
"Host": "billing.baidubce.com"
}
header = await get_auth_header(method=method, url=url, header=header)
async with aiohttp_client.request(
method=method,
url=url,
headers=header,
json=paydata) as res:
await res.json()
ns_record = {
'orderid': ns.get('order_id'),
'ordertype': orders[0]['type'],
'userid': ns.get('userid'),
'reason': '该账号余额不足,无法完成购买'
}
await user_action_record(ns_record)
return {'status': False,'msg': '该账号余额不足,无法完成购买'}
except Exception as e:
import traceback
with open('baiducloud_err.txt', 'w') as f:
f.write(str(e)+ traceback.format_exc())
traceback.print_exc()
ret = await get_baidu_orderlist(params_kw)
return ret