first commit
This commit is contained in:
commit
a9d4966202
81
DevOps/deploy_to_server.py
Normal file
81
DevOps/deploy_to_server.py
Normal file
@ -0,0 +1,81 @@
|
||||
# !/d/ymq/py3/bin/python
|
||||
import asyncio
|
||||
import getpass
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
from appPublic.sshx import SSHNode
|
||||
|
||||
home = os.getenv('HOME')
|
||||
kgadget_build = False
|
||||
|
||||
|
||||
class KbossAppDeploy:
|
||||
def __init__(self, node):
|
||||
self.node = node
|
||||
|
||||
async def update_code(self):
|
||||
await self.node._l2r("/root/backup/www/www_backup", '~/')
|
||||
await self.node._run(f'cd ~')
|
||||
await self.node._run(f'tar xf ./www_backup/kboss.prod.tar.back')
|
||||
await self.node._run('chmod +x bin/web')
|
||||
await self.node._run('tar xzf ./www_backup/files.tar.gz')
|
||||
await self.node._run(f'cp -r ./files/ ~/www/ ')
|
||||
try:
|
||||
await self.node._run(f'tar zxf ./www_backup/kboss_nginx.tar.gz')
|
||||
await self.node._run('sudo cp ./kboss_nginx/*kaiyuancloud.* /etc/nginx/')
|
||||
await self.node._run(f'sudo cp ./kboss_nginx/kbossprod /etc/nginx/sites-enabled/')
|
||||
except Exception as e:
|
||||
print(f"set nginx config fail :{e}")
|
||||
await self.node._run(f'cd ~')
|
||||
await self.node._run('bin/web')
|
||||
print("deploy ok")
|
||||
|
||||
async def init_data(self):
|
||||
await self.node._run(f'mysql -h db -ukboss -pkboss123 kboss_prod < ~/initdata/mysql.ddl.sql')
|
||||
await self.node._run(f'mysql -h db -ukboss -pkboss123 kboss_prod < ~/initdata/kboss_init.sql')
|
||||
|
||||
async def get_remote_data(self):
|
||||
subprocess.run("tar zcf /root/backup/www/www_backup/files.tar.gz files/", shell=True, capture_output=True, text=True)
|
||||
|
||||
async def deploy(self):
|
||||
await self.get_remote_data()
|
||||
await self.node.connect()
|
||||
await self.update_code()
|
||||
self.node.close()
|
||||
|
||||
|
||||
def default_node(host, user, port):
|
||||
node = SSHNode(host,
|
||||
username=user,
|
||||
port=port,
|
||||
password=getpass.getpass(f'{user}@{host} password:')
|
||||
)
|
||||
|
||||
return node
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
exp = f"python3 {sys.argv[0]} tt@192.168.0.11:10022"
|
||||
if len(sys.argv) != 2:
|
||||
print(f'Usage:\n{exp}')
|
||||
sys.exit(1)
|
||||
if re.findall(r'^[\w\d]+@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+$', sys.argv[1]):
|
||||
user_ip_prod = sys.argv[1]
|
||||
user, host = user_ip_prod.split('@')
|
||||
host, port = host.split(':')
|
||||
if not port:
|
||||
port = 22
|
||||
port = int(port)
|
||||
else:
|
||||
print(f'ip not defined ip:{sys.argv[1]}')
|
||||
sys.exit(1)
|
||||
node = default_node(host, user, port)
|
||||
if not node:
|
||||
sys.exit(1)
|
||||
d = KbossAppDeploy(node)
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.run_until_complete(d.deploy())
|
||||
55
DevOps/kboss_domain.py
Normal file
55
DevOps/kboss_domain.py
Normal file
@ -0,0 +1,55 @@
|
||||
import asyncio
|
||||
|
||||
from pyppeteer import launch
|
||||
|
||||
|
||||
async def main(mode):
|
||||
browser = await launch(headless=False, args=['--disable-blink-features=AutomationControlled'])
|
||||
page = await browser.newPage()
|
||||
await page.setViewport({'width': 1020, 'height': 1080})
|
||||
|
||||
await page.waitFor(1000)
|
||||
url = "https://signin.aliyun.com/login.htm#/main"
|
||||
await page.goto(url)
|
||||
await page.waitFor(2000)
|
||||
|
||||
await page.type('#loginName', 'www_domain@1953083695298848.onaliyun.com')
|
||||
await page.keyboard.press('Enter')
|
||||
await page.waitFor(3000)
|
||||
await page.screenshot({'path': 'screenshot.png'})
|
||||
|
||||
await page.type('#loginPassword', 'Kyy@123456789')
|
||||
await page.keyboard.press('Enter')
|
||||
await page.waitFor(3000)
|
||||
await page.screenshot({'path': 'screenshot1.png'})
|
||||
|
||||
url = "https://dns.console.aliyun.com/#/dns/setting/kaiyuancloud.cn"
|
||||
await page.goto(url)
|
||||
await page.waitFor(3000)
|
||||
await page.waitForSelector('#keyword')
|
||||
await page.type('#keyword', mode)
|
||||
await page.keyboard.press('Enter')
|
||||
await page.waitFor(1000)
|
||||
|
||||
element = await page.querySelector(
|
||||
'#app-common-page > div > div._1_aZzbvH > div > div.ant-tabs-content.ant-tabs-content-no-animated.ant-tabs-top-content.ant-tabs-card-content > div.ant-tabs-tabpane.ant-tabs-tabpane-active > div:nth-child(2) > div > div > div:nth-child(2) > div.ant-table-wrapper._3PHtW8UK > div > div > div > div > div.ant-table-fixed-right > div > div > table > tbody > tr:nth-child(1) > td > span > span:nth-child(3)'
|
||||
)
|
||||
if element:
|
||||
await element.click()
|
||||
else:
|
||||
await page.waitFor(1000)
|
||||
element = await page.querySelector(
|
||||
'#app-common-page > div > div._1_aZzbvH > div > div.ant-tabs-content.ant-tabs-content-no-animated.ant-tabs-top-content.ant-tabs-card-content > div.ant-tabs-tabpane.ant-tabs-tabpane-active > div:nth-child(2) > div > div > div:nth-child(2) > div.ant-table-wrapper._3PHtW8UK > div > div > div > div > div.ant-table-fixed-right > div > div > table > tbody > tr:nth-child(4) > td > span > span:nth-child(3)'
|
||||
)
|
||||
if element:
|
||||
await element.click()
|
||||
|
||||
await page.screenshot({'path': 'screenshot.png'})
|
||||
await page.waitFor(2000)
|
||||
url = "https://account.aliyun.com/logout/logout.htm?spm=a2c1d.8251892.top-nav.dsign-out.2b3c5b76Cv4sYC&oauth_callback=https%3A%2F%2Fdns.console.aliyun.com%2F%3Fspm%3D5176.100251.111252.28.d2344f156kVH5u%26accounttraceid%3D61009978d16c4f1091b041d678f33d56mntp%23%2Fdns%2Fsetting%2Fkaiyuancloud.cn"
|
||||
await page.goto(url)
|
||||
await page.waitFor(1000)
|
||||
await browser.close()
|
||||
|
||||
mode = '@'
|
||||
asyncio.get_event_loop().run_until_complete(main(mode=mode))
|
||||
BIN
DevOps/kboss生产环境恢复.docx
Normal file
BIN
DevOps/kboss生产环境恢复.docx
Normal file
Binary file not shown.
7
DevOps/m.files.sh
Normal file
7
DevOps/m.files.sh
Normal file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
SOURCE_DIR="/home/kbossprod/www/files/"
|
||||
DEST_DIR="root@192.168.0.2:/root/backup/www/files/"
|
||||
inotifywait -m -r -e create --format "%w%f" "$SOURCE_DIR" | while read NEW_FILE
|
||||
do
|
||||
rsync -avz --relative -e "ssh -p 10022" "$NEW_FILE" "$DEST_DIR"
|
||||
done
|
||||
11
DevOps/m.sh
Normal file
11
DevOps/m.sh
Normal file
@ -0,0 +1,11 @@
|
||||
#!/bin/bash
|
||||
source_dir="/home/kbossprod/kboss.prod.tar.back"
|
||||
previous_state=$(ls -l $source_dir)
|
||||
while true; do
|
||||
sleep 30
|
||||
current_state=$(ls -l $source_dir)
|
||||
if [ "$previous_state" != "$current_state" ]; then
|
||||
scp -P 10022 $source_dir root@192.168.0.2:/root/backup/www
|
||||
previous_state=$current_state
|
||||
fi
|
||||
done
|
||||
11
README.md
Normal file
11
README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Kboss
|
||||
|
||||
kaiyuan business operator support system
|
||||
|
||||
## Dependent
|
||||
* [bricks](https://github.com/yumoqing/bricks) use as kboss frontend development framework
|
||||
* [ahserver](https://github.com/yumoqing/ahserver) as kboss backend application server
|
||||
* [sqlor](https://github.com/yumoqing/sqlor) used by ahserver for databases operation
|
||||
* [aiohttp](https://github.com/aio-libs/aiohttp) use as web server.
|
||||
|
||||
##
|
||||
1
alipay/dev/appid.txt
Normal file
1
alipay/dev/appid.txt
Normal file
@ -0,0 +1 @@
|
||||
2021004106675236
|
||||
1
alipay/dev/huidiao.txt
Normal file
1
alipay/dev/huidiao.txt
Normal file
@ -0,0 +1 @@
|
||||
https://www.kaiyuancloud.cn/dev/pay/payhuidiao.dspy
|
||||
3
alipay/dev/private.txt
Normal file
3
alipay/dev/private.txt
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCLODFiJDK+3UB2/zELdFuCYzx3diDMLr8pj/yWz01kYxjw96k8yAIRXFBJDxc/PIEQBifASS4irV1TVtbns+L7ANtDnYtFe8ewO+875rJagqq1tIS6IthiWlGg6rmbzrTtYLSNoCy2rt2hoZyhvE9vm96cjTBc+o+WzIsw1Vex/vahSk0JnviX1kiw9vddAUtupuyLcHIV0VOH04MRfT+C8KsDUZNEmCwlGI/DFmO6DFpniy+jlNb3U8yJqD3FTJhky4I90uYvYRvFeGQA7beZwFnL+oOuspk+gBFZBXyPonHMgxR9Olk6gUkXT3nFibnKqtltZIS82oes24dRLZJfAgMBAAECggEAYui0ZRZ0mxeT8jcRwCKV1Qft8K2TVZ0soTmz6e0z/ctN7/z0VsN+fJkKTS2UhY/V3e2RllInnelvcYMzwYATFeMg5GPsi5wKXhHmwLcBJb7Jy7iJx7hz5URn1ByPa7uq3S8kd65BtjR8L5YjMuEXyqKBwNWqc5RsKWX+yd34pPMEQ0qBeOxtAk3ugVhY7WgJu1GcUhseJu/oUC45ARge2AkMz7m7Fi+xxyfDYklcn10s8d8ripRXFBc2Tmg0oHBldjrnNK+o2wqOV/KadmegE5fLntDx4bIe8bXPEZMXWWhWrXG2WpbEBMkBe1GsqIo5XWbEmzbi/xJM68KxeHyk+QKBgQC9EFK+eTQlt5VQ89WSe1s5W2jOs916ILCSKR6a1QesjAk6sUJxh/g9vwm/WhQC8fOXo9oHycqBg860TlbDNS/nX+PoUMWp3LzwTfaboaDOOCQ3DPCrxztHLSObLyYnAHYEU5daLzM2AsBClmqSWv+6OOvQJJ5dCx1be7jcRaqXOwKBgQC8gkQlyexShdkJeAZbrGH4NyCVGUv2wM01mcPW08YHb8xbCzv50Kqvk9Ulej3vRgccKKd3M51RE+1e4p0UDTeYM9crnPMfM2BgFNv0sWM1pSZp0rlpkxG7pPz8t8/muuQjJjy+is82YDhpO3OU2VxWKt6OpG/Mu59+Wy0vUwUnLQKBgQC6lHVUDADuh/IPZdMLMDmirRcNhmu3rrMSSwos+rcMDVa+WVic+fZ92R4hfR/qmCQxLj5pGTeEATPotLbjBoYz7GnaRnwLWhALhqUsiaFMYhM7UMXigEd7wow1BZ69NrNBKc1f7ty3HJfoHtElhjCA8tOlIb43TFS4h6yzlPz5KQKBgFe7dMX1jRP3EUSz5Jmjx9DCr1pU9KK5pofssVV5KC/r2zsAJoCkmduvPML9eneyqrpzPUVf8zZ5xL6lTx+26wneDqVQnWIHAjKVYq0mJZsg6pjTptE4zkb7iXaAgbTLhEPLlvfDGJ8g9wAa2DcNVkkQGJZgd1vccmVXP9dHlx1dAoGBAIayI4cBHVqO9frmRfH64T1Ztxi4OvmJvXlZdocjdwdBNtQEDQ6r6pQR4cDhSBHj9BPo51Qc3rCu4dcxkl78YcbNjUzBzts8KpGwtOavzON36mUG7NUhHDcXqnM7fQWuWsM3WZhZH2y1UeUVsXOIKenqDluVkh9BVEwgZjMEYpE7
|
||||
-----END RSA PRIVATE KEY-----
|
||||
3
alipay/dev/public.txt
Normal file
3
alipay/dev/public.txt
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAogRDEu+GlU0KEZfcWS7P2hcsKLB1/shRXw2AF2bozuc1rrfl2noufAEP7ULMd9kw66C8fJd8H/tPIfff2expmQGa5dJBELZqKlMdTtxxa7t5+OGFWZsqzBlCPci9XjVwWfxamLw5IZTX5qocTUkCgFd62y/fpMsQfQPmU1vAdUSWp7CpS0E/ljks1Gl44hv5UOBZdOxEY6/ww+R3mPosycFk3kaMxe4P002kq7gfcNmZdRm8O9i+q0KsG+LF+Q2qDWQ/xO1UF8R4au50DijGk2S2X3bJk1tjytaDTNHZmcJGWP5qNuHZ82KAT42b0iHAg8HO7XqAmCp9bskX+3gSMwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
1
alipay/prod/appid.txt
Normal file
1
alipay/prod/appid.txt
Normal file
@ -0,0 +1 @@
|
||||
2021004120652840
|
||||
1
alipay/prod/huidiao.txt
Normal file
1
alipay/prod/huidiao.txt
Normal file
@ -0,0 +1 @@
|
||||
https://www.kaiyuancloud.cn/pay/payhuidiao.dspy
|
||||
3
alipay/prod/private.txt
Normal file
3
alipay/prod/private.txt
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCXl2cIrTPP07WqtIdGlskI3G/UCe2APu13MuJQmyk8RK+VlRFv25JTboa24Hdr7gKbatj4+RzTP/EKxOtRVuNeTijLFvRJf3dEgJzWwDa0zU/J40AmGiPGeqJID6mAKFaI2ugRMO/HO7X6fZxGP+fMn0qSErnXtMyveYSRhgrV5HF0Hpbp+6a5vT3ifOXy5fzzlGKLkmlIw6XolRl2xF4/jl7o9BNjQTcBTY50ENyByMXRckX5McTh/fsOsrMmw8CBiJRWf0Vm/01Gt9pqddh1gIlBKb6M8ZSt52lAGMI7phe1ka54hfu4Z2Ofj3WZTUWy1lz8P5zn7oUxrZ8rJAC1AgMBAAECggEAYt6knMwaltoGCqhj8m42AEmFxk4TUSm5x5ywbtJEOsKxomXvUX1sGm5j/rK4MPSzTpqJmRkg68cwd02oDQ0WjlN717nI6obwSwV3Rbln9NRTzeEh3bf+zVz+qvFMJAIrLmdYJJ4+RTt0nUN/wXG8xYC/KjZ8b2vEdE5VYHSEbKvojg1/yX1L4AGmTYXNtRmPyEfWf7tYm5h4aj1j1bkwY/A6VcABTcs1hmD+ab6ejCnEjtBlCLAycEQ6nwktBtwpcZhrzdBOj80ZeoBZEmi0ZajBBwFDjRaKO7QZ2mYcnOczochqdnKuT6OAWtsOyEyCIQsfIXEArIeZiPPk5w3kAQKBgQDTzmC2+IwbhLimJKQvDzmrfs6qXGA+qXfBOTSaEsiInPQdOIqXTOW8uim0+qN7zHoshks8FvnRs4rpikhtPEFRGhy8skynPtJbs0PDm165dtrvlC1JxyRoEk9D+h1NPA33rP9aIWzHomi0TRYWovSKviS2iw/TTShEAvVItnJf1QKBgQC3OKe0NFcHLLIk8lWzU44CAU3M1mbecljzFzfIcIHDWXu/CsMiylcMvSi1PE7Osz6v8/gDQ+HUzT3eFj1zMZsDRwVS4nXQUkTww4wevvsZWct1pX97ut1femaFrwITMInkR6Yj2+IG49GlgoK0RoiUvF1SbEx5jnWIVIn4ewBtYQKBgQCb6UUEKv1nnFEX68z33ytCdDvI5+ro9XJzx5pS+BSpi2+euuo56Z8LR7Y/xGfnT2N3tvtWpksK9DEDLImX70zdWG1i8ZS/X90VJ2ZwbMRTnYwX42la77565U936Hr9SYG2mZ/2Rrh+U6zjXAMwco+0ObdosADcN+W1+r934OVcaQKBgQCoKejKnetum1haTs3XzI2fS4ETy4kZDAyV+S5q2tBO8veADamyadJhz8/oIBUY5C1aI2rz3D8PKN1q1DDMZLAo3uuE+nM1o/zAmkomAhXHW8JBFYgfkRATzO0CL/GQmVFGY3iamvsmZb0K0vGR8tby5LwmpV2/h8BaQ3VqycJHoQKBgGpXBBt1cvKzGe/Ot25jYiZrZ4niPy8R1ENzv8+rTIbO396auCk2h7tsyNOph1ZrNz5W+qr9yLQHqimz2OvkKGxlzSa6o7xDQ0mSeng+hWO0cJcXOhzQh3jjE2fRZUmgTCWISjFLVp78/K9MFSofk5/+hoqYniIEeaSjX+cHn/D1
|
||||
-----END RSA PRIVATE KEY-----
|
||||
3
alipay/prod/public.txt
Normal file
3
alipay/prod/public.txt
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgD4YlfnWKd4vEHsim6vxLwustbnBBh9IUJwF5rGJ3b7wjYyzMnQZ36Cgf81A685IQ+Ni9GogNDaUWZx9V+qGxZRwaLbktSLnUNwPMudKlUoPyQtqyygU+Bmwg1B+UBzZsz8eG72qOuvu9xNbT72QZqFxzLlo0vzWldijnaPcqukUhTaeIYe1AObI9v3ySAa72GkGCHaSkQqvBLydCJt2mu3zJYhPMKre1oNmQkGYUxLKCwonbABaugOEl7t1vL8mAMlwFg2ihJbYiogGfr2Imt/Y1jy8rftiW41opX1UQ30rgfRYeuEsKvVwuoyqffGHeBSjs53xZkYStYKj0m+8AQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
1
alipay/requirements.txt
Normal file
1
alipay/requirements.txt
Normal file
@ -0,0 +1 @@
|
||||
qrcode
|
||||
1
alipay/test/appid.txt
Normal file
1
alipay/test/appid.txt
Normal file
@ -0,0 +1 @@
|
||||
2021004117685170
|
||||
1
alipay/test/huidiao.txt
Normal file
1
alipay/test/huidiao.txt
Normal file
@ -0,0 +1 @@
|
||||
https://www.kaiyuancloud.cn/test/pay/payhuidiao.dspy
|
||||
3
alipay/test/private.txt
Normal file
3
alipay/test/private.txt
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2eSZvVqn+PKRijVTUt0t6WP5O0JM/F2buhF2sfnQjZf7cnU13GCwIZLOjtko+h484rBitO7d1yCb/90FHnB0nvqsYFSUbLrViU4Zz9iljLqIvo4O+NFli+esbnC6MLs1jkCnfHhNLaXyNBfY+2DX4KYjJ376xBVWtwkb5a+jTWitQzufZwi2ihUgY87jLlxw1eb3R5V0g3cP5fF9zrbNHycPfw+qFu5WcOz22Pq2/WTECY7iX+9boXuzpwXexTm2MK/lhqNJGufWHtdSSKfurso0leMXBwmWkoYQ3s2SyFFFropbDtqio0zbu2QV52Dhmt06tDKYBdTJVcWKRlpqvAgMBAAECggEADyvphy5Uef/+xvbrS7hlvSlzE4iCBafjdgdpZnMpItxTIXKuwy0uVBBTY1Q/vg01Wkfs0VJ6wX8/xt5+/f476lcPELSJXkY27JL3ReL8s/NnpsBYrtLZb8JJywTkVeF6UEHnSVbN0eJWab9KJxWA/z4s0mQZDczcv9K8ZfaT6CadyV5iKmlfChHtU8cVzL/Shnkeg0ynOwNlbRQ7tyT6MCok1Rm/B5BIeRV9wLxdtr4ff14X9rwP+S8UVNNyiEKTX8QB1OT5GsNwmRkWX3Ud/qrb03BKuijbU5ms3K8+XV9SZWR/nZAieJ10zUFx66p1W6hjRQg31VN3v/1LvuwYiQKBgQD6SB4dT3+0tAfUH6O3JwtVgxP3PV7oqH0sWFzy+jXAkg16H6o3rG/FVO09n3sHu4UCx2IO0YzYbRY/x4AgJySUkQx3i1gvEjtMBm+GTuTv3DRKolJIPBFzl+fd6D5KMNm08yQBQgb2O6Nd1pbG8upkEt1BsyJXKe9XyWg6+vyKpQKBgQC6pGzIz7gvksjWyfux+HjUcs1GlYEG+RN5xijsbumIYpA4TxVqz+6l+nH+21Pb/bqckOg7GIIhDE/jHpnibfhAsv062nVgdRF2CRCVjfJWkUwPkiG8yNjDPC0Pe/GN3IcngExcX+ssZrT5DjF2thSKa7rn12iBajsOZIXCzbfTwwKBgD6WrFk+GTySTObiJqnVrMLsraCFi2d5QxxE2LG2mpyWqaIhqwqTJ7xcWZuwdy7e2Qtx2vbDtook9YxrkoH35/DzOP/oK9xRndyMO3WF40CMe9MyNotz4hVbJpPa0UDyaG8U4qsh3OXU0izUTg5gjvcJtKUKbAsKJJ16c4NUYrU1AoGAXvc+qsaWTw5+xlsriBiHUoG/VQTJDAU8FZ/wPq0Igm60NxJ2MUzvfuB5lFWAy9TEWNmacEc+Hxamp0dwwTd3M2RfWMzDIHswkUB3gcEh504yx1FxfR8su9ooi1JjS+1Dj6PGNtJPVN5Fgtvn6yEmPnAmP8To1cB5oA8hyEboHAUCgYEAyTnK5p3pexDtuBD1K5b2dv3oPgZ4QfbPt9vQ2RIYFGJ3GM9T0c5DlVzwZiYHNktNoK4NyogRh2wDK/2M2CZl3XrYUhqQCI4jtr16o77lYl8PA5fsfxNI/pmK/9vJ8UDFxzdvat2nkU18AxMmWQHSM6AMfrrDylDtbUjUdwIJSj8=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
3
alipay/test/public.txt
Normal file
3
alipay/test/public.txt
Normal file
@ -0,0 +1,3 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgD4YlfnWKd4vEHsim6vxLwustbnBBh9IUJwF5rGJ3b7wjYyzMnQZ36Cgf81A685IQ+Ni9GogNDaUWZx9V+qGxZRwaLbktSLnUNwPMudKlUoPyQtqyygU+Bmwg1B+UBzZsz8eG72qOuvu9xNbT72QZqFxzLlo0vzWldijnaPcqukUhTaeIYe1AObI9v3ySAa72GkGCHaSkQqvBLydCJt2mu3zJYhPMKre1oNmQkGYUxLKCwonbABaugOEl7t1vL8mAMlwFg2ihJbYiogGfr2Imt/Y1jy8rftiW41opX1UQ30rgfRYeuEsKvVwuoyqffGHeBSjs53xZkYStYKj0m+8AQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
56
b/Endofday/index.html
Normal file
56
b/Endofday/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
32
b/Endofday/supplier_accounts.dspy
Normal file
32
b/Endofday/supplier_accounts.dspy
Normal file
@ -0,0 +1,32 @@
|
||||
async def supplier_accounts(ns):
|
||||
"""供应商日结"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
account_config = await sor.R('account_config',{'partytype':'供应商','del_flg':'0'})
|
||||
provider = await sor.R('provider',{"del_flg":'0','settle_mode':'1'})
|
||||
for i in provider:
|
||||
org = await sor.R('organization', {"id": i['orgid'],'del_flg':'0'})
|
||||
for j in account_config:
|
||||
acc = await getAccountByName(sor, org[0]['parentid'], i['orgid'], j['subjectname'])
|
||||
if acc != None:
|
||||
accountid = await sor.R('acc_balance',{'accountid':acc})
|
||||
if len(accountid) >= 1:
|
||||
settle_log = {
|
||||
'accounting_orgid': org[0]['parentid'],
|
||||
'providerid': i['orgid'],
|
||||
'settle_date': await get_business_date(sor=None),
|
||||
'settle_mode': '1',
|
||||
'sale_mode': '',
|
||||
'settle_amt': accountid[0]['balance'],
|
||||
'business_op': 'SETTLE'
|
||||
}
|
||||
ai = SettleAccounting(settle_log)
|
||||
await ai.accounting(sor)
|
||||
return {'status': True, 'msg': '成功'}
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {'status': False, 'msg': '失败'}
|
||||
|
||||
ret = await supplier_accounts(params_kw)
|
||||
return ret
|
||||
25
b/Organization/addOrganization.dspy
Normal file
25
b/Organization/addOrganization.dspy
Normal file
@ -0,0 +1,25 @@
|
||||
async def addOrganization(ns):
|
||||
|
||||
"""
|
||||
添加机构
|
||||
:param orgname:
|
||||
:param contactor:
|
||||
:param contact_method:
|
||||
:param reseller_id:
|
||||
:param province_id:
|
||||
:param city_id:
|
||||
:param distinct_id:
|
||||
:param address:
|
||||
:param main_business:
|
||||
:param orgcode:
|
||||
:param license_img:
|
||||
:param `org_type` VARCHAR(1) comment '机构类型:1为机构,2为个人客户、3为公司客户':
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
ns['id'] = uuid()
|
||||
await sor.C('organization', ns)
|
||||
return {'status': True, 'msg': '添加成功'}
|
||||
|
||||
ret = await addOrganization(params_kw)
|
||||
return ret
|
||||
38
b/Organization/delOrganization.dspy
Normal file
38
b/Organization/delOrganization.dspy
Normal file
@ -0,0 +1,38 @@
|
||||
async def delOrganization(ns,sor=None):
|
||||
|
||||
"""删除机构"""
|
||||
|
||||
if not sor:
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
ns['del_flg'] = '1'
|
||||
await sor.U('organization', ns)
|
||||
sql_user = """update users set del_flg = 1 where orgid = '%s'""" % ns.get('id')
|
||||
await sor.sqlExe(sql_user,{})
|
||||
|
||||
sql_customer = """update customer set del_flg = 1 where customerid = '%s'""" % ns.get('id')
|
||||
await sor.sqlExe(sql_customer,{})
|
||||
dictns = {'parentid': ns['id']}
|
||||
reacs = await sor.R('organization', dictns)
|
||||
for i in reacs:
|
||||
await delOrganization({'id': i['id']},sor)
|
||||
return {'status': True, 'msg': '删除成功'}
|
||||
else:
|
||||
if ns:
|
||||
ns['del_flg'] = '1'
|
||||
await sor.U('organization', ns)
|
||||
sql_user = """update users set del_flg = 1 where orgid = '%s'""" % ns.get('id')
|
||||
await sor.sqlExe(sql_user, {})
|
||||
|
||||
sql_customer = """update customer set del_flg = 1 where customerid = '%s'""" % ns.get('id')
|
||||
await sor.sqlExe(sql_customer, {})
|
||||
dictns = {'parentid': ns['id']}
|
||||
reacs = await sor.R('organization', dictns)
|
||||
for i in reacs:
|
||||
await delOrganization({'id': i['id']}, sor)
|
||||
return {'status': True, 'msg': '删除成功'}
|
||||
return {'status': False, 'msg': '删除失败'}
|
||||
|
||||
ret = await delOrganization(params_kw)
|
||||
return ret
|
||||
55
b/Organization/getOrganization.dspy
Normal file
55
b/Organization/getOrganization.dspy
Normal file
@ -0,0 +1,55 @@
|
||||
async def getOrganization(ns):
|
||||
"""展示机构"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if not ns.get('parentid') and not ns.get('type'):
|
||||
sql = """select * from organization where org_type = ${org_type}$ and del_flg = 0"""
|
||||
reacs = await sor.sqlExe(sql,ns)
|
||||
list = []
|
||||
dict = {}
|
||||
if reacs:
|
||||
for i in reacs:
|
||||
dict[i['id']] = i
|
||||
for j in reacs:
|
||||
if j['parentid'] == None or j['parentid'] == '':
|
||||
list.append(j)
|
||||
else:
|
||||
if 'son' not in dict[j['parentid']]:
|
||||
dict[j['parentid']]['son'] = []
|
||||
dict[j['parentid']]['son'].append(j)
|
||||
return {'status': True, 'data': list}
|
||||
elif ns.get('parentid'):
|
||||
sql = """select * from organization where org_type = ${org_type}$ and del_flg = 0 and parentid = ${parentid}$ """
|
||||
reacs = await sor.sqlExe(sql, ns)
|
||||
return {'status': True, 'data': reacs}
|
||||
elif ns.get('type'):
|
||||
user = await sor.R('users', {'del_flg': '0', 'id': ns['id']})
|
||||
orgid = user[0]['orgid']
|
||||
if ns.get('orgname'):
|
||||
datalist = []
|
||||
reacs = await sor.R('customer', {'del_flg': '0'})
|
||||
for i in reacs:
|
||||
userid = await sor.R('users', {'del_flg': '0', 'id': i['salemanid']})
|
||||
if len(userid) >= 1:
|
||||
if userid[0]['orgid'] == orgid:
|
||||
nss = {'id': i['customerid'], 'pattern': '%' + ns.get('orgname') + '%'}
|
||||
sql = """select * from organization where del_flg = 0 and orgname like ${pattern}$ and id = ${id}$"""
|
||||
reacse = await sor.sqlExe(sql, nss)
|
||||
if len(reacse) >= 1:
|
||||
datalist.append(reacse[0])
|
||||
return {'status': True, 'data': datalist}
|
||||
else:
|
||||
datalist = []
|
||||
reacs = await sor.R('customer', {'del_flg': '0'})
|
||||
for i in reacs:
|
||||
userid = await sor.R('users', {'del_flg': '0','id':i['salemanid']})
|
||||
if len(userid) >= 1:
|
||||
if userid[0]['orgid'] == orgid:
|
||||
organization = await sor.R('organization', {'del_flg': '0','id':i['customerid']})
|
||||
if len(organization) >= 1:
|
||||
if organization[0] not in datalist:
|
||||
datalist.append(organization[0])
|
||||
return {'status': True, 'data': datalist}
|
||||
|
||||
ret = await getOrganization(params_kw)
|
||||
return ret
|
||||
56
b/Organization/index.html
Normal file
56
b/Organization/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
22
b/Organization/myOrganization.dspy
Normal file
22
b/Organization/myOrganization.dspy
Normal file
@ -0,0 +1,22 @@
|
||||
async def myOrganization(ns):
|
||||
"""我的机构
|
||||
参数:
|
||||
id:当前登录者id
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
ns['sort'] = 'create_at desc'
|
||||
ns['del_flg'] = '0'
|
||||
user = await sor.R('users', ns)
|
||||
ns['id'] = user[0]['orgid']
|
||||
reacs = await sor.R('organization', ns)
|
||||
nss = {'orgid': user[0]['orgid'], 'del_flg': '0'}
|
||||
userall = await sor.R('users', nss)
|
||||
if ns.get('uid'):
|
||||
userall = await sor.R('users', {'id':ns.get('uid')})
|
||||
return {'status': True, 'dada': reacs, 'users': userall}
|
||||
return {'status': False, 'msg': '参数错误'}
|
||||
|
||||
ret = await myOrganization(params_kw)
|
||||
return ret
|
||||
12
b/Organization/upOrganization.dspy
Normal file
12
b/Organization/upOrganization.dspy
Normal file
@ -0,0 +1,12 @@
|
||||
async def upOrganization(ns):
|
||||
|
||||
"""修改机构"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
await sor.U('organization', ns)
|
||||
return {'status': True, 'msg': '修改成功'}
|
||||
return {'status': False, 'msg': '修改失败'}
|
||||
|
||||
ret = await upOrganization(params_kw)
|
||||
return ret
|
||||
45
b/README.md
Normal file
45
b/README.md
Normal file
@ -0,0 +1,45 @@
|
||||
# gadget
|
||||
a light wight web server base on aiohttp
|
||||
|
||||
## Dependent
|
||||
* [ahserver](https://github.com/yumoqing/ahserver)
|
||||
* [sqlor](https://github.com/yumoqing/sqlor) if you want to use database
|
||||
* [apppublic](https://github.com/yumoqing/apppublic)
|
||||
|
||||
## Download
|
||||
```
|
||||
git clone git@github.com:yumoqing/gadget.git
|
||||
```
|
||||
|
||||
## Configuration
|
||||
please look [ahserver](https://github.com/yumoqing/ahserver) to learn how to configure
|
||||
|
||||
### support https
|
||||
under "website" in the conf/config.json file, identify ssl with "crtfile" and "keyfile"
|
||||
like this.
|
||||
```
|
||||
"website":{
|
||||
"ssl":{
|
||||
"crtfile":"$[workdir]$/conf/www.bsppo.com.pem",
|
||||
"keyfile":"$[workdir]$/conf/www.bsppo.com.key"
|
||||
}
|
||||
}
|
||||
```
|
||||
### log configure
|
||||
In the conf/config.json, need to config log, you need to identify "name", "levelname" and "logfile"
|
||||
|
||||
|
||||
```
|
||||
"logger":{
|
||||
"name":"gadget",
|
||||
"levelname":"debug",
|
||||
"logfile":"$[workdir]$/logs/gadget.log"
|
||||
}
|
||||
```
|
||||
## Test
|
||||
the test folder contains everything need for a base test.
|
||||
|
||||
please to go test folder and run
|
||||
```
|
||||
python ../src/main.py
|
||||
```
|
||||
0
b/__init__.py
Normal file
0
b/__init__.py
Normal file
31
b/account/addledgers.dspy
Normal file
31
b/account/addledgers.dspy
Normal file
@ -0,0 +1,31 @@
|
||||
async def addledgers(ns):
|
||||
""" 录入客户余额
|
||||
action: RECHARGE = 充值;RECHARGE_REVERSE = 充值冲账
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if not ns.get('apv_id'):
|
||||
return {'status': False, 'msg': '充值失败'}
|
||||
if ns.get('apv_id'):
|
||||
if ns.get('status') != 'agree':
|
||||
return {'status': False, 'msg': '充值失败'}
|
||||
apv = await sor.R('apv_data',{'apv_id':ns.get('apv_id')})
|
||||
balance = float(apv[0]['apv_text'][5:])
|
||||
date = await get_business_date(sor=None)
|
||||
recharge_log = {'customerid': apv[0]['result_org'], 'recharge_amt': balance,
|
||||
'action': 'RECHARGE', 'recharge_path': '2', 'recharge_date': date}
|
||||
try:
|
||||
ra = RechargeAccounting(recharge_log)
|
||||
await ra.accounting(sor)
|
||||
await sor.C('recharge_log', {'id': uuid(), 'customerid': apv[0]['result_org'],
|
||||
'recharge_date': datetime.datetime.now().strftime("%Y-%m-%d"),
|
||||
'recharge_path': '2', 'recharge_amt': balance,
|
||||
'recharge_timestamp': date, 'action': 'RECHARGE', 'op_userid': apv[0]['apv_sender'],
|
||||
})
|
||||
return {'status': True, 'msg': '充值成功'}
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {'status': False, 'msg': '充值失败'}
|
||||
|
||||
ret = await addledgers(params_kw)
|
||||
return ret
|
||||
120
b/account/email_info.dspy
Normal file
120
b/account/email_info.dspy
Normal file
@ -0,0 +1,120 @@
|
||||
# 输入邮件地址,口令和 POP3 服务器地址
|
||||
email = "billing-specific@kaiyuancloud.cn"
|
||||
password = "KYY@1234"
|
||||
# 在对于的邮箱设置的SMTP/POP3里,找到对应的服务地址
|
||||
pop3_server = "pop.qiye.aliyun.com"
|
||||
|
||||
# 连接到POP3服务器:
|
||||
server = poplib.POP3(pop3_server)
|
||||
# 可以打开或关闭调试信息:
|
||||
server.set_debuglevel(1)
|
||||
# 可选:打印POP3服务器的欢迎文字:
|
||||
print(server.getwelcome().decode('utf-8'))
|
||||
|
||||
# 身份认证
|
||||
server.user(email)
|
||||
server.pass_(password)
|
||||
|
||||
# stat()返回邮件数量和占用空间:
|
||||
print('邮件数量: %s. 大小: %s' % server.stat())
|
||||
# list()返回所有邮件的编号:
|
||||
resp, mails, octets = server.list()
|
||||
|
||||
|
||||
# 获取最新一封邮件, 注意索引号从1开始:
|
||||
index = len(mails)
|
||||
resp, lines, octets = server.retr(index)
|
||||
|
||||
# lines存储了邮件的原始文本的每一行,
|
||||
# 可以获得整个邮件的原始文本:
|
||||
msg_content = b'\r\n'.join(lines).decode('utf-8')
|
||||
# 稍后解析出邮件,即完成下载邮件
|
||||
msg = Parser().parsestr(msg_content)
|
||||
|
||||
# 接下来解析文件
|
||||
async def decode_str(s):
|
||||
value, charset = decode_header(s)[0]
|
||||
if charset:
|
||||
value = value.decode(charset)
|
||||
return value
|
||||
|
||||
async def guess_charset(msg):
|
||||
charset = msg.get_charset()
|
||||
if charset is None:
|
||||
content_type = msg.get('Content-Type', '').lower()
|
||||
pos = content_type.find('charset=')
|
||||
if pos >= 0:
|
||||
charset = content_type[pos + 8:].strip()
|
||||
return charset
|
||||
|
||||
|
||||
# indent用于缩进显示:
|
||||
async def email_info(msg, indent=0):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if indent == 0:
|
||||
for header in ['From', 'To', 'Subject']:
|
||||
value = msg.get(header, '')
|
||||
if value:
|
||||
if header=='Subject':
|
||||
value = await decode_str(value)
|
||||
else:
|
||||
hdr, addr = parseaddr(value)
|
||||
name = await decode_str(hdr)
|
||||
value = u'%s <%s>' % (name, addr)
|
||||
print('%s%s: %s' % (' ' * indent, header, value))
|
||||
if (msg.is_multipart()):
|
||||
parts = msg.get_payload()
|
||||
for n, part in enumerate(parts):
|
||||
print('%spart %s' % (' ' * indent, n))
|
||||
print('%s--------------------' % (' ' * indent))
|
||||
await email_info(part, indent + 1)
|
||||
else:
|
||||
content_type = msg.get_content_type()
|
||||
if content_type=='text/plain' or content_type=='text/html':
|
||||
content = msg.get_payload(decode=True)
|
||||
charset = await guess_charset(msg)
|
||||
if charset:
|
||||
content = content.decode(charset)
|
||||
try:
|
||||
#解析交易金额
|
||||
start_index = content.find("交易金额:") + len("交易金额:")
|
||||
end_index = content.find("\n", start_index)
|
||||
find_data = content[start_index:end_index]
|
||||
price = find_data.strip()[1:]
|
||||
|
||||
#解析交易id码
|
||||
start_index = content.find("摘要:") + len("摘要:")
|
||||
end_index = content.find("\n", start_index)
|
||||
find_data = content[start_index:end_index]
|
||||
index = find_data.index("<")
|
||||
name = find_data[:index]
|
||||
if price and name:
|
||||
mail_code = await sor.R('mail_code',{'mailcode':name,'del_flg':'0'})
|
||||
date = await get_business_date(sor=None)
|
||||
recharge_log = {'customerid': mail_code[0]['customer_id'], 'recharge_amt': price,
|
||||
'action': 'RECHARGE', 'recharge_path': '2', 'recharge_date': date}
|
||||
try:
|
||||
ra = RechargeAccounting(recharge_log)
|
||||
await ra.accounting(sor)
|
||||
await sor.C('recharge_log', {'id': uuid(), 'customerid': mail_code[0]['customer_id'],
|
||||
'recharge_date': datetime.datetime.now().strftime("%Y-%m-%d"),
|
||||
'recharge_path': '2', 'recharge_amt': price,
|
||||
'recharge_timestamp': date, 'action': 'RECHARGE',
|
||||
# 'op_userid': apv[0]['apv_sender'],
|
||||
})
|
||||
|
||||
await sor.U('mail_code', {'id': mail_code[0]['id'], 'del_flg': '1'})
|
||||
return {'status': True, 'msg': '充值成功'}
|
||||
except Exception as e:
|
||||
raise e
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
print('%sAttachment: %s' % (' ' * indent, content_type))
|
||||
return {"code":'200'}
|
||||
|
||||
|
||||
msg = Parser().parsestr(msg_content)
|
||||
ret = await email_info(msg)
|
||||
return ret
|
||||
35
b/account/getrechargelog.dspy
Normal file
35
b/account/getrechargelog.dspy
Normal file
@ -0,0 +1,35 @@
|
||||
async def getrechargelog(ns):
|
||||
""" 展示我的客户充值记录 """
|
||||
db = DBPools()
|
||||
users_id = await get_user()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
recharge_log = await sor.R('recharge_log',
|
||||
{'sort': 'create_at desc', 'page': ns['page'], 'op_userid': users_id,
|
||||
'del_flg': '0'})
|
||||
if len(recharge_log['rows']) >= 1:
|
||||
billid = await sor.R('bill', {'sort': 'create_at desc','customerid': recharge_log['rows'][0]['customerid']})
|
||||
for j in recharge_log['rows']:
|
||||
RECHARGE_REVERSE = await sor.R('recharge_log',
|
||||
{'sort': 'create_at desc','del_flg': '0', 'op_userid': users_id, 'original_id': j['id']})
|
||||
if len(RECHARGE_REVERSE) >= 1:
|
||||
j['RECHARGE_REVERSE'] = '冲账'
|
||||
org = await sor.R('organization', {'sort': 'create_at desc','id': j['customerid'], 'del_flg': '0'})
|
||||
if len(org) >= 1:
|
||||
j['customerid'] = org[0]['orgname']
|
||||
j['orgid'] = org[0]['id']
|
||||
if j['recharge_path'] == '0':
|
||||
j['recharge_path'] = '支付宝'
|
||||
elif j['recharge_path'] == '1':
|
||||
j['recharge_path'] = '微信'
|
||||
elif j['recharge_path'] == '2':
|
||||
j['recharge_path'] = '线下充值'
|
||||
if j['action'] == 'RECHARGE':
|
||||
j['action'] = '充值'
|
||||
else:
|
||||
j['action'] = '充值冲账'
|
||||
else:
|
||||
continue
|
||||
return {'status': True, 'data': recharge_log,'billid':billid}
|
||||
|
||||
ret = await getrechargelog(params_kw)
|
||||
return ret
|
||||
56
b/account/index.html
Normal file
56
b/account/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
9
b/account/open_provider_acc.dspy
Normal file
9
b/account/open_provider_acc.dspy
Normal file
@ -0,0 +1,9 @@
|
||||
async def openacc(ns):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
accounting_orgid = ns.get('accounting_orgid') #'sBAkKZjSl35T5lr3p9-_1'
|
||||
orgid = ns.get('orgid') #'wuNnN1VtiwipC_ju1tKOW'
|
||||
await openProviderAccounts(sor, accounting_orgid, orgid)
|
||||
return {'code':200}
|
||||
ret = await openacc(params_kw)
|
||||
return ret
|
||||
7
b/account/openacc.dspy
Normal file
7
b/account/openacc.dspy
Normal file
@ -0,0 +1,7 @@
|
||||
async def openacc(ns):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await openOwnerAccounts(sor,'mIWUHBeeDM8mwAFPIQ8pS')
|
||||
return {'code':200}
|
||||
ret = await openacc(params_kw)
|
||||
return ret
|
||||
64
b/account/settle_accounts.dspy
Normal file
64
b/account/settle_accounts.dspy
Normal file
@ -0,0 +1,64 @@
|
||||
async def settle_accounts(ns):
|
||||
"""供应商结算统计 年、月、日、周、季
|
||||
0:实时结算,1:日结;2:周结;3:月结;4:季结;5:年结
|
||||
参数:id 用户id
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
orgid = await sor.R('users',ns)
|
||||
account = await sor.R('account', {'id':orgid[0]['orgid']})
|
||||
if len(account) >= 1:
|
||||
newdate = await get_business_date(sor=None)
|
||||
provider = await sor.R('provider',{'orgid':orgid[0]['orgid']})
|
||||
if provider[0]['settle_mode'] == '1':
|
||||
date = strdate_add(newdate,-1,0,0)
|
||||
bill = await sor.R('bill',{'providerid':provider[0]['id'],'bill_date':date})
|
||||
if len(bill) >= 1:
|
||||
for i in bill:
|
||||
org = await sor.R('organization',{'id':i['customerid']})
|
||||
i['customerid'] = org[0]
|
||||
elif provider[0]['settle_mode'] == '2':
|
||||
date = strdate_add(newdate, -7, 0, 0)
|
||||
nss = {'providerid': provider[0]['id'], 'bill_date': newdate, 'date': date}
|
||||
sql = """select * from bill where bill_date > ${date}$ and bill_date < ${newdate}$ and providerid = ${providerid}$;"""
|
||||
bill = await sor.sqlExe(sql,nss)
|
||||
if len(bill) >= 1:
|
||||
for i in bill:
|
||||
org = await sor.R('organization', {'id': i['customerid']})
|
||||
i['customerid'] = org[0]
|
||||
elif provider[0]['settle_mode'] == '3':
|
||||
date = strdate_add(newdate, 0, -1, 0)
|
||||
nss = {'providerid': provider[0]['id'], 'bill_date': newdate, 'date': date}
|
||||
sql = """select * from bill where bill_date > ${date}$ and bill_date < ${newdate}$ and providerid = ${providerid}$;"""
|
||||
bill = await sor.sqlExe(sql, nss)
|
||||
if len(bill) >= 1:
|
||||
for i in bill:
|
||||
org = await sor.R('organization', {'id': i['customerid']})
|
||||
i['customerid'] = org[0]
|
||||
elif provider[0]['settle_mode'] == '4':
|
||||
date = strdate_add(newdate, 0, -3, 0)
|
||||
nss = {'providerid': provider[0]['id'], 'bill_date': newdate, 'date': date}
|
||||
sql = """select * from bill where bill_date > ${date}$ and bill_date < ${newdate}$ and providerid = ${providerid}$;"""
|
||||
bill = await sor.sqlExe(sql, nss)
|
||||
if len(bill) >= 1:
|
||||
for i in bill:
|
||||
org = await sor.R('organization', {'id': i['customerid']})
|
||||
i['customerid'] = org[0]
|
||||
elif provider[0]['settle_mode'] == '5':
|
||||
date = strdate_add(newdate, 0, 0, -1)
|
||||
nss = {'providerid': provider[0]['id'], 'bill_date': newdate, 'date': date}
|
||||
sql = """select * from bill where bill_date > ${date}$ and bill_date < ${newdate}$ and providerid = ${providerid}$;"""
|
||||
bill = await sor.sqlExe(sql, nss)
|
||||
if len(bill) >= 1:
|
||||
for i in bill:
|
||||
org = await sor.R('organization', {'id': i['customerid']})
|
||||
i['customerid'] = org[0]
|
||||
return {'status': True, 'data': bill}
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {'status': False, 'msg': '获取失败'}
|
||||
|
||||
|
||||
ret = await settle_accounts(params_kw)
|
||||
return ret
|
||||
30
b/account/upledger.dspy
Normal file
30
b/account/upledger.dspy
Normal file
@ -0,0 +1,30 @@
|
||||
async def upledger(ns):
|
||||
""" 客户充值冲账
|
||||
action: RECHARGE = 充值;RECHARGE_REVERSE = 充值冲账
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if not ns.get('apv_id'):
|
||||
return {'status': False, 'msg': '充值失败'}
|
||||
if ns.get('apv_id'):
|
||||
if ns.get('status') != 'agree':
|
||||
return {'status': False, 'msg': '充值失败'}
|
||||
apv = await sor.R('apv_data',{'apv_id':ns.get('apv_id')})
|
||||
balance = float(apv[0]['apv_text'][5:])
|
||||
date = await get_business_date(sor=None)
|
||||
recharge_log = {'customerid': apv[0]['result_org'], 'recharge_amt': balance,
|
||||
'action': 'RECHARGE_REVERSE', 'recharge_path': '2', 'recharge_date': date}
|
||||
ra = RechargeAccounting(recharge_log)
|
||||
r = await ra.accounting(sor)
|
||||
if r == True:
|
||||
await sor.C('recharge_log', {'id': uuid(), 'customerid': apv[0]['result_org'],'recharge_date': date,
|
||||
'recharge_path': '2', 'recharge_amt': balance,
|
||||
'recharge_timestamp': datetime.datetime.now(), 'action': 'RECHARGE_REVERSE',
|
||||
'original_id': apv[0]['original_id'],
|
||||
'op_userid': apv[0]['apv_sender']})
|
||||
return {'status': True, 'msg': '充值冲账成功'}
|
||||
else:
|
||||
return {'status': True, 'msg': '充值冲账失败'}
|
||||
|
||||
ret = await upledger(params_kw)
|
||||
return ret
|
||||
30
b/account/upledgers.dspy
Normal file
30
b/account/upledgers.dspy
Normal file
@ -0,0 +1,30 @@
|
||||
async def upledgers(ns):
|
||||
""" 客户充值冲账
|
||||
action: RECHARGE = 充值;RECHARGE_REVERSE = 充值冲账
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if not ns.get('apv_id'):
|
||||
return {'status': False, 'msg': '充值失败'}
|
||||
if ns.get('apv_id'):
|
||||
if ns.get('status') != 'agree':
|
||||
return {'status': False, 'msg': '充值失败'}
|
||||
apv = await sor.R('apv_data',{'apv_id':ns.get('apv_id')})
|
||||
balance = float(apv[0]['apv_text'][7:])
|
||||
date = await get_business_date(sor=None)
|
||||
recharge_log = {'customerid': apv[0]['result_org'], 'recharge_amt': balance,
|
||||
'action': 'RECHARGE_REVERSE', 'recharge_path': '2', 'recharge_date': date}
|
||||
ra = RechargeAccounting(recharge_log)
|
||||
r = await ra.accounting(sor)
|
||||
if r == True:
|
||||
await sor.C('recharge_log', {'id': uuid(), 'customerid': apv[0]['result_org'],'recharge_date': date,
|
||||
'recharge_path': '2', 'recharge_amt': balance,
|
||||
'recharge_timestamp': datetime.datetime.now(), 'action': 'RECHARGE_REVERSE',
|
||||
'original_id': apv[0]['original_id'],
|
||||
'op_userid': apv[0]['apv_sender']})
|
||||
return {'status': True, 'msg': '充值冲账成功'}
|
||||
else:
|
||||
return {'status': True, 'msg': '充值冲账失败'}
|
||||
|
||||
ret = await upledgers(params_kw)
|
||||
return ret
|
||||
247
b/ali/DescribeRegions.dspy
Normal file
247
b/ali/DescribeRegions.dspy
Normal file
@ -0,0 +1,247 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time: 2023/8/29 11:06
|
||||
|
||||
class KYYAliECS:
|
||||
def __init__(self):
|
||||
# self.access_key_id = 'LTAI5tSX7wQnsx6dRfUc3Wfe'
|
||||
# self.access_key_secret = 'bWiuPh0eCWIaaXXpF9axsPVHX6kWzY'
|
||||
|
||||
self.access_key_id = 'LTAI5tGYr9XoLaJD1vBR8Vu7'
|
||||
self.access_key_secret = 'jbFPoDHinlCOMXhIfQLag9nWX78IMb'
|
||||
self.sms_client = self.create_client()
|
||||
|
||||
def create_client(self):
|
||||
"""
|
||||
使用AK&SK初始化账号Client
|
||||
@param access_key_id:
|
||||
@param access_key_secret:
|
||||
@return: Client
|
||||
@throws Exception
|
||||
"""
|
||||
config = open_api_models.Config(
|
||||
access_key_id=self.access_key_id,
|
||||
access_key_secret=self.access_key_secret
|
||||
)
|
||||
# Endpoint 请参考 https://api.aliyun.com/product/Ecs
|
||||
config.endpoint = f'ecs-cn-hangzhou.aliyuncs.com'
|
||||
return Ecs20140526Client(config)
|
||||
|
||||
async def get_describe_regions(self, nss):
|
||||
"""
|
||||
instance_charge_type
|
||||
PrePaid:包年包月。此时,您必须确认自己的账号支持余额支付或者信用支付,否则将报错InvalidPayMethod
|
||||
PostPaid:按量付费
|
||||
SpotWithPriceLimit: 枚举值
|
||||
默认值为PostPaid。
|
||||
resource_type:
|
||||
instance:ECS实例
|
||||
disk:磁盘
|
||||
reservedinstance:预留实例券
|
||||
scu:存储容量单位包
|
||||
默认值:instance
|
||||
accept_language:
|
||||
zh-CN:中文。
|
||||
en-US:英文。
|
||||
ja:日文。
|
||||
默认值为zh-CN。
|
||||
:return:
|
||||
"""
|
||||
describe_regions_request = ecs_20140526_models.DescribeRegionsRequest(
|
||||
instance_charge_type=nss.get('instance_charge_type'),
|
||||
resource_type=nss.get('resource_type'),
|
||||
accept_language=nss.get('accept_language')
|
||||
)
|
||||
runtime = util_models.RuntimeOptions()
|
||||
resp = await self.sms_client.describe_regions_with_options_async(describe_regions_request, runtime)
|
||||
# ConsoleClient.log(UtilClient.to_jsonstring(resp))
|
||||
return UtilClient.to_jsonstring(resp)
|
||||
|
||||
async def describe_available_resource(self, ns={}):
|
||||
describe_available_resource_request = ecs_20140526_models.DescribeAvailableResourceRequest(
|
||||
region_id=ns.get('region_id'),
|
||||
memory=ns.get('memory'),
|
||||
resource_type=ns.get('resource_type'),
|
||||
scope=ns.get('scope'),
|
||||
cores=ns.get('cores'),
|
||||
network_category=ns.get('network_category'),
|
||||
data_disk_category=ns.get('data_disk_category'),
|
||||
system_disk_category=ns.get('system_disk_category'),
|
||||
instance_type=ns.get('instance_type'),
|
||||
dedicated_host_id=ns.get('dedicated_host_id'),
|
||||
io_optimized=ns.get('io_optimized'),
|
||||
zone_id=ns.get('zone_id'),
|
||||
destination_resource=ns.get('destination_resource'),
|
||||
spot_duration=ns.get('spot_duration'),
|
||||
spot_strategy=ns.get('spot_strategy'),
|
||||
instance_charge_type=ns.get('instance_charge_type')
|
||||
)
|
||||
runtime = util_models.RuntimeOptions()
|
||||
try:
|
||||
# 复制代码运行请自行打印 API 的返回值
|
||||
result = await self.sms_client.describe_available_resource_with_options_async(describe_available_resource_request, runtime)
|
||||
return result
|
||||
except Exception as error:
|
||||
# 如有需要,请打印 error
|
||||
return UtilClient.assert_as_string(error.message)
|
||||
|
||||
async def describe_instance_types(self, ns={}):
|
||||
describe_instance_types_request = ecs_20140526_models.DescribeInstanceTypesRequest(
|
||||
instance_type_family=ns.get('instance_type_family'),
|
||||
instance_types=ns.get('instance_types'),
|
||||
minimum_cpu_core_count=ns.get('minimum_cpu_core_count'),
|
||||
maximum_cpu_core_count=ns.get('maximum_cpu_core_count'),
|
||||
minimum_memory_size=ns.get('minimum_memory_size'),
|
||||
maximum_memory_size=ns.get('maximum_memory_size'),
|
||||
minimum_gpuamount=ns.get('minimum_gpuamount'),
|
||||
maximum_gpuamount=ns.get('maximum_gpuamount'),
|
||||
gpuspec=ns.get('gpuspec'),
|
||||
instance_category=ns.get('instance_category'),
|
||||
cpu_architecture=ns.get('cpu_architecture'),
|
||||
minimum_cpu_speed_frequency=ns.get('minimum_cpu_speed_frequency'),
|
||||
maximum_cpu_speed_frequency=ns.get('maximum_cpu_speed_frequency'),
|
||||
minimum_cpu_turbo_frequency=ns.get('minimum_cpu_turbo_frequency'),
|
||||
maximum_cpu_turbo_frequency=ns.get('maximum_cpu_turbo_frequency'),
|
||||
physical_processor_model=ns.get('physical_processor_model'),
|
||||
instance_family_level=ns.get('instance_family_level'),
|
||||
minimum_instance_pps_rx=ns.get('minimum_instance_pps_rx'),
|
||||
minimum_instance_pps_tx=ns.get('minimum_instance_pps_tx'),
|
||||
minimum_instance_bandwidth_rx=ns.get('minimum_instance_bandwidth_rx'),
|
||||
minimum_instance_bandwidth_tx=ns.get('minimum_instance_bandwidth_tx'),
|
||||
minimum_primary_eni_queue_number=ns.get('minimum_primary_eni_queue_number'),
|
||||
minimum_secondary_eni_queue_number=ns.get('minimum_secondary_eni_queue_number'),
|
||||
minimum_eni_quantity=ns.get('minimum_eni_quantity'),
|
||||
minimum_queue_pair_number=ns.get('minimum_queue_pair_number'),
|
||||
minimum_eri_quantity=ns.get('minimum_eri_quantity'),
|
||||
minimum_eni_private_ip_address_quantity=ns.get('minimum_eni_private_ip_address_quantity'),
|
||||
minimum_eni_ipv_6address_quantity=ns.get('minimum_eni_ipv_6address_quantity'),
|
||||
minimum_local_storage_amount=ns.get('minimum_local_storage_amount'),
|
||||
minimum_local_storage_capacity=ns.get('minimum_local_storage_capacity'),
|
||||
minimum_disk_quantity=ns.get('minimum_disk_quantity'),
|
||||
local_storage_category=ns.get('local_storage_category'),
|
||||
nvme_support=ns.get('nvme_support'),
|
||||
minimum_baseline_credit=ns.get('minimum_baseline_credit'),
|
||||
minimum_initial_credit=ns.get('minimum_initial_credit'),
|
||||
max_results=ns.get('max_results'),
|
||||
next_token=ns.get('next_token'),
|
||||
)
|
||||
runtime = util_models.RuntimeOptions()
|
||||
try:
|
||||
# 复制代码运行请自行打印 API 的返回值
|
||||
result = await self.sms_client.describe_instance_types_with_options_async(describe_instance_types_request, runtime)
|
||||
return result
|
||||
except Exception as error:
|
||||
# 如有需要,请打印 error
|
||||
return UtilClient.assert_as_string(error.message)
|
||||
|
||||
async def describe_price(self, ns={}):
|
||||
scheduler_options = ecs_20140526_models.DescribePriceRequestSchedulerOptions(
|
||||
dedicated_host_id='dh-bp67acfmxazb4p****'
|
||||
)
|
||||
data_disk_0 = ecs_20140526_models.DescribePriceRequestDataDisk(
|
||||
category='cloud_ssd',
|
||||
size=3000,
|
||||
performance_level='PL1'
|
||||
)
|
||||
# 快速购买 默认存在
|
||||
system_disk = ecs_20140526_models.DescribePriceRequestSystemDisk(
|
||||
category=ns.get('system_disk').get('category'),
|
||||
size=ns.get('system_disk').get('size')
|
||||
)
|
||||
describe_price_request = ecs_20140526_models.DescribePriceRequest(
|
||||
region_id=ns.get('region_id'),
|
||||
resource_type=ns.get('resource_type'),
|
||||
image_id=ns.get('image_id'),
|
||||
instance_type=ns.get('instance_type'),
|
||||
dedicated_host_type=ns.get('dedicated_host_type'),
|
||||
io_optimized=ns.get('io_optimized'),
|
||||
instance_network_type=ns.get('instance_network_type'),
|
||||
internet_charge_type=ns.get('internet_charge_type'),
|
||||
internet_max_bandwidth_out=ns.get('internet_max_bandwidth_out'),
|
||||
system_disk=system_disk,
|
||||
data_disk=ns.get('data_disk'),
|
||||
period=ns.get('period'),
|
||||
price_unit=ns.get('price_unit'),
|
||||
amount=ns.get('amount'),
|
||||
offering_type=ns.get('offering_type'),
|
||||
instance_amount=ns.get('instance_amount'),
|
||||
scope=ns.get('scope'),
|
||||
platform=ns.get('platform'),
|
||||
capacity=ns.get('capacity'),
|
||||
assurance_times=ns.get('assurance_times'),
|
||||
instance_cpu_core_count=ns.get('instance_cpu_core_count'),
|
||||
isp=ns.get('isp'),
|
||||
instance_type_list=ns.get('instance_type_list'),
|
||||
spot_strategy=ns.get('spot_strategy'),
|
||||
spot_duration=ns.get('spot_duration'),
|
||||
zone_id=ns.get('zone_id'),
|
||||
scheduler_options=ns.get('scheduler_options')
|
||||
)
|
||||
runtime = util_models.RuntimeOptions()
|
||||
try:
|
||||
result = await self.sms_client.describe_price_with_options_async(describe_price_request, runtime)
|
||||
return result
|
||||
except Exception as error:
|
||||
return UtilClient.assert_as_string(error.message)
|
||||
|
||||
async def describe_images(self, ns={}):
|
||||
describe_images_request = ecs_20140526_models.DescribeImagesRequest(
|
||||
region_id='cn-qingdao'
|
||||
# region_id=ns.get('region_id'),
|
||||
# show_expired=ns.get('show_expired'),
|
||||
# is_support_io_optimized=ns.get('is_support_io_optimized'),
|
||||
# is_support_cloudinit=ns.get('is_support_cloudinit'),
|
||||
# ostype=ns.get('ostype'),
|
||||
# architecture=ns.get('architecture'),
|
||||
# usage=ns.get('usage'),
|
||||
# dry_run=ns.get('dry_run'),
|
||||
# action_type=ns.get('action_type'),
|
||||
# resource_group_id=ns.get('resource_group_id'),
|
||||
# is_public=ns.get('is_public'),
|
||||
# image_owner_id=ns.get('image_owner_id'),
|
||||
# page_number=ns.get('page_number'),
|
||||
# page_size=ns.get('page_size'),
|
||||
)
|
||||
runtime = util_models.RuntimeOptions()
|
||||
try:
|
||||
result = await self.sms_client.describe_images_with_options_async(describe_images_request, runtime)
|
||||
return result
|
||||
except Exception as error:
|
||||
# 如有需要,请打印 error
|
||||
return UtilClient.assert_as_string(error.message)
|
||||
|
||||
async def DescribeRegions(ns={}):
|
||||
"""
|
||||
获取可用区域
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
# ns = {
|
||||
# 'instance_charge_type': 'PrePaid',
|
||||
# 'resource_type': 'instance',
|
||||
# 'accept_language': 'zh-CN'
|
||||
# # 'resource_type': 'disk'
|
||||
# }
|
||||
nss = {
|
||||
'instance_charge_type': ns.get('instance_charge_type'),
|
||||
'resource_type': ns.get('resource_type'),
|
||||
'accept_language': ns.get('accept_language')
|
||||
}
|
||||
regions = await KYYAliECS().get_describe_regions(nss)
|
||||
result = json.loads(regions)['body']
|
||||
result['Regions']['Region_filter'] = {'Asia_China': [], 'Asia_Other': [], 'Europe_America': [], 'Middle_East': []}
|
||||
for content in result['Regions']['Region']:
|
||||
if 'cn' in content['RegionId']:
|
||||
result['Regions']['Region_filter']['Asia_China'].append(content)
|
||||
elif 'ap' in content['RegionId']:
|
||||
result['Regions']['Region_filter']['Asia_Other'].append(content)
|
||||
elif 'en' in content['RegionId'] or 'us' in content['RegionId']:
|
||||
result['Regions']['Region_filter']['Europe_America'].append(content)
|
||||
elif 'me' in content['RegionId']:
|
||||
result['Regions']['Region_filter']['Middle_East'].append(content)
|
||||
print(result)
|
||||
return result
|
||||
|
||||
ret = await DescribeRegions(params_kw)
|
||||
return ret
|
||||
|
||||
|
||||
68
b/ali/GetResourceList.dspy
Normal file
68
b/ali/GetResourceList.dspy
Normal file
@ -0,0 +1,68 @@
|
||||
async def product_salemode_search(ns={}):
|
||||
"""
|
||||
产品价格不落地
|
||||
查找sale_protocol以后 具体产品配置查找
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
if ns.get('salemode') == '0':
|
||||
res_list = []
|
||||
ns_search = {
|
||||
'protocolid': ns.get('protocolid'),
|
||||
'del_flg': '0'
|
||||
}
|
||||
res = await sor.R('product_salemode', ns_search)
|
||||
# 首先查找不是*的产品 加到产品列表
|
||||
# 已经存在的id列表
|
||||
prd_singles = [item.get('productid') for item in res if item.get('productid') != '*']
|
||||
# 已经存在的id列表 包含对应折扣
|
||||
prd_single_ids = [(item.get('productid'), item.get('discount')) for item in res if item.get('productid') != '*']
|
||||
for prd_single in prd_single_ids:
|
||||
single_sql = """select * from product where id = '%s' and del_flg = '0' and CURRENT_DATE
|
||||
between effect_date and expire_date;""" % prd_single[0]
|
||||
single_res_li = await sor.sqlExe(single_sql, {})
|
||||
single_res = single_res_li[0] if single_res_li else {}
|
||||
single_res['discount'] = prd_single[1]
|
||||
res_list.append(single_res)
|
||||
|
||||
# 查找*的所有产品id 通过prd_single筛选
|
||||
nss = {
|
||||
'productid': '*',
|
||||
'protocolid': ns.get('protocolid'),
|
||||
'del_flg': '0'
|
||||
}
|
||||
res_star = await sor.R('product_salemode', nss)
|
||||
if res_star:
|
||||
# 针对产品设置的统一折扣
|
||||
start_discount = res_star[0].get('discount')
|
||||
provider_star = res_star[0].get('providerid')
|
||||
res_product_sql = """select * from product where providerid = '%s' and del_flg = '0' and CURRENT_DATE
|
||||
between effect_date and expire_date;""" % provider_star
|
||||
res_product_li = await sor.sqlExe(res_product_sql, {})
|
||||
for res_product in res_product_li:
|
||||
res_product_id = res_product.get('id')
|
||||
if res_product_id not in prd_singles:
|
||||
res_product['discount'] = start_discount
|
||||
res_list.append(res_product)
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "product_salemode search success",
|
||||
"data": res_list
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "product_salemode search failed",
|
||||
'data': e
|
||||
}
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "product_salemode search failed",
|
||||
"data": 111,
|
||||
}
|
||||
|
||||
ret = await product_salemode_search(params_kw)
|
||||
return ret
|
||||
56
b/ali/index.html
Normal file
56
b/ali/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
73
b/ali/jiajie_get_token_redirect.dspy
Normal file
73
b/ali/jiajie_get_token_redirect.dspy
Normal file
@ -0,0 +1,73 @@
|
||||
async def jiajie_get_token_redirect(ns={}):
|
||||
"""
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
# target_host = 'https://testing.vstecscloud.shop'
|
||||
target_host = 'https://aliyun.kaiyuancloud.cn'
|
||||
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
|
||||
password = "weishijiajiekyy"
|
||||
|
||||
# 创建一个md5 hash对象
|
||||
md5_hash = hashlib.md5()
|
||||
# 对字符串进行编码
|
||||
md5_hash.update(password.encode('utf-8')) # 注意:需要先将字符串编码为字节串
|
||||
# 获取十六进制形式的MD5编码
|
||||
digest = md5_hash.hexdigest()
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
username = await sor.R('weishijiajie_users', {'user_id': userid})
|
||||
if not username:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '用户未同步'
|
||||
}
|
||||
# 构造请求数据
|
||||
request_data = {
|
||||
"grant_type": "password",
|
||||
"scope": "all",
|
||||
"username": username[0]['jiajie_username'],
|
||||
"password": digest
|
||||
}
|
||||
|
||||
# 发送HTTP请求
|
||||
url = "%s/api/blade-auth/oauth/token" % target_host
|
||||
|
||||
if 'kaiyuancloud' in target_host:
|
||||
tenantid = '502332'
|
||||
else:
|
||||
tenantid = '024060'
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
"Tenant-Id": tenantid,
|
||||
"Authorization" : "Basic c3dvcmQ6c3dvcmRfc2VjcmV0",
|
||||
}
|
||||
|
||||
method = 'POST'
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=headers,
|
||||
data=request_data) as res:
|
||||
result = await res.json()
|
||||
if result.get('access_token'):
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get token success',
|
||||
'data': target_host + '/kaiyuany/sso?token=' + result.get('access_token')
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'stauts': False,
|
||||
'msg': 'get token failed, status: %s, text: %s' % (res.status, result)
|
||||
}
|
||||
|
||||
ret = await jiajie_get_token_redirect(params_kw)
|
||||
return ret
|
||||
78
b/ali/jiajie_sync_user.dspy
Normal file
78
b/ali/jiajie_sync_user.dspy
Normal file
@ -0,0 +1,78 @@
|
||||
async def jiajie_sync_user(ns={}):
|
||||
"""
|
||||
{'code': 200, 'success': True, 'data': {'userId': '1934862636731187202', 'userName': '68510cdfd558b975a05dc1a5'}, 'msg': '操作成功'}
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
if ns.get('userid'):
|
||||
userid = ns.get('userid')
|
||||
else:
|
||||
userid = await get_user()
|
||||
|
||||
if not userid:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '用户还未登录'
|
||||
}
|
||||
# target_host = 'https://testing.vstecscloud.shop'
|
||||
target_host = 'https://aliyun.kaiyuancloud.cn'
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
exits_user = await sor.R('weishijiajie_users', {'user_id': userid})
|
||||
if exits_user:
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'Synchronized users'
|
||||
}
|
||||
userinfos = await sor.R('users', {'id': userid})
|
||||
phone = userinfos[0]['mobile']
|
||||
email = userinfos[0]['email']
|
||||
name = userinfos[0]['username']
|
||||
|
||||
# 构造请求数据 筛选条件: 手机号/邮箱
|
||||
request_data = {
|
||||
"password": "weishijiajiekyy",
|
||||
"phone": phone,
|
||||
"email": email,
|
||||
"realname": name
|
||||
}
|
||||
|
||||
# 数字信封加密
|
||||
json_string = json.dumps(request_data)
|
||||
encrypted_result = await KaiYyEnDecryptUtil.encrypt_by_digital_envelope(json_string)
|
||||
|
||||
# 发送HTTP请求
|
||||
url = '%s/api/blade-user/syncinfo/user/v1' % target_host
|
||||
method = 'POST'
|
||||
header = {
|
||||
"AESKey": encrypted_result["AESKey"]
|
||||
}
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
data=encrypted_result["data"].encode("utf-8")) as res:
|
||||
result = await res.json()
|
||||
|
||||
# 处理响应
|
||||
if result.get('success'):
|
||||
# 正确同步 存库
|
||||
sync_info = {
|
||||
'id': uuid(),
|
||||
'user_id': userid,
|
||||
'jiajie_userid': result['data']['userId'],
|
||||
'jiajie_username': result['data']['userName']
|
||||
}
|
||||
await sor.C('weishijiajie_users', sync_info)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'sync user success'
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': f"请求失败,状态码: {result.get('code')},响应内容: {result.get('msg')}"
|
||||
}
|
||||
|
||||
ret = await jiajie_sync_user(params_kw)
|
||||
return ret
|
||||
68
b/ali/product_salemode_search - 副本.dspy
Normal file
68
b/ali/product_salemode_search - 副本.dspy
Normal file
@ -0,0 +1,68 @@
|
||||
async def product_salemode_search(ns={}):
|
||||
"""
|
||||
产品价格不落地
|
||||
查找sale_protocol以后 具体产品配置查找
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
if ns.get('salemode') == '0':
|
||||
res_list = []
|
||||
ns_search = {
|
||||
'protocolid': ns.get('protocolid'),
|
||||
'del_flg': '0'
|
||||
}
|
||||
res = await sor.R('product_salemode', ns_search)
|
||||
# 首先查找不是*的产品 加到产品列表
|
||||
# 已经存在的id列表
|
||||
prd_singles = [item.get('productid') for item in res if item.get('productid') != '*']
|
||||
# 已经存在的id列表 包含对应折扣
|
||||
prd_single_ids = [(item.get('productid'), item.get('discount')) for item in res if item.get('productid') != '*']
|
||||
for prd_single in prd_single_ids:
|
||||
single_sql = """select * from product where id = '%s' and del_flg = '0' and CURRENT_DATE
|
||||
between effect_date and expire_date;""" % prd_single[0]
|
||||
single_res_li = await sor.sqlExe(single_sql, {})
|
||||
single_res = single_res_li[0] if single_res_li else {}
|
||||
single_res['discount'] = prd_single[1]
|
||||
res_list.append(single_res)
|
||||
|
||||
# 查找*的所有产品id 通过prd_single筛选
|
||||
nss = {
|
||||
'productid': '*',
|
||||
'protocolid': ns.get('protocolid'),
|
||||
'del_flg': '0'
|
||||
}
|
||||
res_star = await sor.R('product_salemode', nss)
|
||||
if res_star:
|
||||
# 针对产品设置的统一折扣
|
||||
start_discount = res_star[0].get('discount')
|
||||
provider_star = res_star[0].get('providerid')
|
||||
res_product_sql = """select * from product where providerid = '%s' and del_flg = '0' and CURRENT_DATE
|
||||
between effect_date and expire_date;""" % provider_star
|
||||
res_product_li = await sor.sqlExe(res_product_sql, {})
|
||||
for res_product in res_product_li:
|
||||
res_product_id = res_product.get('id')
|
||||
if res_product_id not in prd_singles:
|
||||
res_product['discount'] = start_discount
|
||||
res_list.append(res_product)
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "product_salemode search success",
|
||||
"data": res_list
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "product_salemode search failed",
|
||||
'data': e
|
||||
}
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "product_salemode search failed",
|
||||
"data": 111,
|
||||
}
|
||||
|
||||
ret = await product_salemode_search(params_kw)
|
||||
return ret
|
||||
54
b/appcode/appCodesAdd.dspy
Normal file
54
b/appcode/appCodesAdd.dspy
Normal file
@ -0,0 +1,54 @@
|
||||
async def appCodesAdd(ns={}):
|
||||
"""
|
||||
add new app code
|
||||
`id` VARCHAR(32) 'id',
|
||||
`name` VARCHAR(255) '编码名称',
|
||||
`hierarchy_flg` VARCHAR(1) '多级标志',
|
||||
`del_flg` VARCHAR(1) DEFAULT '0' comment '删除标志',
|
||||
`create_at` TIMESTAMP comment '创建时间戳'
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
# if add kv table and id exists
|
||||
if ns.get('kv'):
|
||||
ns['id'] = uuid()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.C('appcodes_kv', ns)
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "appcodes_kv add success"
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appcodes_kv add failed"
|
||||
}
|
||||
app_code = {
|
||||
'id': ns.get('id'),
|
||||
'name': ns.get('name'),
|
||||
'hierarchy_flg': ns.get('hierarchy_flg')
|
||||
}
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "app code id is empty"
|
||||
}
|
||||
# insert into appcodes
|
||||
await sor.C('appcodes', app_code)
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "app codes add success"
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "app codes add failed"
|
||||
}
|
||||
|
||||
|
||||
ret = await appCodesAdd(params_kw)
|
||||
return ret
|
||||
48
b/appcode/appCodesDelete.dspy
Normal file
48
b/appcode/appCodesDelete.dspy
Normal file
@ -0,0 +1,48 @@
|
||||
async def appCodesDelete(ns={}):
|
||||
"""
|
||||
delete app code
|
||||
`id` VARCHAR(32) 'id',
|
||||
`name` VARCHAR(255) '编码名称',
|
||||
`hierarchy_flg` VARCHAR(1) '多级标志',
|
||||
`del_flg` VARCHAR(1) DEFAULT '0' comment '删除标志',
|
||||
`create_at` TIMESTAMP comment '创建时间戳'
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if not ns.get('id'):
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appCodes id is empty, please check"
|
||||
}
|
||||
if ns.get('kv'):
|
||||
ns['del_flg'] = '1'
|
||||
try:
|
||||
await sor.U('appcodes_kv', ns)
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "appCodes_kv delete success"
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appCodes_kv delete failed"
|
||||
}
|
||||
try:
|
||||
ns['del_flg'] = '1'
|
||||
await sor.U('appcodes',ns)
|
||||
delete_kv_sql = """update appcodes_kv set del_flg = 1 where codeid = '%s'""" % ns.get('id')
|
||||
await sor.sqlExe(delete_kv_sql, {})
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "appCodes delete success"
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appCodes delete failed"
|
||||
}
|
||||
|
||||
ret = await appCodesDelete(params_kw)
|
||||
return ret
|
||||
43
b/appcode/appCodesKvSearch.dspy
Normal file
43
b/appcode/appCodesKvSearch.dspy
Normal file
@ -0,0 +1,43 @@
|
||||
async def appCodesSearch(ns={}):
|
||||
"""
|
||||
search new appcodes
|
||||
`id` VARCHAR(32) 'id',
|
||||
`name` VARCHAR(255) '编码名称',
|
||||
`hierarchy_flg` VARCHAR(1) '多级标志',
|
||||
`del_flg` VARCHAR(1) DEFAULT '0' comment '删除标志',
|
||||
`create_at` TIMESTAMP comment '创建时间戳'
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at'
|
||||
ns['order'] = 'desc'
|
||||
ns['page'] = ns.get('page') if ns.get('page') else 1
|
||||
if ns.get('kv'):
|
||||
if not ns.get('codeid'):
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appCodes_kv search failed, the id is empty",
|
||||
"data": ""
|
||||
}
|
||||
app_code_result = await sor.R('appcodes_kv', ns)
|
||||
else:
|
||||
app_code_result = await sor.R('appcodes',ns)
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "appCodes search success",
|
||||
"data": app_code_result
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appCodes search failed",
|
||||
"data": ""
|
||||
}
|
||||
|
||||
|
||||
ret = await appCodesKvSearch(params_kw)
|
||||
return ret
|
||||
66
b/appcode/appCodesSearch.dspy
Normal file
66
b/appcode/appCodesSearch.dspy
Normal file
@ -0,0 +1,66 @@
|
||||
async def get_children(parent_id, data):
|
||||
children = []
|
||||
for item in data:
|
||||
if item['parentid'] == parent_id:
|
||||
child = {'id': item['id'], 'codeid': item['codeid'], 'parentid': item['parentid'], 'k': item['k'], 'v': item['v']}
|
||||
grandchildren = await get_children(item['id'], data)
|
||||
if grandchildren:
|
||||
child['son'] = grandchildren
|
||||
children.append(child)
|
||||
return children
|
||||
|
||||
async def transform_data(data):
|
||||
result = []
|
||||
for item in data:
|
||||
if item['parentid'] is None or item['parentid'] == '':
|
||||
parent = {'id': item['id'], 'codeid': item['codeid'], 'parentid': item['parentid'], 'k': item['k'], 'v': item['v']}
|
||||
children = await get_children(item['id'], data)
|
||||
if children:
|
||||
parent['son'] = children
|
||||
result.append(parent)
|
||||
return result
|
||||
|
||||
async def appCodesSearch(ns={}):
|
||||
"""
|
||||
search new appcodes
|
||||
`id` VARCHAR(32) 'id',
|
||||
`name` VARCHAR(255) '编码名称',
|
||||
`hierarchy_flg` VARCHAR(1) '多级标志',
|
||||
`del_flg` VARCHAR(1) DEFAULT '0' comment '删除标志',
|
||||
`create_at` TIMESTAMP comment '创建时间戳'
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at'
|
||||
ns['order'] = 'desc'
|
||||
ns['page'] = ns.get('page') if ns.get('page') else 1
|
||||
if ns.get('kv'):
|
||||
if not ns.get('codeid'):
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appCodes_kv search failed, the codeid is empty",
|
||||
"data": ""
|
||||
}
|
||||
app_code_result = await sor.R('appcodes_kv', ns)
|
||||
app_code_result = await transform_data(app_code_result.get('rows'))
|
||||
else:
|
||||
app_code_result = await sor.R('appcodes',ns)
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "appCodes search success",
|
||||
"data": app_code_result
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appCodes search failed",
|
||||
"data": ""
|
||||
}
|
||||
|
||||
|
||||
ret = await appCodesSearch(params_kw)
|
||||
return ret
|
||||
46
b/appcode/appCodesUpdate.dspy
Normal file
46
b/appcode/appCodesUpdate.dspy
Normal file
@ -0,0 +1,46 @@
|
||||
async def appCodesUpdate(ns={}):
|
||||
"""
|
||||
delete app code
|
||||
`id` VARCHAR(32) 'id',
|
||||
`name` VARCHAR(255) '编码名称',
|
||||
`hierarchy_flg` VARCHAR(1) '多级标志',
|
||||
`del_flg` VARCHAR(1) DEFAULT '0' comment '删除标志',
|
||||
`create_at` TIMESTAMP comment '创建时间戳'
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
ns_appcode = {
|
||||
'id': ns.get('id'),
|
||||
'name': ns.get('name'),
|
||||
'hierarchy_flg': ns.get('hierarchy_flg')
|
||||
}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
if ns.get('kv'):
|
||||
try:
|
||||
await sor.U('appcodes_kv', ns)
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "appcodes_kv update success"
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appcodes_kv update failed",
|
||||
}
|
||||
|
||||
await sor.U('appcodes',ns_appcode)
|
||||
return {
|
||||
"status": True,
|
||||
"msg": "appcodes update success",
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
"status": False,
|
||||
"msg": "appcodes update failed",
|
||||
}
|
||||
|
||||
|
||||
ret = await appCodesUpdate(params_kw)
|
||||
return ret
|
||||
6
b/appcode/getTime.dspy
Normal file
6
b/appcode/getTime.dspy
Normal file
@ -0,0 +1,6 @@
|
||||
async def get_server_timestamp(params_kw=None):
|
||||
return str(int(time.time() * 1000))
|
||||
|
||||
|
||||
ret = await get_server_timestamp(params_kw=1)
|
||||
return ret
|
||||
56
b/appcode/index.html
Normal file
56
b/appcode/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
291
b/appcode/编码表接口说明.md
Normal file
291
b/appcode/编码表接口说明.md
Normal file
@ -0,0 +1,291 @@
|
||||
### 编码增加
|
||||
|
||||
请求URL:
|
||||
|
||||
<http://47.93.12.75:8888/appcode/appCodesAdd.dspy>
|
||||
|
||||
请求示例
|
||||
|
||||
```
|
||||
添加Code表
|
||||
{
|
||||
'id': 'user_status',
|
||||
'name': '用户状态',
|
||||
'hierarchy_flg': '0'
|
||||
}
|
||||
|
||||
添加kv表
|
||||
{
|
||||
'kv': '1',
|
||||
'codeid':'user_status',
|
||||
'parentid': '123',
|
||||
'k': '2',
|
||||
'v': '休息中'
|
||||
}
|
||||
```
|
||||
|
||||
请求参数说明
|
||||
|
||||
添加Code表
|
||||
|
||||
| 参数 | 类型 | 必填 | 描述 |
|
||||
| ------------- | ------ | ---- | --------------------- |
|
||||
| id | String | 是 | 英文名称例如:status |
|
||||
| name | String | 是 | 中文名称 例如:状态 |
|
||||
| hierarchy_flg | String | 是 | 多级标志 0/1 是否多级 |
|
||||
|
||||
|
||||
|
||||
添加kv表
|
||||
|
||||
| 参数 | 类型 | 必填 | 描述 |
|
||||
| -------- | ------ | ---- | -------------- |
|
||||
| kv | String | 是 | 添加kv表 值为1 |
|
||||
| codeid | String | 是 | Code表中的id |
|
||||
| parentid | String | 是 | 父级id |
|
||||
| k | String | 是 | 键 |
|
||||
| v | String | 是 | 值 |
|
||||
|
||||
返回示例
|
||||
|
||||
```
|
||||
添加成功
|
||||
{
|
||||
"status": true,
|
||||
"msg": "add success"
|
||||
}
|
||||
添加失败
|
||||
{
|
||||
"status": False,
|
||||
"msg": "add failed"
|
||||
}
|
||||
```
|
||||
|
||||
### 编码删除
|
||||
|
||||
请求URL:
|
||||
|
||||
<http://47.93.12.75:8888/appcode/appCodesDelete.dspy>
|
||||
|
||||
请求示例
|
||||
|
||||
```
|
||||
删除Code表对应字段
|
||||
{
|
||||
'id': 'user_status'
|
||||
}
|
||||
|
||||
添加kv表
|
||||
{
|
||||
'kv': '1',
|
||||
'id': 'kv表中对应id'
|
||||
}
|
||||
```
|
||||
|
||||
请求参数说明
|
||||
|
||||
| 参数 | 类型 | 必填 | 描述 |
|
||||
| ---- | ------ | ---- | --------------- |
|
||||
| kv | String | 是 | 删除kv表 值为1 |
|
||||
| id | String | 是 | Code/kv表中的id |
|
||||
|
||||
返回示例
|
||||
|
||||
```
|
||||
删除成功
|
||||
{
|
||||
"status": true,
|
||||
"msg": "appCodes delete success"
|
||||
}
|
||||
删除失败
|
||||
{
|
||||
"status": False,
|
||||
"msg": "appCodes delete failed"
|
||||
}
|
||||
```
|
||||
|
||||
### 编码更新
|
||||
|
||||
请求URL:
|
||||
|
||||
<http://47.93.12.75:8888/appcode/appCodesUpdate.dspy>
|
||||
|
||||
请求示例
|
||||
|
||||
```
|
||||
更新Code表
|
||||
{
|
||||
'id': 'user_status',
|
||||
'name': '用户状态',
|
||||
'hierarchy_flg': '0'
|
||||
}
|
||||
|
||||
更新kv表
|
||||
{
|
||||
'kv': '1',
|
||||
'codeid':'user_status',
|
||||
'parentid': '123',
|
||||
'k': '2',
|
||||
'v': '休息中'
|
||||
}
|
||||
```
|
||||
|
||||
请求参数说明
|
||||
|
||||
更新Code表
|
||||
|
||||
| 参数 | 类型 | 必填 | 描述 |
|
||||
| ------------- | ------ | ---- | --------------------- |
|
||||
| id | String | 是 | 英文名称例如:status |
|
||||
| name | String | 否 | 中文名称 例如:状态 |
|
||||
| hierarchy_flg | String | 否 | 多级标志 0/1 是否多级 |
|
||||
|
||||
|
||||
|
||||
更新kv表
|
||||
|
||||
| 参数 | 类型 | 必填 | 描述 |
|
||||
| -------- | ------ | ---- | -------------- |
|
||||
| kv | String | 是 | 更新kv表 值为1 |
|
||||
| codeid | String | 否 | Code表中的id |
|
||||
| parentid | String | 否 | 父级id |
|
||||
| k | String | 否 | 键 |
|
||||
| v | String | 否 | 值 |
|
||||
|
||||
返回示例
|
||||
|
||||
```
|
||||
添加成功
|
||||
{
|
||||
"status": true,
|
||||
"msg": "update success"
|
||||
}
|
||||
添加失败
|
||||
{
|
||||
"status": False,
|
||||
"msg": "update failed"
|
||||
}
|
||||
```
|
||||
|
||||
### 编码查询
|
||||
|
||||
请求URL:
|
||||
|
||||
<http://47.93.12.75:8888/appcode/appCodesSearch.dspy>
|
||||
|
||||
请求示例
|
||||
|
||||
```
|
||||
查询code表时不需要参数
|
||||
返回data为[{},{},{}]
|
||||
|
||||
查询kv表
|
||||
{
|
||||
'kv': '1',
|
||||
'codeid': 'kv表中对应id'
|
||||
}
|
||||
```
|
||||
|
||||
请求参数说明
|
||||
|
||||
| 参数 | 类型 | 必填 | 描述 |
|
||||
| ---- | ------ | ----------------- | --------------- |
|
||||
| kv | String | 否/查询kv为必填项 | 查询kv表 值为1 |
|
||||
| id | String | 否/查询kv为必填项 | Code/kv表中的id |
|
||||
|
||||
返回示例
|
||||
|
||||
```
|
||||
查询成功
|
||||
{
|
||||
"status": True,
|
||||
"msg": "appCodes_kv search success",
|
||||
"data": app_code_result
|
||||
}
|
||||
查询失败
|
||||
{
|
||||
"status": False,
|
||||
"msg": "appCodes_kv search failed",
|
||||
"data": ""
|
||||
}
|
||||
|
||||
查询成功示例
|
||||
[
|
||||
{
|
||||
"parentid": null,
|
||||
"k": "0",
|
||||
"v": "未认证",
|
||||
"id": "8KxM0iIY",
|
||||
"codeid": "status"
|
||||
},
|
||||
{
|
||||
"parentid": null,
|
||||
"k": "1",
|
||||
"v": "认证",
|
||||
"id": "GZx0dzSd",
|
||||
"codeid": "status",
|
||||
"son": [
|
||||
{
|
||||
"parentid": "1",
|
||||
"k": "0",
|
||||
"v": "手机号",
|
||||
"id": "37HmJ8T7",
|
||||
"codeid": "status",
|
||||
"son": [
|
||||
{
|
||||
"parentid": "1-0",
|
||||
"k": "0",
|
||||
"v": "华南地区",
|
||||
"id": "eVF9aerQ",
|
||||
"codeid": "status"
|
||||
},
|
||||
{
|
||||
"parentid": "1-0",
|
||||
"k": "1",
|
||||
"v": "华中地区",
|
||||
"id": "j1rhnW6p",
|
||||
"codeid": "status"
|
||||
},
|
||||
{
|
||||
"parentid": "1-0",
|
||||
"k": "2",
|
||||
"v": "华北地区",
|
||||
"id": "Cr0nWLIU",
|
||||
"codeid": "status",
|
||||
"son": [
|
||||
{
|
||||
"parentid": "1-0-2",
|
||||
"k": "0",
|
||||
"v": "甘肃",
|
||||
"id": "Gnd5WA4b",
|
||||
"codeid": "status"
|
||||
},
|
||||
{
|
||||
"parentid": "1-0-2",
|
||||
"k": "1",
|
||||
"v": "内蒙古",
|
||||
"id": "FRHOrEep",
|
||||
"codeid": "status"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"parentid": "1",
|
||||
"k": "1",
|
||||
"v": "微信",
|
||||
"id": "f1MRJscT",
|
||||
"codeid": "status"
|
||||
},
|
||||
{
|
||||
"parentid": "1",
|
||||
"k": "2",
|
||||
"v": "QQ",
|
||||
"id": "m3M39BI8",
|
||||
"codeid": "status"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
123
b/appcode/编码表接口说明.txt
Normal file
123
b/appcode/编码表接口说明.txt
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
编码增加
|
||||
请求地址: http://47.93.12.75:8888/appcode/appCodesAdd.dspy
|
||||
|
||||
请求参数:
|
||||
`id` VARCHAR(32) 'id',
|
||||
`name` VARCHAR(255) '编码名称',
|
||||
`hierarchy_flg` VARCHAR(1) '多级标志',
|
||||
`del_flg` VARCHAR(1) DEFAULT '0' comment '删除标志',
|
||||
`create_at` TIMESTAMP comment '创建时间戳'
|
||||
|
||||
从code表开始添加 同时添加code_kv表 需要提交的字段
|
||||
{
|
||||
'id': '英文字段 例如:user_status',
|
||||
'name': '中文字段 例如: 用户状态',
|
||||
'hierarchy_flg': '层级 默认是 0',
|
||||
|
||||
# 以下data是同时添加到kv表中的内容
|
||||
'data':[
|
||||
{'codeid':'user_status', 'parentid': '123', 'k': '0', 'v': '在线'},
|
||||
{'codeid':'user_status', 'parentid': '123', 'k': '1', 'v': '未在线'}
|
||||
]
|
||||
}
|
||||
|
||||
单独添加code_kv表中字段需要提交的字段 kv和codeid为必填项
|
||||
{'kv': '1', 'codeid':'user_status', 'parentid': '123', 'k': '1', 'v': '休息中'}
|
||||
|
||||
|
||||
响应内容:
|
||||
增加成功:
|
||||
{
|
||||
"status": True,
|
||||
"msg": "app codes and appcodes_kv add success"
|
||||
}
|
||||
增加失败:
|
||||
{
|
||||
"status": False,
|
||||
"msg": "app codes and appcodes_kv add failed"
|
||||
}
|
||||
|
||||
|
||||
|
||||
编码删除
|
||||
请求地址: http://47.93.12.75:8888/appcode/appCodesDelete.dspy
|
||||
|
||||
请求参数:
|
||||
只删除kv表中对应字段对应参数 kv和id为必填项
|
||||
{'kv': '1', 'id': 'kv表对应id'}
|
||||
|
||||
删除code表中字段(同时把kv表对应字段删除) (kv不能为0, 置空或不添加)
|
||||
{'kv': '', 'id': 'code表中对应id'}
|
||||
|
||||
响应内容:
|
||||
删除成功:
|
||||
{
|
||||
"status": True,
|
||||
"msg": "appCodes delete success"
|
||||
}
|
||||
删除失败:
|
||||
{
|
||||
"status": False,
|
||||
"msg": "appCodes delete failed"
|
||||
}
|
||||
|
||||
|
||||
编码更新
|
||||
请求地址: http://47.93.12.75:8888/appcode/appCodesUpdate.dspy
|
||||
|
||||
请求参数:
|
||||
只更新kv表中对应字段对应参数 kv和id为必填项
|
||||
{'kv': '1', 'id': 'J9dAtdLP','codeid':'user_status', 'parentid': '123', 'k': '0', 'v': '在线'}
|
||||
|
||||
更新code表中字段(同时把kv表对应字段删除) id为必填项,(kv不能为0, 置空或不添加)
|
||||
{
|
||||
'kv': '',
|
||||
'id': 'user_status',
|
||||
'name': '客户状态',
|
||||
'hierarchy_flg': '0'
|
||||
}
|
||||
|
||||
响应内容:
|
||||
更新成功:
|
||||
{
|
||||
"status": True,
|
||||
"msg": "appcodes update success"
|
||||
}
|
||||
更新失败:
|
||||
{
|
||||
"status": False,
|
||||
"msg": "appcodes update failed"
|
||||
}
|
||||
|
||||
编码查询:
|
||||
|
||||
请求地址:
|
||||
|
||||
查询code:
|
||||
http://47.93.12.75:8888/appcode/appCodesSearch.dspy
|
||||
|
||||
|
||||
请求参数:
|
||||
查询code:
|
||||
查询code表时不需要参数
|
||||
|
||||
从code点击字段查询code_kv表: kv必填项 codeid为必填项
|
||||
{
|
||||
'kv': '1',
|
||||
'codeid': 'user_status'
|
||||
}
|
||||
|
||||
响应内容:
|
||||
查询成功:
|
||||
{
|
||||
"status": True,
|
||||
"msg": "appCodes_kv search success",
|
||||
"data": app_code_result
|
||||
}
|
||||
查询失败:
|
||||
{
|
||||
"status": False,
|
||||
"msg": "appCodes_kv search failed",
|
||||
"data": ""
|
||||
}
|
||||
27
b/apv/apv_business.dspy
Normal file
27
b/apv/apv_business.dspy
Normal file
@ -0,0 +1,27 @@
|
||||
async def apv_business(ns={}):
|
||||
try:
|
||||
data = {
|
||||
"id": ns.get("id", None),
|
||||
"business_name": ns["business_name"],
|
||||
"callback_url": ns["callback_url"],
|
||||
"role_level": ns.get("role_level"),
|
||||
}
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"参数解析错误,请检查参数:{e}"}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if data['id']:
|
||||
data['update_at'] = '{}'.format(datetime.datetime.now())
|
||||
num = await sor.U("apv_business", data)
|
||||
if num == 0:
|
||||
return {"status": False, "msg": "更新失败,数据未更改"}
|
||||
else:
|
||||
return {"status": True, "msg": "success"}
|
||||
else:
|
||||
data['id'] = uuid()
|
||||
await sor.C("apv_business", data)
|
||||
return {"status": True, "msg": "success", "data": data['id']}
|
||||
|
||||
|
||||
ret = await apv_business(params_kw)
|
||||
return ret
|
||||
25
b/apv/apv_template.dspy
Normal file
25
b/apv/apv_template.dspy
Normal file
@ -0,0 +1,25 @@
|
||||
async def apv_template(ns={}):
|
||||
try:
|
||||
data = {
|
||||
"id": ns.get("id", None),
|
||||
"business_id": ns["business_id"],
|
||||
"title_template": ns["title_template"],
|
||||
"detail_template": ns["detail_template"],
|
||||
}
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"参数解析错误,请检查参数:{e}"}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if data['id']:
|
||||
data['update_at'] = '{}'.format(datetime.datetime.now())
|
||||
num = await sor.U("apv_content_template", data)
|
||||
if num == 0:
|
||||
return {"status": False, "msg": "更新失败,数据未更改"}
|
||||
else:
|
||||
data['id'] = uuid()
|
||||
await sor.C("apv_content_template", data)
|
||||
return {"status": True, "msg": "success","data":data['id']}
|
||||
|
||||
|
||||
ret = await apv_template(params_kw)
|
||||
return ret
|
||||
233
b/apv/callback_apv.dspy
Normal file
233
b/apv/callback_apv.dspy
Normal file
@ -0,0 +1,233 @@
|
||||
class DingCallbackCrypto3:
|
||||
def __init__(self, token, encodingAesKey, key):
|
||||
self.encodingAesKey = encodingAesKey
|
||||
self.key = key
|
||||
self.token = token
|
||||
self.aesKey = base64.b64decode(self.encodingAesKey + '=')
|
||||
|
||||
## 生成回调处理完成后的success加密数据
|
||||
def getEncryptedMap(self, content):
|
||||
encryptContent = self.encrypt(content)
|
||||
timeStamp = str(int(datetime.datetime.now().timestamp()))
|
||||
nonce = self.generateRandomKey(16)
|
||||
sign = self.generateSignature(nonce, timeStamp, self.token, encryptContent)
|
||||
return {'msg_signature': sign, 'encrypt': encryptContent, 'timeStamp': timeStamp, 'nonce': nonce}
|
||||
|
||||
##解密钉钉发送的数据
|
||||
def getDecryptMsg(self, msg_signature, timeStamp, nonce, content):
|
||||
"""
|
||||
解密
|
||||
:param content:
|
||||
:return:
|
||||
"""
|
||||
sign = self.generateSignature(nonce, timeStamp, self.token, content)
|
||||
print(sign, msg_signature)
|
||||
if msg_signature != sign:
|
||||
raise ValueError('signature check error')
|
||||
# 对密文BASE64解码
|
||||
content = base64.decodebytes(content.encode('UTF-8')) ##钉钉返回的消息体
|
||||
|
||||
iv = self.aesKey[:16] ##初始向量
|
||||
aesDecode = AES.new(self.aesKey, AES.MODE_CBC, iv)
|
||||
decodeRes = aesDecode.decrypt(content)
|
||||
pad = int(decodeRes[-1])
|
||||
if pad > 32:
|
||||
raise ValueError('Input is not padded or padding is corrupt')
|
||||
decodeRes = decodeRes[:-pad]
|
||||
l = struct.unpack('!i', decodeRes[16:20])[0]
|
||||
##获取去除初始向量,四位msg长度以及尾部corpid
|
||||
nl = len(decodeRes)
|
||||
|
||||
if decodeRes[(20 + l):].decode() != self.key:
|
||||
raise ValueError('corpId 钉钉回调校验错误')
|
||||
return decodeRes[20:(20 + l)].decode()
|
||||
|
||||
def encrypt(self, content):
|
||||
"""
|
||||
加密
|
||||
:param content:
|
||||
:return:
|
||||
"""
|
||||
msg_len = self.length(content)
|
||||
content = ''.join([self.generateRandomKey(16), msg_len.decode(), content, self.key])
|
||||
contentEncode = self.pks7encode(content)
|
||||
iv = self.aesKey[:16]
|
||||
aesEncode = AES.new(self.aesKey, AES.MODE_CBC, iv)
|
||||
aesEncrypt = aesEncode.encrypt(contentEncode.encode('UTF-8'))
|
||||
return base64.encodebytes(aesEncrypt).decode('UTF-8')
|
||||
|
||||
### 生成回调返回使用的签名值
|
||||
def generateSignature(self, nonce, timestamp, token, msg_encrypt):
|
||||
info(f"{type(nonce)=}, {type(timestamp)=}, {type(token)=}, {type(msg_encrypt)=}")
|
||||
v = msg_encrypt
|
||||
signList = ''.join(sorted([nonce, timestamp, token, v]))
|
||||
return hashlib.sha1(signList.encode()).hexdigest()
|
||||
|
||||
def length(self, content):
|
||||
"""
|
||||
将msg_len转为符合要求的四位字节长度
|
||||
:param content:
|
||||
:return:
|
||||
"""
|
||||
l = len(content)
|
||||
return struct.pack('>l', l)
|
||||
|
||||
def pks7encode(self, content):
|
||||
"""
|
||||
安装 PKCS#7 标准填充字符串
|
||||
:param text: str
|
||||
:return: str
|
||||
"""
|
||||
l = len(content)
|
||||
output = io.StringIO()
|
||||
val = 32 - (l % 32)
|
||||
for _ in range(val):
|
||||
output.write('%02x' % val)
|
||||
# print "pks7encode",content,"pks7encode", val, "pks7encode", output.getvalue()
|
||||
return content + binascii.unhexlify(output.getvalue()).decode()
|
||||
|
||||
def pks7decode(self, content):
|
||||
nl = len(content)
|
||||
val = int(binascii.hexlify(content[-1]), 16)
|
||||
if val > 32:
|
||||
raise ValueError('Input is not padded or padding is corrupt')
|
||||
|
||||
l = nl - val
|
||||
return content[:l]
|
||||
|
||||
def generateRandomKey(self, size,
|
||||
chars=string.ascii_letters + string.ascii_lowercase + string.ascii_uppercase + string.digits):
|
||||
"""
|
||||
生成加密所需要的随机字符串
|
||||
:param size:
|
||||
:param chars:
|
||||
:return:
|
||||
"""
|
||||
return ''.join(random.choice(chars) for i in range(size))
|
||||
|
||||
|
||||
async def save_data(apv_id, finis_hTime, apv_status) -> str:
|
||||
"""
|
||||
保存审批回调数据
|
||||
:param apv_id: 审批id
|
||||
:param finis_hTime: 创建时间
|
||||
:param apv_status: 流程状态
|
||||
"""
|
||||
data = {
|
||||
"apv_id": apv_id,
|
||||
"apv_status": apv_status,
|
||||
"update_at": str(datetime.datetime.now())[:19],
|
||||
}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
sql = "update apv_data set apv_status = ${apv_status}$ , apv_finish_time=${update_at}$,update_at=${update_at}$ where apv_id = ${apv_id}$"
|
||||
await sor.sqlExe(sql, data)
|
||||
|
||||
data = {
|
||||
"id": uuid(),
|
||||
"apv_id": apv_id,
|
||||
"apv_status": apv_status,
|
||||
}
|
||||
await sor.C("apv_status_history", data)
|
||||
info("数据入库成功")
|
||||
|
||||
|
||||
async def get_key(oid: str) -> str:
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
sql = "select http_token,http_aes_key,app_key from apv_key where del_flg = '0' and orgid = ${oid}$"
|
||||
data = await sor.sqlExe(sql, {"oid": oid})
|
||||
if data:
|
||||
return data[0]
|
||||
else:
|
||||
raise f"oid:{oid},get key is null."
|
||||
|
||||
|
||||
# 内部回调
|
||||
async def call_back_inner(processInstanceId, status):
|
||||
"""
|
||||
内部回调
|
||||
:param processInstanceId: apv_id
|
||||
:param status: 审批状态
|
||||
:return:
|
||||
"""
|
||||
# get callback url
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
sql = "SELECT b.callback_url FROM apv_data d LEFT JOIN apv_business b ON d.business_id=b.id WHERE d.apv_id=${processInstanceId}$"
|
||||
data = await sor.sqlExe(sql, {"processInstanceId": processInstanceId})
|
||||
if len(data) == 0:
|
||||
info(f"钉钉内部回调获取失败:apv_id:{processInstanceId}")
|
||||
return 0
|
||||
data = data[0]
|
||||
url = data.get("callback_url") + f"?apv_id={processInstanceId}&status={status}"
|
||||
# url = "https://dev.kaiyuancloud.cn/account/addledgers.dspy?apv_id=ehV03fARQjqtT69piTFtzw07441693812206&status=agree"
|
||||
async with aiohttp_client.request("GET",url) as res:
|
||||
try:
|
||||
json_data = await res.json()
|
||||
info(f"apv_id:{processInstanceId},回调内部响应:{res.status},resp json:{json_data}")
|
||||
except Exception as e:
|
||||
info(f"apv_id:{processInstanceId},回调内部响应:{res.status},resp:{res.text}")
|
||||
|
||||
async def get_sender_by_apv_id(apv_id):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data = await sor.R("apv_data", {"apv_id": apv_id})
|
||||
if not data:
|
||||
return None
|
||||
else:
|
||||
return data[0]["user_id"]
|
||||
return None
|
||||
async def callback_apv(ns={}):
|
||||
"""
|
||||
审批回调
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
oid = ns.get("oid")
|
||||
if not oid:
|
||||
return "oid is None"
|
||||
|
||||
data = await get_key(oid)
|
||||
|
||||
token = password_decode(data["http_token"])
|
||||
aes_key = password_decode(data["http_aes_key"])
|
||||
key = password_decode(data["app_key"])
|
||||
|
||||
test = DingCallbackCrypto3(token, aes_key, key)
|
||||
|
||||
# 解密参数
|
||||
text = test.getDecryptMsg(msg_signature=ns.get("signature"), timeStamp=ns.get("timestamp"), nonce=ns.get("nonce"), content=ns.get("encrypt"))
|
||||
|
||||
text = json.loads(text)
|
||||
info(f"回调数据:{text}")
|
||||
t = text.get("type", None)
|
||||
if t != "finish":
|
||||
status = t
|
||||
else:
|
||||
status = text.get("result", t)
|
||||
|
||||
processInstanceId = text.get("processInstanceId",None)
|
||||
# 加密返回
|
||||
res = test.getEncryptedMap("success")
|
||||
|
||||
if processInstanceId:
|
||||
# 判断是否是 api 发起
|
||||
f = await get_sender_by_apv_id(processInstanceId)
|
||||
if not f:
|
||||
info(f"apv_id:{processInstanceId} is not use api")
|
||||
return res
|
||||
|
||||
# 保存数据
|
||||
await save_data(apv_id=processInstanceId, finis_hTime=text.get("finishTime"), apv_status=status)
|
||||
try:
|
||||
# 回调内部接口
|
||||
info(f"开始回调内部接口:{processInstanceId}")
|
||||
await call_back_inner(processInstanceId=processInstanceId, status=status)
|
||||
except Exception as e:
|
||||
info(f"回调内部接口失败:{e}")
|
||||
return res
|
||||
|
||||
|
||||
ret = await callback_apv(params_kw)
|
||||
return ret
|
||||
21
b/apv/delete_apv_business.dspy
Normal file
21
b/apv/delete_apv_business.dspy
Normal file
@ -0,0 +1,21 @@
|
||||
async def delete_apv_business(ns={}):
|
||||
try:
|
||||
data = {
|
||||
"id": ns["id"],
|
||||
"del_flg": ns["del_flg"],
|
||||
}
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"参数解析错误,请检查参数:{e}"}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data['update_at'] = '{}'.format(datetime.datetime.now())
|
||||
sql = "update apv_business set del_flg = ${del_flg}$,update_at = ${update_at}$ where id = ${id}$ and del_flg = 0"
|
||||
num = await sor.sqlExe(sql, data)
|
||||
if num == 0:
|
||||
return {"status": False, "msg": "删除失败,数据未更改"}
|
||||
else:
|
||||
return {"status": True, "msg": "success"}
|
||||
|
||||
|
||||
ret = await delete_apv_business(params_kw)
|
||||
return ret
|
||||
21
b/apv/delete_apv_template.dspy
Normal file
21
b/apv/delete_apv_template.dspy
Normal file
@ -0,0 +1,21 @@
|
||||
async def delete_apv_template(ns={}):
|
||||
try:
|
||||
data = {
|
||||
"id": ns["id"],
|
||||
"del_flg": ns["del_flg"],
|
||||
}
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"参数解析错误,请检查参数:{e}"}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data['update_at'] = '{}'.format(datetime.datetime.now())
|
||||
sql = "update apv_content_template set del_flg = ${del_flg}$, update_at = ${update_at}$ where id = ${id}$ and del_flg = 0"
|
||||
num = await sor.sqlExe(sql, data)
|
||||
if num == 0:
|
||||
return {"status": False, "msg": "删除失败,数据未更改"}
|
||||
else:
|
||||
return {"status": True, "msg": "success"}
|
||||
|
||||
|
||||
ret = await delete_apv_template(params_kw)
|
||||
return ret
|
||||
14
b/apv/get_apv_business.dspy
Normal file
14
b/apv/get_apv_business.dspy
Normal file
@ -0,0 +1,14 @@
|
||||
async def get_apv_business(ns={}):
|
||||
"""
|
||||
获取业务列表
|
||||
"""
|
||||
ns["del_flg"] = ns.get("del_flg", "0")
|
||||
ns["sort"] = ns.get("sort", "update_at desc")
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data = await sor.R("apv_business", ns)
|
||||
return {"status": True, "data": data}
|
||||
|
||||
|
||||
res = await get_apv_business(params_kw)
|
||||
return res
|
||||
36
b/apv/get_apv_flow.dspy
Normal file
36
b/apv/get_apv_flow.dspy
Normal file
@ -0,0 +1,36 @@
|
||||
# 获取审批流参数配置
|
||||
async def get_apv_flow(ns={}):
|
||||
orgid = ns.get("orgid")
|
||||
business_id = ns.get("business_id")
|
||||
if not orgid or not business_id:
|
||||
return {"status": False, "msg": "orgid or business_id is None"}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data = await sor.R("apv_flow", {"orgid": orgid, "del_flg": 0, "business_id": business_id})
|
||||
if not data:
|
||||
return {"status": True, "data":{}}
|
||||
flow = {}
|
||||
flow["orgid"] = data[0]["orgid"]
|
||||
flow["user_id"] = data[0]["user_id"]
|
||||
flow["dd_template_id"] = data[0]["dd_template_id"]
|
||||
flow["del_flg"] = data[0]["del_flg"]
|
||||
flow["levels"] = {}
|
||||
for i in data:
|
||||
l_id = str(i["level"])
|
||||
now_level = flow["levels"].get(l_id, None)
|
||||
if now_level:
|
||||
now_level["apv_dd_user_phone"][i["apv_dd_user_id_index"]] = i["apv_dd_user_phone"]
|
||||
now_level["mode"] = i["mode"]
|
||||
else:
|
||||
user_data = {
|
||||
"apv_dd_user_phone": {
|
||||
i["apv_dd_user_id_index"]: i["apv_dd_user_phone"]
|
||||
},
|
||||
"mode": i["mode"]
|
||||
}
|
||||
flow["levels"][l_id] = user_data
|
||||
data = flow
|
||||
return {"status": True, "data": data}
|
||||
|
||||
ret = await get_apv_flow(params_kw)
|
||||
return ret
|
||||
11
b/apv/get_apv_form.dspy
Normal file
11
b/apv/get_apv_form.dspy
Normal file
@ -0,0 +1,11 @@
|
||||
# 获取审批表单
|
||||
async def get_apv_form(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data = await sor.R('apv_form', {'del_flg': '0'})
|
||||
return {"status": True, "data": data}
|
||||
return {"status": False, "msg": "sql error"}
|
||||
|
||||
|
||||
ret = await get_apv_form(params_kw)
|
||||
return ret
|
||||
21
b/apv/get_apv_key.dspy
Normal file
21
b/apv/get_apv_key.dspy
Normal file
@ -0,0 +1,21 @@
|
||||
# 获取审批参数配置
|
||||
async def get_apv_key(ns={}):
|
||||
orgid = ns.get('orgid')
|
||||
if not orgid:
|
||||
return {"status": False, "data": [], "msg": "orgid is null."}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data = await sor.R('apv_key', {'orgid': orgid, 'del_flg': '0'})
|
||||
if not data:
|
||||
return {"status": False, "data": [], "msg": "get key is null."}
|
||||
data = data[0]
|
||||
data["app_key"] = password_decode(data["app_key"])
|
||||
data["app_secret"] = password_decode(data["app_secret"])
|
||||
data["http_aes_key"] = password_decode(data["http_aes_key"])
|
||||
data["http_token"] = password_decode(data["http_token"])
|
||||
return {"status": True, "data": data}
|
||||
return {"status": False, "data": [], "msg": "sql error"}
|
||||
|
||||
ret = await get_apv_key(params_kw)
|
||||
return ret
|
||||
14
b/apv/get_apv_list.dspy
Normal file
14
b/apv/get_apv_list.dspy
Normal file
@ -0,0 +1,14 @@
|
||||
# 获取审批列表
|
||||
async def get_apv_list(ns={}):
|
||||
user_id = ns.get("user_id")
|
||||
if not user_id:
|
||||
return {"status": False, "msg": "user_id is None"}
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data = await sor.R("apv_data", {"user_id": user_id, "del_flg": 0, "sort": "update_at desc"})
|
||||
return {"status": True, "data": data}
|
||||
|
||||
|
||||
ret = await get_apv_list(params_kw)
|
||||
return ret
|
||||
17
b/apv/get_apv_template.dspy
Normal file
17
b/apv/get_apv_template.dspy
Normal file
@ -0,0 +1,17 @@
|
||||
# 获取审批列表
|
||||
async def get_apv_template(ns={}):
|
||||
business_id = ns.get("business_id")
|
||||
if not business_id:
|
||||
return {"status": False, "msg": "business_id is None"}
|
||||
|
||||
ns["del_flg"] = ns.get("del_flg", "0")
|
||||
ns["sort"] = ns.get("sort", "update_at desc")
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data = await sor.R("apv_content_template", ns)
|
||||
return {"status": True, "data": data}
|
||||
|
||||
|
||||
ret = await get_apv_template(params_kw)
|
||||
return ret
|
||||
56
b/apv/index.html
Normal file
56
b/apv/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
71
b/apv/save_apv_flow.dspy
Normal file
71
b/apv/save_apv_flow.dspy
Normal file
@ -0,0 +1,71 @@
|
||||
|
||||
async def save_apv_flow(ns={}):
|
||||
flag = ns.get("flag", "").lower()
|
||||
if flag not in ["add", "update"]:
|
||||
return {"status": False, "msg": f"参数解析错误,请检查参数:flag"}
|
||||
db = DBPools()
|
||||
try:
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
user_id = ns["user_id"]
|
||||
orgid = ns["orgid"]
|
||||
business_id = ns["business_id"]
|
||||
level_data = ns["level_data"]
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"参数解析错误,请检查参数:{e}"}
|
||||
if not isinstance(level_data, list):
|
||||
return {"status": False, "msg": f"参数类型错误,请检查参数:{level_data}"}
|
||||
for _f, l in enumerate(level_data):
|
||||
try:
|
||||
level_mode = l["level_mode"]
|
||||
apv_dd_user_phone = l["apv_dd_user_phone"]
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"参数解析错误,请检查参数:{e}"}
|
||||
if not isinstance(apv_dd_user_phone, list):
|
||||
return {"status": False, "msg": f"参数类型错误,请检查参数:{apv_dd_user_phone}"}
|
||||
if len(apv_dd_user_phone) == 1 and level_mode != "NONE":
|
||||
return {"status": False, "msg": f"审核模式错误,一个审批人必须为'单人审批'"}
|
||||
|
||||
for _f, l in enumerate(level_data):
|
||||
level_id = l["level_id"]
|
||||
level_mode = l["level_mode"]
|
||||
apv_dd_user_phone = l["apv_dd_user_phone"]
|
||||
for i, p in enumerate(apv_dd_user_phone):
|
||||
|
||||
# 通过手机号获取发送人userid
|
||||
resp = await get_id_by_phone(orgid=orgid, phone=p)
|
||||
info(f"get_id_by_phone_resp:{resp}")
|
||||
if not resp['status']:
|
||||
return {"status": False, "msg": f"钉钉用户id获取失败,请检查手机号:{p}"}
|
||||
|
||||
dd_user_id = resp['user_id']
|
||||
data = {
|
||||
"user_id": user_id, # '用户id',
|
||||
"orgid": orgid, # '机构id',
|
||||
"business_id": business_id, # '业务id',
|
||||
"level": level_id, # '节点级别',
|
||||
"mode": level_mode, # 节点审核模式,会签:AND;或签:OR;单人:NONE',
|
||||
"apv_dd_user_id_index": i, # '节点审核人员id index',
|
||||
"apv_dd_user_id": dd_user_id, # '节点审核人员id',
|
||||
"apv_dd_user_phone":p # '节点审核人员手机号',
|
||||
|
||||
}
|
||||
|
||||
if flag == "update":
|
||||
if _f == 0 and i == 0:
|
||||
sql = "update apv_flow set del_flg = 1 ,update_at=${update_at}$ where orgid=${orgid}$ and business_id=${business_id}$"
|
||||
await sor.sqlExe(sql, {"orgid": orgid, "update_at": f"{datetime.datetime.now()}", "business_id": business_id})
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
data["id"] = uuid()
|
||||
await sor.C("apv_flow", data)
|
||||
return {"status": True, "msg": "保存成功"}
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"数据库操作失败:{e}"}
|
||||
return {"status": False, "msg": f"数据库操作失败"}
|
||||
|
||||
|
||||
ret = await save_apv_flow(params_kw)
|
||||
return ret
|
||||
31
b/apv/save_apv_key.dspy
Normal file
31
b/apv/save_apv_key.dspy
Normal file
@ -0,0 +1,31 @@
|
||||
# 保存审批参数配置
|
||||
async def save_apv_key(ns={}):
|
||||
_f = ns.get("flag")
|
||||
try:
|
||||
data = {
|
||||
"id": ns.get('id'),
|
||||
"user_id": ns["user_id"], # 用户id
|
||||
"orgid": ns["orgid"], # 机构id
|
||||
"source": ns["source"], # key所属公司
|
||||
"app_key": password_encode(ns["app_key"]), # 应用凭证key
|
||||
"app_secret": password_encode(ns["app_secret"]), # 应用凭证secret
|
||||
"http_aes_key": password_encode(ns["http_aes_key"]), # 加密aes_key
|
||||
"http_token": password_encode(ns["http_token"]), # 签名token
|
||||
}
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"参数解析错误,请检查参数:{e}"}
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if _f == "add":
|
||||
data["id"] = uuid()
|
||||
await sor.C("apv_key", data)
|
||||
elif _f == "update":
|
||||
data["update_time"] = "{}".format(datetime.datetime.now())
|
||||
await sor.U("apv_key", data)
|
||||
else:
|
||||
return {"status": False, "msg": "flag is error"}
|
||||
return {"status": True, "msg": "success"}
|
||||
|
||||
|
||||
ret = await save_apv_key(params_kw)
|
||||
return ret
|
||||
46
b/apv/send_key_create.dspy
Normal file
46
b/apv/send_key_create.dspy
Normal file
@ -0,0 +1,46 @@
|
||||
def get_process_code(url):
|
||||
process_code = url.split('processCode')[-1].replace("%3D", "").replace("=", "")
|
||||
# if len(process_code) != 41:
|
||||
# return None
|
||||
return process_code
|
||||
|
||||
|
||||
# 保存审批参数配置
|
||||
async def send_key_create(ns={}):
|
||||
process_code = get_process_code(ns.get("process_code"))
|
||||
if not process_code:
|
||||
return {"status": False, "msg": "process_code,参数错误"}
|
||||
|
||||
try:
|
||||
data = {
|
||||
"id": ns["id"],
|
||||
"user_id": ns["user_id"], # 用户id
|
||||
"orgid": ns["orgid"], # 机构id
|
||||
"send_dd_user_phone": ns["send_phone"], # 发送人的钉钉id
|
||||
"source": ns["source"], # key所属公司
|
||||
"business_id": ns["business_id"], # 业务id
|
||||
"process_code": process_code, # 钉钉审批模板id
|
||||
"process_name": ns["process_name"], # 钉钉表单名字
|
||||
}
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"参数解析错误,请检查参数:{e}"}
|
||||
|
||||
# 通过手机号获取发送人userid
|
||||
resp = await get_id_by_phone(orgid=ns["orgid"], phone=ns["send_phone"])
|
||||
if not resp['status']:
|
||||
return {"status": False, "msg": f"{resp['msg']}\n钉钉用户id获取失败,请检查手机号:{ns['send_phone']}"}
|
||||
data['send_dd_user_id'] = resp['user_id']
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if data['id']:
|
||||
data["update_time"] = "{}".format(datetime.datetime.now())
|
||||
await sor.U("apv_send_key", data)
|
||||
else:
|
||||
data["id"] = uuid()
|
||||
await sor.C("apv_send_key", data)
|
||||
return {"status": True, "msg": "success"}
|
||||
|
||||
|
||||
ret = await send_key_create(params_kw)
|
||||
return ret
|
||||
21
b/apv/send_key_select.dspy
Normal file
21
b/apv/send_key_select.dspy
Normal file
@ -0,0 +1,21 @@
|
||||
# 获取审批流发送参数配置
|
||||
async def send_key_select(ns={}):
|
||||
try:
|
||||
orgid = ns["orgid"]
|
||||
business_id = ns["business_id"]
|
||||
except Exception as e:
|
||||
return {"status": False, "msg": f"servers get key error, please check key:{str(e)}"}
|
||||
db = DBPools()
|
||||
data = {}
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
data = await sor.R("apv_send_key", {"orgid": orgid, "del_flg": 0, "business_id": business_id})
|
||||
if not data:
|
||||
return {"status": False, "msg": "未找到发送参数配置"}
|
||||
data = data[0]
|
||||
return {"status": True, "data": data}
|
||||
|
||||
return {"status": False, "msg": "sql error"}
|
||||
|
||||
|
||||
ret = await send_key_select(params_kw)
|
||||
return ret
|
||||
516
b/baiduc/baidu_confirm_refund_order.dspy
Normal file
516
b/baiduc/baidu_confirm_refund_order.dspy
Normal file
@ -0,0 +1,516 @@
|
||||
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 == 'REFUND':
|
||||
# 找到资源并更新时间
|
||||
resource_find_sql = """select id from customer_goods where resourceid = '%s';""" % 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, 'del_flg': '1'})
|
||||
|
||||
# 处理续费逻辑
|
||||
elif 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:
|
||||
await sor.rollback()
|
||||
raise error
|
||||
|
||||
async def get_baidu_orderlist(ns={}):
|
||||
"""
|
||||
百度支付
|
||||
1、获取订单
|
||||
2、算出购买的产品折扣
|
||||
3、比对账号余额
|
||||
"""
|
||||
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']
|
||||
|
||||
# 可能获取得到的是延迟订单
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] != 'CREATED':
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'delay_order'
|
||||
}
|
||||
|
||||
# 避免重复退订
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] == 'CREATED':
|
||||
order_history = await sor.R('bz_order', {'provider_orderid': ns.get('order_id'), 'business_op': 'BUY_REVERSE', 'order_status': '1'})
|
||||
if order_history:
|
||||
print('此订单之前已经退费成功')
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '此订单之前已经退费成功'
|
||||
}
|
||||
|
||||
# 如果是退款 更新数据库状态
|
||||
if orders[0]['type'] == 'REFUND':
|
||||
updatetime = await time_convert(orders[0]['updateTime']) if orders[0].get('updateTime') else None
|
||||
update_refund_sql = """UPDATE baidu_orders SET price = '%s', status = '%s', updatetime = '%s' WHERE orderid = '%s';""" % \
|
||||
(float(orders[0]['price']), orders[0]['status'], updatetime, ns.get('order_id'))
|
||||
await sor.sqlExe(update_refund_sql, {})
|
||||
|
||||
# 判断订单item中productType是否有后付费的产品
|
||||
for item in orders:
|
||||
order_items = item['orderItems']
|
||||
for order_info in order_items:
|
||||
postpay_price = order_info['itemFee']['price'] if order_info.get('itemFee') else order_info['catalogPrice']
|
||||
if order_info['productType'] == 'postpay' and postpay_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': '支付形式目前仅包含购买,续费,退订'
|
||||
}
|
||||
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['catalogPrice']
|
||||
financePrice = abs(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'] = abs(i['realCatalogPrice'] / i['count'])
|
||||
else:
|
||||
nss['list_price'] = abs(i['realCatalogPrice'])
|
||||
nss['discount'] = product_salemode[0]['discount']
|
||||
nss['quantity'] = i['count']
|
||||
nss['price'] = abs(round(nss['list_price'] * product_salemode[0]['discount'], 2))
|
||||
# 计算总价
|
||||
# nss['amount'] = round(total_price, 2)
|
||||
nss['amount'] = abs(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 order_type == 'REFUND':
|
||||
count = total_price + 0.1
|
||||
|
||||
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': '支付错误, 请联系售后'
|
||||
}
|
||||
|
||||
# 预配置local_refund用于本地操作
|
||||
if order_type == 'REFUND' and not ns.get('local_refund'):
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '本地退费成功'
|
||||
}
|
||||
else:
|
||||
# 调用支付订单接口
|
||||
# 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()
|
||||
|
||||
async def baidu_confirm_refund_order(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
refund_status_li = await sor.R('baidu_orders', {'orderid': ns.get('order_id')})
|
||||
refundstatus = refund_status_li[0]['refundstatus']
|
||||
refund_id = refund_status_li[0]['id']
|
||||
|
||||
if not refundstatus:
|
||||
# data_ = {}
|
||||
# 调用支付订单接口
|
||||
paydata = {'queryAccountId': ns.get('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': 'REFUND',
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '远程退款成功'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await sor.U('baidu_orders', {'id': refund_id, 'refundstatus': '1'})
|
||||
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(10)
|
||||
else:
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': 'REFUND',
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '产品退费失败, %s' % str(data_)[:400]
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品退款出错!%s' % str(data_)[:400]
|
||||
}
|
||||
|
||||
if refundstatus == '2':
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '已退款成功'
|
||||
}
|
||||
|
||||
# 获取created状态后再去退款
|
||||
local_refund_status = await get_baidu_orderlist({'order_id': ns.get('order_id'), 'userid': ns.get('user_id')})
|
||||
print('local_refund_status', local_refund_status)
|
||||
if local_refund_status.get('status'):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
await sor.U('baidu_orders', {'id': refund_id, 'refundstatus': '2'})
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '百度云给平台退款成功,平台给客户退款成功'
|
||||
}
|
||||
else:
|
||||
if local_refund_status.get('msg') == 'delay_order':
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '百度远程订单还未生成, 请十秒后重试'
|
||||
}
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '百度云退款成功,本机构给客户退款出错!'
|
||||
}
|
||||
|
||||
ret = await baidu_confirm_refund_order(params_kw)
|
||||
return ret
|
||||
29
b/baiduc/baidu_kafka_ca.pem
Normal file
29
b/baiduc/baidu_kafka_ca.pem
Normal file
@ -0,0 +1,29 @@
|
||||
Bag Attributes
|
||||
friendlyName: caroot
|
||||
2.16.840.1.113894.746875.1.1: <Unsupported tag 6>
|
||||
subject=/C=CN/ST=beijing/L=beijing/O=Beijing Baidu Netcom Science Technology Co., Ltd/OU=bms for kafka/CN=baidubce.com/emailAddress=kafka@baidu.com
|
||||
issuer=/C=CN/ST=beijing/L=beijing/O=Beijing Baidu Netcom Science Technology Co., Ltd/OU=bms for kafka/CN=baidubce.com/emailAddress=kafka@baidu.com
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIID9jCCAt4CCQCoWDtChH/MajANBgkqhkiG9w0BAQsFADCBuzELMAkGA1UEBhMC
|
||||
Q04xEDAOBgNVBAgMB2JlaWppbmcxEDAOBgNVBAcMB2JlaWppbmcxOTA3BgNVBAoM
|
||||
MEJlaWppbmcgQmFpZHUgTmV0Y29tIFNjaWVuY2UgVGVjaG5vbG9neSBDby4sIEx0
|
||||
ZDEWMBQGA1UECwwNYm1zIGZvciBrYWZrYTEVMBMGA1UEAwwMYmFpZHViY2UuY29t
|
||||
MR4wHAYJKoZIhvcNAQkBFg9rYWZrYUBiYWlkdS5jb20wIBcNMjIwMjA3MDM0MTIw
|
||||
WhgPMjEyMjAxMTQwMzQxMjBaMIG7MQswCQYDVQQGEwJDTjEQMA4GA1UECAwHYmVp
|
||||
amluZzEQMA4GA1UEBwwHYmVpamluZzE5MDcGA1UECgwwQmVpamluZyBCYWlkdSBO
|
||||
ZXRjb20gU2NpZW5jZSBUZWNobm9sb2d5IENvLiwgTHRkMRYwFAYDVQQLDA1ibXMg
|
||||
Zm9yIGthZmthMRUwEwYDVQQDDAxiYWlkdWJjZS5jb20xHjAcBgkqhkiG9w0BCQEW
|
||||
D2thZmthQGJhaWR1LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
|
||||
AMAKI035kiy13ECzuHtCXcGybMg2AVsD+auSLHlRncPYB/UaUYM6/eKejEpMgNSk
|
||||
j/wG+mKmmdt0IY8RUEscOTvVW8TMtpgNib0ALIUWR4CwHjvxJ+y3WV6dqyeUVvIL
|
||||
CUqeNwFMnC7tEnOutuwEGglQXHjo+zmcPvc9Xk2CdF8SHyaaU1QUoRLJd6qHZ7Xr
|
||||
/4lC9L+XMrjqzYkXs2dY/2fRbavlOcvETghSavTxKatjpzf7jn/A+s7iYyL9vqQY
|
||||
Tmm1HVQ2P2ek56uyE4lbiIkMww5r4OIlWKI/OVSAVMKoBt8MOt8DI1o952xyeqMA
|
||||
NbB8f0Tc1GLm/cGDO2OLmT8CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAKA1lULGQ
|
||||
poYAbskctj8IBwGqSgyZYECP4OeYLgBdev44MMjRgOiDH4H37+69SIJaOql0WnRt
|
||||
3jrwSznfdjKRZJSzSZ51DcZqBZYP3JfSx/0XG/YwS5yDGo3q8S2DLbcEe8yS7l0q
|
||||
fo7rnMGeLVTsWwpzXIQZY1Ev4ibcgDm+ZOaEvdK/fqbBQ8sQtavDErVHzkOa3U+C
|
||||
pL9bBciKXwS6gpsEPeuATtV+fAOzprlKPVTL2n1vVx1zNNlWgSwW2mPof96d+hRI
|
||||
7aaGF+4luaZ7DC3fxOcIFDmUPA2aJFSs8HnsLV13yvAX3eS8GH0CLgEG+xcXhKYz
|
||||
7DqKOrjwB+QuWQ==
|
||||
-----END CERTIFICATE-----
|
||||
129
b/baiduc/baidu_new_update_resouce.dspy
Normal file
129
b/baiduc/baidu_new_update_resouce.dspy
Normal file
@ -0,0 +1,129 @@
|
||||
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 baidu_new_update_resouce(ns={}):
|
||||
"""
|
||||
百度新购订单刷新定时器
|
||||
用于解决NEED_CONFIRM后订单刷新不及时 不能获取资源ID 资源起始日期的问题
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
crontab_list = await sor.R('baidu_cron_job', {'source': 'baidu', 'ordertype': 'NEW', 'reason': 'buy success', 'refresh': '0'})
|
||||
for cronjob in crontab_list:
|
||||
order_id = cronjob['orderid']
|
||||
userid = cronjob['userid']
|
||||
baidu_users = await sor.R('baidu_users', {'user_id': userid,'del_flg':'0'})
|
||||
# user = await sor.R('users', {'id': userid})
|
||||
# orgid = await sor.R('organization', {'id': user[0]['orgid']})
|
||||
nss = {'uuids': [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()
|
||||
with open('baidu_new_order_after_confirm.txt', 'a+') as f:
|
||||
f.write(json.dumps(data_) + '\n')
|
||||
orders = data_['orders']
|
||||
|
||||
for item in orders:
|
||||
order_items = item['orderItems']
|
||||
for order_info in order_items:
|
||||
resourceids = ','.join(order_info['shortIds']) if order_info.get('shortIds') else ''
|
||||
if not resourceids:
|
||||
ns_cron_job = {
|
||||
'id': cronjob['id'],
|
||||
'feedback': '没有获取到资源ID'
|
||||
}
|
||||
await sor.U('baidu_cron_job', ns_cron_job)
|
||||
return
|
||||
resourcestarttime = await time_convert(order_info.get('resourceStartTime')) if order_info.get(
|
||||
'resourceStartTime') else None
|
||||
resourceendtime = await time_convert(order_info.get('resourceEndTime')) if order_info.get(
|
||||
'resourceEndTime') else None
|
||||
|
||||
order_key = order_info['key']
|
||||
if resourceendtime:
|
||||
update_order_goods_sql = """ UPDATE order_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceids = '%s',
|
||||
og.resourcestarttime = '%s',
|
||||
og.resourceendtime = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, resourceendtime, order_key, order_id)
|
||||
else:
|
||||
update_order_goods_sql = """ UPDATE order_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceids = '%s',
|
||||
og.resourcestarttime = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, order_key, order_id)
|
||||
|
||||
await sor.sqlExe(update_order_goods_sql, {})
|
||||
if resourceendtime:
|
||||
update_customer_goods_sql = """ UPDATE customer_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceid = '%s',
|
||||
og.start_date = '%s',
|
||||
og.expire_date = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, resourceendtime, order_key, order_id)
|
||||
else:
|
||||
update_customer_goods_sql = """ UPDATE customer_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceid = '%s',
|
||||
og.start_date = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, order_key, order_id)
|
||||
|
||||
await sor.sqlExe(update_customer_goods_sql, {})
|
||||
|
||||
ns_cron_job = {
|
||||
'id': cronjob['id'],
|
||||
'refresh': '1',
|
||||
'feedback': 'success'
|
||||
}
|
||||
await sor.U('baidu_cron_job', ns_cron_job)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'update success'
|
||||
}
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '没有找到需要更新数据'
|
||||
}
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': str(e)
|
||||
}
|
||||
|
||||
ret = await baidu_new_update_resouce(params_kw)
|
||||
return ret
|
||||
403
b/baiduc/baidu_order_process.dspy
Normal file
403
b/baiduc/baidu_order_process.dspy
Normal file
@ -0,0 +1,403 @@
|
||||
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 == 'REFUND':
|
||||
# 找到资源并更新时间
|
||||
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, 'del_flg': '1'})
|
||||
|
||||
# 处理续费逻辑
|
||||
elif 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 baidu_order_process(ns={}):
|
||||
"""
|
||||
百度支付
|
||||
1、获取订单
|
||||
2、算出购买的产品折扣
|
||||
3、比对账号余额
|
||||
"""
|
||||
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': '支付形式目前仅包含购买,续费,退订'
|
||||
}
|
||||
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 = abs(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'] = abs(i['realCatalogPrice'] / i['count'])
|
||||
else:
|
||||
nss['list_price'] = abs(i['realCatalogPrice'])
|
||||
nss['discount'] = product_salemode[0]['discount']
|
||||
nss['quantity'] = i['count']
|
||||
nss['price'] = abs(round(nss['list_price'] * product_salemode[0]['discount'], 2))
|
||||
# 计算总价
|
||||
# nss['amount'] = round(total_price, 2)
|
||||
nss['amount'] = abs(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 order_type == 'REFUND':
|
||||
count = total_price + 0.1
|
||||
|
||||
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 baidu_order_process(params_kw)
|
||||
return ret
|
||||
47
b/baiduc/baidu_resource_query.dspy
Normal file
47
b/baiduc/baidu_resource_query.dspy
Normal file
@ -0,0 +1,47 @@
|
||||
async def baidu_resource_query(ns={}):
|
||||
"""
|
||||
用户资源查询
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
userid = ns.get('userid')
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
baiduids = await sor.R('baidu_users', {'user_id': userid})
|
||||
if baiduids:
|
||||
baiduid = baiduids[0]['baidu_id']
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'User not synchronized'
|
||||
}
|
||||
ns['queryAccountId'] = baiduid
|
||||
ns['pageSize'] = 200
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/resource/query?%s' % ns_format
|
||||
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=ns) as res:
|
||||
result = await res.json()
|
||||
result_new = []
|
||||
for i in result['result']:
|
||||
if i.get('status') != 'STOPPED':
|
||||
result_new.append(i)
|
||||
|
||||
result['result'] = result_new
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get resource success',
|
||||
'data': result
|
||||
}
|
||||
|
||||
ret = await baidu_resource_query(params_kw)
|
||||
return ret
|
||||
152
b/baiduc/baidu_sms_kafka_consumer.dspy
Normal file
152
b/baiduc/baidu_sms_kafka_consumer.dspy
Normal file
@ -0,0 +1,152 @@
|
||||
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 baidu_sms_kafka_consumer(ns={}):
|
||||
consumer = BaiduKafKaConsumer({
|
||||
# 接入点
|
||||
'bootstrap.servers': '120.48.10.223:9095,180.76.96.108:9095,180.76.147.36:9095',
|
||||
# 接入协议
|
||||
'security.protocol': 'SASL_SSL',
|
||||
'ssl.endpoint.identification.algorithm': 'none',
|
||||
# 证书文件路径
|
||||
'ssl.ca.location': 'baidu_kafka_ca.pem',
|
||||
# SASL 机制
|
||||
'sasl.mechanism': 'SCRAM-SHA-512',
|
||||
# SASL 用户名
|
||||
'sasl.username': 'kaiyuanyun',
|
||||
# SASL 用户密码
|
||||
'sasl.password': 'Kyy250609#',
|
||||
# 消费组id
|
||||
'group.id': 'kaiyuanyun_msg_group',
|
||||
'auto.offset.reset': 'latest',
|
||||
'fetch.message.max.bytes': '1024*512',
|
||||
})
|
||||
|
||||
# 订阅的主题名称
|
||||
consumer.subscribe(['kaiyuanyun_msg_topic'])
|
||||
|
||||
for i in range(30):
|
||||
msg = consumer.poll(0.1) # 单次轮询获取消息
|
||||
|
||||
if msg is None:
|
||||
continue
|
||||
elif msg.error():
|
||||
print(f"消费者错误: {msg.error()}")
|
||||
else:
|
||||
try:
|
||||
# 解析消息内容为字典(避免变量名冲突)
|
||||
msg_data_ori = json.loads(msg.value().decode('utf-8'))
|
||||
msg_data = msg_data_ori['messages'][0]
|
||||
messageid = msg_data.get('id')
|
||||
taskid = msg_data.get('taskId')
|
||||
|
||||
filename = 'baidu_kafka_msg.txt'
|
||||
# 检查文件是否存在,不存在则创建
|
||||
if not os.path.exists(filename):
|
||||
with open(filename, 'w', encoding='utf-8') as f:
|
||||
print(f"文件不存在,已创建 {filename}")
|
||||
|
||||
# 读取文件内容进行检查
|
||||
with open(filename, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
if messageid in content:
|
||||
print(f"文件中已存在 '{messageid}',跳过写入")
|
||||
continue
|
||||
else:
|
||||
# 追加写入目标内容
|
||||
with open(filename, 'a', encoding='utf-8') as f:
|
||||
f.write(messageid + '\n')
|
||||
print(f"已写入 '{messageid}' 到文件")
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 1. 去重检查(messageid和taskid)
|
||||
exist_msg = await sor.R('baidu_kafka_msg', {'messageid': messageid, 'taskid': taskid})
|
||||
if exist_msg:
|
||||
print(f"消息id {messageid} 已存在,跳过处理")
|
||||
consumer.close()
|
||||
return
|
||||
|
||||
# 2. 构建小写key的ns字典(完整映射所有字段)
|
||||
ns_msg = {
|
||||
'id': uuid(),
|
||||
'messageid': messageid,
|
||||
'taskid': taskid,
|
||||
'userid': msg_data.get('userId'),
|
||||
'accountid': msg_data.get('accountId'),
|
||||
'usertype': msg_data.get('userType'),
|
||||
'receiverid': msg_data.get('receiverId'),
|
||||
'contentvar': msg_data.get('contentVar'),
|
||||
'sendchannel': msg_data.get('sendChannel'),
|
||||
'content': msg_data.get('content'),
|
||||
'messagetemplateid': msg_data.get('messageTemplateId'),
|
||||
'isvirtualstore': msg_data.get('isVirtualStore'),
|
||||
'channelmessageid': msg_data.get('channelMessageId'),
|
||||
'channelstatus': msg_data.get('channelStatus'),
|
||||
'majorcategory': msg_data.get('majorCategory'),
|
||||
'minorcategory': msg_data.get('minorCategory'),
|
||||
'status': msg_data.get('status'),
|
||||
'createtime': await time_convert(msg_data.get('createTime')) if msg_data.get('createTime') else None,
|
||||
'updatetime': await time_convert(msg_data.get('updateTime')) if msg_data.get('updateTime') else None,
|
||||
'expiretime': await time_convert(msg_data.get('expireTime')) if msg_data.get('expireTime') else None,
|
||||
'windowtime': await time_convert(msg_data.get('windowTime')) if msg_data.get('windowTime') else None,
|
||||
'valid': msg_data.get('valid'),
|
||||
'complete': msg_data.get('complete'),
|
||||
'disturbhold': msg_data.get('disturbHold'),
|
||||
'sendcomplete': msg_data.get('sendComplete')
|
||||
}
|
||||
|
||||
# 3. 执行存库
|
||||
await sor.C('baidu_kafka_msg', ns_msg)
|
||||
print(f"消息id {messageid} 存储成功")
|
||||
|
||||
# 4. 触发短信发送(当sendChannel为MOBILE时)
|
||||
send_channel = msg_data.get('sendChannel')
|
||||
if send_channel == 'MOBILE':
|
||||
msg_content = msg_data.get('content')
|
||||
|
||||
# 判断验证码类短信 | 通知类短信
|
||||
if '验证码' in msg_content:
|
||||
sms_stype = '百度kafka普通验证码'
|
||||
else:
|
||||
sms_stype = '百度kafka普通通知'
|
||||
|
||||
# 查询用户手机号
|
||||
account_id = msg_data.get('accountId')
|
||||
user_local_id_li = await sor.R('baidu_users', {'baidu_id': account_id})
|
||||
user_local_id = user_local_id_li[0]['user_id']
|
||||
user_mobile_li = await sor.R('users', {'id': user_local_id, 'del_flg': '0'})
|
||||
mobile = user_mobile_li[0]['mobile']
|
||||
|
||||
# 调用短信发送接口
|
||||
kyy_send_status = await send_vcode(mobile, sms_stype, {'content': msg_content})
|
||||
if kyy_send_status.get('status'):
|
||||
await sor.U('baidu_kafka_msg', {'id': ns_msg['id'], 'kyysendstatus': '1'})
|
||||
print(f"已触发短信发送至 {mobile}")
|
||||
|
||||
except json.JSONDecodeError:
|
||||
print("错误:消息内容非有效JSON")
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '错误:消息内容非有效JSON'
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"处理异常: {str(e)}")
|
||||
return {
|
||||
'status': False,
|
||||
'msg': f"处理异常: {str(e)}"
|
||||
}
|
||||
|
||||
consumer.close() # 确保消费者关闭
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '获取信息执行结束'
|
||||
}
|
||||
|
||||
ret = await baidu_sms_kafka_consumer(params_kw)
|
||||
return ret
|
||||
666
b/baiduc/baidu_users_get_post_pay.dspy
Normal file
666
b/baiduc/baidu_users_get_post_pay.dspy
Normal file
@ -0,0 +1,666 @@
|
||||
async def resource_offline(ns={}):
|
||||
# ns = {
|
||||
# "accountId": "139fc7a23b314596ad78b6bb8e7c1503",
|
||||
# "service": "EIP",
|
||||
# "region": "bj"
|
||||
# }
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/resource/opt/offline?%s' % ns_format
|
||||
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=ns) as res:
|
||||
data_ = await res.json()
|
||||
print('下线返回结果, ', data_)
|
||||
|
||||
async def resource_online(ns={}):
|
||||
# ns = {
|
||||
# "accountId": "139fc7a23b314596ad78b6bb8e7c1503",
|
||||
# "service": "EIP",
|
||||
# "region": "bj"
|
||||
# }
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/resource/opt/online?%s' % ns_format
|
||||
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=ns) as res:
|
||||
data_ = await res.json()
|
||||
print('上线返回结果, ', data_)
|
||||
|
||||
async def get_valid_admin_person(nss={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 查找客户所在的机构
|
||||
who_is_org = (await sor.R('organization', {'id': nss['customerid']}))[0]['parentid']
|
||||
# 查找销售的电话
|
||||
saleman_phone = 0
|
||||
saleman_id_li = await sor.R('customer', {'customerid': nss['customerid'], 'del_flg': '0'})
|
||||
if saleman_id_li and saleman_id_li[0]['salemanid']:
|
||||
saleman_phone_li = await sor.R('users', {'id': saleman_id_li[0]['salemanid']})
|
||||
if saleman_phone_li and saleman_phone_li[0]['mobile']:
|
||||
saleman_phone = saleman_phone_li[0]['mobile']
|
||||
return saleman_id_li[0]['salemanid'], saleman_phone
|
||||
|
||||
if (not saleman_phone) or (not saleman_id_li):
|
||||
# 首先查找运营电话
|
||||
yunying_mobile = 0
|
||||
current_yunying_id = await get_role_user_from_org(orgid=who_is_org, role='运营')
|
||||
if current_yunying_id:
|
||||
yunying_mobile = (await sor.R('users', {'id': current_yunying_id, 'del_flg': '0'}))[0]['mobile']
|
||||
if yunying_mobile:
|
||||
return current_yunying_id, yunying_mobile
|
||||
if (not yunying_mobile) or (not current_yunying_id):
|
||||
# 查找管理员电话
|
||||
current_admin_id = await get_role_user_from_org(orgid=who_is_org, role='管理员')
|
||||
if current_admin_id:
|
||||
admin_mobile = (await sor.R('users', {'id': current_admin_id, 'del_flg': '0'}))[0]['mobile']
|
||||
if admin_mobile:
|
||||
return current_admin_id, admin_mobile
|
||||
print('%s 没有找到对应的管理人员进行电话,站内信发送' % nss['customerid'])
|
||||
return None, None
|
||||
|
||||
|
||||
async def innder_mail_add_msg(nss={}):
|
||||
"""
|
||||
:param ns:
|
||||
:return:
|
||||
senderid发送人id
|
||||
receiverid收件人id
|
||||
msgtitle消息标头
|
||||
msgtext消息内容
|
||||
"""
|
||||
user_orgid = nss['user_orgid']
|
||||
user_id = nss['userid']
|
||||
mail_should_send = False
|
||||
send_type = '欠费通知'
|
||||
# 记录到欠费表中
|
||||
# 首先查询欠费表中时间是否再范围内
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
customer_name = (await sor.R('organization', {'id': user_orgid}))[0]['orgname']
|
||||
mail_exist_li = await sor.R('message', {'receiverid': user_id, 'send_type': send_type, 'sort': ['sendtime desc']})
|
||||
saleman_id, saleman_mobile = await get_valid_admin_person({'customerid': user_orgid})
|
||||
if mail_exist_li:
|
||||
# 如果原来发送成功 时间范围大于24小时 再次发送
|
||||
sms_exist_time = mail_exist_li[0]['sendtime']
|
||||
time_diff = await get_time_diff(sms_exist_time, time.strftime('%Y-%m-%d %H:%M:%S'))
|
||||
# 如果发送过的短信在一天范围内 不再发送短信
|
||||
if time_diff >= 24 * 60:
|
||||
mail_should_send = True
|
||||
else:
|
||||
print('%s 站内信已经发送过, 但是没有超过阈值时间, 不再发送...' % customer_name)
|
||||
|
||||
if mail_should_send or not mail_exist_li:
|
||||
ns_customer = {
|
||||
'id': uuid(),
|
||||
'senderid': 'inner',
|
||||
'receiverid': user_id,
|
||||
'msgtitle': '系统新消息通知',
|
||||
'msgtype': '欠费通知',
|
||||
'msgtext': '尊敬的用户, 您购买的产品 %s 已欠费, 请及时续费以免影响正常使用。' % nss.get('productname'),
|
||||
}
|
||||
ns_saleman = {
|
||||
'id': uuid(),
|
||||
'senderid': 'inner',
|
||||
'receiverid': saleman_id,
|
||||
'msgtitle': '系统新消息通知',
|
||||
'msgtype': '欠费通知',
|
||||
'msgtext': '您好, 客户 %s 购买的产品 %s 已欠费, 请及时联系通知。' % (customer_name, nss.get('productname')),
|
||||
}
|
||||
await sor.C('message', ns_customer)
|
||||
await sor.C('message', ns_saleman)
|
||||
return {'status': True, 'msg': '添加成功'}
|
||||
|
||||
async def get_time_diff(time_old=None, time_new=None):
|
||||
|
||||
# # 定义两个时间字符串
|
||||
# time_old = '2023-12-01 09:40:00'
|
||||
# time_new = '2023-12-01 23:15:00'
|
||||
|
||||
# 将时间字符串解析为datetime对象
|
||||
time_dt1 = datetime.datetime.strptime(time_old, '%Y-%m-%d %H:%M:%S')
|
||||
time_dt2 = datetime.datetime.strptime(time_new, '%Y-%m-%d %H:%M:%S')
|
||||
|
||||
# 计算时间差
|
||||
time_difference = time_dt2 - time_dt1
|
||||
|
||||
# 提取时间差中的分钟数
|
||||
minutes_difference = time_difference.total_seconds() / 60
|
||||
# day = time_difference.days
|
||||
# hour = time_difference.total_seconds() / 3600
|
||||
return minutes_difference
|
||||
|
||||
async def diff_sms_send_save(sor=None, productname=None, time_interval=None, send_type=None, user_orgid=None, sms_send_dict=None):
|
||||
sms_should_send = False
|
||||
send_type = send_type
|
||||
# 记录到欠费表中
|
||||
# 首先查询欠费表中时间是否再范围内
|
||||
try:
|
||||
print('引用发送短信...')
|
||||
customer_phone = (await sor.R('organization', {'id': user_orgid}))[0]['contactor_phone']
|
||||
customer_name = (await sor.R('organization', {'id': user_orgid}))[0]['orgname']
|
||||
sms_exist_li = await sor.R('sms_record', {'mobile': customer_phone, 'send_type': send_type, 'send_status': '1',
|
||||
'sort': ['send_time desc']})
|
||||
if sms_exist_li:
|
||||
# 如果原来发送成功 时间范围大于24小时 再次发送
|
||||
if sms_exist_li[0]['send_status']:
|
||||
sms_exist_time = sms_exist_li[0]['send_time']
|
||||
time_diff = await get_time_diff(sms_exist_time, time.strftime('%Y-%m-%d %H:%M:%S'))
|
||||
# 如果发送过的短信在一天范围内 不再发送短信
|
||||
if time_diff >= time_interval:
|
||||
sms_should_send = True
|
||||
else:
|
||||
print('%s %s短信已经发送过, 但是没有超过阈值时间, 不再发送...' % (send_type, customer_phone))
|
||||
else:
|
||||
print('%s %s短信没有发送过, 发送...' % (send_type, customer_phone))
|
||||
sms_should_send = True
|
||||
|
||||
if sms_should_send or not sms_exist_li:
|
||||
# 给个人发送短信
|
||||
await send_vcode(customer_phone, send_type, sms_send_dict)
|
||||
|
||||
# 给相关管理人员发送短信
|
||||
saleman_id, saleman_mobile = await get_valid_admin_person({'customerid': user_orgid})
|
||||
if saleman_mobile:
|
||||
sms_send_dict_saleman = {
|
||||
'username': customer_name,
|
||||
'productname': productname
|
||||
}
|
||||
if send_type == '用户欠费通知':
|
||||
print('sms_send_dict_saleman', sms_send_dict_saleman)
|
||||
await send_vcode(saleman_mobile, '责任人用户欠费通知', sms_send_dict_saleman)
|
||||
except Exception as e:
|
||||
print('发送短信失败: %s' % e)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '发送短信失败',
|
||||
'data': e
|
||||
}
|
||||
|
||||
|
||||
async def baidu_post_pay_charge(bill_exist=None, info_detail=None, baidu_orgid=None, userid=None, baidu_id=None, user_orgid=None, user_parentid=None, sor=None):
|
||||
"""
|
||||
计算折扣后的价格
|
||||
获取针对个人的折扣配置
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
info_detail_id = info_detail['id']
|
||||
bill_date = info_detail['starttime']
|
||||
financeprice = info_detail['catalogprice']
|
||||
servicetype = info_detail['servicetype']
|
||||
|
||||
# utc时间转本地时间
|
||||
# bill_date_local_time = await utc2local(bill_date)
|
||||
# 查找对应的产品id
|
||||
productid_li = await sor.R('product', {'providerid': baidu_orgid, 'providerpid': 'baidu_' + servicetype, 'del_flg': '0'})
|
||||
if productid_li:
|
||||
productid_soure = productid_li[0]['id']
|
||||
product_name = productid_li[0]['name']
|
||||
else:
|
||||
productid_soure = None
|
||||
product_name = None
|
||||
real_discount = 1.0
|
||||
person_discount_sql = """select * from saleprotocol where offer_orgid = '%s' and bid_orgid = '%s' and
|
||||
salemode = '0' and del_flg = '0' and CURRENT_DATE <= end_date and
|
||||
CURRENT_DATE >= start_date""" % (user_parentid, user_orgid)
|
||||
tongyi_discount_sql = """select * from saleprotocol where offer_orgid = '%s' and bid_orgid = '*' and
|
||||
salemode = '0' and del_flg = '0' and CURRENT_DATE <= end_date and
|
||||
CURRENT_DATE >= start_date""" % user_parentid
|
||||
# 没有个人配置 获取百度产品统一配置折扣
|
||||
for sql_detail in [person_discount_sql, tongyi_discount_sql]:
|
||||
person_discount_li = await sor.sqlExe(sql_detail, {})
|
||||
for person_discount in person_discount_li:
|
||||
protocolid = person_discount['id']
|
||||
xieyi_zi_search_li = await sor.R('product_salemode', {'protocolid': protocolid, 'del_flg': '0'})
|
||||
for xieyi_zi in xieyi_zi_search_li:
|
||||
provider_zi_id = xieyi_zi['providerid']
|
||||
zi_discount = xieyi_zi['discount']
|
||||
zi_productid = xieyi_zi['productid']
|
||||
if provider_zi_id == baidu_orgid and zi_productid == productid_soure:
|
||||
# 判断产品是否存在 有可能在产品表已经删除
|
||||
prd_res_exists_li = await sor.R('product', {'id': xieyi_zi['productid'], 'del_flg': '0'})
|
||||
if not prd_res_exists_li:
|
||||
continue
|
||||
real_discount = float(zi_discount)
|
||||
break
|
||||
if real_discount != 1.0:
|
||||
break
|
||||
# 计算实际支付费用
|
||||
amount = round(real_discount * float(financeprice), 6)
|
||||
|
||||
# 根据params表中bussiness_date进行扣费
|
||||
bussiness_date = (await sor.R('params', {'pname': 'business_date', 'del_flg': '0'}))[0]['pvalue']
|
||||
nss_bill = {
|
||||
'id': uuid(),
|
||||
'customerid': user_orgid,
|
||||
'business_op': 'BUY',
|
||||
'provider_amt': financeprice,
|
||||
'amount': amount,
|
||||
'bill_date': bussiness_date,
|
||||
'bill_timestamp': bussiness_date + ' 00:00:00',
|
||||
'bill_state': 0,
|
||||
'productid': productid_soure,
|
||||
'providerid': baidu_orgid,
|
||||
'quantity': 1
|
||||
}
|
||||
|
||||
# 比对账户余额和账单金额
|
||||
db_balance = DBPools()
|
||||
async with db_balance.sqlorContext('kboss') as sor_balance:
|
||||
balance_yuan = await getCustomerBalance(sor_balance, user_orgid)
|
||||
print('%s orgid: %s, 余额为: %s' % (time.strftime('%Y-%m-%d %H:%M:%S'), user_orgid, balance_yuan))
|
||||
print('将要扣除的金额: %s' % nss_bill['amount'])
|
||||
|
||||
if balance_yuan < amount:
|
||||
sms_send_dict = {
|
||||
'time': time.strftime('%Y-%m-%d %H:') + '00:00',
|
||||
'productname': product_name
|
||||
}
|
||||
db_sms = DBPools()
|
||||
async with db_sms.sqlorContext('kboss') as sor_sms:
|
||||
await diff_sms_send_save(sor=sor_sms, productname=product_name, time_interval=24*60, send_type='用户欠费通知', user_orgid=user_orgid, sms_send_dict=sms_send_dict)
|
||||
await innder_mail_add_msg({'user_orgid': user_orgid, 'userid': userid, 'productname': product_name})
|
||||
# 查找是否已经存在
|
||||
exist_qianfei = await sor.R('arrears', {'billid': info_detail['billid']})
|
||||
if exist_qianfei:
|
||||
print('%s 欠费账单已经存在...' % info_detail['billid'])
|
||||
else:
|
||||
nss_bill['starttime'] = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
nss_bill['source'] = '百度智能云'
|
||||
nss_bill['localid'] = info_detail['id']
|
||||
nss_bill['billid'] = info_detail['billid']
|
||||
nss_bill['del_flg'] = 0
|
||||
await sor.C('arrears', nss_bill)
|
||||
|
||||
# 直接创建账单 不再进行扣费再创建账单流程
|
||||
if not bill_exist:
|
||||
info_detail['kaiyuanprice'] = amount
|
||||
await sor.C('baidu_post_bill', info_detail)
|
||||
|
||||
print('%s 用户%s 余额不足' % (time.strftime('%Y-%m-%d %H:%M:%S'), user_orgid))
|
||||
|
||||
# 产品欠费下线
|
||||
ns_offline = {
|
||||
"accountId": baidu_id,
|
||||
"service": servicetype,
|
||||
"region": info_detail['region']
|
||||
}
|
||||
print('*************', ns_offline)
|
||||
await resource_offline(ns_offline)
|
||||
|
||||
return
|
||||
# 如果当前余额不足当前账单24小时内支付 发送预警短信
|
||||
if amount * 24 > balance_yuan:
|
||||
sms_send_dict = {
|
||||
'time': time.strftime('%Y-%m-%d %H:') + '00:00',
|
||||
'balance': int(balance_yuan)
|
||||
}
|
||||
dbs = DBPools()
|
||||
async with dbs.sqlorContext('kboss') as sor_sms:
|
||||
await diff_sms_send_save(sor=sor_sms, productname=product_name, time_interval=24*60*2, send_type='余额不足提醒', user_orgid=user_orgid, sms_send_dict=sms_send_dict)
|
||||
|
||||
# 记账
|
||||
# 日期 12-06/12-07 凌晨扣费时出错 由于是事务, 12-06/12-07同时出错 无法扣费
|
||||
# 所以另开事务 至少有一天可以扣费成功
|
||||
# 扣费不成功的原因:
|
||||
# business_date和账单日期对不上/acc_balance余额表中所有日期存在大于账单日期
|
||||
# 余额部分满足时 扣除可用余额后 事务中余额没变化 此处创建新的事务
|
||||
db_bill = DBPools()
|
||||
async with db_bill.sqlorContext('kboss') as sor_bill:
|
||||
try:
|
||||
ba = BillAccounting(nss_bill)
|
||||
await ba.accounting(sor_bill)
|
||||
|
||||
# 不存在就在此处创建
|
||||
if not bill_exist:
|
||||
info_detail['bill_state'] = 1
|
||||
info_detail['kaiyuanprice'] = amount
|
||||
await sor_bill.C('baidu_post_bill', info_detail)
|
||||
|
||||
# 修改本地bill状态 0:未支付,1:已支付;2:已取消
|
||||
# 已经存在就更新
|
||||
ns_bill_status = {
|
||||
'id': info_detail_id,
|
||||
'bill_state': 1,
|
||||
'kaiyuanprice': amount
|
||||
}
|
||||
await sor_bill.U('baidu_post_bill', ns_bill_status)
|
||||
print('百度账单扣费: %s, 扣费成功' % info_detail['billid'])
|
||||
except Exception as e:
|
||||
print('用户: %s, 账单: %s, 扣费失败: %s' % (user_orgid, info_detail['billid'], e))
|
||||
if not bill_exist:
|
||||
await sor_bill.C('baidu_post_bill', info_detail)
|
||||
|
||||
|
||||
async def save_baidu_post_bill(data_bill, userid=None, baidu_id=None, user_orgid=None, user_parentid=None, sor=None):
|
||||
try:
|
||||
# 查找百度orgid 方便一下查找对应产品的productid
|
||||
baidu_orgid_li = await sor.R('organization', {'orgname': '百度智能云'})
|
||||
if baidu_orgid_li:
|
||||
baidu_orgid = baidu_orgid_li[0]['id']
|
||||
else:
|
||||
raise ValueError("无法找到百度机构id, 百度供应商名称是: 百度智能云")
|
||||
# count = 0
|
||||
for bill_detail in data_bill['bills']:
|
||||
# count += 1
|
||||
# if count > 9:
|
||||
# return
|
||||
info_detail = {
|
||||
'id': uuid(),
|
||||
'billid': bill_detail.get('billId'),
|
||||
'accountid': data_bill['subAccountId'],
|
||||
'servicetype': bill_detail.get('serviceType'),
|
||||
'servicetypename': bill_detail.get('serviceTypeName'),
|
||||
'producttype': bill_detail.get('productType'),
|
||||
'region': bill_detail.get('region'),
|
||||
'instanceid': bill_detail.get('instanceId'),
|
||||
'shortid': bill_detail.get('shortId'),
|
||||
'starttime': bill_detail.get('startTime'),
|
||||
'endtime': bill_detail.get('endTime'),
|
||||
'configurationch': bill_detail.get('configurationCH'),
|
||||
'unitprice': bill_detail.get('unitPrice'),
|
||||
'pricingunit': bill_detail.get('pricingUnit'),
|
||||
'chargeitem': bill_detail.get('chargeItem'),
|
||||
'chargeitemdesc': bill_detail.get('chargeItemDesc'),
|
||||
'amount': bill_detail.get('amount'),
|
||||
'amountunit': bill_detail.get('amountUnit'),
|
||||
'discountamount': bill_detail.get('discountAmount'),
|
||||
'originprice': bill_detail.get('originPrice'),
|
||||
'catalogprice': bill_detail.get('catalogPrice'),
|
||||
'financeprice': bill_detail.get('financePrice'),
|
||||
'couponprice': bill_detail.get('couponPrice'),
|
||||
'discountcouponprice': bill_detail.get('discountCouponPrice'),
|
||||
'cashequivalentcouponprice': bill_detail.get('cashEquivalentCouponPrice'),
|
||||
'discountprice': bill_detail.get('discountPrice'),
|
||||
'sysgold': bill_detail.get('sysGold'),
|
||||
'deductprice': bill_detail.get('deductPrice'),
|
||||
'originconfig': json.dumps(bill_detail),
|
||||
'bill_state': 0,
|
||||
'del_flg': '0'
|
||||
}
|
||||
db_sor_bill = DBPools()
|
||||
async with db_sor_bill.sqlorContext('kboss') as sor_find_bill:
|
||||
exist_bill_id = await sor_find_bill.R('baidu_post_bill', {'billid': info_detail['billid']})
|
||||
bill_exist = 0
|
||||
if exist_bill_id:
|
||||
if exist_bill_id[0]['bill_state'] == '0':
|
||||
print('%s 百度后付费账单已经存在, 没有扣款, 账单号: %s' % (user_orgid, info_detail['billid']))
|
||||
# 此时id已经存在 不再生成新的id
|
||||
info_detail['id'] = exist_bill_id[0]['id']
|
||||
bill_exist = 1
|
||||
else:
|
||||
# print('%s 百度后付费账单已经存在, 已经扣款, 账单号: %s' % (user_orgid, info_detail['billid']))
|
||||
continue
|
||||
else:
|
||||
pass
|
||||
# 数据库同时插入和更新死锁 此处不再插入
|
||||
# await sor.C('baidu_post_bill', info_detail)
|
||||
|
||||
# 扣费
|
||||
await baidu_post_pay_charge(bill_exist=bill_exist, info_detail=info_detail, baidu_orgid=baidu_orgid, userid=userid, baidu_id=baidu_id, user_orgid=user_orgid, user_parentid=user_parentid, sor=sor)
|
||||
except Exception as e:
|
||||
print('save_baidu_post_bill: %s' % e)
|
||||
raise e
|
||||
|
||||
|
||||
async def get_auth_header(method: str, url: str, header: dict, query={}, get_res=False):
|
||||
import urllib
|
||||
import hmac
|
||||
AK = 'ALTAKPk92fX9cgGDax83yNL8mP'
|
||||
SK = '9b16b8efd4dc463d8bbd5462db1db8a5'
|
||||
# 解析uri
|
||||
url_parse = urllib.parse.urlparse(url)
|
||||
uri = url_parse.path
|
||||
url_query = url_parse.query
|
||||
|
||||
# 获取query
|
||||
if url_query:
|
||||
query = dict(urllib.parse.parse_qsl(url_query))
|
||||
|
||||
# 2.x-bce-date
|
||||
x_bce_date = time.gmtime()
|
||||
x_bce_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', x_bce_date)
|
||||
|
||||
# 4.认证字符串前缀
|
||||
authStringPrefix = "bce-auth-v1" + "/" + AK + "/" + x_bce_date + "/" + "1800"
|
||||
|
||||
# windows下为urllib.parse.quote,Linux下为urllib.quote
|
||||
# 5.生成CanonicalRequest
|
||||
# 5.1生成CanonicalURI
|
||||
CanonicalURI = urllib.parse.quote(uri)
|
||||
|
||||
# 如果您调用的接口的query比较复杂的话,需要做额外处理
|
||||
# 5.2生成CanonicalQueryString
|
||||
# CanonicalQueryString = query
|
||||
result = ['%s=%s' % (k, urllib.parse.quote(str(v))) for k, v in query.items() if k.lower != 'authorization']
|
||||
result.sort()
|
||||
CanonicalQueryString = '&'.join(result)
|
||||
|
||||
# 5.3生成CanonicalHeaders
|
||||
result = []
|
||||
signedHeaders_list = []
|
||||
for key,value in header.items():
|
||||
tempStr = str(urllib.parse.quote(key.lower(),safe="")) + ":" + str(urllib.parse.quote(value,safe=""))
|
||||
signedHeaders_list.append(str(urllib.parse.quote(key.lower(),safe="")))
|
||||
result.append(tempStr)
|
||||
result.sort()
|
||||
signedHeaders = ';'.join(sorted(signedHeaders_list))
|
||||
CanonicalHeaders = "\n".join(result)
|
||||
|
||||
# 5.4拼接得到CanonicalRequest
|
||||
CanonicalRequest = method + "\n" + CanonicalURI + "\n" + CanonicalQueryString +"\n" + CanonicalHeaders
|
||||
|
||||
# 6.生成signingKey
|
||||
signingKey = hmac.new(SK.encode('utf-8'), authStringPrefix.encode('utf-8'), hashlib.sha256)
|
||||
|
||||
# 7.生成Signature
|
||||
Signature = hmac.new((signingKey.hexdigest()).encode('utf-8'), CanonicalRequest.encode('utf-8'), hashlib.sha256)
|
||||
|
||||
# 8.生成Authorization并放到header里
|
||||
header['Authorization'] = authStringPrefix + "/" + signedHeaders + "/" + Signature.hexdigest()
|
||||
|
||||
if get_res:
|
||||
# 异步请求链接 返回结果
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
allow_redirects=True,
|
||||
json=query) as res:
|
||||
return res
|
||||
else:
|
||||
return header
|
||||
|
||||
|
||||
async def arrears_charge(customerid=None, source=None):
|
||||
"""
|
||||
优先扣除欠费表中的账单
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
# customerid = 'gKG8UaYPjA_29K7puzaTM'
|
||||
# source = '百度智能云'
|
||||
db_arrears = DBPools()
|
||||
async with db_arrears.sqlorContext('kboss') as sor_arrears:
|
||||
bill_date = (await sor_arrears.R('params', {'pname': 'business_date', 'del_flg': '0'}))[0]['pvalue']
|
||||
try:
|
||||
arrear_li = await sor_arrears.R('arrears', {'source': source, 'customerid': customerid, 'bill_state': '0'})
|
||||
arrear_product_types = []
|
||||
for arr in arrear_li:
|
||||
nss_bill = {
|
||||
'id': uuid(),
|
||||
'customerid': arr['customerid'],
|
||||
'business_op': arr['business_op'],
|
||||
'provider_amt': arr['provider_amt'],
|
||||
'amount': arr['amount'],
|
||||
'bill_date': bill_date,
|
||||
'bill_timestamp': bill_date + ' 00:00:00',
|
||||
'bill_state': 0,
|
||||
'productid': arr['productid'],
|
||||
'providerid': arr['providerid'],
|
||||
'quantity': arr['quantity']
|
||||
}
|
||||
ba = BillAccounting(nss_bill)
|
||||
await ba.accounting(sor_arrears)
|
||||
|
||||
# 修改本地bill状态 0:未支付,1:已支付;2:已取消
|
||||
# 已经存在就更新
|
||||
arrear_status = {
|
||||
'id': arr['id'],
|
||||
'bill_state': 1,
|
||||
'endtime': time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
}
|
||||
await sor_arrears.U('arrears', arrear_status)
|
||||
print('%s 百度账单-欠费账单-扣费成功, 状态更新成功: %s' % (arr['customerid'], arr['id']))
|
||||
baidu_post_bill_status = {
|
||||
'id': arr['localid'],
|
||||
'bill_state': 1
|
||||
}
|
||||
await sor_arrears.U('baidu_post_bill', baidu_post_bill_status)
|
||||
print('%s 百度账单-欠费账单扣费成功---本地账单-更新成功, 状态更新成功: %s' % (arr['customerid'], arr['billid']))
|
||||
|
||||
# 获取百度下线类型列表 用于产品上线
|
||||
products = await sor_arrears.R('baidu_post_bill', {'id': arr['localid']})
|
||||
ns_type = {
|
||||
"accountId": products[0]['accountid'],
|
||||
"service": products[0]['servicetype'],
|
||||
"region": products[0]['region']
|
||||
}
|
||||
arrear_product_types.append(ns_type)
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'data': [dict(t) for t in {frozenset(d.items()) for d in arrear_product_types}]
|
||||
}
|
||||
except Exception as e:
|
||||
print('用户: %s, 欠费账单扣费失败: %s' % (customerid, e))
|
||||
return {
|
||||
'status': False
|
||||
}
|
||||
|
||||
|
||||
async def get_resourcechargeitem_billlist(userid=None, baidu_id=None, user_orgid=None, user_parentid=None, pageno=1, sor=None):
|
||||
"""
|
||||
分页获取后付费资源计费项账单详情, 颗粒度:小时 不能查看当月账单
|
||||
1. 账单过来后余额充足正常扣费
|
||||
1048条:扣费前余额:18327.51 扣费后余额: 18267.13 实际扣除:60.38 实际账单应扣除总额: 62.4347
|
||||
前10条: 扣费前余额:18267.13 扣费后余额: 18266.93 实际扣除:0.2 实际账单应扣除总额: 0.2255
|
||||
2. 账单过来后余额不足短信通知
|
||||
2.1 账单过来后余额不足短信通知-时间范围内是否重复发送
|
||||
2.1.1 重复发送 创建一个单独事务 修复
|
||||
2.1.2 充值-但只足够部分账单扣费 余额查询创建单独事务 修复
|
||||
2.2 账单过来后余额不足短信通知-超过时间范围是否发送 正常发送
|
||||
2.3 是否在欠费账单里
|
||||
2.3.1 后续还在欠费 是否在欠费账单重复 不重复
|
||||
2.3.2 后续余额充足 是否把欠费补充完成 是
|
||||
3. 余额充足 3个账单 正常扣费 balance由于是小数点两位 造成误差
|
||||
余额充足 但是不够24小时费用 正常扣费 客户短信正常发送 销售短信发送失败:productname=None 修复
|
||||
余额部分满足 正常扣费 短信不能正常发送/post_bill kaiyuanprice为空没有正常录入 创建新事务 修复
|
||||
欠费表已存在 重复请求是否重复 不重复
|
||||
欠费表已存在 余额充足 是否正常扣费 欠费表和post_bill表重复扣费 欠费表创建单独的事务 在查询存在账单时创建事务 修复
|
||||
欠费表单独事务 - 每一次欠费项一个事务 否则造成欠费表同时不成功 但post_bill表反而扣费成功了 造成不同步 (测试发现状态可以正常改变)
|
||||
存在问题 1. 小数点过小无法扣除 实际扣除0.0 应扣除0.0205
|
||||
2. import urllib hmac
|
||||
3. accounting.bill.BillAccounting 线上删除accounting.bill 此处报错 但账单已保存 测试
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
# 优先扣除欠费信息 欠费表/取消释放/忽略小数点后几位较小误差
|
||||
arrear_types = await arrears_charge(customerid=user_orgid, source='百度智能云')
|
||||
# 扣费成功 开启下线的服务
|
||||
if arrear_types and arrear_types.get('status') and arrear_types.get('data'):
|
||||
for roline in arrear_types['data']:
|
||||
await resource_online(roline)
|
||||
|
||||
# 获取当前日期和时间
|
||||
current_time = datetime.datetime.now()
|
||||
|
||||
# 指定开始日期
|
||||
# date_string = "2023-11-30"
|
||||
# format = '%Y-%m-%d' # specifify the format of the date_string.
|
||||
# current_time = datetime.datetime.strptime(date_string, format)
|
||||
|
||||
# 计算七天前的日期
|
||||
days_ago = current_time - datetime.timedelta(days=7)
|
||||
# 获取账单百度指定必须在同一个月内
|
||||
if current_time.month != days_ago.month:
|
||||
days_ago = datetime.datetime(current_time.year, current_time.month, 1)
|
||||
|
||||
# 将日期时间格式化为字符串
|
||||
current_day = current_time.strftime("%Y-%m-%d")
|
||||
days_ago_time = days_ago.strftime("%Y-%m-%d")
|
||||
|
||||
ns = {
|
||||
"beginTime": days_ago_time,
|
||||
"endTime": current_day,
|
||||
"queryAccountId" : baidu_id,
|
||||
"pageNo": pageno,
|
||||
"pageSize": 100
|
||||
}
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/bill/resource/chargeitem?%s' % ns_format
|
||||
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=ns) as res:
|
||||
data_bill = await res.json()
|
||||
if data_bill.get('bills'):
|
||||
await save_baidu_post_bill(data_bill=data_bill, userid=userid, baidu_id=baidu_id, user_orgid=user_orgid, user_parentid=user_parentid, sor=sor)
|
||||
real_page_no = int(data_bill['totalCount'] / data_bill['pageSize']) + 1
|
||||
if data_bill['pageNo'] < real_page_no:
|
||||
await get_resourcechargeitem_billlist(userid=userid, baidu_id=baidu_id, user_orgid=user_orgid, user_parentid=user_parentid, pageno=data_bill['pageNo'] + 1, sor=sor)
|
||||
else:
|
||||
print('%s 账号ID: %s 后付费账单同步成功, 同步页面数量: %s' % (current_time.strftime("%Y-%m-%d %H:%M:%S"), data_bill['subAccountId'], data_bill['pageNo']))
|
||||
else:
|
||||
print('%s 账号ID: %s 或空bills, 后付费账单同步成功, 同步页面数量: %s' % (
|
||||
current_time.strftime("%Y-%m-%d %H:%M:%S"), data_bill['subAccountId'], data_bill['pageNo']))
|
||||
|
||||
|
||||
async def baidu_users_get_post_pay(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
# 获取所有百度用户
|
||||
baidu_users = await sor.R('baidu_users', {'del_flg': '0'})
|
||||
for baidu_user in baidu_users:
|
||||
userid = baidu_user['user_id']
|
||||
baidu_id = baidu_user['baidu_id']
|
||||
|
||||
# if baidu_id != 'dcf0fa1519d24de893b186e52d733bd2':
|
||||
# continue
|
||||
try:
|
||||
user_orgid = (await sor.R('users', {'id': userid}))[0]['orgid']
|
||||
user_parentid = (await sor.R('organization', {'id': user_orgid}))[0]['parentid']
|
||||
await get_resourcechargeitem_billlist(userid=userid, baidu_id=baidu_id, user_orgid=user_orgid, user_parentid=user_parentid, pageno=1, sor=sor)
|
||||
except Exception as e:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '百度后付费账单发生错误',
|
||||
'data': e
|
||||
}
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '百度账户后付费扣费成功...'
|
||||
}
|
||||
|
||||
ret = await baidu_users_get_post_pay(params_kw)
|
||||
return ret
|
||||
22
b/baiduc/get_baidu_users_base_org.dspy
Normal file
22
b/baiduc/get_baidu_users_base_org.dspy
Normal file
@ -0,0 +1,22 @@
|
||||
async def get_baidu_users_base_org(ns={}):
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns.get('user_id_or_name'):
|
||||
user_find_sql = """ SELECT DISTINCT b.user_id, u.username FROM organization o INNER JOIN users u ON o.id = u.orgid INNER JOIN baidu_users b ON u.id = b.user_id WHERE o.parentid = '%s' AND b.del_flg = '0' AND (b.user_id = '%s' OR u.username = '%s'); """ % (ns['orgid'], ns['user_id_or_name'], ns['user_id_or_name'])
|
||||
user_find_li = await sor.sqlExe(user_find_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search user success',
|
||||
'data': user_find_li
|
||||
}
|
||||
else:
|
||||
user_find_sql = """ SELECT DISTINCT b.user_id, u.username FROM organization o INNER JOIN users u ON o.id = u.orgid INNER JOIN baidu_users b ON u.id = b.user_id WHERE o.parentid = '%s' AND b.del_flg = '0'; """ % ns['orgid']
|
||||
user_find_li = await sor.sqlExe(user_find_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'search user success',
|
||||
'data': user_find_li
|
||||
}
|
||||
|
||||
ret = await get_baidu_users_base_org(params_kw)
|
||||
return ret
|
||||
45
b/baiduc/get_local_baidu_orders.dspy
Normal file
45
b/baiduc/get_local_baidu_orders.dspy
Normal file
@ -0,0 +1,45 @@
|
||||
async def get_local_baidu_orders(ns={}):
|
||||
order_page_size = int(ns['pageSize']) if ns.get('pageSize') else 20
|
||||
order_page_offset = (int(ns['pageNo']) - 1) * order_page_size if ns.get('pageNo') else 0
|
||||
|
||||
ordertype = ns.get('ordertype')
|
||||
servicetype = ns.get('servicetype')
|
||||
producttype = ns.get('producttype')
|
||||
status = ns.get('status')
|
||||
autoreneworder = ns.get('autoreneworder')
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns.get('user_id_or_name'):
|
||||
orders_find_sql = """ SELECT u.username, bs.user_id, bo.* FROM baidu_orders bo INNER JOIN baidu_users bs ON bs.baidu_id = bo.accountid INNER JOIN users u ON bs.user_id = u.id WHERE (bs.user_id = '%s' OR u.username = '%s') AND bo.del_flg = '0'""" % (ns.get('user_id_or_name'), ns.get('user_id_or_name'))
|
||||
else:
|
||||
orders_find_sql = """ SELECT u.username, bs.user_id, bo.* FROM baidu_orders bo INNER JOIN baidu_users bs ON bs.baidu_id = bo.accountid INNER JOIN users u ON bs.user_id = u.id WHERE bo.del_flg = '0'"""
|
||||
if ordertype:
|
||||
orders_find_sql += """ AND ordertype = '%s' """ % ordertype
|
||||
if servicetype:
|
||||
orders_find_sql += """ AND servicetype = '%s' """ % servicetype
|
||||
if producttype:
|
||||
orders_find_sql += """ AND producttype = '%s' """ % producttype
|
||||
if status:
|
||||
orders_find_sql += """ AND status = '%s' """ % status
|
||||
if autoreneworder:
|
||||
orders_find_sql += """ AND autoreneworder = '%s' """ % autoreneworder
|
||||
|
||||
count_num_li = await sor.sqlExe(orders_find_sql, {})
|
||||
count_num = len(count_num_li)
|
||||
|
||||
orders_find_sql += """ORDER BY bo.createtime DESC LIMIT %s OFFSET %s; """ % (order_page_size, order_page_offset)
|
||||
orders_find = await sor.sqlExe(orders_find_sql, {})
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get baidu orders success',
|
||||
'data': {
|
||||
'pageSize': order_page_size,
|
||||
'totalCount': count_num,
|
||||
'pageNo': ns['pageNo'],
|
||||
'orders': orders_find
|
||||
}
|
||||
}
|
||||
|
||||
ret = await get_local_baidu_orders(params_kw)
|
||||
return ret
|
||||
47
b/baiduc/get_tokenid.dspy
Normal file
47
b/baiduc/get_tokenid.dspy
Normal file
@ -0,0 +1,47 @@
|
||||
async def get_tokenid(ns={}):
|
||||
userid = await get_user()
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
baidu_user_id_li = await sor.R('baidu_users', {'user_id': userid, 'del_flg': '0'})
|
||||
if baidu_user_id_li:
|
||||
baidu_user_id = baidu_user_id_li[0]['baidu_id']
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '没有找到对应的百度用户'
|
||||
}
|
||||
|
||||
method = "POST"
|
||||
url = 'https://sts.bj.baidubce.com/v1/signinSecurityToken?userId=%s' % baidu_user_id
|
||||
|
||||
x_bce_date = time.gmtime()
|
||||
x_bce_date = time.strftime('%Y-%m-%dT%H:%M:%SZ', x_bce_date)
|
||||
|
||||
header = {
|
||||
"Host": "sts.bj.baidubce.com",
|
||||
"Content-Type": "application/json",
|
||||
'x_bce_date': x_bce_date
|
||||
}
|
||||
header2 = x_bce_date
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header) as res:
|
||||
data_token = await res.json()
|
||||
if data_token.get('sessionToken'):
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'get token success',
|
||||
'data': data_token.get('sessionToken')
|
||||
}
|
||||
else:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'get token failed, %s' % data_token,
|
||||
'header': header,
|
||||
'header2': header2
|
||||
}
|
||||
|
||||
ret = await get_tokenid(params_kw)
|
||||
return ret
|
||||
56
b/baiduc/index.html
Normal file
56
b/baiduc/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
97
b/baiduc/update_baidu_order_list.dspy
Normal file
97
b/baiduc/update_baidu_order_list.dspy
Normal file
@ -0,0 +1,97 @@
|
||||
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 get_order_list_base_page(baidu_id, pageNo=1, pageSize=500):
|
||||
ns = {'queryAccountId': baidu_id, 'pageNo': pageNo, 'pageSize': pageSize}
|
||||
method = 'POST'
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://billing.baidubce.com/v1/order/list?%s' % ns_format
|
||||
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=ns) as res:
|
||||
data_orders = await res.json()
|
||||
return data_orders
|
||||
|
||||
|
||||
async def update_baidu_order_list(ns={}):
|
||||
"""
|
||||
ns = {'queryAccountId': '139fc7a23b314596ad78b6bb8e7c1503', 'orderType': 'REFUND'}
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
username = None
|
||||
# 更新机构下全部用户订单信息
|
||||
if ns.get('orgid'):
|
||||
users_find_sql = """SELECT DISTINCT b.baidu_id FROM organization o INNER JOIN users u ON o.id = u.orgid INNER JOIN baidu_users b ON u.id = b.user_id WHERE o.parentid = '%s' AND b.del_flg = '0';""" % ns.get('orgid')
|
||||
users = await sor.sqlExe(users_find_sql, {})
|
||||
|
||||
# 更新个人订单信息
|
||||
elif ns.get('userid'):
|
||||
users = await sor.R('baidu_users', {'user_id': ns['userid']})
|
||||
username_li = await sor.R('users', {'id': ns['userid']})
|
||||
username = username_li[0]['username'] if username_li else None
|
||||
else:
|
||||
users = []
|
||||
|
||||
update_count = 0
|
||||
add_count = 0
|
||||
for baidu_id in users:
|
||||
data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=1, pageSize=1000)
|
||||
page_num_count = int(data_orders['totalCount'] / data_orders['pageSize']) + 1
|
||||
for page_num in range(1, page_num_count + 1):
|
||||
data_orders = await get_order_list_base_page(baidu_id['baidu_id'], pageNo=page_num, pageSize=1000)
|
||||
orders = data_orders['orders']
|
||||
for item in orders:
|
||||
updatetime = await time_convert(item.get('updateTime')) if item.get('updateTime') else None
|
||||
ns_dic = {
|
||||
"id": uuid(),
|
||||
"orderid": item.get("uuid"),
|
||||
"ordertype": item.get("type"),
|
||||
"accountid": item.get("accountId"),
|
||||
"servicetype": item.get("serviceType"),
|
||||
"producttype": item.get("productType"),
|
||||
"shortids": ','.join(item['shortIds']) if item.get('shortIds') else '',
|
||||
"price": item.get("price"),
|
||||
"status": item.get("status"),
|
||||
"autoreneworder": '1' if item.get("autoRenewOrder") else '0',
|
||||
"createtime": await time_convert(item.get('createTime')) if item.get(
|
||||
'createTime') else None,
|
||||
"updatetime": updatetime
|
||||
}
|
||||
ns_exist_order = {
|
||||
'orderid': item.get("uuid")
|
||||
}
|
||||
exist_order = await sor.R('baidu_orders', ns_exist_order)
|
||||
if exist_order and exist_order[0]['updatetime'] != updatetime:
|
||||
update_refund_sql = """UPDATE baidu_orders SET price = '%s', status = '%s', updatetime = '%s' WHERE orderid = '%s';""" % \
|
||||
(item.get("price"), item.get("status"), updatetime,
|
||||
item.get("uuid"))
|
||||
await sor.sqlExe(update_refund_sql, {})
|
||||
update_count += 1
|
||||
|
||||
if not exist_order:
|
||||
await sor.C('baidu_orders', ns_dic)
|
||||
add_count += 1
|
||||
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '同步数据成功, 新增 %s 条, 更新 %s 条' % (add_count, update_count),
|
||||
'data': {
|
||||
'username': username
|
||||
}
|
||||
}
|
||||
|
||||
ret = await update_baidu_order_list(params_kw)
|
||||
return ret
|
||||
55
b/baiducloud/create_baiduuser.dspy
Normal file
55
b/baiducloud/create_baiduuser.dspy
Normal file
@ -0,0 +1,55 @@
|
||||
async def create_baiduuser(ns):
|
||||
"""
|
||||
ns = {
|
||||
"name": "用户名",
|
||||
"email": "邮箱",
|
||||
"mobilePhone": "手机号",
|
||||
"accountType": "0"为个人|“1”为企业
|
||||
}
|
||||
:param ns:
|
||||
:return:
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
user = await sor.R('users',{'id':ns.get('userid')})
|
||||
data = {'name':user[0]['username'],'mobilePhone':user[0]['mobile'],'accountType':'0'}
|
||||
method = "POST"
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in ns.items()])
|
||||
url = 'https://iam.bj.baidubce.com/v1/vs/account?%s' % ns_format
|
||||
header = {
|
||||
"Host": "iam.bj.baidubce.com",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
header = await get_auth_header(method=method, url=url, header=header)
|
||||
|
||||
async with aiohttp_client.request(
|
||||
method=method,
|
||||
url=url,
|
||||
headers=header,
|
||||
json=data) as res:
|
||||
data_ = await res.json()
|
||||
if not data_.get('userId'):
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '创建用户失败',
|
||||
'data': data_
|
||||
}
|
||||
else:
|
||||
#用户创建成功
|
||||
userdata = {
|
||||
'id' : uuid(),
|
||||
# 'id' : UUID(),
|
||||
'user_id' : ns.get('userid'),
|
||||
'baidu_id' : data_.get('userId'),
|
||||
'baidu_username' : data_.get('name'),
|
||||
}
|
||||
await sor.C('baidu_users',userdata)
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '创建用户成功',
|
||||
'data': data_
|
||||
}
|
||||
|
||||
|
||||
ret = await create_baiduuser(params_kw)
|
||||
return ret
|
||||
33
b/baiducloud/get_baiduQualifyInfo.dspy
Normal file
33
b/baiducloud/get_baiduQualifyInfo.dspy
Normal file
@ -0,0 +1,33 @@
|
||||
async def get_baiduQualifyInfo(ns):
|
||||
"""
|
||||
获取百度实名认证接口
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
user = await sor.R('baidu_users',{'user_id':ns.get('user_id')})
|
||||
if len(user) >= 1:
|
||||
nss = {}
|
||||
nss['accountId'] = user[0]['baidu_id']
|
||||
ns_format = '&'.join(['%s=%s' % (k, v) for k, v in nss.items()])
|
||||
url = 'https://qualify.baidubce.com/v1/getQualifyInfo?%s' % ns_format
|
||||
method = 'GET'
|
||||
header = {
|
||||
"Host": "qualify.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=ns) as res:
|
||||
data_ = await res.json()
|
||||
if data_['qualifyType'] != None and data_['status'] == 'PASS':
|
||||
return {'status': True, 'msg': '实名认证通过'}
|
||||
else:
|
||||
return {'status': False, 'msg': '实名认证未通过'}
|
||||
else:
|
||||
return {'status': False, 'msg': '百度用户创建失败'}
|
||||
|
||||
ret = await get_baiduQualifyInfo(params_kw)
|
||||
return ret
|
||||
627
b/baiducloud/get_baidu_orderlist.dspy
Normal file
627
b/baiducloud/get_baidu_orderlist.dspy
Normal file
@ -0,0 +1,627 @@
|
||||
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 == 'REFUND':
|
||||
# 找到资源并更新时间
|
||||
resource_find_sql = """select id from customer_goods where resourceid = '%s';""" % 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, 'del_flg': '1'})
|
||||
|
||||
# 处理续费逻辑
|
||||
elif 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']
|
||||
nss['orderkey'] = j['orderkey']
|
||||
|
||||
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 baidu_new_update_resouce(ns={}):
|
||||
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(12)
|
||||
|
||||
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()
|
||||
with open('baidu_new_order_after_confirm.txt', 'a+') as f:
|
||||
f.write(json.dumps(data_) + '\n')
|
||||
orders = data_['orders']
|
||||
|
||||
for item in orders:
|
||||
order_items = item['orderItems']
|
||||
for order_info in order_items:
|
||||
resourceids = ','.join(order_info['shortIds']) if order_info.get('shortIds') else ''
|
||||
if not resourceids:
|
||||
continue
|
||||
resourcestarttime = await time_convert(order_info.get('resourceStartTime')) if order_info.get(
|
||||
'resourceStartTime') else None
|
||||
resourceendtime = await time_convert(order_info.get('resourceEndTime')) if order_info.get(
|
||||
'resourceEndTime') else None
|
||||
|
||||
order_key = order_info['key']
|
||||
update_order_goods_sql = """ UPDATE order_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceids = '%s',
|
||||
og.resourcestarttime = '%s',
|
||||
og.resourceendtime = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, resourceendtime, order_key, ns.get('order_id'))
|
||||
await sor.sqlExe(update_order_goods_sql, {})
|
||||
update_customer_goods_sql = """ UPDATE customer_goods og
|
||||
JOIN bz_order o ON og.orderid = o.id
|
||||
SET
|
||||
og.resourceid = '%s',
|
||||
og.start_date = '%s',
|
||||
og.expire_date = '%s'
|
||||
WHERE
|
||||
og.orderkey = '%s'
|
||||
AND o.provider_orderid = '%s'; """ \
|
||||
% (resourceids, resourcestarttime, resourceendtime, order_key, ns.get('order_id'))
|
||||
await sor.sqlExe(update_customer_goods_sql, {})
|
||||
|
||||
async def baidu_order_cancel(ns={}):
|
||||
baidu_id = ns['baidu_id']
|
||||
order_id = ns['order_id']
|
||||
paydata = {'queryAccountId': baidu_id, 'orderIds': [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()
|
||||
return {
|
||||
'status': True,
|
||||
'msg': 'order cancel success'
|
||||
}
|
||||
|
||||
async def get_baidu_orderlist(ns={}):
|
||||
"""
|
||||
百度支付
|
||||
1、获取订单
|
||||
2、算出购买的产品折扣
|
||||
3、比对账号余额
|
||||
"""
|
||||
# 增加延迟
|
||||
import asyncio
|
||||
await asyncio.sleep(2)
|
||||
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()
|
||||
with open('baidu_new_order.txt', 'a+') as f:
|
||||
f.write(json.dumps(data_) + '\n')
|
||||
orders = data_['orders']
|
||||
serviceType = orders[0]['orderItems']
|
||||
|
||||
# 可能获取得到的是延迟订单
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] != 'CREATED':
|
||||
return {
|
||||
'status': False,
|
||||
'msg': 'delay_order'
|
||||
}
|
||||
|
||||
# 避免重复退订
|
||||
if orders[0]['type'] == 'REFUND' and orders[0]['status'] == 'CREATED':
|
||||
order_history = await sor.R('bz_order', {'provider_orderid': ns.get('order_id'), 'business_op': 'BUY_REVERSE', 'order_status': '1'})
|
||||
if order_history:
|
||||
print('此订单之前已经退费成功')
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '此订单之前已经退费成功'
|
||||
}
|
||||
|
||||
# 如果是退款 更新数据库状态
|
||||
if orders[0]['type'] == 'REFUND':
|
||||
updatetime = await time_convert(orders[0]['updateTime']) if orders[0].get('updateTime') else None
|
||||
update_refund_sql = """UPDATE baidu_orders SET price = '%s', status = '%s', updatetime = '%s' WHERE orderid = '%s';""" % \
|
||||
(float(orders[0]['price']), orders[0]['status'], updatetime, ns.get('order_id'))
|
||||
await sor.sqlExe(update_refund_sql, {})
|
||||
|
||||
productType = 'prepay'
|
||||
# 判断订单item中productType是否有后付费的产品
|
||||
for item in orders:
|
||||
order_items = item['orderItems']
|
||||
for order_info in order_items:
|
||||
postpay_price = order_info['itemFee']['price'] if order_info.get('itemFee') else order_info['catalogPrice']
|
||||
if not postpay_price:
|
||||
# cpt1Price: 固定配置,按分钟计费
|
||||
postpay_price = order_info['pricingDetail'].get('cpt1Price') if order_info.get('pricingDetail') else 0
|
||||
|
||||
# 确定是否是后付费订单
|
||||
if order_info['productType'] == 'postpay' and postpay_price != 0:
|
||||
productType = 'postpay'
|
||||
# 获取余额
|
||||
user_balance = await getCustomerBalance(sor, orgid[0]['id'])
|
||||
# 判断余额是否大于50
|
||||
if user_balance < 50:
|
||||
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': '后付费 该账号余额不足50,无法完成购买'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '您的余额小于该产品的起购金额50元, 目前无法购买立即充值'
|
||||
}
|
||||
# 实付价格
|
||||
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': '支付形式目前仅包含购买,续费,退订'
|
||||
}
|
||||
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['originalprice'] = sum(i['catalogPrice'] for i in serviceType)
|
||||
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'})
|
||||
if not product:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '未配置该产品, 请联系售后处理'
|
||||
}
|
||||
# 获取协议
|
||||
saleprotocol_to_person = await sor.R('saleprotocol',
|
||||
{'bid_orgid': orgid[0]['id'], 'offer_orgid': orgid[0]['parentid'],
|
||||
'del_flg': '0'})
|
||||
# 等于空就代表这个客户没有特殊折扣,就要找到买方为*的协议
|
||||
saleprotocol_to_all = await sor.R('saleprotocol', {'bid_orgid': '*', 'offer_orgid': orgid[0]['parentid'],
|
||||
'del_flg': '0', 'salemode': '0'})
|
||||
|
||||
if saleprotocol_to_person:
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol_to_person[0]['id'],
|
||||
'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
if not product_salemode:
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol_to_all[0]['id'],
|
||||
'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
else:
|
||||
product_salemode = await sor.R('product_salemode',
|
||||
{'protocolid': saleprotocol_to_all[0]['id'],
|
||||
'productid': product[0]['id'],
|
||||
'del_flg': '0'})
|
||||
if not product_salemode:
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '还未上线这个产品的协议配置'
|
||||
}
|
||||
supply_price = i['itemFee']['price'] if i.get('itemFee') else i['catalogPrice']
|
||||
financePrice = abs(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'] = abs(i['realCatalogPrice'] / i['count'])
|
||||
else:
|
||||
nss['list_price'] = abs(i['realCatalogPrice'])
|
||||
nss['discount'] = product_salemode[0]['discount']
|
||||
nss['quantity'] = i['count']
|
||||
nss['price'] = abs(round(nss['list_price'] * product_salemode[0]['discount'], 2))
|
||||
# 计算总价
|
||||
# nss['amount'] = round(total_price, 2)
|
||||
nss['amount'] = abs(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 ''
|
||||
nss['orderkey'] = i.get('key')
|
||||
|
||||
# 如果是续费订单 由于没有返回日期, 重新计算日期
|
||||
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:
|
||||
if i.get('resourceStartTime'):
|
||||
nss['resourcestarttime'] = await time_convert(i.get('resourceStartTime'))
|
||||
else:
|
||||
nss['resourcestarttime'] = await time_convert(orders[0]['updateTime'])
|
||||
|
||||
if i.get('resourceEndTime'):
|
||||
nss['resourceendtime'] = await time_convert(i.get('resourceEndTime'))
|
||||
|
||||
# 后付费没有资源结束时间
|
||||
if i.get('productType') == 'prepay':
|
||||
end_time = await time_convert(orders[0]['updateTime'])
|
||||
nss['resourceendtime'] = await cal_expire_time(history_time=end_time,
|
||||
chargeduration=nss['chargeduration'],
|
||||
unit=nss['unit'])
|
||||
else:
|
||||
nss['resourceendtime'] = 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:
|
||||
await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
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()
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品错误, 请联系售后'
|
||||
}
|
||||
|
||||
# 判断用户账户余额是否足够支付
|
||||
try:
|
||||
count = await getCustomerBalance(sor, orgid[0]['id'])
|
||||
if order_type == 'REFUND':
|
||||
count = total_price + 0.1
|
||||
|
||||
if round(total_price,2) <= count:
|
||||
#判断预付费或者后付费
|
||||
if productType == 'prepay' or productType == 'postpay':
|
||||
# 调用扣费接口
|
||||
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': '支付错误, 请联系售后'
|
||||
}
|
||||
|
||||
# 预配置local_refund用于本地操作
|
||||
if order_type == 'REFUND' and not ns.get('local_refund'):
|
||||
return {
|
||||
'status': True,
|
||||
'msg': '本地退费成功'
|
||||
}
|
||||
else:
|
||||
# 调用支付订单接口
|
||||
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}:
|
||||
ns_record = {
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': '购买成功'
|
||||
}
|
||||
await user_action_record(ns_record)
|
||||
ns_cron_job = {
|
||||
'id': uuid(),
|
||||
'source': 'baidu',
|
||||
'orderid': ns.get('order_id'),
|
||||
'ordertype': orders[0]['type'],
|
||||
'userid': ns.get('userid'),
|
||||
'reason': 'buy success'
|
||||
}
|
||||
await sor.C('baidu_cron_job', ns_cron_job)
|
||||
# return {
|
||||
# 'status': True,
|
||||
# 'orderid': bz_ns['id']
|
||||
# }
|
||||
else:
|
||||
await sor.rollback()
|
||||
await baidu_order_cancel(
|
||||
{'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
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:
|
||||
await baidu_order_cancel({'baidu_id': baidu_users[0]['baidu_id'], 'order_id': ns.get('order_id')})
|
||||
import traceback
|
||||
with open('baiducloud_err.txt', 'w') as f:
|
||||
f.write(str(e)+ traceback.format_exc())
|
||||
traceback.print_exc()
|
||||
await sor.rollback()
|
||||
return {
|
||||
'status': False,
|
||||
'msg': '产品错误, 请联系售后'
|
||||
}
|
||||
# 更新资源时间 资源id
|
||||
# if order_type == 'NEW':
|
||||
# await baidu_new_update_resouce(ns)
|
||||
return {
|
||||
'status': True,
|
||||
'orderid': bz_ns['id'],
|
||||
'originalprice': bz_ns.get('originalprice'),
|
||||
'servicename': bz_ns.get('servicename'),
|
||||
'amount': total_price
|
||||
}
|
||||
|
||||
ret = await get_baidu_orderlist(params_kw)
|
||||
return ret
|
||||
56
b/baiducloud/index.html
Normal file
56
b/baiducloud/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
13
b/bill/addbill.dspy
Normal file
13
b/bill/addbill.dspy
Normal file
@ -0,0 +1,13 @@
|
||||
async def addbill(ns):
|
||||
|
||||
"""添加账单"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
ns['id'] = uuid()
|
||||
await sor.C('bill', ns)
|
||||
return {'status': True, 'msg': '添加成功'}
|
||||
return {'status': False, 'msg': '添加失败'}
|
||||
|
||||
ret = await addbill(params_kw)
|
||||
return ret
|
||||
12
b/bill/dlebill.dspy
Normal file
12
b/bill/dlebill.dspy
Normal file
@ -0,0 +1,12 @@
|
||||
async def dlebill(ns):
|
||||
"""删除账单"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
ns['del_flg'] = '1'
|
||||
await sor.U('bill', ns)
|
||||
return {'status': True, 'msg': '删除成功'}
|
||||
return {'status': False, 'msg': '删除失败'}
|
||||
|
||||
ret = await dlebill(params_kw)
|
||||
return ret
|
||||
17
b/bill/getbill.dspy
Normal file
17
b/bill/getbill.dspy
Normal file
@ -0,0 +1,17 @@
|
||||
async def getbill(ns):
|
||||
"""查询账单"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at'
|
||||
ns['order'] = 'desc'
|
||||
reacs = await sor.R('bill',ns)
|
||||
for i in reacs['rows']:
|
||||
ns = {'id':i['customerid'],'del_fig':'0'}
|
||||
customer = await sor.R('organization', ns)
|
||||
i['orgname'] = customer[0]['orgname']
|
||||
return {'status': True, 'data': reacs}
|
||||
|
||||
ret = await getbill(params_kw)
|
||||
return ret
|
||||
56
b/bill/index.html
Normal file
56
b/bill/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
11
b/bill/upbill.dspy
Normal file
11
b/bill/upbill.dspy
Normal file
@ -0,0 +1,11 @@
|
||||
async def upbill(ns):
|
||||
"""修改账单"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
await sor.U('bill', ns)
|
||||
return {'status': True, 'msg': '修改成功'}
|
||||
return {'status': False, 'msg': '修改失败'}
|
||||
|
||||
ret = await upbill(params_kw)
|
||||
return ret
|
||||
56
b/bo_old/addbz_order.dspy
Normal file
56
b/bo_old/addbz_order.dspy
Normal file
@ -0,0 +1,56 @@
|
||||
async def addbz_order(ns):
|
||||
"""
|
||||
生成订单 立即下单
|
||||
userid : 用户id
|
||||
`goods`:'产品id',
|
||||
`spec_id`: '规格id',
|
||||
`quantity`:'数量',
|
||||
`transname` :'交易名称',
|
||||
`providerid` : '供应商id',
|
||||
`order_status` : '0:未支付,1:已交付;2:已关闭;3:已取消;4:后付费',
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
try:
|
||||
user = await sor.R('users', {'id': await get_user()})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid']})
|
||||
amountadll = 0
|
||||
bz_ns = {}
|
||||
# bz_ns['id'] = UUID()
|
||||
bz_ns['id'] = uuid()
|
||||
bz_ns['order_status'] = '0'
|
||||
bz_ns['business_op'] = 'BUY'
|
||||
bz_ns['userid'] = await get_user()
|
||||
bz_ns['customerid'] = orgid[0]['id']
|
||||
bz_ns['order_date'] = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
if ns.get('specdataid'):
|
||||
bz_ns['specdataid'] = ns['specdataid']
|
||||
await sor.C('bz_order', bz_ns)
|
||||
# 添加账户表
|
||||
nss = {}
|
||||
nss['id'] = uuid()
|
||||
# nss['id'] = UUID()
|
||||
nss['orderid'] = bz_ns['id']
|
||||
nss['productid'] = ns.get('productid')
|
||||
nss['providerid'] = ns.get('providerid')
|
||||
nss['list_price'] = ns.get('list_price')
|
||||
nss['discount'] = ns.get('discount')
|
||||
nss['quantity'] = ns.get('quantity')
|
||||
nss['price'] = ns.get('amount')
|
||||
nss['spec_id'] = ns.get('spec_id')
|
||||
if int(ns.get('quantity')) > 1:
|
||||
nss['amount'] = float(ns['amount']) * int(ns['quantity'])
|
||||
amountadll += nss['amount']
|
||||
else:
|
||||
nss['amount'] = ns['amount']
|
||||
amountadll += float(nss['amount'])
|
||||
await sor.C('order_goods', nss)
|
||||
await sor.U('bz_order', {'id': bz_ns['id'], 'amount': amountadll})
|
||||
return {'status': True, 'msg': '添加成功', 'bz_id': bz_ns['id']}
|
||||
except Exception as error:
|
||||
raise error
|
||||
return {'status': False, 'msg': '添加失败'}
|
||||
|
||||
ret = await addbz_order(params_kw)
|
||||
return ret
|
||||
93
b/bo_old/affirmbz_order.dspy
Normal file
93
b/bo_old/affirmbz_order.dspy
Normal file
@ -0,0 +1,93 @@
|
||||
async def affirmbz_order(ns):
|
||||
"""确认支付"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
# 查询产品说明是否是product_sync
|
||||
order_productid_providerid = await sor.R('order_goods', {'orderid': ns['orderid']})
|
||||
order_productid = order_productid_providerid[0]['productid']
|
||||
order_providerid = order_productid_providerid[0]['providerid']
|
||||
description = (await sor.R('product', {'id': order_productid}))[0]['description']
|
||||
if description == 'product_sync':
|
||||
# 根据orderid在order_goods里查询对应账单
|
||||
# order_providerid = (await sor.R('order_goods', {'orderid': ns['orderid']}))[0]['providerid']
|
||||
# 查询阿里云得id
|
||||
ali_id_li = await sor.R('organization', {'orgname': '阿里云'})
|
||||
if ali_id_li:
|
||||
ali_id = ali_id_li[0]['id']
|
||||
else:
|
||||
ali_id = None
|
||||
# 查询开元云得id
|
||||
k_id_li = await sor.R('organization', {'orgname': '开元云'})
|
||||
if k_id_li:
|
||||
k_id = k_id_li[0]['id']
|
||||
else:
|
||||
k_id = None
|
||||
|
||||
target_id = None
|
||||
if order_providerid == ali_id:
|
||||
target_id = ali_id
|
||||
if order_providerid == k_id:
|
||||
target_id = k_id
|
||||
if target_id:
|
||||
# 查询业主机构针对所有客户的普通协议
|
||||
protocolid = (await sor.R('saleprotocol', {'offer_orgid': 'mIWUHBeeDM8mwAFPIQ8pS', 'bid_orgid': '*', 'salemode': '2', 'del_flg': '0'}))[0]['id']
|
||||
# 在产品价格表中更新价格配置
|
||||
id_sql = """select id, price from product_salemode where protocolid = '%s' and providerid = '%s' and productid = '%s' order by price desc limit 1;""" % (protocolid, target_id, order_productid)
|
||||
id_find = (await sor.sqlExe(id_sql, {}))[0]['id']
|
||||
# 查询价格
|
||||
current_price = (await sor.R('bz_order', {'id': ns['orderid']}))[0]['amount']
|
||||
await sor.U('product_salemode', {'id': id_find, 'price': current_price})
|
||||
|
||||
orgid = await sor.R('bz_order', {'id': ns['orderid']})
|
||||
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:
|
||||
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'] = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
if ns.get('product_url'):
|
||||
nss['product_url'] = ns.get('product_url')
|
||||
await sor.C('customer_goods', nss)
|
||||
v = {}
|
||||
v['orderid'] = orgid[0]['id']
|
||||
v['customerid'] = orgid[0]['customerid']
|
||||
v['providerid'] = product[0]['providerid']
|
||||
v['productid'] = product[0]['id']
|
||||
v['quantity'] = j['quantity']
|
||||
await path_call('../pub/hpc_save_bill.dspy', v)
|
||||
return {'status': True, 'msg': '支付成功'}
|
||||
except Exception as error:
|
||||
raise error
|
||||
else:
|
||||
return {'status': False, 'msg': '参数错误'}
|
||||
return {'status': False, 'msg': '支付失败'}
|
||||
|
||||
ret = await affirmbz_order(params_kw)
|
||||
return ret
|
||||
18
b/bo_old/cancelbz_order.dspy
Normal file
18
b/bo_old/cancelbz_order.dspy
Normal file
@ -0,0 +1,18 @@
|
||||
async def cancelbz_order(ns):
|
||||
"""取消订单"""
|
||||
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
try:
|
||||
# 需要加事务
|
||||
await sor.U('bz_order', {'id': ns['orderid'], 'order_status': '3'})
|
||||
return {'status': True, 'msg': '取消订单'}
|
||||
except Exception as error:
|
||||
raise error
|
||||
else:
|
||||
return {'status': False, 'msg': '参数错误'}
|
||||
return {'status': False, 'msg': '取消失败'}
|
||||
|
||||
ret = await cancelbz_order(params_kw)
|
||||
return ret
|
||||
24
b/bo_old/chargeback.dspy
Normal file
24
b/bo_old/chargeback.dspy
Normal file
@ -0,0 +1,24 @@
|
||||
async def chargeback(ns):
|
||||
""" 退单
|
||||
id:订单的id
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
await sor.U('bz_order', {'id':ns['id'],'business_op':'BUY_REVERSE','order_status':'0'})
|
||||
await order2bill(ns['id'], sor)
|
||||
bills = await sor.R('bill', {'orderid':ns.get('id')})
|
||||
for i in bills:
|
||||
ba = BillAccounting(i)
|
||||
r = await ba.accounting(sor)
|
||||
order_goods = await sor.R('customer_goods', {'orderid': ns['id']})
|
||||
for j in order_goods:
|
||||
await sor.U('customer_goods', {'id': j['id'],'del_flg':'1'})
|
||||
await sor.U('bz_order', {'id': ns['id'], 'order_status':'3'})
|
||||
return {'status': True, 'msg': '成功'}
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {'status': False, 'msg': '失败'}
|
||||
|
||||
ret = await chargeback(params_kw)
|
||||
return ret
|
||||
51
b/bo_old/customer_cartpay.dspy
Normal file
51
b/bo_old/customer_cartpay.dspy
Normal file
@ -0,0 +1,51 @@
|
||||
async def customer_cartpay(ns):
|
||||
""" 购物车下单
|
||||
"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
try:
|
||||
customer_cart = await sor.R('customer_cart', {'id':ns['id']})
|
||||
amount = 0
|
||||
count = 0
|
||||
bz_ns = {}
|
||||
# bz_ns['id'] = UUID()
|
||||
bz_ns['id'] = uuid()
|
||||
for i in eval(ns.get('goods')):
|
||||
count += 1
|
||||
cart_goods = await sor.R('cart_goods', {'id': i})
|
||||
amount += float(cart_goods[0]['amount'])
|
||||
nss = {}
|
||||
nss['id'] = uuid()
|
||||
# nss['id'] = UUID()
|
||||
nss['orderid'] = bz_ns['id']
|
||||
nss['productid'] = cart_goods[0]['productid']
|
||||
product = await sor.R('product', {'id': cart_goods[0]['productid']})
|
||||
nss['providerid'] = product[0]['providerid']
|
||||
nss['list_price'] = cart_goods[0].get('list_price')
|
||||
nss['discount'] = cart_goods[0].get('discount')
|
||||
nss['quantity'] = cart_goods[0].get('quantity')
|
||||
nss['price'] = cart_goods[0].get('price')
|
||||
nss['spec_id'] = cart_goods[0].get('spec_id')
|
||||
nss['amount'] = cart_goods[0].get('amount')
|
||||
await sor.C('order_goods', nss)
|
||||
sql = """ UPDATE cart_goods SET del_flg = '1' WHERE id = ${id}$ """
|
||||
nsa = {'id': i}
|
||||
await sor.sqlExe(sql, nsa)
|
||||
bz_ns['order_status'] = '0'
|
||||
bz_ns['business_op'] = 'BUY'
|
||||
bz_ns['amount'] = amount
|
||||
bz_ns['customerid'] = customer_cart[0]['customerid']
|
||||
bz_ns['order_date'] = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
await sor.C('bz_order', bz_ns)
|
||||
olen = customer_cart[0]['goods_cnt']
|
||||
ncount = olen - count
|
||||
oamount = float(customer_cart[0]['amount'])
|
||||
namount = oamount - amount
|
||||
await sor.U('customer_cart', {'id': ns['id'],'amount':namount,'goods_cnt':ncount})
|
||||
return {'status': True, 'msg': '添加成功', 'bz_id': bz_ns['id']}
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {'status': False, 'msg': '添加失败'}
|
||||
|
||||
ret = await customer_cartpay(params_kw)
|
||||
return ret
|
||||
12
b/bo_old/dlebz_order.dspy
Normal file
12
b/bo_old/dlebz_order.dspy
Normal file
@ -0,0 +1,12 @@
|
||||
async def dlebz_order(ns):
|
||||
"""删除订单"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
ns['del_flg'] = '1'
|
||||
await sor.U('bz_order', ns)
|
||||
return {'status': True, 'msg': '删除成功'}
|
||||
return {'status': False, 'msg': '删除失败'}
|
||||
|
||||
ret = await dlebz_order(params_kw)
|
||||
return ret
|
||||
93
b/bo_old/getbz_order.dspy
Normal file
93
b/bo_old/getbz_order.dspy
Normal file
@ -0,0 +1,93 @@
|
||||
async def getbz_order(ns):
|
||||
"""查询订单详情/我的所有订单"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
try:
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at desc'
|
||||
if ns.get('id') and not ns.get('type'):
|
||||
# 查询订单详情
|
||||
reacs = await sor.R('bz_order', ns)
|
||||
reacsgoods = await sor.R('order_goods', {'orderid': ns['id'], 'del_flg': '0'})
|
||||
for i in reacsgoods:
|
||||
if i['discount'] == None or i['discount'] == 1.0:
|
||||
del i['discount']
|
||||
goods = await sor.R('product', {'id': i['productid'], 'del_flg': '0'})
|
||||
if len(goods) >= 1:
|
||||
i['productid'] = goods[0]['name']
|
||||
i['ptype'] = goods[0]['ptype']
|
||||
reacs[0]['order_goods'] = reacsgoods
|
||||
return {'status': True, 'data': reacs}
|
||||
elif ns.get('type') == '200':
|
||||
#筛选支付类型
|
||||
user = await sor.R('users', {'id': await get_user(), 'del_flg': '0'})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid'], 'del_flg': '0'})
|
||||
ns['customerid'] = orgid[0]['id']
|
||||
if ns.get('id'):
|
||||
#根据订单号搜索
|
||||
reacs = await sor.R('bz_order', {'id': ns['id']})
|
||||
elif ns.get('start_time'):
|
||||
sql = """select * from bz_order where del_flg = 0 AND customerid = ${customerid}$ AND order_date >= ${start_time}$ AND order_date <= ${end_time}$ ORDER BY order_date DESC """
|
||||
start_time = ns.get('start_time') + ' 00:00:00'
|
||||
end_time = ns.get('end_time') + ' 23:59:59'
|
||||
reacs = await sor.sqlExe(sql, {'start_time': start_time,'end_time': end_time,'customerid' :ns['customerid']})
|
||||
|
||||
else:
|
||||
reacs = await sor.R('bz_order', {'customerid':ns['customerid'],'sort':'order_date desc','order_status':ns.get('order_status'),'del_flg':'0'})
|
||||
all_price = 0
|
||||
if len(reacs) >= 1:
|
||||
for j in reacs:
|
||||
reacsgoods = await sor.R('order_goods', {'orderid': j['id'], 'del_flg': '0'})
|
||||
countlist_price = 0
|
||||
for i in reacsgoods:
|
||||
if i['discount'] == None or i['discount'] == 1.0:
|
||||
del i['discount']
|
||||
goods = await sor.R('product', {'id': i['productid'], 'del_flg': '0'})
|
||||
if len(goods) >= 1:
|
||||
i['productid'] = goods[0]['name']
|
||||
j['order_goods'] = reacsgoods
|
||||
countlist_price += i['list_price']
|
||||
countlist_price *= i['quantity']
|
||||
if j['order_status'] == '1':
|
||||
all_price += countlist_price
|
||||
j['countprice'] = round(countlist_price,2)
|
||||
if j['countprice'] == 0:
|
||||
j['countprice'] = j['originalprice']
|
||||
return {'status': True, 'data': reacs, 'all_price': round(all_price, 2)}
|
||||
else:
|
||||
# 我的所有订单
|
||||
ns['del_flg'] = '0'
|
||||
ns['sort'] = 'create_at desc'
|
||||
user = await sor.R('users', {'id': await get_user(), 'del_flg': '0'})
|
||||
orgid = await sor.R('organization', {'id': user[0]['orgid'], 'del_flg': '0'})
|
||||
ns['customerid'] = orgid[0]['id']
|
||||
reacs = await sor.R('bz_order', {'customerid':ns['customerid'],'sort':'create_at desc','del_flg':'0'})
|
||||
all_price = 0
|
||||
for j in reacs:
|
||||
reacsgoods = await sor.R('order_goods', {'orderid': j['id'], 'del_flg': '0'})
|
||||
countlist_price = 0
|
||||
for i in reacsgoods:
|
||||
if i['discount'] == None or i['discount'] == 1.0:
|
||||
del i['discount']
|
||||
goods = await sor.R('product', {'id': i['productid'], 'del_flg': '0'})
|
||||
if len(goods) < 1:
|
||||
continue
|
||||
i['ptype'] = goods[0]['ptype']
|
||||
if len(goods) >= 1:
|
||||
i['productid'] = goods[0]['name']
|
||||
j['order_goods'] = reacsgoods
|
||||
countlist_price += i['list_price']
|
||||
countlist_price *= i['quantity']
|
||||
if j['order_status'] == '1':
|
||||
all_price += countlist_price
|
||||
j['countprice'] = round(countlist_price,2)
|
||||
if j['countprice'] == 0:
|
||||
j['countprice'] = j['originalprice']
|
||||
return {'status': True, 'data': reacs,'all_price': round(all_price,2)}
|
||||
except Exception as e:
|
||||
raise e
|
||||
return {'status': False, 'msg': '信息错误'}
|
||||
|
||||
ret = await getbz_order(params_kw)
|
||||
return ret
|
||||
56
b/bo_old/index.html
Normal file
56
b/bo_old/index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE HTML>
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: 'Courgette', cursive;
|
||||
}
|
||||
body{
|
||||
background:#f3f3e1;
|
||||
}
|
||||
.wrap{
|
||||
margin:0 auto;
|
||||
width:1000px;
|
||||
}
|
||||
.logo{
|
||||
margin-top:50px;
|
||||
}
|
||||
.logo h1{
|
||||
font-size:200px;
|
||||
color:#8F8E8C;
|
||||
text-align:center;
|
||||
margin-bottom:1px;
|
||||
text-shadow:1px 1px 6px #fff;
|
||||
}
|
||||
.logo p{
|
||||
color:rgb(228, 146, 162);
|
||||
font-size:20px;
|
||||
margin-top:1px;
|
||||
text-align:center;
|
||||
}
|
||||
.logo p span{
|
||||
color:lightgreen;
|
||||
}
|
||||
.sub a{
|
||||
color:white;
|
||||
background:#8F8E8C;
|
||||
text-decoration:none;
|
||||
padding:7px 120px;
|
||||
font-size:13px;
|
||||
font-family: arial, serif;
|
||||
font-weight:bold;
|
||||
-webkit-border-radius:3em;
|
||||
-moz-border-radius:.1em;
|
||||
-border-radius:.1em;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div class="wrap">
|
||||
<div class="logo">
|
||||
<h1>404</h1>
|
||||
<p>The Page not Found</p>
|
||||
<div class="sub">
|
||||
<p><a href="/">Back</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
11
b/bo_old/upbz_order.dspy
Normal file
11
b/bo_old/upbz_order.dspy
Normal file
@ -0,0 +1,11 @@
|
||||
async def upbz_order(ns):
|
||||
"""修改订单"""
|
||||
db = DBPools()
|
||||
async with db.sqlorContext('kboss') as sor:
|
||||
if ns:
|
||||
await sor.U('bz_order', ns)
|
||||
return {'status': True, 'msg': '修改成功'}
|
||||
return {'status': False, 'msg': '修改失败'}
|
||||
|
||||
ret = await upbz_order(params_kw)
|
||||
return ret
|
||||
4536
b/bricks/bricks.js
Normal file
4536
b/bricks/bricks.js
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user