diff --git a/README.md b/README.md new file mode 100644 index 0000000..302822e --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# 统一支付 + +支持微信,支付宝,paypal支持 + +## 支付重要信息 +支付重要信息都通过环境变量设置 + +### 微信支付 + +### 支付宝 + +### paypal + diff --git a/json/payment_log.json b/json/payment_log.json new file mode 100644 index 0000000..6b94237 --- /dev/null +++ b/json/payment_log.json @@ -0,0 +1,16 @@ +{ + "tblname": "payment_log", + "title": "充值记录", + "params": { + "sortby": "init_timestamp desc", + "browserfields": { + "exclouded": ["id"], + "logined_userorgid":"customerid", + "alters": { + } + }, + "editexclouded": [ + "id" + ] + } +} diff --git a/models/payment_log.xlsx b/models/payment_log.xlsx new file mode 100644 index 0000000..eb41678 Binary files /dev/null and b/models/payment_log.xlsx differ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..59514a1 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,4 @@ +[build-system] +requires = ["setuptools>=61", "wheel"] +build-backend = "setuptools.build_meta" + diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..59ae3c6 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,15 @@ +[metadata] +name=pricing +version = 0.0.1 +description = A pricing module for online store +author = "yu moqing" +author_email = "yumoqing@gmail.com" +readme = "README.md" +license = "MIT" +[options] +packages = find: +requires_python = ">=3.8" +install_requires = + apppublic + ahserver + sqlor diff --git a/unipay/.notify.py.swp b/unipay/.init.py.swp similarity index 68% rename from unipay/.notify.py.swp rename to unipay/.init.py.swp index 8e3d135..211d800 100644 Binary files a/unipay/.notify.py.swp and b/unipay/.init.py.swp differ diff --git a/unipay/init.py b/unipay/init.py index f69b040..4c94113 100644 --- a/unipay/init.py +++ b/unipay/init.py @@ -1,7 +1,8 @@ # init.py import os -from unipay.notify import get_provider +from unipay.notify import get_provider, get_provider_channel from ahserver.serverenv import ServerEnv +from paylog import PaymentLog # 从 env 或配置载入 provider conf(这里只示例) CONF = { @@ -40,8 +41,21 @@ async def create_payment(request, params_kw=None): if provider not in PROVIDERS: return {"error":"unknown provider"} try: - res = await PROVIDERS[provider].create_payment(data) - return res + pl = PaymentLog(request._run_ns) + channel = get_provider_channel(provider) + userid = await get_suer() + orgid = await get_userorgid() + client_ip = request['client_ip'] + # userid, customerid, channel, payment_name, amount, client_ip, currency='CNY' + payment_name = data.payment_name or "充值", + amount = data.amount + currency = data.currency + id = await pl.new_log(userid, orgid, payment_name, amount, client_ip, currency=currency) + if id: + data.out_trade_no = id + res = await PROVIDERS[provider].create_payment(data) + return res + raise Exception('write payment_log error') except Exception as e: return {"error": str(e)} @@ -86,6 +100,9 @@ async def payment_notify(request, callback, params_kw=None): # 这里 data 应包含标准化字段:out_trade_no/status/attach 等 # TODO: 业务幂等处理 # 返回厂商要求的固定成功响应 + logid = data['out_trade_no'] + pl = PaymentLog(request._run_ns) + await pl.payed_log(logid) await callback(request, data) if provider == "wechat": return {"code":"SUCCESS", "message":"OK"} diff --git a/unipay/notify.py b/unipay/notify.py index 3df05a8..2f75d08 100644 --- a/unipay/notify.py +++ b/unipay/notify.py @@ -6,6 +6,16 @@ from .providers.alipay import AlipayGateway from .providers.stripe import StripeGateway # 简单工厂:你可以按需扩展配置注入 + +def get_provider_channel(name:str): + channels = { + "wechat":"0", + "paypal":"1", + "alipay":"2", + "stripe":"3" + } + return channels.get(name, '9') + def get_provider(name: str, conf: Dict): if name == "wechat": return WechatGateway(**conf) diff --git a/unipay/paylog.py b/unipay/paylog.py new file mode 100644 index 0000000..528dcac --- /dev/null +++ b/unipay/paylog.py @@ -0,0 +1,48 @@ +from sqlor.dbpools import DBPools + +class PaymentLog: + def __init__(self, env): + self.db = DBPools() + self.env = env + + async def new_log(self, userid, customerid, channel, payment_name, amount, client_ip, currency='CNY'): + dbname = await self.env.get_module_dbname('unipay') + async with self.db.sqlorContext(dbname) as sor: + ns = { + "id": self.env.uuid(), + "customerid": customerid, + "payment_channel": channel, + "payment_name": payment_name, + "payer_client_ip": client_ip, + "currency": currency, + "payment_status": '0', + "init_timestamp": timestampstr(), + "userid": userid + } + await sor.C('payment_log', ns) + return True + return False + + async def cancel_log(self, logid): + dbname = await self.env.get_module_dbname('unipay') + async with self.db.sqlorContext(dbname) as sor: + ns = { + "id": logid, + "cancel_timestamp": timestampstr() + } + await sor.U('payment_log', ns) + return True + return False + + async def payed_log(self, logid): + dbname = await self.env.get_module_dbname('unipay') + async with self.db.sqlorContext(dbname) as sor: + ns = { + "id": logid, + "payed_timestamp": timestampstr() + } + await sor.U('payment_log', ns) + return True + return False + + diff --git a/wwwroot/menu.ui b/wwwroot/menu.ui new file mode 100644 index 0000000..48fc451 --- /dev/null +++ b/wwwroot/menu.ui @@ -0,0 +1,15 @@ +{ + "widgettype":"Menu", + "items":[ + { + "name":"recharge", + "label":"充值", + "url":"{{entire_url('recharge.ui')}}" + }, + { + "name":"payment_log", + "label":"充值历史", + "url":"{{entire_url('payment_log')}}" + } + ] +} diff --git a/wwwroot/recharge.dspy b/wwwroot/recharge.dspy new file mode 100644 index 0000000..7d08a0d --- /dev/null +++ b/wwwroot/recharge.dspy @@ -0,0 +1,9 @@ +url = await create_payment(request) +return { + "widgettype":"Iframe", + "options":{ + "url": url, + "height": "100%", + "width":"100%" + } +} diff --git a/wwwroot/recharge.ui b/wwwroot/recharge.ui new file mode 100644 index 0000000..2f37383 --- /dev/null +++ b/wwwroot/recharge.ui @@ -0,0 +1,74 @@ +{ + "widgettype":"Form", + "options":{ + "width": "100%", + "height": "100%", + "fields":[ + { + "name":"provider", + "uitype":"code", + "required":true, + "defautvalue":"wechat", + "label":"充值渠道", + "data":[ + { + "value":"wechat", + "text":"微信支付" + }, + { + "value":"alipay", + "text":"支付宝" + } + ] + }, + { + "name":"amount", + "label":"充值金额", + "required":true, + "uitype":"float", + "lenght":18, + "dec":2 + }, + { + "name":"currency", + "label":"币种", + "uitype":"code", + "defaultvalue":"CNY", + "data":[ + { + "value":"CNY", + "text":"人民币" + }, + { + "value":"USD", + "text": "美元" + } + ] + } + + ] + }, + "binds":[ + { + "wid": "self", + "evnet":"submit", + "actiontype":"urlwidget", + "target":"PopupWindow", + "popup_options":{ +{% if params_kw._is_mobile %} + "width": "95%", + "height": "95%", +{% else %} + "width": "50%", + "height": "50%", +{% endif %} + "archor":"cc" + }, + "options":{ + "url":"{{entire_url('recharge.dspy')}}", + "method":"POST", + "params":{} + } + } + ] +}