zoukankan      html  css  js  c++  java
  • 支付宝支付流程

    支付宝支付
      -如何接入支付宝支付
        -商户号:需要跟支付宝申请,需要有公司的营业执照
          -开发人员在开发之前就拿到了
        -appid,开发用的,商户唯一的id(沙箱环境的appid:2016092000554xxx)
        -开发人员需要去支付宝官方文档按照步骤一步一步做(有人帮你封装好了)
        -沙箱环境(测试环境)
        -三种密钥(非对称加密)
          -应用私钥(商户私钥):不能外泄
          -应用公钥:可以给别人
          上面这两个是:用https://alipay.open.taobao.com/docs/doc.htm?treeId=291&articleId=105971&docType=1生成

          -支付宝公钥:在支付宝开发平台配置上应用公钥,自动生成的
         -在项目中配置两个密钥:
          -应用私钥
          -支付宝公钥(不是应用公钥)
        -支付宝支付流程****************************:
          -1 生成一个AliPay对象,传入,appid,get回调地址,post回调地址,商户私钥,支付宝公钥
            -商户公钥和私钥是支付宝提供的软件生成的
            -支付宝的公钥:在网站上通过商户公钥生成的
          -2 调用对象的direct_pay()方法,传入商品描述,商品订单号,商品价格,返回一堆字符串,拼接到支付宝网关的后面
          -3 向支付宝网关发送get请求,看到支付页面,用户付款
          -4 付款成功,支付宝会有一个get回调,一个post回调(需要对回调内容进行验签,alipay.verify)
            -一般get回调用于显示页面
            -post回调用于修改订单状态

    支付宝
    1.搜索蚂蚁金服,进入蚂蚁金服开放平台->登录

    2.需要使用沙箱环境进行开发。开发文档->沙箱环境

    3.首次需要生成秘钥。开发文档->签名工具,windows需要下载软件,生成一对公钥和密钥

    4.三个密钥:
      应用私钥:需要配置在支付宝中(若在后续使用时遇见验签问题,查看是否配置时出错)
      应用公钥:需要配置在项目中(不可泄露)
      支付宝公钥:在个人信息配置中点击查看支付宝公钥,需要配置在项目中

    5.在文档中心->支付API->alipay.trade.pay(统一收单交易支付接口)查看api接口规范,其中最重要的两个参数sign和biz_content

    6.已封装好的接口代码,单独建立文件alipay.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 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)

    7. views中使用

    class PayViewset()
        alipay = AliPay(
            appid="2016346813xxx",  # appid
            app_notify_url="http://54.28.33.60/page1",  # post请求,用于最后检测是否支付成功(异步)
            app_private_key_path="../KEYS/app-private-2048.txt",
            alipay_public_key_path="../KEYS/alipay-public-2048.txt",  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥
            return_url="http://54.28.33.60/page2",  # get请求,用于支付宝支付完成后立即跳转的页面(同步)
            debug=True,  # 默认False,
        )
        url = alipay.direct_pay(
            subject="测试订单",  # 订单名称
            out_trade_no="201702021222",  # 订单号
            total_amount=100  # 支付金额
        )
        re_url = "https://openapi.alipaydev.com/gateway.do?{data}".format(data=url)  # 此链接就是支付页面的链接
        return redirect(re_url)
    
    
    class Alipay(APIView):
        def get(self):
            '''
            处理return_url接收到的请求
            :return:
            '''
            # 处理与notify_url请求相似,根据业务需求
            pass
    
        def post(self,request):
            '''
            处理notify_url接收到的请求
            :return:
            '''
            processed_dict = {}  # 定义一个字典,用来存放支付宝发来的信息,后面用起来方便
            for key,value in request.POST.items():
                processed_dict[key] = value
            sign = processed_dict.pop('sign',None)  # 将签名取出并删除掉
            
            # 再次实例化一下
            alipay = AliPay(
                appid="2016346813545",  #
                app_notify_url="http://54.28.33.60/page1",  
                app_private_key_path="../KEYS/app-private-2048.txt",
                alipay_public_key_path="../KEYS/alipay-public-2048.txt",  
                return_url="http://54.28.33.60/page2",  
                debug=True,  # 默认False,
            )
    
            verify_result = alipay.verify(processed_dict,sign)  # verify方法会解析所接收的数据,得到是否支付成功的结果,True or False
            if verify_result 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)
    
                '''order_sn,trade_no,trade_status都是支付宝返回的订单状态,我们 就可以根据这些状态进行其他操作,如修改数据库订单状态等......'''
                
                return Response('success')  # 最后记着给支付宝返回一个信息
            else:
                '''如果verify_result为False,则说明可能是其他恶意请求访问,直接忽略就行'''
                pass   
  • 相关阅读:
    007 连接
    006 group by having
    005 运算null 排序 模糊查询 聚合函数
    004 列、distinct、between、in、null
    003 约束和关系
    002 表的概念操作
    5-04用Sql语句创建表
    5-03使用视图创建表
    5-01表达基本概念
    4-04数据库的备份与还原
  • 原文地址:https://www.cnblogs.com/gyk1030/p/11675871.html
Copyright © 2011-2022 走看看