支付宝沙箱环境 支付
一 什么是沙箱:
沙箱环境是支付宝开放平台为开发者提供的安全低门槛的测试环境
支付宝正式和沙箱环境的区别 :
AI:
-
从沙箱到正式环境:
-
当应用程序开发完成后,需要将应用程序从沙箱环境迁移到正式环境。
-
这通常涉及到更新应用程序中的配置文件,更换正式的 AppID 和密钥等凭证。
二 注册使用
网址:登录 - 支付宝 点击 进行注册
查看信息:appid
点击查看 应用密钥与支付宝公钥 :appPrivateKey 与 publiceKey
记录一下卖家信息:
三 实现
支付实现的步骤:1.导入依赖 2.配置参数 3.调用方法(API调用) 4.处理响应或异常
具体实现可查看官网文档: 小程序文档 - 支付宝文档中心
小程序文档 - 支付宝文档中心
简易版概述小程序文档 - 支付宝文档中心
小程序文档 - 支付宝文档中心
查看api使用规范 根据需求选择对应的接口方法
比如下面我们要实现的电脑网站的支付功能
对应的就是 Factory.Payment.Page.pay()
Easy 版
有拦截器的 注意放开路径
3.1 导入项目依赖
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-easysdk -->
<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-easysdk</artifactId><version>2.2.0</version>
</dependency>
3.2 编写配置信息:
其中关于//@PostConstruct 是一个 Java 注解,用于标记需要在依赖注入完成后执行的方法。它表示该方法应该在对象创建和属性注入完毕后由容器自动调用,以完成初始化工作。
@Component
@ConfigurationProperties(prefix = "alipay")
@Datapublic class AlipayConfig {// 应用Idprivate String appId;// 应用私钥private String appPrivateKey;// 支付宝公钥private String publiceKey;// 回调接口路径private String notifyUrl;// 支付宝网关地址private String gatewayHost;@PostConstruct//@PostConstruct 是一个 Java 注解,用于标记需要在依赖注入完成后执行的方法。// 它表示该方法应该在对象创建和属性注入完毕后由容器自动调用,以完成初始化工作。// 此注解的方法无参数,返回类型可为空或其他类型。主要用于确保对象完全初始化。public void init(){Config config = new Config();// 基础配置config.protocol = "https";config.gatewayHost = this.gatewayHost;// 支付宝网关地址config.signType = "RSA2";// 业务配置config.appId = this.appId;config.merchantPrivateKey = this.appPrivateKey;config.alipayPublicKey = this.publiceKey;config.notifyUrl = this.notifyUrl;// 将配置信息, 添加到相应的工厂类Factory.setOptions(config);System.out.println("支付宝初始化配置完成");}
}
application.properties
其中 appid appPrivateKey publiceKey 在开发者平台获取
gatewayHost 大家都一样 无需更改
notifyUrl 是内网穿透这里使用不到 现在随便写都可以
alipay.appid=9021000139682312
alipay.appPrivateKey=MIIEvwIBADANBgkqhkiG9w0BAQEFAAS...
alipay.publiceKey=MIIBIjANBgkqhkiG9w0BAQEFAAOC.......
alipay.notifyUrl=http://xxxxxxx/api/alipay/notify
alipay.gatewayHost=openapi-sandbox.dl.alipaydev.com
3.3 调用支付方法
我这里直接在cotroller层编写
@RestController
@RequestMapping("/api/alipay")
public class PayController {/*** 订单支付接口, 核心是调用支付宝的 Factory.Payment.Page().pay() 方法* @param subject 支付对象信息* @param outTradeNo 订单号* @param totalAmount 订单金额* @param returnUrl 支付成功以后返回的页面地址* @return*/@GetMapping("/pay")public void pay(String subject, String outTradeNo, String totalAmount, String returnUrl, HttpServletResponse httpResponse) throws Exception {// 使用支付宝支付页面接口进行支付AlipayTradePagePayResponse response = Factory.Payment.Page().pay(subject, outTradeNo, totalAmount, returnUrl);System.out.println(response);// response.getBody();// 设置HTTP响应内容类型为HTML,编码为UTF-8httpResponse.setContentType("text/html;charset=utf-8");// 向HTTP响应写入支付宝支付页面接口返回的响应体httpResponse.getWriter().write(response.getBody());// 刷新HTTP响应输出流,确保数据立即发送到客户端httpResponse.getWriter().flush();// 关闭HTTP响应输出流,释放资源httpResponse.getWriter().close();}}
Java
可以进行测试后端了!!!!!!!!
可以进行测试后端了!!!!!!!!
可以进行测试后端了!!!!!!!!
http://localhost:8080/api/alipay/pay?subject=%E7%81%AB%E8%BD%A6%E7%A5%A8%E6%94%AF%E4%BB%98&outTradeNo=63172637&totalAmount=16.8&returnUrl=http%3A%2F%2Flocalhost%3A8080%2Fpayok.html%3ForderId%3D312323
3.4 回调方法 配合内网穿透使用
回调就是支付宝在进行扣款操作之后 调用我们的后端 告诉我们支付结果
回调方法如下:
回调中有个验证操作来源于:调用官方给我们提供的方法来验证数据的真实性。
@PostMapping("/notify")public String notify(@RequestParam Map parameterMap) throws Exception {String tradeStatus = parameterMap.getOrDefault("trade_status","").toString();if (tradeStatus.trim().equals("TRADE_SUCCESS")) {// 验证请求的有效性if (Factory.Payment.Common().verifyNotify(parameterMap)) {System.out.println("通过支付宝的验证");System.out.println("订单id:" + parameterMap.get("out_trade_no"));}else {System.out.println("支付验证不通过");}}return "success";}
需要先开启内网穿透
服务器为localhost:8080 支付宝无法调用:
注意:如果是部署云服务器就不需要内网穿透了 只不过需要我我们对回调的参数进行相对应的修改!!!!
3.5 内网穿透工具
1.路由侠-局域网变公网
设置 信息 主机号
查看内网映射:
测试: 说明映射是没有问题的 成功调用了后端
修改 alipay.notifyUrl 的 配置信息
alipay.notifyUrl=http://xxxk.w1.luyouxia.net/api/alipay/notify
再次进行支付测试:s
这里加上vue进行测试:
前端 vue:
3.6 前端
<template><h2>支付</h2><el-form :inline="true" :model="form" class="demo-form-inline"><el-form-item label="支付对象信息"><el-input v-model="form.subject" placeholder="请输入" clearable /></el-form-item><el-form-item label="订单号"><el-input v-model="form.outTradeNo" placeholder="请输入" clearable /></el-form-item><el-form-item label="订单金额"><el-input-number v-model="form.totalAmount" placeholder="请输入" clearable /></el-form-item><el-form-item label="支付成功以后返回的页面地址"><el-input v-model="form.returnUrl" placeholder="请输入" clearable /></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">提交</el-button></el-form-item></el-form><br><h2>退款</h2><el-form :inline="true" :model="form2" class="demo-form-inline"><el-form-item label="退款单号"><el-input v-model="form2.outTradeNo" placeholder="请输入" clearable /></el-form-item><el-form-item label="退款金额"><el-input-number v-model="form2.refundAmount" placeholder="请输入" clearable /></el-form-item><el-form-item><el-button type="primary" @click="onSubmit2">提交</el-button></el-form-item></el-form>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import dayjs from 'dayjs';
import router from '@/router';
import { ElNotification } from 'element-plus'
import { alipayApi } from '@/api';
const form = ref({subject: '小米su8',outTradeNo: dayjs().format('YYYYMMDDHHmmss'),totalAmount: 188888,returnUrl: 'http://localhost:5000/paysuccess'
})const form2 = ref({outTradeNo: '20220422164101',refundAmount: 18888,
})
const onSubmit = () => {let returnUrl = encodeURIComponent(form.value.returnUrl)window.location.href = "http://localhost:8080/api/alipay/pay?subject=" + `${form.value.subject}` + "&outTradeNo=" + `${form.value.outTradeNo}`+ "&totalAmount=" + `${form.value.totalAmount}` + "&returnUrl=" + `${returnUrl}`
}
const onSubmit2 = () => {alipayApi.refund.call({outTradeNo: form2.value.outTradeNo,refundAmount: form2.value.refundAmount}).then(_res => {ElNotification({title: '提示',message: '退款成功',type: 'success',})})
}</script>
测试结果
一方面 : 前端返回我们设置的 returnUrl 界面
另一方: 后端执行 配置的 alipay.notifyUrl=http://xxxk.w1.luyouxia.net/api/alipay/notify
成功
3.7 退款
调用 refund 交易退款方法
@GetMapping("/refund")public String refund( String outTradeNo,Float refundAmount) {try {
com.alipay.easysdk.payment.common.models.AlipayTradeRefundResponse response = Factory.Payment.Common().refund(outTradeNo, String.valueOf(refundAmount));System.out.println(response);if (response.msg.equals("Success")){return "退款成功";}else {throw new BizException(777, "退款失败");}}catch (Exception e){e.printStackTrace();throw new BizException(777, "退款失败");}}
通用版
小程序文档 - 支付宝文档中心
通用版
导入依赖
<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.34.0.ALL</version></dependency>
配置
@Component
@ConfigurationProperties(prefix = "alipay2")
@Data
public class Alipay2Config extends com.alipay.api.AlipayConfig {// 网关地址private String serverUrl;// 应用Idprivate String appId;// 应用私钥private String appPrivateKey;//请求格式private String format;//字符集编码private String charset;//签名类型private String signType;// 支付宝公钥private String publiceKey;// 回调接口路径private String notifyUrl;}
支付
@GetMapping("/pay2")public void pay2(String subject, String outTradeNo, String totalAmount, String returnUrl, HttpServletResponse httpResponse) throws Exception {AlipayClient alipayClient = new DefaultAlipayClient(alipay2Config.getServerUrl(), alipay2Config.getAppId(),alipay2Config.getAppPrivateKey(), alipay2Config.getFormat(), alipay2Config.getCharset(), alipay2Config.getAlipayPublicKey(), alipay2Config.getSignType());AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();request.setNotifyUrl(alipay2Config.getNotifyUrl());request.setReturnUrl(returnUrl);JSONObject bizContent = new JSONObject();bizContent.put("out_trade_no", outTradeNo);bizContent.put("total_amount", totalAmount);bizContent.put("subject", subject);bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");request.setBizContent(bizContent.toString());String form = "";try {// 调用SDK生成表单form = alipayClient.pageExecute(request).getBody();} catch (AlipayApiException e) {e.printStackTrace();}httpResponse.setContentType("text/html;charset=UTF-8");// 直接将完整的表单html输出到页面httpResponse.getWriter().write(form);httpResponse.getWriter().flush();httpResponse.getWriter().close();}
退款
/*** 退款接口** @return*/@GetMapping("/refund2")public String refund2 (String outTradeNo, Float refundAmount){AlipayClient alipayClient = new DefaultAlipayClient("https://openapi-sandbox.dl.alipaydev.com/gateway.do",alipayConfig.getAppId(),alipayConfig.getAppPrivateKey(),"JSON","utf-8",alipayConfig.getPubliceKey(),"RSA2");AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();// 获取获取对应订单信息JSONObject bizContent = new JSONObject();bizContent.put("out_trade_no", outTradeNo);bizContent.put("refund_amount", refundAmount);bizContent.put("out_request_no", "HZ01RF002"); //退款标识,用于查询状态是操作request.setBizContent(bizContent.toString());// 使用支付宝支付页面接口进行支付try {AlipayTradeRefundResponse response = alipayClient.execute(request);System.out.println(response);if (response.isSuccess()) {System.out.println("退款成功");return "退款成功";} else {System.out.println("退款失败");throw new BizException(777, "退款失败");}} catch (Exception e) {e.printStackTrace();System.out.println("退款失败");throw new BizException(777, "退款失败");}}
相关文章:

支付宝沙箱环境 支付
一 什么是沙箱: 沙箱环境是支付宝开放平台为开发者提供的安全低门槛的测试环境 支付宝正式和沙箱环境的区别 : AI: 从沙箱到正式环境: 当应用程序开发完成后,需要将应用程序从沙箱环境迁移到正式环境。 这通常涉及…...
获取unity中prefab的中文文本内容以及和prefab有关的问题
背景1:经常会在开发中遇到策划需要改某个界面,但是我们不知道那是什么界面,只看到一些关键字比如圣诞活动,那这样我就可以轻易找到这个预设了。另外还可以扩展就是收集项目中的所有中文文本然后归集到多语言表中,然后接…...
Web自动化中常用XPath定位方式
在进行Web自动化测试时,元素定位是一个至关重要的环节。XPath(XML Path Language)是一种用于在XML文档中定位节点的语言。在Web自动化中,XPath广泛应用于定位HTML元素。本文将详细介绍几种常用的XPath定位方式,包括绝对…...

Unity3D播放GIF图片使用Animation来制作动画
系列文章目录 unity工具 文章目录 系列文章目录👉前言👉一、下载GIF动图,用PS制作导出帧动画图片👉二、使用Animation制作动画👉三、脚本控制动画播放👉壁纸分享👉总结👉前言 unity播放gif图片,本身是不支持的,但是可以使用其他方法来实现, 1.有一种使用System…...
redo log 和 bin log 的两阶段提交
两阶段提交的过程 当事务提交后,有一个两阶段提交策略。 在开启两阶段提交时,会开启一个 XA 事务(宏观上的事务), Prepare 阶段:将 redo log 的状态设置为 prepare,然后将 事务XID 写入 redo…...
Go基础学习07-map注意事项;多协程对map的资源竞争;sync.Mutex避免竟态条件
文章目录 Go中map使用以及注意事项map使用时的并发安全问题 Go中map使用以及注意事项 Go语言中map使用简单示例: func main() {var mp map[string]int// mp : map[string]int{}val, ok : mp["one"]if ok {fmt.Println(val)} else {fmt.Println(val)}mp[…...

远程服务器安装anaconda并创建虚拟环境
1、承接上文新用户zrcs,在服务器的zrcs文件夹下直接下载anaconda(很慢): wget https://repo.anaconda.com/archive/Anaconda3-2024.06-1-Linux-x86_64.sh 或者选择本地下载,清华大学开源软件镜像站:https:/…...
什么是IIC通信协议?
IIC(Inter-Integrated Circuit)通信协议,又称为I2C(Inter-Integrated Circuit 2)协议,是一种广泛使用的串行通信协议。它由飞利浦半导体公司(现NXP Semiconductors)开发,…...

P3131 [USACO16JAN] Subsequences Summing to Sevens S Python题解
[USACO16JAN] Subsequences Summing to Sevens S 题目描述 Farmer John’s N N N cows are standing in a row, as they have a tendency to do from time to time. Each cow is labeled with a distinct integer ID number so FJ can tell them apart. FJ would like to ta…...

鸿蒙NEXT开发-ArkUI(基于最新api12稳定版)
注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…...

Matplotlib 使用 LaTeX 渲染图表中的文本、标题和数学公式
Matplotlib 使用 LaTeX 渲染图表中的文本、标题和数学公式 Matplotlib 是一个功能强大的 Python 库,用于绘制各种高质量的图表和图形。在许多科研和技术文档中,数学公式是不可或缺的一部分,LaTeX 提供了精美的数学公式渲染能力。Matplotlib …...

Android 安卓内存安全漏洞数量大幅下降的原因
谷歌决定使用内存安全的编程语言 Rust 向 Android 代码库中写入新代码,尽管旧代码(用 C/C 编写)没有被重写,但内存安全漏洞却大幅减少。 Android 代码库中每年发现的内存安全漏洞数量(来源:谷歌)…...

c++primier第十二章类和动态内存
本章内容包括: 对类成员使用动态内存分配隐式和显式地复制构造函数隐式和显式地重载赋值操作符在构造函数中使用new所必须完成的工作使用静态类成员 将布局new操作符用于对象使用指向对象的指针实现队列抽象数据类型(ADT) 动态内存和类 复习范例和静态类成员 首…...

Ansible学习之ansible-pull命令
想要知道ansible-pull是用来做什么的,就需要了解Ansible的工作模,Ansible的工作模式有两种: push模式 push推送,这是Ansible的默认模式,在主控机上编排好playbook文件,push到远程主机上来执行。pull模式 p…...

Linux:磁盘管理
一、静态分区管理 静态的分区方法不可以动态的增加或减少分区的容量。 1、磁盘分区-fdisk 该命令是用于查看磁盘分区情况,和分区管理的命令 命令格式:fdisk [选项] 设备文件名常用命令: -h:查看分区信息 fdisk系统常用命令&…...

FP7209: 用于紫外线消毒灯的 升压LED恒流驱动芯片
现在社会对于居家消毒也越发重视起来。而居家消毒除了75%浓度酒精及各类消毒液外,利用紫外线灯给衣物表面、房间消毒也是一种很好的选择。FP7209 定位于低压线性恒流驱动,精度高、外围电路简单、使用方便且可靠性高,更可广泛应用于商业照明系…...
【华为HCIP实战课程二】OSPF基础介绍和OSPF RID NBMA配置详解
一、OSPF多区域 自治系统(Autonomous System) 一个自治系统是指使用同一种路由协议交换路由信息的一组路由器 1、Area0为骨干区域 2、ABR--关乎3类LSA后续详解 ABR用来连接骨干区域Area0和非骨干区域,它与骨干区域之间既可以是物理连接,也可以是逻辑上的连接。 3、AS…...
网络编程(13)——单例模式
十三、day13 今天学习如何单例模式实现逻辑层的设计。内容包括服务器如何能捕获信号使其安全退出、单例模标类 1. 什么是单例模式? 单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点&…...

基于定制开发与2+1链动模式的商城小程序搭建策略
摘要:本文探讨商城小程序的搭建策略,对比自主组建团队和第三方开发两种方式,强调以第三方开发模式为主的优势。阐述在第三方开发模式下,结合定制开发和21链动模式,如何搭建一款有助于企业商业模式创新与智能商业升级的…...

银河麒麟,apt 安装软件报错640Unknown Status
今天把银行麒麟的机器恢复出厂了,然后apt install 安装极其不稳定,故障现象如下图所示: 错误提示里面有: 640 Unknown Status [IP: 106.116.184.122 80] E: 无法下载 http://archive.kylinos.cn/kylin/KYLIN-ALL/pool/universe/f…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...