2025-03-17 18:06:54 +08:00

181 lines
8.2 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.

#!/bin/python
#coding: utf-8
# +-------------------------------------------------------------------
# | system: django-vue-lyadmin
# +-------------------------------------------------------------------
# | Author: lybbn
# +-------------------------------------------------------------------
# | QQ: 1042594286
# +-------------------------------------------------------------------
# ------------------------------
# 支付宝支付
# ------------------------------
# 支付官网文档地址https://opendocs.alipay.com/open/00a0ut
# ------------------------------
from extra_apps.python_alipay_sdk import AliPay
from config import ALIPAY_APPID,ALIPAY_PRIVATE_KEY_PATH,ALIPAY_PUBLIC_KEY_PATH
from utils.common import float2dot
ALIPAY_URL = 'https://openapi.alipaydev.com/gateway.do?'
# 获取公私钥字符串
app_private_key_string = open(ALIPAY_PRIVATE_KEY_PATH).read()
alipay_public_key_string = open(ALIPAY_PUBLIC_KEY_PATH).read()
# 生成支付宝对象
def initalipay():
alipay = AliPay(
appid=ALIPAY_APPID,
app_notify_url=None,# 默认回调url
app_private_key_string=app_private_key_string, # 私钥路径
alipay_public_key_string=alipay_public_key_string, # 公钥路径(支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥)
sign_type="RSA2",
debug=False,# 上线则改为False , 沙箱True
)
return alipay
def alipay_trade_app(out_trade_no,total_amount,subject,notify_url):
"""
功能app支付场景
out_trade_no:本地订单号
total_amount:需要支付金额
subject:标注,支付回调通知时会原样返回
notify_url:异步回调通知地址
return 返回支付地址
"""
alipay = initalipay()
order_string=alipay.api_alipay_trade_app_pay(
subject=subject,
out_trade_no=out_trade_no,
total_amount=float2dot(total_amount),
notify_url=notify_url# 可选, 不填则使用默认notify url
)
# 拼接应答地址(支付宝app支付不需要拼接ALIPAY_URL)
pay_url = order_string
return pay_url
def alipay_trade_refund(trade_no,refund_amount,notify_url):
"""
功能:支付宝退款申请
trade_no:原支付宝支付返回的订单号
total_amount:需要支付金额
return 返回支付地址
"""
alipay = initalipay()
order_string=alipay.api_alipay_trade_refund(
trade_no=trade_no,
refund_amount=float2dot(refund_amount),
notify_url=notify_url# 可选, 不填则使用默认notify url
)
res = order_string
return res
def alipay_cashout(out_trade_no,payee_account,amount,payee_real_name=None, remark=None, payer_show_name=None,payee_type="ALIPAY_LOGONID"):
"""
功能:支付宝转账(提现)
:param out_biz_no: 转账订单号(必选)
:param payee_account: 收款方账户 (必选) 与payee_type配合使用。付款方和收款方不能是同一个账户
:param amount: 转账金额 (必选) 如12.23
:param payee_real_name:收款方姓名 (可选)如:如果本参数不为空,则会校验该账户在支付宝登记的实名是否与收款方真实姓名一致。
:param remark: 转账备注 (可选)
:param payer_show_name:付款方姓名 (可选) 如:上海交通卡退款
:param payee_type: 收款方账户类型(必选) ALIPAY_USERID 支付宝账号对应的支付宝唯一用户号。以2088开头的16位纯数字组成、ALIPAY_LOGONID 支付宝登录号,支持邮箱和手机号格式
:return:
"""
alipay = initalipay()
result = alipay.api_alipay_fund_trans_toaccount_transfer(
out_biz_no=out_trade_no,
payee_type=payee_type, # 收款方账户类型
payee_account=payee_account, # 收款方账户
amount=amount, # 转账金额
payee_real_name=payee_real_name, # 收款方姓名(可选,若不匹配则转账失败)
remark=remark, # 转账备注
payer_show_name=payer_show_name # 付款方姓名
)
# result={'code':'10000','msg':'Success','order_id': '','out_biz_no': '', 'pay_date': '2017-06-26 14:36:25'}
# 接口文档https://docs.open.alipay.com/api_28/alipay.fund.trans.toaccount.transfer
# if result['code'] == '10000':
# if result['msg'] == "Success":
# print("转账成功" + " 交易单号:" + result["order_id"])
#
# else:
# print(result)
# print(result['sub_msg'])
return result
def alipay_trade_query(out_trade_no=None, trade_no=None):
"""
支付宝账单查询
"""
alipay = initalipay()
result = alipay.api_alipay_trade_query(out_trade_no,trade_no)
return result
def alipay_trade_precreate(subject=None,out_trade_no=None,total_amount=0,notify_url=None):
"""
支付宝当面付:统一收单线下交易预创建(用户扫商家收款码)
"""
alipay = initalipay()
if not subject:
subject = out_trade_no
if float(total_amount)<=0:
raise ValueError("total_amount金额错误")
result = alipay.api_alipay_trade_precreate(subject,out_trade_no,float2dot(total_amount),notify_url)
if not result['code'] == "10000":
raise ValueError("%s"%result['sub_msg'])
return result
#支付宝回调实例
# class alipay_notify(APIView):
# """
# 支付成功后,支付宝服务器异步通知回调(用于修改订单状态)
# 返回fail之后支付宝会再回调一次也就是失败的回调一共回调2次
# """
# def post(self,request):
# # 1. 先将sign剔除掉
# processed_dict = {}
# for key, value in request.POST.items():
# processed_dict[key] = value
# # 异步通知data参数转换字典后示例如下
# """
# {'gmt_create': '2021-11-22 08:53:05', 'charset': 'utf-8', 'seller_email': 'xxx@126.com', 'subject': '20211122085257269506402001', 'sign': 'dAUOnG1u8/Fap+aDCSa+P2AXFv4vqr3BK4vKTxevai4F3sdN4X6an8GulmKjk3cx1Z9OMp05JAcBCPi+1CXJoy6opybYqr+M/uDUiAYH+MA4ilazSskS/WC22iZhS4oAVjwouGp+Wbu6pmNMM/gFNCxnlf3K+bCa/gzDDPTCTEoZT3IoeQdZ4ERmuNi7WdCCIm8jNaS8nRXS8bEkk7r7PvYs1kO3H9uZhViSKmlx+Qfklm+mRa1xheNd2UJ1pYcVGK4snlUJL4tKO/VEzPb2trFxYfI3y4q2EPBPCHcI24L1IZeZXrugx6mFJm02SntCrTA+/ysb7e59zoNrBmu+gQ==', 'buyer_id': '2088312606228550', 'invoice_amount': '0.01', 'notify_id': '2021112200222085305028551438751992', 'fund_bill_list': '[{"amount":"0.01","fundChannel":"PCREDIT"}]', 'notify_type': 'trade_status_sync', 'trade_status': 'TRADE_SUCCESS', 'receipt_amount': '0.01', 'app_id': '2021002194665673', 'buyer_pay_amount': '0.01', 'sign_type': 'RSA2', 'seller_id': '2088341077382474', 'gmt_payment': '2021-11-22 08:53:05', 'notify_time': '2021-11-22 08:56:13', 'version': '1.0', 'out_trade_no': '20211122085257269506402001', 'total_amount': '0.01', 'trade_no': '2021112222001428551424684280', 'auth_app_id': '2021002194665673', 'buyer_logon_id': '159****7057', 'point_amount': '0.00'}
# """
# logger.error("收到支付宝回调通知:%s" % (processed_dict))
# sign = processed_dict.pop("sign", None)
# # 2. 生成一个Alipay对象
# alipay = initalipay()
# # 3. 进行验签,确保这是支付宝给我们的
# verify_re = alipay.verify(processed_dict, sign)
# # 如果验签成功
# if verify_re is True:
# order_sn = processed_dict.get('out_trade_no', None)#自己平台的订单号
# trade_no = processed_dict.get('trade_no', None)#支付宝的订单号
# trade_status = processed_dict.get('trade_status', None)
# if trade_status == "TRADE_SUCCESS":#支付成功
# # 查询数据库中存在的订单
# order = BuyVipRecord.objects.filter(orderno=order_sn,status=False).first()
# if not order:
# return HttpResponse('fail')
# order.tradeno = trade_no
# order.status = True
# order.save()
# #其他逻辑处理
# orderpaysuccess(order.id)
# return HttpResponse('success')
# else:
# return HttpResponse('fail')
# else:
# return HttpResponse('fail')
## 测试代码
# if __name__ == '__main__':
# alipay_trade_app('123123',50,"testpay",None)