django支付宝沙箱使用

该文章介绍了一个使用Python实现的支付宝支付接口,包括直接支付和查询接口,涉及RSA加密和签名验证。同时,文章提到了在Vue前端如何获取支付跳转链接并处理支付回调。此外,还展示了如何初始化支付对象和验证签名。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.安装Copyto

pip install pycryptodome

2.在app目录下创建一个工具文件: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 query_pay(self, out_trade_no,return_url=None, **kwargs):
        biz_content = {
            "out_trade_no": out_trade_no,
           
            # "product_code": "FAST_INSTANT_TRADE_PAY",
            # "qr_pay_mode":4
        }

        biz_content.update(kwargs)
        data = self.build_body("alipay.trade.query", 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)

3. 在应用文件夹下的comm.py中初始化阿里支付对象(也可以新建一个py文件,我的comm文件一般都用来初始化对象)

		修改app_id
		在应用目录下创建keys文件夹存放应用私钥和支付宝公钥

在这里插入图片描述
公钥私钥格式:

private.txt中:
-----BEGIN RSA PRIVATE KEY-----
应用私钥
-----END RSA PRIVATE KEY-----

public.txt中:
-----BEGIN PUBLIC KEY-----
支付宝公钥
-----END PUBLIC KEY-----

from .pay import AliPay

#初始化阿里支付对象
def get_ali_object():
    # 沙箱环境地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info
    app_id = "xxxxxxxxxxxxxxx"  #  APPID (沙箱应用)

    # 支付完成后,支付偷偷向这里地址发送一个post请求,识别公网IP,如果是 192.168.20.13局域网IP ,支付宝找不到,def page2() 接收不到这个请求
    notify_url = "http://localhost:8000/xxx/xxxx"

    # 支付完成后,跳转的地址。
    return_url = "http://localhost:8000/xxx/xxxx"   

    merchant_private_key_path = "/xxx/xxx/keys/private.txt" # 应用私钥
    alipay_public_key_path = "/xxx/xxx/keys/public.txt"  # 支付宝公钥

    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

4.在vue中获取支付宝跳转链接,进入链接进行支付

class OrderRechargeView(APIView):
    def post(self,request):
        # 获取参数
        # 写入充值记录表
        uid = request.data.get('uid')
        timesign = str(time.time()).split('.')
        # 设置订单号
        orderid = timesign[0]+timesign[1]+uid
        # 获取充值金额
        money = float(request.data.get('money'))
        pay = get_ali_object()
        query_params = pay.direct_pay(
            subject="test",  # 商品简单描述
            out_trade_no=str(orderid),  # 用户购买的商品订单号(每次不一样) 20180301073422891
            total_amount=float(money),  # 交易金额(单位: 元 保留俩位小数)
        )
        pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址(沙箱应用)
        return Response({"code": 200, 'payurl': pay_url})

    def get(self,request):
        uid = request.data.get('uid')
        data = request.GET
        print("***进入")
        print(data)
        rdata = {k:v for k,v in data.items()}
        sign = rdata.pop('sign')
        #验签
        alipay = get_ali_object()
        flag = alipay.verify(rdata,sign)
        if flag == True:
            print("通过签名###")
            with transaction.atomic():
                # 创建事务保存点
                save_id = transaction.savepoint()  # 记录了当前数据库的状态
                try:
                    #更新充值订单表
                    #更新用户
                    print("更新成功")
                    transaction.savepoint_commit(save_id)
                except:
                    transaction.savepoint_rollback(save_id)
        return Response({"code":200})

5.前端vue

<template>
    <div class="goodscontent">
        <!-- 充值 -->
        <van-field class="formname"
            v-model="money"
            name="金额"
            label="金额"
            placeholder="金额"
            :rules="[{ required: true, message: '请填写金额' }]"
        />
        <van-button round block type="info" @click="paymoney">支付</van-button>
    </div>
</template>

paymoney(){
            const data = {
                'uid':this.uid,
                'money':this.money
            }
            this.$axios.post('alipayback',data)
            .then(resp=>{
                window.localStorage.href=resp.data.payurl
                if(resp.data.code==200){
                    window.open(resp.data.payurl,'_self')
                    # window.open(url,'_blank'/'_slef')跳转外部链接'_bland'跳转打开新的页面,'_self'在本页面跳转
                }
            })
        }
Django是一个流行的Python Web框架,要将Django应用与支付宝(Alipay)集成并在沙箱环境中进行测试,你需要遵循以下几个步骤: 1. **安装依赖**: 首先,确保你在项目中安装了`django-payments`库,它提供了一套API来处理第三方支付。你可以通过pip安装: ``` pip install django-payments alipay-sdk-python ``` 2. **设置配置**: 在你的Django项目的settings.py中,添加`payments`到INSTALLED_APPS,并配置支付宝的相关信息,如商户ID、私钥等。在`PAYMENTS_PROVIDERS`字典中配置支付宝: ```python PAYMENTS_PROVIDERS = { 'alipay': { 'ENGINE': 'django_payments.alipay.AlibabaProvider', 'APP_ID': '<your_app_id>', 'ALIPAY_PUBLIC_KEY': '<your_public_key>', # 商户公钥 'ALIPAY_PRIVATE_KEY_FILE': os.path.join(BASE_DIR, 'private_keys', 'alipay_private.pem'), # 私钥文件路径 'MODE': 'sandbox', # 使用沙箱环境 }, } ``` 确保替换实际的`<your_app_id>`和`<your_public_key>`。 3. **创建支付视图**: 在`views.py`中,创建一个支付处理视图,例如接收来自Alipay的异步通知: ```python from payments.views import PaymentStatusView class AlipayNotificationView(PaymentStatusView): template_name = 'payment/alipay_notification.html' success_url = '/success/' failure_url = '/failure/' def get_provider(self): return self.request.GET.get('service', '').split('.')[0] ``` 4. **URL路由**: 在urls.py中,添加相应路由指向支付通知视图: ```python path('alipay/notification/', AlipayNotificationView.as_view(), name='alipay_notification'), ``` 5. **前端模板**: 创建一个HTML模板,引导用户点击链接跳转到支付宝支付页面。使用`alipay.js`库来发起请求: ```html <script> // ... 引入alipay.js 和你的支付参数 window.location.href = '{% url 'alipay_payment' %}'; </script> ``` 6. **生成支付链接**: 使用`alipay.provider().get_form()`在后端生成沙箱环境下的支付链接,然后返回给前端展示给用户。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值