【畅购商城】微信支付之支付回调和支付状态
目录
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 语法,但在某些遗留系统中,这种写法…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...
