电商中的订单支付(内网穿透)

支付页面

在这里插入图片描述

接口文档

在这里插入图片描述
在这里插入图片描述

@Operation(summary="获取订单信息")
@GetMapping("auth/{orderId}")
public Reuslt<OrderInfo> getOrderInfo(@Parameter(name="orderId",description="订单id",required=true) @PathVaariable Long orderId){OrderInfo orderInfo = orderInfoService.getOrderInfo(orderId);return Reuslt.build(orderInfo,ResultCode.SUCCESS);
}
@Override
public OrderInfo getOrderInfo(Long orderId){return orderInfoMapper.getById(orderId);
}
//mapper
OrderInfo getById(Long orderId);
<select id="getById"resultType="com.xxx.OrderInfo" >select *from order_infowhere id=#{orderId}</select>

不经过购物车,直接购买

@Operation(summary="立即购买")
@GetMapping("auth/buy/{skuId}")
public Result buy(@PathVariable Long skuId){TradeVo tradeVo = orderInfoService.buy(skuId);return Result.build(tredeVo,ResultCodeEnum.SUCCESS);
}
@Override
public TradeVo buy(Long skuId){List<OrderItem> orderItemList = new ArrayList<>();ProductSku productSku = productFeignClient.getBySkuId(skuId);OrderIntem orderItem = new OrderItem();orderItem.setSkuId(skuId);orderItem.setSkuName(productSku.getSkuName());orderItem.setSkuNum(1);orderItem.setSkuPrice(productSku.getSalePrice());orderItem.setThumbImg(productSku.getThumbImg());orderItemList.add(orderItem);TradeVo tradeVo = new TradeVo();trade.setOrderItemList(orderItemList);trade.setTotalAmount(productSku.getSalePrice());return tradeVo;
}

查询订单
在这里插入图片描述

@Operation(summary="获取订单分页列表")
@GetMapping("auth/{page}/{limit}")
public Result<PageInfo<OrderInfo>> list(@Parameter(name="page",description="当前页码",required=true)@PathVariable Integer page,@Parameter(name="limit",description="每页记录数",required=true)@PathVariable Integer limit,@Parameter(name="orderStatus",description="订单状态",required=false)@RequestParam(required=false,defaultValue="") Integer orderStatus){PageInfo<OrderInfo> pageInfo = orderInfoService.findUserPage(page,limit,orderStatus);return Result.build(pageInfo,ResultCodeEnum.SUCCESS);
}
@Override
public PageInfo<OrderInfo> findOrderPage(Integer page,Integer limit,Integer orderStatus){PageHelper.startPage(page,limit);//查询订单信息Long userId = AuthContextUtil.getUserInfo().getId();List<OrderItem> orderInfoList = orderInfoMapper.findUserPage(userId,orderStatus);//查询订单里所有的订单项orderInfoList.forEach(orderInfo -> {//订单id查询订单里面的订单项List<OrderItem> orderItemList = orderItemMapper.findByOrderId(orderInfo.getId());orderInfo.setOrderItemList(orderItemList);});return new PageInfo<>(orderInfoList);
}

在这里插入图片描述

在这里插入图片描述

===================================================================================

支付宝支付

在这里插入图片描述

在这里插入图片描述
通过营业执照进行开通

获取的参数
在这里插入图片描述

在这里插入图片描述

①、创建模块service-pay

配置文件、启动类……

spring:profiles:active: devserver:port:
spring:application:name:cloud:nacos:discovery:server-addr: localhost:8848datasource:type: com.zaxxer.hikari.HikariDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl:username:password:data:redis:host: localhostport: 6379
mybatis:config-localtion: classpath:mybatis-config.xmlmapper-location: classpath:mapper/*/*.xml

②、保存支付记录

public interface PaymetInfoService{PaymentInfo savePaymentInfo(String orderNo);
}
@Service
public class PaymentInfoService implements PaymentInfoService{@Autowiredprivate PaymentInfoMapper paymentInfoMapper; @Overridepublic PaymentInfo savePaymentInfo(String orderNo){PaymentInfo paymentInfo = paymentInfoMapper.getByOrderNo(orderNo);if(paymentInfo==null){//如果支付记录不存在,则远程调用订单信息OrderInfo orderInfo = orderFeignClient.getOrderInfoByOrderNo(orderNo).getData();paymentInfo = new PaymentInfo();paymentInfo.setUserId(orderInfo.getUserId());paymentInfo.setPayType(orderInfo.getPayType());String content = "";for(OrderItem item:orderInfo.getOrderItemList()){content += item.getSkuName() + "";}paymentInfo.setContent(content);paymentInfo.setAmount(orderInfo.getTotalAmount());paymentInfo.setOrderNo(orderNo);paymentInfoMapper.save(paymentInfo);}return paymentInfo;}
}
@Mapper
public interface PaymentInfoMapper{PaymentInfo getByOrderNo(String orderNo);void save(PaymentInfo paymentInfo);
}
<sql id="columns">id,user_id,order_no,pay_type,out_trade_no,amount,content,payment_status,callback_time,callback_content
</sql><select id="getByOrderNo" resultMap="paymentInfoMap">select <include refid="colums"></include>from payment_infowhere order_no = #{orderNo}
</select><insert id="save" useGeneratedKeys="true" keyProperty="id">insert into payment_info(id,user_id,order_no,pay_type,out_tread_no,amount,coutent,payment_status,)
</insert>

在这里插入图片描述

在这里插入图片描述

③、支付接口

Ⅰ、service-pay模块中添加alipay-sdk依赖

Ⅱ、application-alipay.yml文件,添加配置
在这里插入图片描述
Ⅲ、application-dev.yml配置文件需要引入application-alipay.yml

spring:config:import: application-alipay.yml

Ⅳ、读取配置文件

@Data
@Configuration(prefix="spzx.alipay")
public class AlipayProperties{//属性名必需和配置文件中的保持一致private String alipayUrl;private String appPrivateKey;public String alipayPublicKey;private String appId;public String returnPaymetUrl;public String notifyPaymentUrl;public final static String format="json";public final static String charset="utf-8";public final static String sign_type="RAS2";
}

Ⅴ、启动类添加注解@EnableConfigurationProperties(value={AlipayProperties.class})

④、配置发送请求的核心对象AlipayClient

@Configuration
public class AlipayConfiguration{@Autowiredprivate AlipayProperties alipayProperties;@Beanpublic AlipayClient alipayClient(){AlipayClient alipayClient = new DefaultAlipayClient(alipayProperties.getAlipayUrl(),alipayProperties.getAppPrivateKey(),alipayProperties.format,alipayProperties.charset,alipayProperties.getAlipayPublicKey(),alipayProperties.sign_type);return alipayClient;}
}

⑤、返回支付宝支付页面

@Controller
@RequestMapping()
public class AlipayController{@Autowiredprivate AlipayService alipayService;@Operation(summary="支付宝下单")@GetMapping("submitAlipay/{orderNo}")public Result<String> submitAliPay(@Parameter(name="orderNo",description="订单号",required=true),@PathVariable(value="orderNo") String orderNo){String form = aliapyService.submitAlipay(orderNo);//返回表单页面return Result.build(form,ResultCodeEnum.SUCCESS);}
}
@Override
public String submitAlipay(String orderNo){//保存支付记录PaymentInfo payementInfo = paymentInfoService.savePaymentInfo(orderNo);//调用支付宝服务接口封装参数AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();//同步回调alipayRequest.setReturnUrl(alipayProperties.getReturnPaymentUrl());//异步回调alipayRequest.setNotifyUrl(alipayProperties.getNotifyPaymentUrl());//准备请求参数HashMap<String,Object> map = new HashMap<>();map.put("out_trade_no",paymentInfo.getOrderNo());map.put("product_code","QUICK_WAP_WAY");map.put("total_amount",paymentInfo.getAmount());//map.put("total_amount",new BigDecimal("0.01")); 为了便于测试map.put("subject",paymentInfo.getContent());alipayRequest.setBizContent(JSON.toJSONString(map));try{//发送请求AlipayTradeWapPayResponse response = alipayClient.pageExecute(alipayRequest);if(response.isSuccess()){log.info("调用成功");String form = response.getBody();//返回支付页面return form;}else{log.info("调用失败");throw new GuiguException(ResultCodeEnum.DATA_ERROR);}}catch(AlipayApiException e){throw new RuntimeException(e);}}

在这里插入图片描述

⑥、完成支付

  • 内网穿透,方便用来开发测试

在这里插入图片描述

  • 支付成功之后到达的页面:修改自定义的页面
  • 本地的接口路径:修改为内网穿透绑定到后端网关接口赠送的域名地址
    在这里插入图片描述

在这里插入图片描述

@Operation(summary="支付宝异步回调")
@ReqeustMapping("callback/notify")//该路径和配置文件中的notify_payment_url
@ResponseBody
public String alipayNotify(@RequestParam Map<String,String> paramMap,HttpServletRequest request){log.info("AlipayController...alipayNotify方法执行了");boolean signVerified = false;//调用SDK验证签名(验证是否是支付宝传递过来)try{signVerified = AlipaySignature.rsaCheckVl(paramMap,alipayProperties.getAlipayPublicKey(),AlipayProperties.charset,AlipayProperties.sign_type);}catch(AlipayApiException e){e.printStackTrace();}//交易状态String trade_status = paramMap.get("trade_status");if(signVerified){//进行二次校验if("TRADE_SUCCESS".equals(trade_status)||"TRADE_FINISHED".equals(trade_status)){//正常的支付成功,更新交易记录状态paymentInfoService.updatePaymentStatus(paraMap,2);return "success";}}else{//验签失败,记录异常日志return "failture";}
}
//支付状态的更新
@Override
public void updatePaymentStatus(Map<String,String> map){//根据订单编号查询支付记录信息PaymentInfo paymentInfo = paymentInfoMapper.getByOrderNo(map.get("out_trade_no"));//如果支付记录已经完成,不需要更新if(paymentInfo.getPaymentStatus()==1){return;}//没有完成才更新paymentInfo.setPaymentStatus(1);paymentInfo.setOutTradeNo(map.get("trade_no"));paymentInfo.setCallbackTime(new Date());paymentInfo.set.CallbackContent(JSON.toJSONString(map));paymentInfoMapper.updatePaymentInfo(paymentInfo);//远程调用,更新订单模块(根据订单编号修改)orderFeignClient.updateOorderStatus(paymentInfo.getOrderNo());//更新sku商品销售
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

配置内网穿透

  • 本质上就是因为无法直接调用本地服务,所以通过内网穿透便于第三方服务通过域名来调用本地服务
  • ngrok工具:https://ngrok.cc/login/register 注册用户
  • 完成实名认证
  • 开通隧道管理
  • 绑定本地服务开发者的service-gateway网关模块,获取赠送的域名
  • 复制隧道id,下载客户端工具windows_amd64zip

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

MySQL表的使用(4)

首先回顾一下之前所学的增删查改&#xff0c;这些覆盖了平时使用的80% 我们上节课中学习到了MySQL的约束 其中Primary key 是主键约束&#xff0c;我们今天要学习的是外键约束 插入一个表 外键约束 父表 子表 这条记录中classid为5时候&#xff0c;不能插入&#xff1b; 删除…

Kotlin作用域函数

在 Kotlin 中&#xff0c;.apply 是一个 作用域函数&#xff08;Scope Function&#xff09;&#xff0c;它允许你在一个对象的上下文中执行代码块&#xff0c;并返回该对象本身。它的设计目的是为了 对象初始化 或 链式调用 时保持代码的简洁性和可读性。 // 不使用 apply va…

C#集合List<T>与HashSet<T>的区别

在C#中&#xff0c;List和HashSet都是用于存储元素的集合&#xff0c;但它们在内部实现、用途、性能特性以及使用场景上存在一些关键区别。 内部实现 List&#xff1a;基于数组实现的&#xff0c;可以包含重复的元素&#xff0c;并且元素是按照添加的顺序存储的。 HashSet&…

Python 实现的运筹优化系统数学建模详解(最大最小化模型)

一、引言 在数学建模的实际应用里&#xff0c;最大最小化模型是一种极为关键的优化模型。它的核心目标是找出一组决策变量&#xff0c;让多个目标函数值里的最大值尽可能小。该模型在诸多领域&#xff0c;如资源分配、选址规划等&#xff0c;都有广泛的应用。本文将深入剖析最大…

数据库的种类及常见类型

一&#xff0c;数据库的种类 最常见的数据库类型分为两种&#xff0c;关系型数据库和非关系型数据库。 二&#xff0c;关系型数据库介绍 生产环境主流的关系型数据库有 Oracle、SQL Server、MySQL/MariaDB等。 关系型数据库在存储数据时实际就是采用的一张二维表&#xff0…

PE文件(十五)绑定导入表

我们在分析Windows自带的一些程序时&#xff0c;常常发现有的程序&#xff0c;如notepad&#xff0c;他的IAT表在文件加载内存前已经完成绑定&#xff0c;存储了函数的地址。这样做可以使得程序是无需修改IAT表而直接启动&#xff0c;这时程序启动速度变快。但这种方式只适用于…

计算机网络分层模型:架构与原理

前言 计算机网络通过不同的层次结构来实现通信和数据传输&#xff0c;这种分层设计不仅使得网络更加模块化和灵活&#xff0c;也使得不同类型的通信能够顺利进行。在网络协议和通信体系中&#xff0c;最广为人知的分层模型有 OSI模型 和 TCP/IP模型。这两种模型分别定义了计算…

Ollama模型显存管理机制解析与Flask部署方案对比

一、Ollama显存释放机制 Ollama部署模型后&#xff0c;显存占用分为两种情况&#xff1a; 首次调用后短暂闲置&#xff08;约5分钟内&#xff09;&#xff1a; • 释放KV Cache等中间计算数据&#xff08;约回收30%-50%显存&#xff09;。 • 模型权重仍保留在显存中&#xf…

KWDB创作者计划—KWDB技术重构:重新定义数据与知识的神经符号革命

引言&#xff1a;数据洪流中的范式危机 在AI算力突破千卡集群、大模型参数量级迈向万亿的时代&#xff0c;传统数据库系统正面临前所未有的范式危机。当GPT-4展现出跨领域推理能力&#xff0c;AlphaFold3突破蛋白质预测精度时&#xff0c;数据存储系统却仍在沿用基于关系代数的…

Unified Modeling Language,统一建模语言

UML&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;是一种标准化的图形化建模语言&#xff0c;用于可视化、规范和文档化软件系统的设计。UML 提供了一套通用的符号和规则&#xff0c;帮助开发者、架构师和团队成员更好地理解和沟通软件系统的结构…

IO模式精讲总结

一、IO模型概述 Java中的IO模型主要分为BIO&#xff08;同步阻塞IO&#xff09;、NIO&#xff08;同步非阻塞IO&#xff09;和AIO&#xff08;异步非阻塞IO&#xff09;三种。它们分别适用于不同的业务场景&#xff0c;理解其核心机制对高性能网络编程至关重要。 二、BIO&…

使用pybind11开发c++扩展模块输出到控制台的中文信息显示乱码的问题

使用pybind11开发供Python项目使用的C++扩展模块时,如果在扩展模块的C++代码中向控制台输出的信息中包含中文,python程序的控制台很容易出现乱码。以如下C++扩展框架代码为例(这是对上一篇文章简明使用pybind11开发pythonc+扩展模块教程-CSDN博客中的C++扩展框架代码进行少量…

通过jstack分析线程死锁场景

死锁的四个必要条件&#xff1a;互斥、持有并等待、不可抢占、循环等待。 死锁场景是两个线程各自持有某个锁&#xff0c;并试图获取对方持有的锁&#xff0c;导致互相等待。 创建死锁示例代码 package io.renren.controller;import org.springframework.web.bind.annotation…

PyTorch梯度:深度学习的引擎与实战解析

一、梯度&#xff1a;深度学习中的指南针 1.1 什么是梯度&#xff1f; 梯度是函数在某一点变化率最大的方向及其大小&#xff0c;就像爬山时最陡峭的上坡方向。在深度学习中&#xff0c;梯度告诉我们如何调整神经网络参数&#xff0c;使损失函数最小化。 1.2 梯度的重要性 …

【Python爬虫】详细入门指南

目录 一、简单介绍 二、详细工作流程以及组成部分 三、 简单案例实现 一、简单介绍 在当今数字化信息飞速发展的时代&#xff0c;数据的获取与分析变得愈发重要&#xff0c;而网络爬虫技术作为一种能够从互联网海量信息中自动抓取所需数据的有效手段&#xff0c;正逐渐走入…

Golang|Channel 相关用法理解

文章目录 用 channel 作为并发小容器channel 的遍历channel 导致的死锁问题用 channel 传递信号用 channel 并行处理文件用channel 限制接口的并发请求量用 channel 限制协程的总数量 用 channel 作为并发小容器 注意这里的 ok 如果为 false&#xff0c;表示此时不仅channel为空…

Windows单机模拟MySQL主从复制

这里写自定义目录标题 下载MySQL ZIP压缩包安装主库1、创建配置文件2、安装服务3、初始化数据库4、启动服务5、配置主库 安装从库1、配置ini文件2、安装服务3、初始化数据库4、启动服务5、配置从库6、验证从库状态 操作主库验证 下载MySQL ZIP压缩包 https://dev.mysql.com/do…

OSPF路由引入

一、基本概念与作用 1.OSPF路由引入指通过自治系统边界路由器&#xff08;ASBR&#xff09;将外部路由&#xff08;如BGP、RIP、静态路由或其他OSPF进程的路由&#xff09;注入当前OSPF域&#xff0c;实现跨协议或跨区域的网络互通‌。 其核心作用包括&#xff1a; ‌扩展网…

弱口令爆破

1.简单介绍 弱口令是指一些简单易猜的密码&#xff0c;可通过社工方式和一些爆破工具进行破解&#xff0c;以下介绍一款爆破工具的用法。burpsuite简称BP&#xff0c;一款可以利用字典破解账户密码的工具。 2.部署网站 可以使用PHPstudy的Apache服务&#xff0c;也可以使用I…

Vue3+Vite前端项目部署后部分图片资源无法获取、动态路径图片资源报404错误的原因及解决方案

目录 Vue3vite前端项目部署后部分图片资源无法获取、动态路径图片资源报404错误的原因及解决方案 一、情景介绍 1、问题出现的场景 2、无法加载的图片写法 二、反向代理原理简介 三、造成该现象的原因 四、解决方案 1、放弃动态渲染 2、在页面挂载的时候引入图片资源 …