码迷,mamicode.com
首页 > 其他好文 > 详细

支付宝接口

时间:2019-02-27 01:07:01      阅读:249      评论:0      收藏:0      [点我收藏+]

标签:out   ini   img   需要   not   类型   发送post请求   build   bsp   

蚂蚁金服开放平台

1、沙箱环境

技术图片

 

技术图片

 

2、设置公钥私钥

技术图片

技术图片

 

技术图片

下载完解压,查看文档

技术图片

 

按要求执行

点击RSA签名验签工具.bat文件

技术图片

 

生成后如下

技术图片

 

然后在文件中会自动保存生成的秘钥公钥

技术图片

 

复制应用公钥,然后保存。

技术图片

保存后生成如下

技术图片

上传应用公钥自动生成支付宝公钥,

然后需要下载沙箱支付宝APP。注意:仅供安卓手机。

技术图片

沙箱账号

技术图片

 

具体项目使用

依赖  pip install pycryptodome

技术图片

utils中的pay.py

技术图片
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 urllib.parse import urlparse, parse_qs
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)
pay.py

url.py

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r‘^admin/‘, admin.site.urls),
    url(r‘^index/‘, views.index),
    url(r‘^pay_result/‘, views.pay_result),
    url(r‘^update_order/‘, views.update_order),
]

 models.py

from django.db import models

class Order(models.Model):

    title = models.CharField(max_length=32)
    order_num = models.CharField(max_length=32)
    status_choices = (
        (1,‘未支付‘),
        (2,‘已支付‘),
    )
    status = models.IntegerField(choices=status_choices,default=1)

 views.py

技术图片
from django.shortcuts import render,redirect,HttpResponse
from django.views.decorators.csrf import csrf_exempt
from utils.pay import AliPay
import time
from django.conf import settings

def aliPay():
    obj = AliPay(
        appid=settings.APPID,
        app_notify_url=settings.NOTIFY_URL,  # 如果支付成功,支付宝会向这个地址发送POST请求(校验是否支付已经完成)
        return_url=settings.RETURN_URL,  # 如果支付成功,重定向回到你的网站的地址。
        alipay_public_key_path=settings.PUB_KEY_PATH,  # 支付宝公钥
        app_private_key_path=settings.PRI_KEY_PATH,  # 应用私钥
        debug=True,  # 默认False,
    )
    return obj

def index(request):
    if request.method == GET:
        return render(request,index.html)



    alipay = aliPay()

    # 对购买的数据进行加密
    money = float(request.POST.get(price))
    out_trade_no = "x2" + str(time.time())
    # 1. 在数据库创建一条数据:状态(待支付)

    query_params = alipay.direct_pay(
        subject="充气式韩红",  # 商品简单描述
        out_trade_no= out_trade_no,  # 商户订单号
        total_amount=money,  # 交易金额(单位: 元 保留俩位小数)
    )

    pay_url = "https://openapi.alipaydev.com/gateway.do?{}".format(query_params)

    return redirect(pay_url)


def pay_result(request):
    """
    支付完成后,跳转回的地址
    :param request:
    :return:
    """
    params = request.GET.dict()
    sign = params.pop(sign, None)

    alipay = aliPay()

    status = alipay.verify(params, sign)

    if status:
        return HttpResponse(支付成功)
    return HttpResponse(支付失败)



@csrf_exempt
def update_order(request):
    """
    支付成功后,支付宝向该地址发送的POST请求(用于修改订单状态)
    :param request:
    :return:
    """
    if request.method == POST:
        from urllib.parse import parse_qs

        body_str = request.body.decode(utf-8)
        post_data = parse_qs(body_str)

        post_dict = {}
        for k, v in post_data.items():
            post_dict[k] = v[0]

        alipay = aliPay()

        sign = post_dict.pop(sign, None)
        status = alipay.verify(post_dict, sign)
        if status:
            # 修改订单状态
            out_trade_no = post_dict.get(out_trade_no)
            print(out_trade_no)
            # 2. 根据订单号将数据库中的数据进行更新
            return HttpResponse(支付成功)
        else:
            return HttpResponse(支付失败)
    return HttpResponse(‘‘)
views.py

settings.py

# 支付相关配置
APPID = "2016082500309412"
NOTIFY_URL = "http://47.98.134.86:80/update_order/"
RETURN_URL = "http://47.98.134.86:80/pay_result/"
PRI_KEY_PATH = "keys/app_private_2048.txt"
PUB_KEY_PATH = "keys/alipay_public_2048.txt"

 注意事项:

支付宝支付使用的是RSA加密

需要的是由app公钥生成的支付宝公钥,app私钥

支付宝提交的金额最多保留两位小数

支付宝接口

标签:out   ini   img   需要   not   类型   发送post请求   build   bsp   

原文地址:https://www.cnblogs.com/weidaijie/p/10441010.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!