【畅购商城】微信支付之支付回调和支付状态
目录
Nuxt.js IP 启动
支付回调
回调接口
后端实现
查看支付状态
后端实现
前端实现
前置技术:RabbitMQ
更新订单状态
Nuxt.js IP 启动
"config": {"nuxt": {"host": "0.0.0.0","port": "3000"}},
支付回调
回调接口
步骤一:修改yml文件,添加notifyUrl配置
步骤二:修改配置文件
步骤三:修改工具类
步骤一:修改yml文件,添加notifyUrl配置
sc:pay:notifyUrl: http://40m459492i.wicp.vip/order-service/pay/callback
步骤二:修改配置文件
private String notifyUrl; //回调路径
步骤三:修改工具类
package com.czxy.changgou4.utils;import com.czxy.changgou4.config.PayProperties;
import com.github.wxpay.sdk.WXPay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;import java.util.HashMap;
import java.util.Map;/*** @author 桐叔* @email liangtong@itcast.cn*/
@Component
@EnableConfigurationProperties(PayProperties.class)
public class PayHelper {private WXPay wxPay;private PayProperties payProperties;@Beanpublic WXPay wxPay(PayProperties payProperties){if(wxPay == null){this.payProperties = payProperties;wxPay = new WXPay(payProperties);}return wxPay;}private static final Logger logger = LoggerFactory.getLogger(PayHelper.class);public PayHelper() {}public PayHelper(PayProperties payProperties) {wxPay = new WXPay(payProperties);}public String createPayUrl(Long sn) {String key = "pay.url." + sn;try {Map<String, String> data = new HashMap<>();// 商品描述data.put("body", "商城测试");// 订单号data.put("out_trade_no", sn.toString());//货币data.put("fee_type", "CNY");//金额,单位是分data.put("total_fee", "1");//调用微信支付的终端IP(商城的IP)data.put("spbill_create_ip", "127.0.0.1");//回调地址data.put("notify_url", this.payProperties.getNotifyUrl());// 交易类型为扫码支付data.put("trade_type", "NATIVE");//商品id,使用假数据data.put("product_id", "1234567");Map<String, String> result = this.wxPay.unifiedOrder(data);if ("SUCCESS".equals(result.get("return_code"))) {if("SUCCESS".equals(result.get("result_code"))){String url = result.get("code_url");return url;} else {logger.error("创建预交易订单失败,错误信息:{}", result.get("err_code_des"));return null;}} else {logger.error("创建预交易订单失败,错误信息:{}", result.get("return_msg"));return null;}} catch (Exception e) {logger.error("创建预交易订单异常", e);return null;}}/*** 查询订单状态* 交易状态参考:(trade_state)SUCCESS—支付成功REFUND—转入退款NOTPAY—未支付CLOSED—已关闭REVOKED—已撤销(付款码支付)USERPAYING--用户支付中(付款码支付)PAYERROR--支付失败(其他原因,如银行返回失败)* @param sn* @return*/public PayState queryOrder(Long sn) {Map<String, String> data = new HashMap<>();// 订单号data.put("out_trade_no", sn.toString());try {Map<String, String> result = this.wxPay.orderQuery(data);if("SUCCESS".equals(result.get("return_code"))){if("SUCCESS".equals(result.get("result_code"))) {String tradeState = result.get("trade_state");if ("SUCCESS".equals(tradeState)) {return PayState.SUCCESS;}if ("NOTPAY".equals(tradeState)) {return PayState.NOT_PAY;}if ("CLOSED".equals(tradeState)) {return PayState.CLOSED;}}}return PayState.PAY_ERROR;} catch (Exception e) {logger.error("查询订单状态异常", e);return PayState.PAY_ERROR;}}
}
后端实现
- 步骤一:修改PayController,添加callback方法
- 步骤二:检查网关,放行callback方法
- 步骤三:修改花生壳,访问10010端口
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_7&index=8
步骤一:修改PayController,添加callback方法
@PostMapping("/callback")
public void callback(HttpServletRequest request, HttpServletResponse response) throws IOException {try {//1 获得响应内容String xml = IOUtils.toString(request.getInputStream(), "UTF-8");System.out.println(xml);//解析Map<String, String> map = WXPayUtil.xmlToMap( xml );// 查询成功if("SUCCESS".equals(map.get( "result_code" ) )){// 获得订单号String sn = map.get("out_trade_no");//TODO 更新订单状态System.out.println(sn);//如果成功,给微信支付一个成功的响应response.setContentType("text/xml");String data = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";response.getWriter().write(data);}} catch (Exception e) {e.printStackTrace();response.setContentType("text/xml");String data = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA["+e.getMessage()+"]]></return_msg></xml>";response.getWriter().write(data);}
}
步骤二:检查网关,放行callback方法
步骤三:修改花生壳,访问10010端口
查看控制台结果
<xml><appid><![CDATA[wx8397f8696b538317]]></appid>
<bank_type><![CDATA[COMM_CREDIT]]></bank_type>
<cash_fee><![CDATA[1]]></cash_fee>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[N]]></is_subscribe>
<mch_id><![CDATA[1473426802]]></mch_id>
<nonce_str><![CDATA[47e529ea929e4c9e847ee9699751a648]]></nonce_str>
<openid><![CDATA[oNpSGwZaaw_0uBEMwFpkwIwFsttw]]></openid>
<out_trade_no><![CDATA[1259484402174529500]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[2D4BC610795C1DC303B0B26092D6C6E3]]></sign>
<time_end><![CDATA[20200510220429]]></time_end>
<total_fee>1</total_fee>
<trade_type><![CDATA[NATIVE]]></trade_type>
<transaction_id><![CDATA[4200000568202005108477965385]]></transaction_id>
</xml>
1259484402174529500
查看支付状态
后端实现
- 步骤一:修改PayService,查询订单支付状态
- 步骤二:编写PayService实现类
- 步骤三:修改PayController
步骤一:修改PayService,查询订单支付状态
package com.czxy.changgou4.service;import com.czxy.changgou4.utils.PayState;
import com.czxy.changgou4.vo.PayRequest;/*** @author 桐叔* @email liangtong@itcast.cn*/
public interface PayService {/*** 查看支付状态* @param sn* @return*/public PayState query(Long sn);
}
步骤二:编写PayService实现类
@Override
public PayState query(Long sn) {//查询微信支付状态PayState payState = payHelper.queryOrder(sn);return payState;}
步骤三:修改PayController
@GetMapping("/{sn}")
public BaseResult query(@PathVariable("sn") Long sn){//查询PayState payState = payService.query(sn);//返回if(payState.getCode() == 1) {return BaseResult.ok(payState.getDesc());}return BaseResult.error(payState.getDesc());
}
前端实现
如果订单已经支付,跳转到支付成功页面。
- 步骤一:修改api.js,查询订单支付状态
- 步骤二:修改flow3,“查询订单状态”绑定事件
- 步骤三:修改flow3,编写事件,如果是成功,调到到flow4
- 步骤四:编写flow4,与flow3基本内容一致,提示信息为“支付成功,货物即将送出!”
步骤一:修改api.js,查询订单支付状态
findPayStatus : ( sn ) => {return axios.get("/order-service/pay/"+sn )}
步骤二:修改flow3,“查询订单状态”绑定事件
步骤三:修改flow3,编写事件,如果是成功,调到到flow4
methods: {async findPayStatusFn() {let { data } = await this.$request.findPayStatus( this.sn );if( data.code == 20000) {location.href = 'flow4'} else {alert( data.message );}}},
步骤四:编写flow4,与flow3基本内容一致,提示信息为“支付成功,货物即将送出!”
<template><div><!-- 顶部导航 start --><div class="topnav"><div class="topnav_bd w990 bc"><div class="topnav_left"></div><div class="topnav_right fr"><ul><li>您好,欢迎来到畅购![<a href="login.html">登录</a>] [<a href="register.html">免费注册</a>] </li><li class="line">|</li><li>我的订单</li><li class="line">|</li><li>客户服务</li></ul></div></div></div><!-- 顶部导航 end --><div style="clear:both;"></div><!-- 页面头部 start --><div class="header w990 bc mt15"><div class="logo w990"><h2 class="fl"><a href="index.html"><img src="images/logo.png" alt="畅购商城"></a></h2><div class="flow fr flow3"><ul><li>1.我的购物车</li><li>2.填写核对订单信息</li><li class="cur">3.成功提交订单</li></ul></div></div></div><!-- 页面头部 end --><div style="clear:both;"></div><!-- 主体部分 start --><div class="success w990 bc mt15"><div class="success_hd"><h2>订单支付成功</h2></div><div class="success_bd"><p><span></span>支付成功,货物即将送出!</p></div></div><!-- 主体部分 end --><div style="clear:both;"></div><!-- 底部版权 start --><Footer></Footer><!-- 底部版权 end --></div>
</template><script>
import TopNav from '../components/TopNav'
import Footer from '../components/Footer'export default {head: {title: '首页',link: [{rel:'stylesheet',href: '/style/success.css'},],script: []},components: {TopNav,Footer,}}
</script><style></style>
前置技术:RabbitMQ
更新订单状态
步骤一:配置环境,
rabbitmq中添加order_pay队列
添加依赖
添加yml配置
步骤二:修改回调函数,将sn存放到rabbit中
步骤三:编写监听器(消费者),更新订单状态
步骤四:修改OrderService,完成修改功能
步骤五:修改OrderMapper,完成修改功能
步骤一:配置环境,
rabbitmq中添加order_pay队列,添加rabbit配置类
ackage com.czxy.changgou4.config;import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;/*** @author 桐叔* @email liangtong@itcast.cn*/
@Component
public class OrderPayQueue {private static final String ORDER_PAY_QUEUE = "order_pay";@Beanpublic Queue queue() {return new Queue(ORDER_PAY_QUEUE);}
}
添加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
添加yml配置
spring:rabbitmq:host: 127.0.0.1username: guestpassword: guest
步骤二:修改回调函数,将sn存放到rabbit中
rabbitTemplate.convertAndSend("", "order_pay", sn);
步骤三:编写监听器(消费者),更新订单状态
package com.czxy.changgou4.listener;import com.czxy.changgou4.service.OrderService;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** @author 桐叔* @email liangtong@itcast.cn*/
@Component
@RabbitListener(queues = "order_pay")
public class OrderPayListener {@Autowiredprivate OrderService orderService;/*** 更新支付状态* @param message*/@RabbitHandlerpublic void updatePayStatus(String message){orderService.updatePayStatus( message , "1" );}
}
步骤四:修改OrderService,完成修改功能
package com.czxy.changgou4.service;import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.Order;
import com.czxy.changgou4.pojo.User;
import com.czxy.changgou4.vo.CartVo;
import com.czxy.changgou4.vo.OrderVo;import java.util.List;public interface OrderService extends IService<Order> {void updatePayStatus(String sn, String status);
}
package com.czxy.changgou4.service.impl;import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.pojo.Order;
import com.czxy.changgou4.pojo.OrderGoods;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.util.*;@Service
@Transactional
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {@Overridepublic void updatePayStatus(String sn, String status) {//更新状态baseMapper.updateStatus(sn,status);}
}
步骤五:修改OrderMapper,完成修改功能
package com.czxy.changgou4.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;@Mapper
public interface OrderMapper extends BaseMapper<Order> {/*** 更加sn修改状态* @param sn* @param status*/@Update("UPDATE tb_order SET STATUS = #{status} WHERE sn = #{sn}")void updateStatus(@Param("sn") String sn, @Param("status") String status);
}
测试:在rabbitMQ web控制台,可以手动发布消息
相关文章:

【畅购商城】微信支付之支付回调和支付状态
目录 Nuxt.js IP 启动 支付回调 回调接口 后端实现 查看支付状态 后端实现 前端实现 前置技术:RabbitMQ 更新订单状态 Nuxt.js IP 启动 "config": {"nuxt": {"host": "0.0…...

【Compose multiplatform教程18】多平台资源的设置和配置
要正确配置项目以使用多平台资源,请执行以下操作: 添加库依赖项。 为每种资源创建必要的目录。 为限定资源创建其他目录(例如,深色 UI 主题或本地化字符串的不同图像)。 依赖项和目录设置 要访问多平台项目中的资源…...

MT6765核心板_MTK6765安卓核心板规格参数_联发科MTK模块开发
MTK6765安卓核心板是基于联发科高效八核处理器平台开发的一款强大硬件解决方案。这款核心板的核心是采用12纳米工艺打造的MTK6765 CPU,具备四个主频高达2.3GHz的CORTEX-A53核心和四个主频为1.8GHz的CORTEX-A53核心,提供了卓越的处理性能。用户可以根据需…...

conda常用维护命令
文章目录 1. 初始化和更新 Conda更新 Conda初始化 Conda(如果需要) 2. 管理环境创建新环境激活环境停用当前环境列出所有环境删除环境 3. 管理包安装包卸载包更新包更新所有包查找包列出已安装包 4. 导入导出环境导出环境配置从文件创建环境 5. 管理通道…...

Html——10 关键字和描述
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>淘宝网</title><meta name"keywords" content"我要自学网,自学HTML,自学CSS"/><meta name"description" content"要设置…...

Mysql(MGR)和ProxySQL搭建部署-Docker版本
项目路径:D:\study\backend\mysql\mgr 一、Mysql(MGR) 1.1 docker-compose.yaml volumes: # MySQL配置文件目录 - "./mysql-1/conf.d/my.cnf:/etc/mysql/my.cnf" # MySQL工作目录 - "./mysql-1/data:/var/lib/mysql" …...

QML学习(一) Qt Quick和QML介绍以及适用场景说明
一.介绍 1.Qt Quick 介绍 Qt Quick 提供了一套高动态,丰富的 QML 元素来定制用户界面的说明性框架。Qt Quick 有助于程序开发员与界面设计员的合作为便携式设备建立流畅的用户界面,例如:移动电话、媒体播放器,机顶盒以及上网本等…...

深入理解 PyTorch 的 view() 函数:以多头注意力机制(Multi-Head Attention)为例 (中英双语)
深入理解 PyTorch 的 view() 函数:以多头注意力机制(Multi-Head Attention)为例 在深度学习模型的实现中,view() 是 PyTorch 中一个非常常用的张量操作函数,它能够改变张量的形状(shape)而不改…...

使用PHP函数 “setcookie“ 设置cookie
在网站开发中,cookie是一种非常常用的技术,它用于在用户的浏览器中存储少量的数据,以便在不同页面之间传递信息。PHP提供了一个名为 "setcookie" 的函数,用于设置cookie的值和属性。在本文中,我们将学习如何…...

redis优化
在高并发、高性能、高可用系统中,Redis 的优化至关重要。以下是一些在面试中可以详细说明的 Redis 优化策略,以及具体的实践经验和技术亮点: 1. 数据模型与结构设计优化 使用合适的数据结构 :根据业务需求选择合适的 Redis 数据结…...

数据分析的革命——解读云数据库 SelectDB 版的力量
在当今数据驱动的时代,实时数据分析已成为企业决策中的关键一环。如何在海量数据中快速找到核心价值,如何让决策者在毫秒间洞悉变化,这不仅考验着企业的技术能力,也对基础设施提出了新的要求。云数据库 SelectDB 版,正…...

Ngnix介绍、安装、实战及用法!!!
一、Nginx简介 1、Nginx概述 Nginx (“engine x”) 是一个高性能的 HTTP 和 反向代理服务器,特点是占有内存少,并发能力强,能经受高负载的考验,有报告表明能支持高达 50,000 个并发连接数 。 2、正向代理 正向代理:如果把局…...

算法基础一:冒泡排序
一、冒泡排序 1、定义 冒泡排序(英语:Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。 …...

云开发实战教程:手把手教你高效开发应用
声明:本文仅供实践教学使用,没有任何打广告成分 目录 1.引言 2.云开发 Copilot介绍 云开发 Copilot 的功能与特点 3.环境准备 步骤一登录账号 步骤二新建环境 4.开发实践 4.1AI 生成低代码应用 4.2AI 生成低代码页面/区块 4.3AI 优化低代码组件…...

Git基本操作快速入门(30min)
Git基本操作快速入门(30min) 文章目录 Git基本操作快速入门(30min)1. 建立本地仓库2. 本地仓库链接到远端仓库3. 将本地仓库推送到远端4. Git常用命令 作为一名程序员,使用Github来进行代码的版本管理是必修课…...

VS Code AI开发之Copilot配置和使用详解
随着AI开发工具的迅速发展,GitHub Copilot在Cursor、Winsuf、V0等一众工具的冲击下,推出了免费版本。接下来,我将为大家介绍GitHub Copilot的配置和使用方法。GitHub Copilot基于OpenAI Codex模型,旨在为软件开发者提供智能化的代…...

QT中使用OpenGL function
1.前言 QT做界面编程很方便,QTOpenGL的使用也很方便,因为QT对原生的OpenGL API进行了面向对象化的封装。 如: 函数:initializeOpenGLFunctions()...... 类:QOpenGLVertexArrayObject、QOpenGLBuffer、QOpenGLShader…...

STM32-笔记16-定时器中断点灯
一、实验目的 使用定时器 2 进行中断点灯,500ms LED 灯翻转一次。 二,定时器溢出时间计算 Tout:定时器溢出时间 Ft:定时器的时钟源频率 ARR:自动重装载寄存器的值(可设置ARR从0开始,但是计数到…...

Live555、FFmpeg、GStreamer介绍
Live555、FFmpeg 和 GStreamer 都是处理流媒体和视频数据的强大开源框架和工具,它们广泛应用于实时视频流的推送、接收、处理和播放。每个框架有不同的设计理念、功能特性以及适用场景。下面将详细分析这三个框架的作用、解决的问题、适用场景、优缺点,并…...

oracle基础:理解 Oracle SQL 中的 WHERE 后的 (+) 用法
在使用 Oracle 数据库进行 SQL 查询时,可能会遇到 WHERE 子句后带有 () 的语法。这是 Oracle 专有的外连接(Outer Join)表示法。虽然现代 SQL 标准推荐使用 LEFT JOIN 和 RIGHT JOIN 语法,但在某些遗留系统中,这种写法…...

【linux】进程间通信(IPC)——匿名管道,命名管道与System V内核方案的共享内存,以及消息队列和信号量的原理概述
目录 ✈必备知识 进程间通信概述 🔥概述 🔥必要性 🔥原理 管道概述 🔥管道的本质 🔥管道的相关特性 🔥管道的同步与互斥机制 匿名管道 🔥系统调用接口介绍 🔥内核原理 …...

【深度学习】卷积网络代码实战ResNet
ResNet (Residual Network) 是由微软研究院的何凯明等人在2015年提出的一种深度卷积神经网络结构。ResNet的设计目标是解决深层网络训练中的梯度消失和梯度爆炸问题,进一步提高网络的表现。下面是一个ResNet模型实现,使用PyTorch框架来展示如何实现基本的…...

org.apache.zookeeper.server.quorum.QuorumPeerMain
QuorumPeerMain源代码 package org.apache.zookeeper.server.quorum;import java.io.IOException; import javax.management.JMException; import javax.security.sasl.SaslException; import org.apache.yetus.audience.InterfaceAudience; import org.apache.zookeeper.audi…...

oscp学习之路,Kioptix Level2靶场通关教程
oscp学习之路,Kioptix Level2靶场通关教程 靶场下载:Kioptrix Level 2.zip 链接: https://pan.baidu.com/s/1gxVRhrzLW1oI_MhcfWPn0w?pwd1111 提取码: 1111 搭建好靶场之后输入ip a看一下攻击机的IP。 确定好本机IP后,使用nmap扫描网段&…...

SkyWalking java-agent 是如何工作的,自己实现一个监控sql执行耗时的agent
Apache SkyWalking 是一个开源的应用性能监控 (APM) 工具,支持分布式系统的追踪、监控和诊断。SkyWalking Agent 是其中的一个重要组件,用于在服务端应用中收集性能数据和追踪信息,并将其发送到 SkyWalking 后端服务器进行处理和展示。 SkyW…...

每天40分玩转Django:Django表单集
Django表单集 一、知识要点概览表 类别知识点掌握程度要求基础概念FormSet、ModelFormSet深入理解内联表单集InlineFormSet、BaseInlineFormSet熟练应用表单集验证clean方法、验证规则熟练应用自定义配置extra、max_num、can_delete理解应用动态管理JavaScript动态添加/删除表…...

查看vue的所有版本号和已安装的版本
1.使用npm查看Vue的所有版本: npm view vue versions2.查看项目中已安装的 Vue.js 版本 npm list vue...

钉钉h5微应用,鉴权提示dd.config错误说明,提示“jsapi ticket读取失败
这个提示大多是因为钉钉服务器没有成功读取到该企业的jsticket数据 1. 可能是你的企业corpid不对 登录钉钉管理后台 就可以找到对应企业的corpid 请严格使用这个corpid 。调用获取jsapi_ticket接口,使用的access_token对应的corpid和dd.config中传递的corpid不一致…...

【openGauss】正则表达式次数符号“{}“在ORACLE和openGauss中的差异
一、前言 正则作为一种常用的字符串处理方式,在各种开发语言,甚至数据库中,都有自带的正则函数。但是正则函数有很多标准,不同标准对正则表达式的解析方式不一样,本次在迁移一个ORACLE数据库到openGauss时发现了一个关…...

宏任务和微任务的区别
在 JavaScript 的异步编程模型中,宏任务(Macro Task)和微任务(Micro Task)是事件循环(Event Loop)机制中的两个重要概念。它们用于管理异步操作的执行顺序。 1. 宏任务 (Macro Task) 宏任务是较…...