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学习之asyncore模块用法实例教程
Sep 29 Python
CentOS 7下Python 2.7升级至Python3.6.1的实战教程
Jul 06 Python
Python实现字典按照value进行排序的方法分析
Dec 23 Python
详解Python if-elif-else知识点
Jun 11 Python
python利用插值法对折线进行平滑曲线处理
Dec 25 Python
对python中矩阵相加函数sum()的使用详解
Jan 28 Python
Python实现根据日期获取当天凌晨时间戳的方法示例
Apr 09 Python
关于python3中setup.py小概念解析
Aug 22 Python
python nmap实现端口扫描器教程
May 28 Python
Django自带的加密算法及加密模块详解
Dec 03 Python
python实现音乐播放和下载小程序功能
Apr 26 Python
深入了解python列表(LIST)
Jun 08 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
Ajax+PHP 边学边练 之二 实例
2009/11/24 PHP
PHP项目开发中最常用的自定义函数整理
2010/12/02 PHP
深入解析PHP垃圾回收机制对内存泄露的处理
2013/06/14 PHP
分享微信扫码支付开发遇到问题及解决方案-附Ecshop微信支付插件
2015/08/23 PHP
JavaScript ECMA-262-3 深入解析.第三章.this
2011/09/28 Javascript
js制作的鼠标悬浮时产生的下拉框效果
2012/10/27 Javascript
使用Nodejs开发微信公众号后台服务实例
2014/09/03 NodeJs
javascript文本框内输入文字倒计数的方法
2015/02/24 Javascript
JavaScript代码性能优化总结篇
2016/05/15 Javascript
AngularJS指令中的绑定策略实例分析
2016/12/14 Javascript
jQuery Ajax实现跨域请求
2017/01/21 Javascript
详解如何使用webpack在vue项目中写jsx语法
2017/11/08 Javascript
Angular利用trackBy提升性能的方法
2018/01/26 Javascript
vue 项目中使用Loading组件的示例代码
2018/08/31 Javascript
使用angular-cli webpack创建多个包的方法
2018/10/16 Javascript
超详细的5个Shell脚本实例分享(值得收藏)
2019/08/15 Javascript
在react-antd中弹出层form内容传递给父组件的操作
2020/10/24 Javascript
解读! Python在人工智能中的作用
2017/11/14 Python
python内置函数:lambda、map、filter简单介绍
2017/11/16 Python
对Python多线程读写文件加锁的实例详解
2019/01/14 Python
使用Django简单编写一个XSS平台的方法步骤
2019/03/25 Python
Python实现最常见加密方式详解
2019/07/13 Python
opencv3/C++实现视频背景去除建模(BSM)
2019/12/11 Python
通过代码实例了解Python异常本质
2020/09/16 Python
HTML5 embed标签定义和用法详解
2014/05/09 HTML / CSS
HTML5使用drawImage()方法绘制图像
2014/06/23 HTML / CSS
Html5新增标签有哪些
2017/04/13 HTML / CSS
jurlique茱莉蔻英国官网:澳洲天然护肤品
2018/08/03 全球购物
Skyscanner新西兰:全球领先的旅游搜索网站
2019/08/26 全球购物
俄罗斯运动、健康和美容产品在线商店:Lactomin.ru
2020/07/23 全球购物
客户代表实习人员自我鉴定
2013/09/27 职场文书
党的群众路线教育实践活动批评与自我批评范文
2014/10/16 职场文书
终止劳动合同证明书样本
2014/11/19 职场文书
听证会主持词
2015/07/03 职场文书
《攀登者》:“海拔8000米以上,你不能指望任何人”
2019/11/25 职场文书
mysql sql常用语句大全
2022/06/21 MySQL