# init.py import os from appPublic.log import debug,exception from ahserver.configuredServer import add_startup from ahserver.serverenv import ServerEnv from .notify import get_provider, get_provider_channel from .paylog import PaymentLog, unipay_accounting from .payfee import get_pay_fee, sor_get_pay_fee, get_paychannels, get_pay_feerate # 从 env 或配置载入 provider conf(这里只示例) CONF = { "transfer":{ "pop3server": os.getenv("POP3SERVER", ""), "mail": os.getenv("MAIL", ""), "password": os.getenv("PASSWORD", ""), "from_mail": os.getenv("FROM_MAIL", ""), "account_no": os.getenv("ACCOUNT_NO", "") }, "wechat": { "mchid": os.getenv("WXP_MCHID",""), "appid": os.getenv("WXP_APPID", ""), "cert_serial_no": os.getenv("WXP_SERIAL",""), "private_key_pem": open(os.getenv("WXP_PRIVKEY","./merchant_private_key.pem"),"rb").read(), "api_v3_key": os.getenv("WXP_API_V3_KEY","") }, "paypal": { "client_id": os.getenv("PP_ID",""), "client_secret": os.getenv("PP_SECRET",""), "sandbox": True }, "alipay": { "app_id": os.getenv("ALIPAY_APPID",""), "app_private_key_pem": open(os.getenv("ALIPAY_PRIV","./alipay_priv.pem"),"rb").read(), "alipay_public_key_pem": open(os.getenv("ALIPAY_PUB",""),"rb").read() }, "stripe": { "api_key": os.getenv("STRIPE_KEY","") } } PROVIDERS = {} # 下单接口(统一) async def create_payment(request, params_kw=None): env = request._run_ns if params_kw is None: params_kw = request.params_kw data = params_kw data.request = request provider = data.get("provider") if provider not in PROVIDERS: debug(f'{provider=} is not a valid payment channel') return {"error":"unknown provider"} try: if PROVIDERS[provider] is None: e = Exception(f'{provider} cannot pay') exception(f'{e}') raise e notify_url = env.entire_url(f'notify/{provider}') pl = PaymentLog(request._run_ns) fee = await get_pay_fee(provider, data.amount) channel = get_provider_channel(provider) userid = await env.get_user() orgid = await env.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 plog = await pl.new_log(userid, orgid, provider, amount, fee, client_ip, currency=currency) if plog: data.out_trade_no = plog.id data.customerid = orgid data.userid = userid data.payment_name = payment_name data.notify_url = notify_url data.client_ip = client_ip res = await PROVIDERS[provider].create_payment(data) debug(f'{provider=} instance return {res}') return res raise Exception('write payment_log error') except Exception as e: exception(f'create_payment():{params_kw=}, {e}') raise e # 查询 async def query_payment(request, params_kw=None): if params_kw is None: params_kw = request.params_kw data = params_kw provider = data.get("provider") if provider not in PROVIDERS: return {"error":"unknown provider"} try: if PROVIDERS[provider] is None: e = Exception(f'{provider} cannot pay') exception(f'{e}') raise e res = await PROVIDERS[provider].query(data) return res except Exception as e: exception(f'query_payment():{params_kw}, {e}') raise e # 退款 async def refund_payment(request, params_kw=None): if params_kw is None: params_kw = request.params_kw data = await get_refundable_plog(request, params_kw.id) if data is None: return None if params_kw.amount >= data.total_amount: return None provider = data.channelid if provider not in PROVIDERS: return {"error":"unknown provider"} try: plog = await new_refund_log(request, data.amount, data.id) if PROVIDERS[provider] is None: e = Exception(f'{provider} cannot pay') exception(f'{e}') raise e plog.out_trade_no = plog.origin_id plog.out_request_no = plog.id plog.total_amount = params_kw.amount plog.refund_amount = plog.total_amount plog.notify_url = request.env.entire_url(f'notify/{provider}') res = await PROVIDERS[provider].refund(plog) return res except Exception as e: exception(f'query_payment():{params_kw}, {e}') raise e # 微信支付回调入口 async def wechat_notify(request): debug("wechat notify called .......") json_response = ServerEnv().json_reponse provider = 'wechat' if PROVIDERS[provider] is None: e = Exception(f'{provider} cannot pay') exception(f'{e}') return json_response({"code":"SUCCESS", "message":"OK"}) data = None try: data = await PROVIDERS[provider].handle_notify(request) except Exception as e: e = Exception(f'{provider} cannot pay') exception(f'{e}') return json_response({"code":"SUCCESS", "message":"OK"}) if data is None: return json_response({"code":"SUCCESS", "message":"OK"}) debug(f'{data=}') try: await unipay_accounting(request, data.data) except Exception as e: exception(f'{e}') return json_response({"code":"SUCCESS", "message":"OK"}) # 支付宝回调入口 async def alipay_notify(request): debug("alipay notify called .......") Response = ServerEnv().Response provider = 'alipay' if PROVIDERS[provider] is None: e = Exception(f'{provider} cannot pay') exception(f'{e}') return Response(text='success', status=200) data = None try: data = await PROVIDERS[provider].handle_notify(request) except Exception as e: e = Exception(f'{provider} cannot pay') exception(f'{e}') return Response(text='success', status=200) debug(f'{data=}') try: await unipay_accounting(request, data.data) except Exception as e: exception(f'{e}') return Response(text='success', status=200) async def setup_callback_path(app): app.router.add_post('/unipay/notify/wechat', wechat_notify) app.router.add_post('/unipay/notify/alipay', alipay_notify) # callback url= "/unipay/notify/{provider}" def load_unipay(): PROVIDERS["transfer"] = get_provider("transfer", CONF["transfer"]) PROVIDERS["wechat"] = get_provider("wechat", CONF["wechat"]) PROVIDERS["paypal"] = get_provider("paypal", CONF["paypal"]) PROVIDERS["alipay"] = get_provider("alipay", CONF["alipay"]) PROVIDERS["stripe"] = get_provider("stripe", CONF["stripe"]) env = ServerEnv() env.get_paychannels = get_paychannels env.get_pay_feerate = get_pay_feerate env.create_payment = create_payment env.query_payment = query_payment env.refund_payment = refund_payment env.get_pay_fee = get_pay_fee env.sor_get_pay_fee = sor_get_pay_fee env.PaymentLog = PaymentLog add_startup(setup_callback_path)