支付宝沙箱支付

支付宝沙箱支付

支付宝沙箱(Alipay Sandbox)是支付宝提供的一个模拟环境,用于开发者在不影响真实交易的情况下进行支付宝相关功能的测试和调试。在软件开发中,沙箱环境通常指的是一个隔离的测试环境,可以模拟真实环境的行为,但不会对真实数据产生影响。

支付宝沙箱为开发者提供了一套模拟的支付流程和接口,使开发者能够在沙箱环境中进行支付测试,验证其支付功能是否正常工作,而无需使用真实的资金进行交易。这有助于开发者在应用上线之前进行充分的测试,确保支付流程的稳定性和安全性。

使用支付宝沙箱,开发者可以模拟各种支付场景,包括扫码支付、APP支付、H5支付等。此外,支付宝沙箱还提供了一些调试工具和接口文档,帮助开发者更方便地进行测试和开发。

使用支付宝沙箱环境可以帮助开发者在开发和测试阶段及时发现和解决问题,确保支付功能的稳定和安全。一旦开发者在支付宝沙箱环境中完成了测试和调试,就可以将代码和配置切换到真实的支付宝环境中进行生产部署。

支付宝开放平台 (alipay.com)

准备工作

引入依赖

        <!--支付宝--><dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.38.133.ALL</version></dependency><!--其他--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.33</version></dependency>

配置文件

alipay:appId: # 应用idappPrivateKey: # 应用私钥alipayPublicKey: # 支付宝公钥notifyUrl: # 异步通知地址 gateway: # 支付宝网关
server:port: 8088

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码编写

配置类

AliPayConfig 支付宝支付配置类 方便我们获取配置参数

@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {private String appId;private String appPrivateKey;private String alipayPublicKey;private String notifyUrl;private String gateway;
}

AlipayClientConfig 支付宝客户端配置类

@Configuration
public class AlipayClientConfig {@Autowiredprivate AliPayConfig aliPayConfig;@Beanpublic AlipayClient getAlipayClient(){AlipayClient alipayClient = new DefaultAlipayClient(aliPayConfig.getGateway(),aliPayConfig.getAppId(),aliPayConfig.getAppPrivateKey(),AlipayConstants.FORMAT_JSON,AlipayConstants.CHARSET_UTF8,aliPayConfig.getAlipayPublicKey(),AlipayConstants.SIGN_TYPE_RSA2);return alipayClient;}
}

controller

AlipayController

@RestController
@RequestMapping("/alipay")
public class AlipayController {@Autowiredprivate AlipayService alipayService;/***  支付接口* @param order 订单* @return*/@PostMapping("/pay")public R pay(@RequestBody Order order){// 使用时间当订单号order.setOrderId(String.valueOf(System.currentTimeMillis()));return alipayService.pay(order);}/***  订单状态通知 异步通知* @param request* @return* @throws AlipayApiException*/@GetMapping("/notify")public R payNotify(HttpServletRequest request) throws AlipayApiException {return alipayService.payNotify(request);}
}

Service

AlipayService

public interface AlipayService {/***  支付接口* @param order* @return*/R pay(Order order);/***  异步通知* @param request* @return*/R payNotify(HttpServletRequest request);
}

AlipayServiceImpl

@Service
public class AlipayServiceImpl implements AlipayService {@Value("${alipay.alipayPublicKey}")private String publicKey;@Value("${alipay.notifyUrl}")private String notifyUrl;@Autowiredprivate AlipayClient alipayClient;@Overridepublic R pay(Order order){AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();// 异步通知的地址request.setNotifyUrl(notifyUrl);Map<String,String> map = new HashMap<>();map.put("out_trade_no",order.getOrderId());map.put("total_amount",order.getPrice());map.put("subject",order.getSubject());map.put("body",order.getBody());map.put("product_code","FAST_INSTANT_TRADE_PAY");// 设置业务参数request.setBizContent(JSONObject.toJSONString(map));// 发起支付请求// 发起支付请求AlipayTradePagePayResponse response = null;try {response = alipayClient.pageExecute(request);} catch (AlipayApiException e) {throw new RuntimeException(e);}// 获取响应结果if (response.isSuccess()) {System.out.println("调用成功");System.out.println("支付宝支付链接:" + response.getBody());return R.ok(response.getBody());} else {System.out.println("调用失败");System.out.println("错误信息:" + response.getMsg());return R.fail("调用失败",40010);}}@Overridepublic R payNotify(HttpServletRequest request) {Map<String, String[]> paramMap = request.getParameterMap();Map<String, String> params = new HashMap<>();for (Map.Entry<String, String[]> entry : paramMap.entrySet()) {String name = entry.getKey();String[] values = entry.getValue();StringBuilder valueStr = new StringBuilder();for (int i = 0; i < values.length; i++) {valueStr.append((i == values.length - 1) ? values[i] : values[i] + ",");}params.put(name, valueStr.toString());}// 调用SDK验证签名boolean verifyResult = false;try {verifyResult = AlipaySignature.rsaCheckV1(params, publicKey, AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2);} catch (AlipayApiException e) {throw new RuntimeException(e);}if (verifyResult) {// 验证成功,处理业务逻辑,更新订单状态等// 注意:请防止重复处理,可以通过记录支付状态或者订单号来判断是否已经处理过System.out.println("支付宝异步通知验证成功");// 返回给支付宝成功处理的响应return R.ok();} else {// 验证失败,不处理业务逻辑System.out.println("支付宝异步通知验证失败");// 返回给支付宝失败处理的响应return R.fail("支付失败",40010);}}
}

工具类

Order 订单类

@Data
public class Order {// 订单idprivate String orderId;// 价格private String price;// 商品名称private String subject;// 商品描述private String body;// 支付场景/*** FAST_INSTANT_TRADE_PAY(即时到账):适用于即时交易场景,买家付款后,卖家立即收到款项。* QUICK_MSECURITY_PAY(手机网页支付):适用于手机网页支付场景。* FACE_TO_FACE_PAYMENT(当面付):适用于线下面对面付款场景,比如扫码支付。* APP支付(APP支付场景):适用于在APP内的支付场景。* WAP支付(手机网站支付场景):适用于手机网站支付场景。* PRE_AUTH(预授权):适用于预先授权场景,买家授权预先冻结资金,商家在完成业务后调用支付宝解冻资金*/private String code;
}

R 响应类

@Data
public class R {private String data;private String msg;private int code;public R() {}public R (String msg, int code) {this.msg = msg;this.code = code;}public R( String msg, int code,String data) {this.data = data;this.msg = msg;this.code = code;}public static R ok(){return new R("成功",200);}public static R ok(String data){return new R("成功",200,data);}public static R fail(String message, int code) {return new R( message,code);}
}

测试页面

<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><title>商城</title><script src="https://cdn.jsdelivr.net/npm/vue@2"></script><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="box"><div><h1>订单列表</h1><ul><li v-for="order in orders" :key="order.orderId"><h3>{{ order.subject }}</h3><p>价格: ¥{{ order.price }}</p><p>{{ order.body }}</p><button v-on:click="pay(order)">购买</button><hr></li></ul></div><div v-html="paymentFormHtml"></div>
</div>
<script type="text/javascript">var vm = new Vue({el: '#box',data: {orders: [{"price": "12148.00","subject": "iPhone 15 Pro Max 512GB 原色钛金属","body": "iPhone 15 Pro Max 512GB 原色钛金属"},{"price": "4999","subject": "xiaomi 14 钛金属","body": "xiaomi 14 钛金属 256gb"}],paymentFormHtml: "" // 新增 paymentFormHtml 属性},methods: {pay: function (order) {axios.post('http://127.0.0.1:8088/alipay/pay', order).then(res => {// 处理支付成功的逻辑console.log('支付成功', res.data);this.paymentFormHtml = res.data.data;// 手动提交表单// 在延时后提交表单setTimeout(function () {document.forms['punchout_form'].submit();}, 1000); // 1000毫秒,即1秒}).catch(error => {// 处理支付失败或其他错误的逻辑console.error('支付失败', error);});}}});
</script></body></html>

测试

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/195925.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

单张图像3D重建:原理与PyTorch实现

近年来&#xff0c;深度学习&#xff08;DL&#xff09;在解决图像分类、目标检测、语义分割等 2D 图像任务方面表现出了出色的能力。DL 也不例外&#xff0c;在将其应用于 3D 图形问题方面也取得了巨大进展。 在这篇文章中&#xff0c;我们将探讨最近将深度学习扩展到单图像 3…

开源与闭源:大模型发展的双重走向

目录 前言开源和闭源的优劣势比较开源的优势闭源的优势 开源和闭源对大模型技术发展的影响对技术发展的影响对数据共享的影响对业务拓展的影响 开源与闭源的商业模式比较开源的商业模式闭源的商业模式 处在大模型洪流中&#xff0c;向何处去&#xff1f;结语 前言 随着人工智能…

基于深度学习的恶意软件检测

恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞&#xff0c;例如可以被劫持的合法软件&#xff08;例如浏览器或 Web 应用程序插件&#xff09;中的错误。 恶意软件渗透可能会造成灾难性的后果&#xff0c;包括数据被盗、勒索或网…

2023/11/19总结

项目进度&#xff1a; 地址管理&#xff1a; 显示菜品 购物车相关功能 然后最近在看 支付宝沙盒支付的相关功能&#xff0c;打算把支付给做了 。界面做的不是很好看 &#xff0c;但是后续会改成 手机端的。

原理Redis-IntSet

IntSet IntSet是Redis中set集合的一种实现方式&#xff0c;基于整数数组来实现&#xff0c;并且具备长度可变、有序等特征。 结构如下&#xff1a; typedef struct intset {uint32_t encoding; /* 编码方式&#xff0c;支持存放16位、32位、64位整数*/uint32_t length; /* 元素…

012 C++ AVL_tree

前言 本文将会向你介绍AVL平衡二叉搜索树的实现 引入AVL树 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序普通的二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家G.M…

莹莹API管理系统源码附带两套模板

这是一个API后台管理系统的源码&#xff0c;可以自定义添加接口&#xff0c;并自带两个模板。 环境要求 PHP版本要求高于5.6且低于8.0&#xff0c;已测试通过的版本为7.4。 需要安装PHPSG11加密扩展。 已测试&#xff1a;宝塔/主机亲测成功搭建&#xff01; 安装说明 &am…

【LeetCode每日一题合集】2023.9.25-2023.10.1(⭐LFU缓存Java数据流花期内花的数量)

文章目录 460. LFU 缓存⭐&#xff08;数据结构题&#xff09;解法1——平衡树 哈希表&#xff08;TreeSet HashMap&#xff09; O ( l o g n ) O(logn) O(logn)解法2——双哈希表 双向链表 O ( 1 ) O(1) O(1) &#xff08;LRU缓存的升级版&#xff09; 2582. 递枕头解法—…

Android 13 - Media框架(14)- OpenMax(二)

这一节我们将来解析 media.codec 这个 HIDL service 究竟提供了什么服务&#xff0c;服务是如何启动的。 1、main 函数 我们先来看 frameworks/av/services/mediacodec/main_codecservice.cpp&#xff1a; int main(int argc __unused, char** argv) {strcpy(argv[0], "…

丹麦能源袭击预示着更关键的基础设施成为目标

5 月&#xff0c;22 个丹麦能源部门组织在与俄罗斯 Sandworm APT 部分相关的攻击中受到损害。 丹麦关键基础设施安全非营利组织 SektorCERT 的一份新报告描述了不同的攻击者群体利用合勤防火墙设备中的多个关键漏洞&#xff08;包括两个零日漏洞&#xff09;侵入工业机械&…

Shell条件测试练习

1、取出/etc/passwd文件的第6行&#xff1b; [rootshell ~]# head -6 /etc/passwd | tail -1 sync:x:5:0:sync:/sbin:/bin/sync [rootshell ~]# sed -n 6p /etc/passwd sync:x:5:0:sync:/sbin:/bin/sync [rootshell ~]# awk NR6 /etc/passwd sync:x:5:0:sync:/sbin:/bin/sync 2…

Node.js之TCP(net)

Hi I’m Shendi Node.js之TCP&#xff08;net&#xff09; 最近使用Nodejs编写程序&#xff0c;需要用到自己编写的分布式工具&#xff0c;于是需要将Java版的用NodeJs重新写一遍&#xff0c;需要使用到TCP通信&#xff0c;于是在这里记录下Node.js TCP 的使用方法 依赖 需要使…