209 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)