0
点赞
收藏
分享

微信扫一扫

沙箱环境下后端pc生成支付宝订单流程

ITWYY 2024-01-30 阅读 19

一,支付宝开放平台账户申请

浏览器访问 https://open.alipay.com/develop/sandbox/account

第一次访问会让你填写申请信息注册开发者账号

1,什么是沙箱环境:

按照官方文档上来说,沙箱环境是支付宝开放平台为开发者提供的安全低门槛的测试环境,开发者在沙箱环境中调用接口无需具备所需的商业资质,无需绑定和开通产品,同时不会对生产环境中的数据造成任何影响.

沙箱环境下后端pc生成支付宝订单流程_签名


2,当我们注册好沙箱环境开发者账号页面之后会自动给跳到这里来

沙箱环境下后端pc生成支付宝订单流程_签名_02

注册成功之后会获取到两个值:

  • APPID
  • 支付宝网关地址

开发中需要用到


二,生成秘钥

秘钥用于以后对URL中添加的参数进行加密和校验.

1,下载秘钥生成器

浏览器访问地址:密钥工具下载 - 支付宝文档中心 (alipay.com)

沙箱环境下后端pc生成支付宝订单流程_签名_03

windows平台的下载windows的,mac平台的下载mac的

2,使用秘钥生成器生成密钥

  • 应用公钥
  • 应用私钥

沙箱环境下后端pc生成支付宝订单流程_签名_04


RSA2加密算法默认生成格式为PKCS8(Java适用),如果是非Java的话需要进行格式转换,转换成PKCS1,因为我使用了python代码所以需要先进行格式转换

沙箱环境下后端pc生成支付宝订单流程_支付宝支付_05

测试应用公钥和私钥是否匹配

沙箱环境下后端pc生成支付宝订单流程_签名_06


3,上传应用公钥并获得支付私钥

  • 支付私钥

重新计入沙箱控制台

沙箱环境下后端pc生成支付宝订单流程_签名_07


将应用公钥输入然后加签变更生成支付公钥

沙箱环境下后端pc生成支付宝订单流程_签名_08

沙箱环境下后端pc生成支付宝订单流程_签名_09


上面操作中共获取到三个秘钥:

  • 应用公钥
  • 应用私钥,对以后URL中传入的数据进行签名机密用
  • 支付宝公钥(通过应用公钥生成),在页面支付成功后跳转回来时候,对支付宝给我们传的值进行校验.


4,下载支付宝沙箱app并登录沙箱买家账号

到沙箱控制台

沙箱环境下后端pc生成支付宝订单流程_签名_10

划重点:支付宝沙箱钱包使用沙箱账号登录

划重点:支付宝沙箱钱包使用沙箱账号登录

划重点:支付宝沙箱钱包使用沙箱账号登录

重要的事情说三遍,大家在登录的时候记得 不要直接用自己的账号登

沙箱账号在沙箱账号页签上有提供


三,支付API

参考文档:统一收单下单并支付页面接口 - 支付宝文档中心 (alipay.com)

沙箱环境下后端pc生成支付宝订单流程_签名_11

支付API的方式就是将支付网关地址https://openapi-sandbox.dl.alipaydev.com/gateway.do?{按文档要求加入的参数,并对请求参数进行处理和签名} 得到的支付URL,当用户点击商品购买后就会跳转到这个支付URL上从而完成支付


四,生成签名

对请求参数进行签名,参考文档:签名 - 支付宝文档中心 (alipay.com)


五,代码封装

import datetime
import json
from base64 import encodebytes
from urllib.parse import quote_plus

from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5


class AliPay(object):
    """
    支付宝接口
    """

    def __init__(self, appid, app_notify_url, app_private_key_path,
                 alipay_public_key_path, return_url):
        self.appid = appid
        self.app_notify_url = app_notify_url
        self.app_private_key_path = app_private_key_path
        self.alipay_public_key_path = alipay_public_key_path
        self.return_url = return_url
        with open(self.app_private_key_path) as fp:
            self.app_private_key = RSA.importKey(fp.read())
        with open(self.alipay_public_key_path) as fp:
            self.alipay_public_key = RSA.importKey(fp.read())

    def direct_pay(self, subject, out_trade_no, total_amount, **kwargs):
        print(self)
        biz_content = {
            'out_trade_no': out_trade_no,
            'product_code': 'FAST_INSTANT_TRADE_PAY',
            'total_amount': total_amount,
            'subject': subject
        }
        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):
        print(self)
        data = {
            'app_id': self.appid,
            'method': method,
            'format': 'JSON',
            'charset': 'utf-8',
            'sign_type': 'RSA2',
            'timestamp': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
            'version': '1.0',
            'biz_content': biz_content
        }
        if return_url:
            data['notify_url'] = self.app_notify_url
            data['return_url'] = self.return_url

        return data

    def sign_data(self, data):
        print(self)
        data.pop('sign', None)
        # 排序后的字符串
        unsigned_items = self.orderd_data(data)
        unsigned_string = "&".join("{0}={1}".format(k, v) for k, v in unsigned_items)
        sign = self.sign(unsigned_string.encode('utf-8'))
        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 orderd_data(self, data):
        print(self)
        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):
        # 开始计算签名
        print(self)
        key = self.app_private_key
        signer = PKCS1_v1_5.new(key)
        signature = signer.sign(SHA256.new(unsigned_string))
        sign = encodebytes(signature).decode('utf-8').replace('\n', '')
        return sign

    def verify(self, params, sign):
        print(self)
        sign_string = self.sign_data(params)
        if sign_string == sign:
            return True
        else:
            return False


六,生成支付url进行支付测试

测试代码

import hashlib
import uuid
from alipay import AliPay

SECRET_KEY = 'ns*i&zys*@az$!iy1pk8fbj-^(ob!ptj^wv6bitj0=*hg66&#i'
ALI_GATEWAY = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do'


def md5(string):
    """MD5加密"""

    hash_object = hashlib.md5(SECRET_KEY.encode('utf-8'))
    hash_object.update(string.encode('utf-8'))
    return hash_object.hexdigest()


def uid(string):
    data = "{}-{}".format(uuid.uuid4(), string)
    return md5(data)


order_id = uid("123")
total_price = 50
ali_pay = AliPay(
    appid=你自己应用的appid,
    app_notify_url=你自己的支付回调地址post请求,
    return_url=支付成功之后get跳转地址,
    app_private_key_path=应用公钥文件保存路径,
    alipay_public_key_path=支付宝公钥文件保存路径
)
query_params = ali_pay.direct_pay(
    subject="xx影视vip",
    out_trade_no=order_id,
    total_amount=total_price
)
pay_url = "{}?{}".format(ALI_GATEWAY, query_params)


最终拿到这个pay_url跳转支付页面,用我们之前下载好的沙箱支付宝进行支付测试就可以了,支付回调地址是我们对支付成功或者失败后所需要进行的操作,一般是对订单入库信息的修改,还有触发系统商品发放之类的...

举报

相关推荐

0 条评论