Spring Boot 完善订单【五】集成接入支付宝沙箱支付

1.1.什么是沙箱支付

支付宝沙箱支付(Alipay Sandbox Payment)是支付宝提供的一个模拟支付环境,用于开发和测试支付宝支付功能的开发者工具。在真实的支付宝环境中进行支付开发和测试可能涉及真实资金和真实用户账户,而沙箱环境则提供了一个安全、隔离的环境,使开发者能够模拟支付过程,测试支付功能,而不会使用真实资金。

使用支付宝沙箱支付环境,开发者可以模拟各种支付场景,包括交易创建、支付请求、支付回调等,以验证支付功能的正确性和稳定性。沙箱环境中的所有交易和数据都是虚拟的,不会产生真实的交易或资金流动。

支付宝沙箱支付提供了开发者工具和接口,使开发者能够在模拟环境下进行支付流程的调试和测试。开发者可以在沙箱环境中创建测试账户、配置模拟的交易金额和状态,使用沙箱环境中的接口进行支付操作,并模拟支付回调接口接收支付结果。

通过使用支付宝沙箱支付,开发者可以更安全、更有效地进行支付功能的开发和测试,避免了对真实环境的影响和风险。一旦支付功能在沙箱环境中验证通过,开发者可以将其部署到真实的支付宝生产环境中,与真实用户进行交互和支付。

步骤:

1.2接入支付宝开放平台

登陆支付宝:支付宝开放平台

登录成功之后,点击控制台跳转到控制台主页面,将浏览器进度条滚动到最下面,选择沙箱,最后点击沙箱选项即可,如下:

下载密钥生成工具:

小程序文档 - 支付宝文档中心

手机上的模拟扫码:

前端代码:

$(".pay").click(function () {//地址,手机号,收货人,支付方式,快递方式let el = $(".addres").find(".on")let person = el.find(".tit .fl").text()let address = el.find(".addCon p:first-child").text()let telephone = el.find(".addCon p:last-child").text()let pay = $(".way .on").attr('value')let mail = $(".dis .on").text()let ids = $(this).attr('data-ids')let order={person,telephone,address,pay,mail,ids}$.post('/order/add',order,resp=>{if(resp.code===200){//         进入支付let f = confirm("是否去结算?")if (f){console.log(resp.data)location.href="/order/pay?oid="+resp.data}else {location.href="/"}}},"json")
})

后端代码:

package com.lya.lyaspshop.controller;import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.yitter.idgen.YitIdHelper;
import com.lya.lyaspshop.config.AlipayConfig;
import com.lya.lyaspshop.pojo.Goods;
import com.lya.lyaspshop.pojo.Order;
import com.lya.lyaspshop.pojo.OrderItem;
import com.lya.lyaspshop.pojo.User;
import com.lya.lyaspshop.resp.JsonResponseBody;
import com.lya.lyaspshop.service.IOrderItemService;
import com.lya.lyaspshop.service.IOrderService;
import com.lya.lyaspshop.service.impl.GoodsServiceImpl;
import com.lya.lyaspshop.service.impl.RedisServiceImpl;
import com.lya.lyaspshop.vo.CartItemVo;
import com.lya.lyaspshop.vo.OrderVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate RedisServiceImpl redisService;@Autowiredprivate GoodsServiceImpl goodsService;@Autowiredprivate IOrderItemService iOrderItemService;@Autowiredprivate IOrderService iOrderService;@RequestMapping("/add")public JsonResponseBody<?> toOrder(User user, OrderVo orderVo){String ids = orderVo.getIds();List<CartItemVo> cartItems = redisService.loadCart(user, ids);//所有的购物车中商品的id集合List<Long> gds = cartItems.stream().map(CartItemVo::getGid).collect(Collectors.toList());//根据集合查询所有对应的商品List<Goods> goods = goodsService.listByIds(gds);//遍历集合 赋值给对应的对象for (Goods g : goods) {//找到对应id相同的元素CartItemVo vo = cartItems.stream().filter(v -> Objects.equals(v.getGid(), g.getGid())).findFirst().get();//将商品g的属性赋值给voBeanUtils.copyProperties(g,vo);}long oid = YitIdHelper.nextId();//增加订单项BigDecimal total=new BigDecimal(0);List<OrderItem> orderItems=new ArrayList<>();for (CartItemVo item : cartItems) {//生成订单项OrderItem orderItem = new OrderItem();//赋值属性BeanUtils.copyProperties(item,orderItem);orderItem.setQuantity(item.getNum());orderItem.setOoid(YitIdHelper.nextId());orderItem.setOid(oid);//放到一个集合中 批量增加 只会有一次数据库新增orderItems.add(orderItem);//计算总价 + 当前的小计total = total.add(item.cartprice());}iOrderItemService.saveBatch(orderItems,5);//增加订单Order order = new Order();BeanUtils.copyProperties(orderVo,order);order.setOid(oid);order.setTotal(total);order.setUserId(user.getId());order.setStatus(0);order.setCreateDate(new Date());//订单插入数据库iOrderService.save(order);//删除缓存元素
//        redisService.removeCart(user,orderVo.getIds());return JsonResponseBody.success(oid);}@RequestMapping("/pay")public String pay(User user, String oid){
//        得到结算的订单Order order = iOrderService.getById(oid);
//        调用支付页面
//        传来的是表单String body = new AlipayConfig().goAlipay(order);return body;}
//    这里传递来的数据:@RequestMapping("/payDone")public String payDone(Map<String,String> stringMap){
//        更具成功支付了id来修改状态:String oid = stringMap.get("out_trade_no");iOrderService.update(new UpdateWrapper<Order>().eq("oid",oid).set("status",1).set("pay_date",new Date()));
//        html语句可以解析,json数据只能响应return "<script>\n" +"    alert(\"支付成功\")\n" +"    location.href=\"/\"\n" +"< /script>";}}

这里我们要添加一条代码:(异步通知验签)

//      安全验证:Boolean b = Factory.Payment.Common().verifyNotify(stringMap);if (!b){throw   new BusinessException(JsonResponseStatus.UN_KNOWN);}

支付宝接口:(根据自己数据的来)

package com.lya.lyaspshop.config;import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.lya.lyaspshop.pojo.Order;
import org.springframework.stereotype.Component;@Component
public class AlipayConfig {private Config aliconfig() {Config config = new Config();//沙箱支付宝地址config.gatewayHost = "openapi-sandbox.dl.alipaydev.com";//协议httpsconfig.protocol = "https";//应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号config.appId = "9021000132623583";//支付宝公钥config.alipayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmexyLYPEgC4GHxHtCYEhThPEIOjOoMpr8w+bmOtAPpmLg3wrYt4xMFbTP4Wg8wBSWiLHgXtBl32BekY5PD0pOPRZ5VW8rL84uDt+wnCdS9PjXscFmDdzGvp4c1o4vgjQovylrfEf1AlLINYUsXaTp1Nk5IZGRxERLOoTKVI/COY/qyIvhSueS+gIadpgSXNn1R0K73zorJaKVhJS4WKtHfr1246sslQRptinaFiU5PAvQXzt5iaBLdqc3C0UGz1jTHgemaJOIW/SlhsR3CkKif0MX25IoCrwgpzYbv0JDoGG74pzAIOf2LuNaZbQRwQldYokTLVXIlWis1H0UqiYzQIDAQAB";//签名方式config.signType = "RSA2";//商户私钥(应用私钥),您的PKCS8格式RSA2私钥config.merchantPrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+y08ssgZZsO0y1Xr4dTTD3/Vh9rfpCJ79B5YLJlWhWDZ/+yfGBdyoMtMnPjvuqZNvyloNrxJFAlOc17A6JLEypnJw7G1W7BYIRur0cQx7bVjqqN/lCO9V1dsyOOKhFd+10lbkIgr1DY0FwY4z9bZuniPCRERvKu6M/485Iq68C8vQnBzlXPYSP9STmzLoNtkSDhC/4t5EQus5FEcpNkmXuDM9fGw1J2d4e3SKMZIj4h2+1qByhktEsc5HhKF4RCZK+MR0fhBStF8rRVd2hvDhjcgg3TVoYjvn0fLN2wMX03/lLsIA7+G4ORVxO9RS5PmhCLQab5lqa9YPFpqyoCB7AgMBAAECggEAAUE3CRU2o3pdZPswbtfee/dKFtXXicnLueBF5VbgM0pwOVE+hrfdJqIG73giTsSAurh69SIUna2RPTPR7d/15l5f3ExBv9OXpYBJ5UelDF7AufJYXpo7cLYSVfc3zlVlfj2e4qsypT/skIAgXkkcZQfXNlzaklyW6wh3Oan3ujbau1IQVE/jQBvTdUbAWapFcGJ5RH07MvuBJhz4rG2eAMANxT6JIp8+3rU1Pi//enhb5qTWa5xg+HFtqeNs5T+E0JPzR8ezWYkbCDiXL5iYE1jvoTeyaBfz7iKxRuN1bpgClg/DNB5j3JXo3Ke4SRtLf80WnCQFwV5paeWXUbdsuQKBgQDs7DiGoa1YD3yhXdkXJQONDp2EZb2679d3rC5m5qJsAZi+W+qWe4V7vqqmfJrFjAUe+eNWSaoaUXO9Z5Ps3dcNpFXBnOW0ODpBGcYnT8bu5qqWjRbYFMOAAznh895v/2uNtljWvYTHUrnYEP2ZNkiEzCg9IYgH1L5GWJ8hoPC+jQKBgQDOKDkHfSwELOOIFidOAJqV3qpeo4AzPW5X3GsNKg1fcnN9nRTgUqZhW+woGetXTbbCxuM24uQpVZqpVhZA+TcCBc+kj7yDwkyjhFtO7UQQRSBiyQm0w6qZY+1aKIwf1Z578Nsbcf07FEJjpfxV8YAuF6Vq9PcS1lI4N1rVi5m9JwKBgE6zYUuHpVddPZ8014pSp01SD40NZusUBNUiAv/3mPibxytkyRZXzc1/VpybQ6ZfjsvtYlElgzXe3L2MDJ1gS7GiZ0I7ZippiyBY+XPRklmFkiEUmQQKUa7SY4XlRnyZshaO/g/HQLYditJ1QmiEma5TSwKTguZnCxW/Fo1LMu15AoGBALEc/WHhuB8eMZyI69unySdY1SXZchqTfGkfhRkaN8L4oSAaBAV0/FxIjOsm2Xl32rwcArj01PBuCyHQQ+4uLYQfWfUXR+4qz4zr+UYlsYQI33n/HcefEsIVh6UdkMUI0c/JbXR2yggnr6HMyK1NfcIbrpHlQx974cdKR0+PT9WhAoGBANC3h8Y4FBaKOLcxwHCVDSUrCszCyE+NGvDJI2I5Q7Pjxb5hfHkYR0/cVG5aUJPElWWizaf+7wNCL9XtVCfoUYWZ3DffNs526DL3btN9zby2Tcq7q3NhvRc3ZezSd/XZkGpr7LhWK0wppi5TuvNlhl1VyoGtbMiNUPOrSNWepror";return config;}public String goAlipay(Order order) {try {// 1. 设置参数(全局只需设置一次)Factory.setOptions(aliconfig());// 2. 发起API调用(subject商品标题、outTradeNo订单编号、totalAmount总金额、returnUrl异步通知地址)AlipayTradePagePayResponse response = Factory.Payment.Page().pay("商城项目收款",order.getOid().toString(),order.getTotal().toString(),//支付成功之后的异步通知(跳出到自己系统的哪个位置)"http://localhost:8080/order/payDone");
//            支付宝支付页面return response.body;} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);}}}

注意:

这里的支付宝公钥,应用私钥要填好:失败了多生成几次:

接入成功:

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

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

相关文章

【C++】STL 算法 ⑥ ( 二元谓词 | std::sort 算法简介 | 为 std::sort 算法设置 二元谓词 排序规则 )

文章目录 一、二元谓词1、二元谓词简介2、 std::sort 算法简介3、 代码示例 - 为 std::sort 算法设置 二元谓词 排序规则 一、二元谓词 1、二元谓词简介 " 谓词 ( Predicate ) " 是一个 返回 布尔 bool 类型值 的 函数对象 / 仿函数 或 Lambda 表达式 / 普通函数 , …

安全数据交换系统:有效提升网间文件交换能力

各级政府部门和金融、能源、电力这些行业&#xff0c;以及一些大中型企业组织&#xff0c;为了保护内部的重要数据不外泄&#xff0c;普遍都采用了多网络并行的方式&#xff0c;也是做了网络隔离划分&#xff0c;不同的网络拥有不同的密级以及人员权限。然后再通过安全数据交换…

java中使用redis

1、redis数据类型 1.1、5种数据类型 redis存储的是key-value结构的数据&#xff0c;其中key是字符串类型&#xff0c;value有5种常用的数据类型&#xff1a;字符串 string、哈希 hash、列表 list、集合 set、有序集合 sorted set / zset。 字符串(string)&#xff1a;普通字符…

Day1Qt

1、实现登录窗口界面 头文件 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QIcon>//图标 #include <QLabel>//标签类 #include <QMovie>//动态类 #include <QLineEdit>//行编辑类 #include <QPushButton>…

promethues grafana 安装和使用

文章目录 1、promethues安装2、node-exporter安装3、grafana安装4、配置promethues监控node节点5、grafana操作外传 Docker 镜像下载地址&#xff1a; https://hub.docker.com 比较好的hub.docker.com///-- https://hub.docker.com/u/bitnami grafana监控面板&#xff1a;https…

电子学会C/C++编程等级考试2023年12月(三级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:因子问题 任给两个正整数N、M,求一个最小的正整数a,使得a和(M-a)都是N的因子。 时间限制:10000 内存限制:65536 输入 包括两个整数N、M。N不超过1,000,000。 输出 输出一个整数a,表示结果。如果某个案例中满足条件的正整数不存…

使用Python+selenium3.0实现第一个自动化测试脚本

这篇文章主要介绍了使用Pythonselenium实现第一个自动化测试脚本&#xff0c;文中通过示例代码介绍的非常详细&#xff0c;对大家的学习或者工作具有一定的参考学习价值&#xff0c;需要的朋友们下面随着小编来一起学习学习吧 最近在学web自动化&#xff0c;记录一下学习过程。…

【算法与数据结构】70、LeetCode爬楼梯

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;   程序如下&#xff1a; 复杂度分析&#xff1a; 时间复杂度&#xff1a; O ( ) O() O()。空间复…

【React系列】高阶组件

本文来自#React系列教程&#xff1a;https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. 高阶组件 1.1. 认识高阶组件 什么是高阶组件呢&#xff1f;相信很多同学都听说过&#xff0c;也用过 高阶函数&…

mysql高可用方案之MHA

mysql集群高可用方案&#xff1a; 单主&#xff1a;keepalived、MHA、MMM 多主&#xff1a;MySQL cluster 、PXC MHA的工作原理 MHA node 运行在每台MySQL服务器上&#xff0c;MHA Manager会定时探测集群中的master节点&#xff0c;当master出现故障时&#xff0c;它可以自…

Java方法用法及解析

在 Java 中&#xff0c;方法&#xff08;Method&#xff09;是用于执行特定任务的代码块。它是一个函数&#xff0c;用于封装一段可重复执行的代码&#xff0c;并可以被其他代码调用。方法定义了一系列操作的步骤&#xff0c;并提供了一种结构化和可复用的方式来组织和执行这些…

[VUE]4-状态管理vuex

目录 状态管理 vuex 1、vuex 介绍 2、安装 3、使用方式 4、总结 &#x1f343;作者介绍&#xff1a;双非本科大三网络工程专业在读&#xff0c;阿里云专家博主&#xff0c;专注于Java领域学习&#xff0c;擅长web应用开发、数据结构和算法&#xff0c;初步涉猎Python人工智…

【源码预备】Calcite基础知识与概念:关系代数概念、查询优化、sql关键字执行顺序以及calcite基础概念

文章目录 一. 关系代数的基本知识二. 查询优化三. SQL语句的解析顺序1. FROM2. WHERE3. GROUP BY4. HAVING5. SELECT 四. Apache Calcite中的基本概念1. Adapter2. Calcite中的关系表达式2.1. 关系表达式例子2.2. 源码底层结构 3. Calcite的优化规则4. Calcite的Trait--算子物理…

02 Deep learning algorithm

Neural Networks target&#xff1a; inference&#xff08;prediction&#xff09;training my own modelpractical advice for building machine learning systemdecision Tress application: speech&#xff08;语音识别&#xff09; ----> images(计算机视觉)—> t…

数据结构-测试4

一、判断题 1.队列结构的顺序存储会产生假溢出现象。 &#xff08;T&#xff09; 2.度为二的树就是二叉树。(F) 二叉树的度可以小于等于2 3. 栈是插入和删除只能在一端进行的线性表&#xff1b;队列是插入在一端进行&#xff0c;删除在另一端进行的线性表。&#xff08;T&…

【CMake】1. VSCode 开发环境安装与运行

CMake 示例工程代码 https://github.com/LABELNET/cmake-simple 插件 使用 VSCode 开发C项目&#xff0c;安装 CMake 插件 CMakeCMake ToolsCMake Language Support &#xff08;建议&#xff0c;语法提示) 1. 配置 CMake Language Support , Windows 配置 donet 环境 这…

异地环控设备如何远程维护?贝锐蒲公英解决远程互联难题

青岛某企业致力于孵化设备、养禽设备和养猪设备的研发、生产和服务&#xff0c;历经三十多年发展&#xff0c;目前已成长为行业主要的养殖装备及工程服务提供商&#xff0c;产品覆盖养殖产业链中绝大多数环节&#xff0c;涉及自动化设备、环控设备、整体解决方案等。 在实际应用…

Python3从零基础到入门(1)

目录 一、环境搭建 1.检测Python环境 2.下载安装Python环境 3.VSCode中配置Python环境 二、第一个程序 1.编码 2.输出 3.标识符 4.import 5.保留字 6.注释 7.缩进 三、变量和赋值 1.Python 中的变量 2.变量的赋值 3.多个变量赋值 四、基础数据类型 1.类型查看…

以unity技术开发视角对android权限的讲解

目录 前言 Android权限分类 普通权限 普通权限定义 普通权限有哪些 危险权限 危险权限的定义 危险权限有哪些 动态申请权限实例 申请单个权限实例 第一步&#xff1a;在清单文件中声明权限 第二步&#xff1a;在代码中进行动态申请权限 申请多个权限实例 第一步&am…

以对象为中心的视频编辑;SDXL高质量缩小版;Transformer在FPGA上实现12.8倍速度提升;深入研究ViT固有问题

本文首发于公众号&#xff1a;机器感知 以对象为中心的视频编辑&#xff1b;SDXL高质量缩小版&#xff1b;Transformer在FPGA上实现12.8倍速度提升&#xff1b;深入研究ViT固有问题 VASE: Object-Centric Appearance and Shape Manipulation of Real Videos 现有方法通过文生…