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 相关文章推荐
在Django的form中使用CSS进行设计的方法
Jul 18 Python
Python正则表达式使用范例分享
Dec 04 Python
python先序遍历二叉树问题
Nov 10 Python
火车票抢票python代码公开揭秘!
Mar 08 Python
Python开发虚拟环境使用virtualenvwrapper的搭建步骤教程图解
Sep 19 Python
python执行CMD指令,并获取返回的方法
Dec 19 Python
Python正则表达式和re库知识点总结
Feb 11 Python
从0开始的Python学习016异常
Apr 08 Python
自适应线性神经网络Adaline的python实现详解
Sep 30 Python
python传到前端的数据,双引号被转义的问题
Apr 03 Python
pip 20.3 新版本发布!即将抛弃 Python 2.x(推荐)
Dec 16 Python
pandas提升计算效率的一些方法汇总
May 30 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邮件发送的两种方式
2020/04/28 PHP
分享PHP守护进程类
2015/12/30 PHP
discuz论坛更换域名,详细文件修改步骤
2020/12/09 PHP
两种简单实现菜单高亮显示的JS类代码
2010/06/27 Javascript
jQuery 常见操作实现方式和常用函数方法总结
2011/05/06 Javascript
JS.GetAllChild(element,deep,condition)使用介绍
2013/09/21 Javascript
Javascript 按位与运算符 (&)使用介绍
2014/02/04 Javascript
[将免费进行到底]在Amazon的一年免费服务器上安装Node.JS, NPM和OurJS博客
2014/08/18 Javascript
JavaScript 2048 游戏实例代码(简单易懂)
2016/03/25 Javascript
jQuery简单入门示例之用户校验demo示例
2016/07/09 Javascript
基于JavaScript实现鼠标箭头移动图片跟着移动
2016/08/30 Javascript
vue实现页面加载动画效果
2017/09/19 Javascript
node.js基于express使用websocket的方法
2017/11/09 Javascript
JS表单传值和URL编码转换
2018/03/03 Javascript
node.js利用socket.io实现多人在线匹配联机五子棋
2018/05/31 Javascript
vue-cli3 项目优化之通过 node 自动生成组件模板 generate View、Component
2019/04/30 Javascript
vue项目中使用scss的方法步骤
2019/05/16 Javascript
JQuery实现ul中添加LI和删除指定的Li元素功能完整示例
2019/10/16 jQuery
vue如何搭建多页面多系统应用
2020/06/17 Javascript
vue路由分文件拆分管理详解
2020/08/13 Javascript
[02:32]DOTA2英雄基础教程 祸乱之源
2013/12/23 DOTA
Python中random模块生成随机数详解
2016/03/10 Python
pycharm中连接mysql数据库的步骤详解
2017/05/02 Python
Python编写一个闹钟功能
2017/07/11 Python
使用Python向C语言的链接库传递数组、结构体、指针类型的数据
2019/01/29 Python
查看keras的默认backend实现方式
2020/06/19 Python
Python3爬虫mitmproxy的安装步骤
2020/07/29 Python
Python selenium环境搭建实现过程解析
2020/09/08 Python
联想墨西哥官方网站:Lenovo墨西哥
2016/08/17 全球购物
Lyle & Scott苏格兰金鹰官网:英国皇室御用品牌
2018/05/09 全球购物
大学生自荐书范文
2013/12/10 职场文书
中介公司区域经理岗位职责范本
2014/03/02 职场文书
实习介绍信模板
2015/01/30 职场文书
幼儿园师德师风心得体会
2016/01/12 职场文书
pytorch中F.avg_pool1d()和F.avg_pool2d()的使用操作
2021/05/22 Python
pytorch 两个GPU同时训练的解决方案
2021/06/01 Python