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