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实现新浪博客备份的方法
Apr 27 Python
Python可变参数用法实例分析
Apr 02 Python
TensorFlow实现Batch Normalization
Mar 08 Python
解决Python 使用h5py加载文件,看不到keys()的问题
Feb 08 Python
python3.7简单的爬虫实例详解
Jul 08 Python
python 接口实现 供第三方调用的例子
Aug 13 Python
Python 自动登录淘宝并保存登录信息的方法
Sep 04 Python
python rsa实现数据加密和解密、签名加密和验签功能
Sep 18 Python
python 多维高斯分布数据生成方式
Dec 09 Python
python实现简单文件读写函数
Feb 25 Python
python3 实现mysql数据库连接池的示例代码
Apr 17 Python
pycharm无法安装cv2模块问题
May 20 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
剧场版动画《PSYCHO-PASS 3 FIRST INSPECTOR》3月27日日本上映!
2020/03/06 日漫
用PHP实现将GB编码转换为UTF8
2006/11/25 PHP
判断PHP数组是否为空的代码
2011/09/08 PHP
Notice: Trying to get property of non-object problem(PHP)解决办法
2012/03/11 PHP
php addslashes 利用递归实现使用反斜线引用字符串
2013/08/05 PHP
javascript 火狐(firefox)不显示本地图片问题解决
2008/07/05 Javascript
用Greasemonkey 脚本收藏网站会员信息到本地
2009/10/26 Javascript
父子窗体间传递JSON格式的数据的代码
2010/12/25 Javascript
学习JavaScript的最佳方法分享
2011/10/21 Javascript
关于js new Date() 出现NaN 的分析
2012/10/23 Javascript
javascript数组操作(创建、元素删除、数组的拷贝)
2014/04/07 Javascript
浅谈javascript中的加减时间
2016/07/12 Javascript
详解Angular 自定义结构指令
2017/06/21 Javascript
详解Vue.js Mixins 混入使用
2017/09/15 Javascript
代码分析vue中如何配置less
2018/09/28 Javascript
微信小程序转发事件实现解析
2019/10/22 Javascript
vue 父组件通过v-model接收子组件的值的代码
2019/10/27 Javascript
解决vue的router组件component在import时不能使用变量问题
2020/07/26 Javascript
JS中锚点链接点击平滑滚动并自由调整到顶部位置
2021/02/06 Javascript
React服务端渲染原理解析与实践
2021/03/04 Javascript
python中使用百度音乐搜索的api下载指定歌曲的lrc歌词
2014/07/18 Python
Python中使用装饰器时需要注意的一些问题
2015/05/11 Python
wxPython定时器wx.Timer简单应用实例
2015/06/03 Python
Python模块搜索路径代码详解
2018/01/29 Python
python 中文件输入输出及os模块对文件系统的操作方法
2018/08/27 Python
Python设计模式之组合模式原理与用法实例分析
2019/01/11 Python
基于Python检测动态物体颜色过程解析
2019/12/04 Python
TensorFlow实现批量归一化操作的示例
2020/04/22 Python
用pushplus+python监控亚马逊到货动态推送微信
2021/01/29 Python
香港永安旅游网:Wing On Travel
2017/04/10 全球购物
意大利在线眼镜精品店:Ottica Lipari
2019/11/11 全球购物
2014年创卫实施方案
2014/02/18 职场文书
中学生运动会通讯稿大全
2014/09/18 职场文书
党支部四风整改方案
2014/10/25 职场文书
教师党员个人总结
2015/02/10 职场文书
有关西游记的读书笔记
2015/06/25 职场文书