zoukankan      html  css  js  c++  java
  • django--- 支付宝退款

    from datetime import datetime
    from Crypto.PublicKey import RSA
    from Crypto.Signature import PKCS1_v1_5
    from Crypto.Hash import SHA256
    from urllib.parse import quote_plus
    from urllib.parse import urlparse, parse_qs
    from base64 import decodebytes, encodebytes
    import json
    import requests
    
    class AliPay(object):
        """
        支付宝支付接口(PC端支付接口)
        """
    
        def __init__(self, appid, app_notify_url, app_private_key_path,
                     alipay_public_key_path, return_url, debug=False):
            self.appid = appid
            self.app_notify_url = app_notify_url
            self.app_private_key_path = app_private_key_path
            self.app_private_key = None
            self.return_url = return_url
            with open(self.app_private_key_path) as fp:
                self.app_private_key = RSA.importKey(fp.read())
            self.alipay_public_key_path = alipay_public_key_path
            with open(self.alipay_public_key_path) as fp:
                self.alipay_public_key = RSA.importKey(fp.read())
    
            if debug is True:
                self.__gateway = "https://openapi.alipaydev.com/gateway.do"
            else:
                self.__gateway = "https://openapi.alipay.com/gateway.do"
    
        def direct_pay(self, subject, out_trade_no, total_amount, return_url=None, **kwargs):
            biz_content = {
                "subject": subject,
                "out_trade_no": out_trade_no,
                "total_amount": total_amount,
                "product_code": "FAST_INSTANT_TRADE_PAY",
                # "qr_pay_mode":4
            }
    
            biz_content.update(kwargs)
            data = self.build_body("alipay.trade.page.pay", biz_content, self.return_url)
            return self.sign_data(data)
    
        def build_body(self, method, biz_content, return_url=None):
            data = {
                "app_id": self.appid,
                "method": method,
                "charset": "utf-8",
                "sign_type": "RSA2",
                "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "version": "1.0",
                "biz_content": biz_content
            }
    
            if return_url is not None:
                data["notify_url"] = self.app_notify_url
                data["return_url"] = self.return_url
    
            return data
    
        def sign_data(self, data):
            data.pop("sign", None)
            # 排序后的字符串
            unsigned_items = self.ordered_data(data)
            unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
            sign = self.sign(unsigned_string.encode("utf-8"))
            # ordered_items = self.ordered_data(data)
            quoted_string = "&".join("{0}={1}".format(k, quote_plus(v)) for k, v in unsigned_items)
    
            # 获得最终的订单信息字符串
            signed_string = quoted_string + "&sign=" + quote_plus(sign)
            return signed_string
    
        def ordered_data(self, data):
            complex_keys = []
            for key, value in data.items():
                if isinstance(value, dict):
                    complex_keys.append(key)
    
            # 将字典类型的数据dump出来
            for key in complex_keys:
                data[key] = json.dumps(data[key], separators=(',', ':'))
    
            return sorted([(k, v) for k, v in data.items()])
    
        def sign(self, unsigned_string):
            # 开始计算签名
            key = self.app_private_key
            signer = PKCS1_v1_5.new(key)
            signature = signer.sign(SHA256.new(unsigned_string))
            # base64 编码,转换为unicode表示并移除回车
            sign = encodebytes(signature).decode("utf8").replace("
    ", "")
            return sign
    
        def _verify(self, raw_content, signature):
            # 开始计算签名
            key = self.alipay_public_key
            signer = PKCS1_v1_5.new(key)
            digest = SHA256.new()
            digest.update(raw_content.encode("utf8"))
            if signer.verify(digest, decodebytes(signature.encode("utf8"))):
                return True
            return False
    
        def verify(self, data, signature):
            if "sign_type" in data:
                sign_type = data.pop("sign_type")
            # 排序后的字符串
            unsigned_items = self.ordered_data(data)
            message = "&".join(u"{}={}".format(k, v) for k, v in unsigned_items)
            return self._verify(message, signature)
    
    
        #请求支付宝退款接口
        def api_alipay_trade_refund(self, refund_amount, out_trade_no=None, trade_no=None, **kwargs):
                biz_content = {
                    "refund_amount": refund_amount
                }
                biz_content.update(**kwargs)
                if out_trade_no:
                    biz_content["out_trade_no"] = out_trade_no
                if trade_no:
                    biz_content["trade_no"] = trade_no
                data = self.build_body("alipay.trade.refund", biz_content)
                url = self.__gateway + "?" + self.sign_data(data)
                r = requests.get(url)
                html = r.content.decode("utf-8")
                return html

    这个是pay.py 文件  这个工具类

    然后导入这个工具类

    #支付方法
    from .pay import AliPay
    
    
    #第三方支付
    def get_ali_object():
        # 沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info
        app_id = "2016092500595776"  #  APPID (沙箱应用)
    
        # 支付完成后,支付偷偷向这里地址发送一个post请求,识别公网IP,如果是 192.168.20.13局域网IP ,支付宝找不到,def page2() 接收不到这个请求
        notify_url = "http://localhost:8000/md_admin/alipayreturn"
    
        # 支付完成后,跳转的地址。
        return_url = "http://localhost:8080/user_center_order.html"
    
        merchant_private_key_path = "C:/Users/dell/www/md/keys/alipay_private_2048.txt.txt" # 应用私钥
        alipay_public_key_path = "C:/Users/dell/www/md/keys/alipay_public_2048.txt"  # 支付宝公钥
    
        alipay = AliPay(
            appid=app_id,
            app_notify_url=notify_url,
            return_url=return_url,
            app_private_key_path=merchant_private_key_path,
            alipay_public_key_path=alipay_public_key_path,  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥
            debug=True,  # 默认False,
        )
        return alipay
    
    
    
    
    
    def alipay_return(request):
        alipay = get_ali_object()
        params = request.GET.dict()
        sign = params.pop('sign', None)
        status = alipay.verify(params, sign)
        print('==================开始==================')
        print('GET验证', status)
        print('==================结束==================')
        return HttpResponse('支付成功')
    
    
    
    #退款
    class Refund(APIView):
    
        def post(self,request):
    
            # 根据当前用户的配置,生成URL,并跳转。
            money = float(request.POST.get('price'))
    
            orderno = request.POST.get('orderno')
    
    
            #实例化支付类
            alipay = get_ali_object()
            #调用退款方法
            order_string = alipay.api_alipay_trade_refund(
            #订单号,一定要注意,这是支付成功后返回的唯一订单号
            out_trade_no=str(orderno),
            #退款金额,注意精确到分,不要超过订单支付总金额
            refund_amount=money,
            #回调网址
            notify_url='http://localhost:8000/md_admin/alipayreturn'
            )
            return HttpResponse(order_string)


    # 支付
    class Page(APIView):

    def post(self,request):

    # 根据当前用户的配置,生成URL,并跳转。
    money = float(request.POST.get('price'))
    print("金钱",money)
    orderno = request.POST.get('orderno')
    print("订单",orderno)

    alipay = get_ali_object()
    # 生成支付的url
    query_params = alipay.direct_pay(
    subject="test", # 商品简单描述
    out_trade_no = str(orderno), # 用户购买的商品订单号(每次不一样) 20180301073422891
    total_amount=money, # 交易金额(单位: 元 保留俩位小数)
    )
    pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params) # 支付宝网关地址(沙箱应用)

    # 获取订单id
    id = request.POST.get("id")

    #改变支付状态,以及支付时间
    res = Orders.objects.filter(id=int(id)).update(orderstate=1,paytime=datetime.datetime.now())

    data = {'name':pay_url}
    return Response(data)

    这个就是退款  在我前面的文档中有支付的详细介绍

    就是这样啦~~~~

  • 相关阅读:
    解决Redis Cluster模式下的排序问题
    zookeeper实现商品秒杀抢购
    zookeeper实现互斥锁
    用dubbo+zookeeper+spring搭建一个简单的http接口程序
    [置顶] 一个优秀的程序员怎样做好时间管理
    [置顶] BOF或EOF中有一个是“真”,或者当前的记录已被删除,所需的操作要求一个当前的记录。
    [置顶] 学生管理系统验收出现的问题及解决方法
    [置顶] 学生管理系统的常见问题
    如何让你成为一个专业的程序员(一)
    关于英语学习法
  • 原文地址:https://www.cnblogs.com/weifeng-888/p/10816579.html
Copyright © 2011-2022 走看看