• 第三方支付 -----支付宝支付流程


    大家都知道  第三方支付 已经普遍都在使用,所以我今天就说一下支付宝的支付流程

    首先进入支付宝平台,点击开发中心-》研发服务

    获得沙盒的appid以及商户公钥和支付宝公钥

    然后利用秘钥生成软件生成私钥和公钥

    建立keys文件夹,  将私钥和公钥文件放入keys

    加入头部和尾部代码

    最后用支付宝公钥替换公钥文件

    安装第三方库

    pip3 install -i https://pypi.douban.com/simple pycryptodome

    pay.py

    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

    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 get_ali_object():

        # 沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info

        app_id = "2016092600603658"  #  APPID (沙箱应用)

        # 支付完成后,支付偷偷向这里地址发送一个post请求,识别公网IP,如果是 192.168.20.13局域网IP ,支付宝找不到,def page2() 接收不到这个请求

        notify_url = "http://localhost:8000/md_admin/alipayreturn"

        # 支付完成后,跳转的地址。

        return_url = "http://localhost:8000/md_admin/alipayreturn"

        merchant_private_key_path = "c:/Users/liuyue/www/md/keys/app_private_2048.txt" # 应用私钥

        alipay_public_key_path = "c:/Users/liuyue/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 page1(request):

        if request.method == "POST":

            # 根据当前用户的配置,生成URL,并跳转。

            money = float(request.POST.get('money'))

            alipay = get_ali_object()

            # 生成支付的url

            query_params = alipay.direct_pay(

                subject="test",  # 商品简单描述

                out_trade_no="myorder" + str(time.time()),  # 用户购买的商品订单号(每次不一样) 20180301073422891

                total_amount=money,  # 交易金额(单位: 元 保留俩位小数)

            )

            pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址(沙箱应用)

            return redirect(pay_url)

        else:

            return render(request,'md_admin/page1.html')

    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('支付成功')

  • 相关阅读:
    看门狗定时器
    fork 和 exec
    openwrt procd分析
    减肥经验总结
    gcc
    laravel5验证码
    laravel5通过auth.attempt事件加入登陆验证码
    双向链表
    mysql5.6源码安装
    laravel4通过控制视图模板路劲来动态切换主题
  • 原文地址:https://www.cnblogs.com/weifeng-888/p/10692361.html
Copyright © 2020-2023  润新知