Django调用支付宝接口代码实例详解


Posted in Python onApril 04, 2020

支付宝支付

正式环境:用营业执照,申请商户号,appid

测试环境:沙箱环境:https://openhome.alipay.com/platform/appDaily.htm?tab=info

支付宝提供接口:给商户使用,收钱

  • -Java,php,C#的demo,没有python的demo
  • -git有人封装了
  • -需要安装模块:pip3 install
  • -应用私钥---自己保存,一定不能丢
  • -应用公钥---给别人用
  • -支付宝公钥---支付宝用的
  • -生成公钥私钥:https://docs.open.alipay.com/291/105971
  • -把应用公钥配置在支付宝上:应用公钥,配置完成以后,支付宝自动生成一个支付宝公钥
  • -在程序中:配置应用私钥,支付宝公钥
  • -如果支付成功,支付宝会回调,但是如果你的服务器挂掉了怎么办?
  • -支付宝24小时以内不定时再给你发,你修改掉订单状态即可
  • -支付成功,支付宝会有一个get回调,一个post回调:修改订单状态

支付宝接口

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("\n", "")
    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)

视图函数

from django.shortcuts import render, redirect, HttpResponse
from utils.pay import AliPay
import json
import time
def ali():
  # 沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info
  app_id = "2016092000554611"
  # 支付宝收到用户的支付,会向商户发两个请求,一个get请求,一个post请求
  # POST请求,用于最后的检测
  notify_url = "http://42.56.89.12:80/page2/"
  # GET请求,用于页面的跳转展示
  return_url = "http://42.56.89.12:80/page2/"
  merchant_private_key_path = "keys/app_private_2048.txt"
  alipay_public_key_path = "keys/alipay_public_2048.txt"
  # 生成一个AliPay的对象
  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 == "GET":

    return render(request, 'page1.html')
  else:
    money = float(request.POST.get('money'))
    # 生成一个对象
    alipay = ali()
    # 生成支付的url
    # 对象调用direct_pay
    query_params = alipay.direct_pay(
      subject="充气娃娃", # 商品简单描述
      out_trade_no="x2" + str(time.time()), # 商户订单号
      total_amount=money, # 交易金额(单位: 元 保留俩位小数)
    )

    pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)
    print(pay_url)
    # 朝这个地址发get请求
    return redirect(pay_url)


def page2(request):
  alipay = ali()
  if request.method == "POST":
    # 检测是否支付成功
    # 去请求体中获取所有返回的数据:状态/订单号
    from urllib.parse import parse_qs
    body_str = request.body.decode('utf-8')
    print(body_str)

    post_data = parse_qs(body_str)
    print('支付宝给我的数据:::---------',post_data)
    post_dict = {}
    for k, v in post_data.items():
      post_dict[k] = v[0]
    print('转完之后的字典',post_dict)

    sign = post_dict.pop('sign', None)
    status = alipay.verify(post_dict, sign)
    print('POST验证', status)
    return HttpResponse('POST返回')

  else:
    params = request.GET.dict()
    sign = params.pop('sign', None)
    status = alipay.verify(params, sign)
    print('GET验证', status)
    return HttpResponse('支付成功')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python使用循环实现批量创建文件夹示例
Mar 25 Python
解决Python中字符串和数字拼接报错的方法
Oct 23 Python
matplotlib 输出保存指定尺寸的图片方法
May 24 Python
python实现定时发送qq消息
Jan 18 Python
Django实现发送邮件功能
Jul 18 Python
python从zip中删除指定后缀文件(推荐)
Dec 05 Python
Python pip install如何修改默认下载路径
Apr 29 Python
在 Python 中使用 MQTT的方法
Aug 18 Python
使用sublime text3搭建Python编辑环境的实现
Jan 12 Python
Python Django 后台管理之后台模型属性详解
Apr 25 Python
详解在OpenCV中如何使用图像像素
Mar 03 Python
Python测试框架pytest高阶用法全面详解
Jun 01 Python
基于python检查SSL证书到期情况代码实例
Apr 04 #Python
python zip,lambda,map函数代码实例
Apr 04 #Python
Python关键字及可变参数*args,**kw原理解析
Apr 04 #Python
150行Python代码实现带界面的数独游戏
Apr 04 #Python
Python decorator拦截器代码实例解析
Apr 04 #Python
浅谈Python中os模块及shutil模块的常规操作
Apr 03 #Python
Python实现多线程下载脚本的示例代码
Apr 03 #Python
You might like
两款万能的php分页类
2015/11/12 PHP
关于Yii2框架跑脚本时内存泄漏问题的分析与解决
2019/12/01 PHP
在IE下获取object(ActiveX)的Param的代码
2009/09/15 Javascript
jQuery中filter()和find()的区别深入了解
2013/09/25 Javascript
javascript 获取函数形参个数
2014/07/31 Javascript
JS组件Bootstrap实现下拉菜单效果代码
2016/04/26 Javascript
AngularJS入门教程之Scope(作用域)
2016/07/27 Javascript
BootStrap glyphicon图标无法显示的解决方法
2016/09/06 Javascript
微信小程序 Image API实例详解
2016/09/30 Javascript
javascript中this关键字详解
2016/12/12 Javascript
基于bootstrap的选择框插件icheck
2016/12/23 Javascript
详解nodejs微信公众号开发——3.封装消息响应模块
2017/04/10 NodeJs
javascript 中select框触发事件过程的分析
2017/08/01 Javascript
webpack处理 css\less\sass 样式的方法
2017/08/21 Javascript
axios进阶实践之利用最优雅的方式写ajax请求
2017/12/20 Javascript
p5.js入门教程之图片加载
2018/03/20 Javascript
微信小程序排坑指南详解
2018/05/23 Javascript
Vue数据绑定简析小结
2019/05/07 Javascript
js中调用微信的扫描二维码功能的实现代码
2020/04/11 Javascript
Element InputNumber计数器的使用方法
2020/07/27 Javascript
python导出chrome书签到markdown文件的实例代码
2017/12/27 Python
基于python 二维数组及画图的实例详解
2018/04/03 Python
python 实现判断ip连通性的方法总结
2018/04/22 Python
Python解决走迷宫问题算法示例
2018/07/27 Python
Python使用random模块生成随机数操作实例详解
2019/09/17 Python
泰国王权免税店官方网站:KingPower
2019/03/11 全球购物
学生周末回家住宿长期请假条
2014/02/15 职场文书
岗位职责风险点
2014/03/12 职场文书
大学新生军训自我鉴定
2014/03/18 职场文书
初中学生期末评语
2014/04/24 职场文书
C++程序员求职信
2014/05/07 职场文书
可怜妈妈观后感
2015/06/09 职场文书
教师节大会主持词
2015/07/06 职场文书
二胎满月酒致辞
2015/07/29 职场文书
2016年春节问候语
2015/11/11 职场文书
CSS 鼠标点击拖拽效果的实现代码
2022/12/24 HTML / CSS