python接入支付宝接口

爱⌒轻易说出口 提交于 2019-11-26 08:34:52
  1. 安装包

     # 安装python-alipay-sdk
     # --upgrade 是你之前安装了pycrypto, 加它是升级, 一次都没安装的用户, 直接pip install python-alipay-sdk
     pip install python-alipay-sdk --upgrade
    
  2. 生成密钥文件

     # openssl window上没有, linux下和mac上都带这个命令
     openssl
     OpenSSL> genrsa -out app_private_key.pem   2048  # 私钥
     OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem # 导出公钥
     OpenSSL> exit
    
  3. 把支付宝公钥填写到沙箱环境
    在这里插入图片描述

  4. 把私钥放在项目里
    在这里插入图片描述

  5. 查看支付宝的公钥

在这里插入图片描述

  1. 把支付宝公钥复制粘贴到你项目的alipay_public_key.pem文件夹里, 记得在头加上

    将-----BEGIN PUBLIC KEY-----添加到支付宝公钥的头部
    将-----END PUBLIC KEY-----添加到支付宝的尾部
    
  2. 初始化

     from alipay import AliPay
     alipay = AliPay(
         appid="",  # 沙箱appid 或 线上appid
         app_notify_url=None,  # 默认回调url  不写的话这里用None
         app_private_key_path="", # 私钥 
         alipay_public_key_path="", # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
         sign_type="RSA", # RSA 或者 RSA2
         debug=False  # 默认False   沙箱环境把这里设置为True
     )
    
  3. 根据对象发送请求
    5.1 电脑网站支付 alipay.trade.page.pay

     # 如果你是Python 2用户(考虑考虑升级到Python 3吧),请确保非ascii的字符串为utf8编码:
     subject = u"测试订单".encode("utf8")
     # 如果你是 Python 3的用户,使用默认的字符串即可
     subject = "测试订单"
     
     # 电脑网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string 这是线上环境
     # 电脑网站支付, 需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string 这是沙箱环境
     order_string = alipay.api_alipay_trade_page_pay(
         out_trade_no="20161112",  # 订单编号
         total_amount="0.01",  # 总金额
         subject=subject,  # 订单标题 随便写个字符串
         return_url="https://example.com", # 返回的链接地址
         notify_url="https://example.com/notify" # 可选, 不填则使用默认notify url 不填这里写None
     )
    

    5.2 手机网站支付 alipay.trade.wap.pay

     # 手机网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string 这是线上环境
     # 手机网站支付, 需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string 这是沙箱环境
     order_string = alipay.api_alipay_trade_wap_pay(
         out_trade_no="20161112",  # 订单编号
         total_amount="0.01",  # 总金额
         subject=subject,  # 订单标题 随便写个字符串
         return_url="https://example.com",  # 返回的链接地址
         notify_url="https://example.com/notify" # 可选, 不填则使用默认notify url  不填这里写None
     )
    

    5.3 App支付 alipay.trade.app.pay

     # App支付,将order_string返回给app即可
     order_string = alipay.api_alipay_trade_app_pay(
         out_trade_no="20161112",  # 订单id
         total_amount=0.01,  # 总金额
         subject=subject,  # 订单标题  随便写个字符串
         notify_url="https://example.com/notify" # 可选, 不填则使用默认notify url  不填这里写None
     )
    
  4. 基于flask的简单验证

     from flask import Flask
     from flask import request
     app = Flask(__name__)
     
     @app.route('/', methods=["GET", "POST"])
     def hello_world():
         data = request.form.to_dict()
         # sign 不能参与签名验证
         signature = data.pop("sign")
     
         print(json.dumps(data))
         print(signature)
     
         # verify
         success = alipay.verify(data, signature)
         if success and data["trade_status"] in ("TRADE_SUCCESS", "TRADE_FINISHED" ):
             print("trade succeed") 
    
  5. 列子

    1. 支付宝付款接口链接返回给前端

       from . import api
       from ihome.models import Order
       from ihome.utils.commons import login_required
       from flask import g, current_app, jsonify
       from ihome.utils.response_code import RET
       from ihome import constants
       from alipay import AliPay
       import os
       
       @api.route("/orders/<int:order_id>/payment", methods=["POST"])
       @login_required
       def order_pay(order_id):
           """
           订单支付
           :param order_id: 订单的id
           :return: 支付宝支付的链接地址 格式json
           """
       
           # 接收用户id
           user_id = g.user_id
       
           # 校验参数
           # 根据order_id查询数据库, order_id是否存在, 订单是否属于该用户, 订单是否是待支付状态
           try:
               order = Order.query.filter(Order.id == order_id, Order.user_id == user_id, Order.status == "WAIT_PAYMENT").first()
           except Exception as e:
               current_app.logger.error(e)
               return jsonify(errnum=RET.DBERR, errmsg=u"获取订单信息失败")
       
           if order is None:
               return jsonify(errnum=RET.NODATA, errmsg=u"订单信息不存在")
       
           # 业务处理
           # 创建支付宝sdk的工具对象
           alipay_client = AliPay(
               appid="2016092500596768",  # 沙箱appid 或 线上appid
               app_notify_url=None,  # 默认回调url  不写的话这里用None
               # os.path.dirname(__file__): 获取当前文件所在目录的路径
               app_private_key_path=os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem"),  # 私钥
               alipay_public_key_path=os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem"),  # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
               sign_type="RSA2",  # RSA 或者 RSA2
               debug=False  # 默认False   沙箱环境把这里设置为True
           )
       
           # 手机网站支付,需要跳转到https://openapi.alipay.com/gateway.do? + order_string 这是线上环境
           # 手机网站支付, 需要跳转到https://openapi.alipaydev.com/gateway.do? + order_string 这是沙箱环境
           order_string = alipay_client.api_alipay_trade_wap_pay(
               out_trade_no=order.id,  # 订单编号
               total_amount=str(order.amount/100.0),  # 总金额
               subject=u"订单编号 %s" % order.id,  # 订单标题 随便写个字符串
               return_url="http://172.16.66.238:5000/orders.html",  # 返回的链接地址
               notify_url=None  # 可选, 不填则使用默认notify url  不填这里写None
           )
       
           # 构造让用户跳转的支付链接地址 这里用的是沙箱环境
           pay_url = constants.ALIPAY_URL_PREFIX + order_string
       
           # 返回应答
           return jsonify(errnum=RET.OK, errmsg=u"ok", data={"pay_url": pay_url}) 
      
    2. 前端回跳的参数
      在这里插入图片描述
      在这里插入图片描述

    3. 验证是否是支付宝发送过来的

       @api.route("/order/payment", methods=["PUT"])
       def save_order_payment_result():
           """保存订单支付结果"""
           # 接收参数
           # 将form表单数据转换成字典
           alipay_dict = request.form.to_dict()
       
           # 对支付宝的数据进行分离  提取出支付宝的签名参数sign 和剩下的其他数据
           alipay_sign = alipay_dict.pop("sign")
       
           # 业务处理
           # 创建支付宝sdk的工具对象
           alipay_client = AliPay(
               appid="2016092500596768",  # 沙箱appid 或 线上appid
               app_notify_url=None,  # 默认回调url  不写的话这里用None
               # os.path.dirname(__file__): 获取当前文件所在目录的路径
               app_private_key_path=os.path.join(os.path.dirname(__file__), "keys/app_private_key.pem"),  # 私钥
               alipay_public_key_path=os.path.join(os.path.dirname(__file__), "keys/alipay_public_key.pem"),
               # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
               sign_type="RSA2",  # RSA 或者 RSA2
               debug=False  # 默认False   沙箱环境把这里设置为True
           )
       
           # 借助工具验证参数的合法性
           # 如果确定参数是支付宝的, 返回True, 否则返回False
           result = alipay_client.verify(alipay_dict, alipay_sign)
       
           if result:
               # 获取订单id
               order_id = alipay_dict.get("out_trade_no")
       
               # 获取支付宝交易号
               trade_no = alipay_dict.get("trade_no")
       
               try:
               	 # 这里是根据订单id查询这个订单, 并且更新订单里的status和trade_no着两个字段
                   Order.query.filter_by(id=order_id).update({"status": "WAIT_COMMENT", "trade_no": trade_no})
                   # 保存到数据库中
                   db.session.commit()
               except Exception as e:
               	# 有异常记录log日志
                   current_app.logger.error(e)
                   # 回滚到提交前
                   db.session.commit()
       
           # 返回应答
           return jsonify(errnum=RET.OK, errmsg=u"ok")
      
  6. 线上环境就是把沙箱的appid换成线上的appid, 访问的域名用线上的域名.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!