从零玩转系列之微信支付实战PC端支付微信取消接口搭建 | 技术创作特训营第一期
一、前言
从零玩转系列之微信支付实战PC端支付微信取消接口搭建 | 技术创作特训营第一期
halo各位大佬很久没更新了最近在搞微信支付,因商户号审核了我半个月和小程序认证也找了资料并且将商户号和小程序进行关联,至此微信支付Native支付完成.此篇文章过长我将分几个阶段的文章发布(项目源码都有,小程序和PC端)
在此之前已经更新了微信支付开篇、微信支付安全、微信实战基础框架搭建、本次更新为微信支付实战PC端接口搭建,实战篇分为几个章节因为代码量确实有点多哈.
- 第一章从零玩转系列之微信支付开篇
- 第二章从零玩转系列之微信支付安全
- 第三章从零玩转系列之微信支付实战基础框架搭建
- 第四章从零玩转系列之微信支付实战PC端支付下单接口搭建
- 第五章从零玩转系列之微信支付实战PC端支付微信回调接口搭建
- 第五章从零玩转系列之微信支付实战PC端支付微信取消订单接口搭建
- 第六章从零玩转系列之微信支付实战PC端支付微信退款订单接口搭建

本次项目使用技术栈
后端: SpringBoot3.1.x、Mysql8.0、MybatisPlus
前端: Vue3、Vite、ElementPlus
小程序: Uniapp、Uview
一、取消订单接口
场景
- 用户下单完毕后未支付 可进行取消订单
- 订单超时支付系统自动取消订单
修改 WechatNativeController
/**
* 用户取消订单
*/
@PostMapping("/cancel/{orderNo}")
public R<String> cancel(@PathVariable String orderNo) {
log.info("取消订单");
wxPayService.cancelOrder(orderNo);
return R.ok("订单已取消");
}
修改 wxPayService
/**
* 关闭订单
*/
@SneakyThrows
public void cancelOrder(String orderNo) {
// ...../
}
逻辑分析
在工作中我们逻辑可能是这样子的
step 1 查询该订单状态是否需要关闭订单,如果订单已经关闭则不需要再次关闭
思考: 我们应该去哪里查询订单的状态?

假如我们去数据库查询记录的话,如果数据库因为什么原因导致状态可能不对呢?
所以我们直接去微信服务器查最新的直接更新关闭状态到数据库当中

你看微信也要我们这样子玩那就万无一失直接干
================================================================
好既然我们要去调用微信查询接口我们是不是可以封装一个通用的 后续肯定有其他地方也会调用查询支付信息的情况
文档(商户): https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_2.shtml
有两种查询方式第二种方便就这么简单
代码很好理解传递商户订单号和直连商户号mchid
/**
* 抽出公共获取微信订单信息
*/
private WeChartOrderInfo selectOrderInfo(String orderNo) throws IOException {
log.info("查询订单,直连商户号:{} , 微信支付订单号: {}", orderNo, wxPayConfig.getMchId());
String url = wxPayConfig.getDomain().concat(String.format(WxApiType.ORDER_QUERY_BY_NO.getType(), orderNo)).concat("?mchid=").concat(wxPayConfig.getMchId());
HttpGet httpGet = new HttpGet(url);
httpGet.setHeader("Accept", "application/json");
CloseableHttpResponse response = wxPayClient.execute(httpGet);
WeChartOrderInfo weChartOrderInfo = buildBodyParams(response, WeChartOrderInfo.class);
log.info("查询订单响应, {}", weChartOrderInfo);
response.close();
return weChartOrderInfo;
}
响应结果
{
"amount": {
"currency": "CNY",
"payer_currency": "CNY",
"payer_total": 1,
"total": 1
},
"appid": "wxdace645e0bc2cXXX",
"attach": "",
"bank_type": "OTHERS",
"mchid": "1900006XXX",
"out_trade_no": "44_2126281063_5504",
"payer": {
"openid": "o4GgauJP_mgWEWictzA15WT15XXX"
},
"promotion_detail": [],
"success_time": "2021-03-22T10:29:05+08:00",
"trade_state": "SUCCESS",
"trade_state_desc": "支付成功",
"trade_type": "JSAPI",
"transaction_id": "4200000891202103228088184743"
}
完善逻辑
/**
* 关闭订单
*/
@SneakyThrows
public void cancelOrder(String orderNo) {
// step 1 查询该订单状态是否需要关闭订单
WeChartOrderInfo state = selectOrderInfo(orderNo);
// 判断如果订单已经关闭则不需要再次关闭 更新数据库
if (null == state || state.getTrade_state() == null) {
// 更新本地订单状态超时关闭订单
orderInfoService.lambdaUpdate().eq(OrderInfo::getOrderNo, orderNo).set(OrderInfo::getOrderStatus, OrderStatus.CLOSED.getType()).update();
return;
}
// step 2 还未支付才能取消订单
if (state.getTrade_state().equals(OrderStatus.NOTPAY.name())) {
// step 2 进行调用微信关闭订单接口
sendCloseRequest(orderNo);
// step 2 更新商户端的订单状态用户取消订单
this.orderInfoService.lambdaUpdate().eq(OrderInfo::getOrderNo, orderNo).set(OrderInfo::getOrderStatus, OrderStatus.CANCEL.getType()).update();
}
}
抽出通用订单关闭代码
文档: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_3.shtml
/**
* 发送关闭订单请求
*
* @param orderNo 订单编号
*/
@SneakyThrows
private void sendCloseRequest(String orderNo) {
log.info("关闭订单, 订单号:{}", orderNo);
String url = String.format(wxPayConfig.getDomain().concat(WxApiType.CLOSE_ORDER_BY_NO.getType()), orderNo);
HttpPost httpPost = new HttpPost(url);
Map<String, Object> paramsMap = new HashMap<>(1);
paramsMap.put("mchid", wxPayConfig.getMchId());
String jsonParams = JSONUtil.toJsonStr(paramsMap);
log.info("请求参数 ===> {}", jsonParams);
StringEntity entity = new StringEntity(jsonParams, "utf-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
httpPost.setHeader("Accept", "application/json");
try (CloseableHttpResponse response = wxPayClient.execute(httpPost)) {
log.info("关单响应: {}", response.getEntity());
log.info("解析body {}", buildBodyParams(response, Map.class));
}
}
到这里订单取消就完毕了
二、查询订单接口
根据上面编写的查询订单方法完善一下
修改 WechatNativeController
/**
* 查询订单
*/
@PostMapping("/query/{orderNo}")
public R<WeChartOrderInfo> query(@PathVariable String orderNo) {
log.info("查询订单");
return R.ok(wxPayService.queryOrder(orderNo));
}
修改 WxPayService
/**
* 查询订单信息
*
* @param orderNo 订单号
* @return 订单信息
*/
@SneakyThrows
public WeChartOrderInfo queryOrder(String orderNo) {
return this.selectOrderInfo(orderNo);
}
好了查询接口也写完了so easy to happy !
我们来测试看看是什么效果咯~

三、测试
下单
我们还没编写到前端来所以还是和之前的文章操作一样使接口调试工具操作这里我使用之前推荐的IDEA FastRequest插件如下图

发送

生成二维码
复制codeUrl参数打开草料 https://cli.im/url 不要支付哦我们确保订单是否成功创建,确保二维码没有过期哦

我们也可以先看看订单啥状态上面我们不是写了个查询订单详情的嘛

调用取消订单接口
复制 orderNo 订单编号直接发送取消完成

在查询一下订单看看状态是不是取消成功


【写作提纲】
I. 前言
A. 通过前言表达我每次的文章内容是什么东西
II. 取消订单接口实现
A. 集结生活之中的场景来解析他的逻辑
III. 查询订单接口实现
A. 完善取消订单接口当中已经实现了的功能
IV. 测试
A. 通过测试用例一步步排查编写是否存在BUG
从零玩转系列之微信支付实战PC端支付微信取消接口搭建 | 技术创作特训营第一期的更多相关文章
- 微信开放平台PC端扫码登录功能个人总结
最近公司给我安排一个微信登录的功能,需求是这样的: 1.登录授权 点击二维码图标后,登录界面切换为如下样式(二维码),微信扫描二维码并授权,即可成功登录: 若当前账号未绑定微信账号,扫描后提示“ ...
- c#版在pc端发起微信扫码支付
等了好久,微信官方终于发布了.net的demo. 主要代码: /** * 生成直接支付url,支付url有效期为2小时,模式二 * @param productId 商品ID * @return 模式 ...
- 【微信开发】PC端 微信扫码支付成功之后自动跳转
场景: PC端 微信扫码支付 结果: 支付成功 自动跳转 实现思路: 支付二维码页面,写ajax请求支付状态,请求到结果,无论成功还是失败,都跳转到相应的结果页面 具体实现方法: html部分: ...
- 前端:微信支付和支付宝支付在pc端和h5页面中的应用
1:h5微信支付 使用的是https://pay.weixin.qq.com/wiki/doc/api/index.html 中的 (1):公司需要首先要配置公众号微信支付地址和测试白名单(支付的时 ...
- Java SpringMVC实现PC端网页微信扫码支付完整版
一:前期微信支付扫盲知识 前提条件是已经有申请了微信支付功能的公众号,然后我们需要得到公众号APPID和微信商户号,这个分别在微信公众号和微信支付商家平台上面可以发现.其实在你申请成功支付功能之后,微 ...
- 【weixin】微信支付---Native支付模式二(PC端支付大多采用此模式)
[模式二]:商户后台系统调用微信支付[统一下单API]生成预付交易,将接口返回的链接生成二维码,用户扫码后输入密码完成支付交易.注意:该模式的预付单有效期为2小时,过期后无法支付 模式二与模式一相比, ...
- pc端用微信扫一扫实现微信第三方登陆
官方文档链接 第一步:获取AppID AppSecret (微信开发平台申请PC端微信登陆) 第二步:生成扫描二维码,获取code https://open.weixin.qq.com/conn ...
- 支付宝pc端支付接入PHP实现
引入支付宝接口 放入一个插件库中,方便管理 创建支付类 1.发起支付 public function init() { $order_id = $_REQUEST['order_id']; $orde ...
- Python接入支付宝进行PC端支付
1. 支付宝开放平台登录,使用支付宝账号登录 https://open.alipay.com/platform/home.htm 2.选择沙箱模式 [支付宝提供了测试环境] https://docs ...
- PC端网站微信扫码登录
需求分析:用户通过扫描我们网页的二维码,如果已经绑定我们平台的账户,即成功进入首页,否则提示先绑定个人微信账号. 1.绑定微信账号:是通过关注微信公众号实现绑定个人微信账号.首先通过后台接口获取到ti ...
随机推荐
- 在nuxt下引入外部js
最近在踩nuxt.js的坑,遇到了许多问题,在这里记录一下,方便以后查阅. 1.如何引入外部js 如果是插件,可以在package.json中写明名字和版本,在nuxt.config.js中注册,然后 ...
- 解决pod健康检查问题
解决pod健康检查问题 引自:Solving the mystery of pods health checks failures in Kubernetes.原文中的某些描述并不清晰,本文作了调整. ...
- Vulhub activewq_漏洞复现——源码分析
Vulhub activewq_漏洞复现--源码分析 漏洞简介 Apache ActiveMQ是由美国阿帕奇(Apache)软件基金会开发的开源消息中间件,支持Java消息服务.集群.Spring框架 ...
- 2022-12-12:有n个城市,城市从0到n-1进行编号。小美最初住在k号城市中 在接下来的m天里,小美每天会收到一个任务 她可以选择完成当天的任务或者放弃该任务 第i天的任务需要在ci号城市完成,
2022-12-12:有n个城市,城市从0到n-1进行编号.小美最初住在k号城市中 在接下来的m天里,小美每天会收到一个任务 她可以选择完成当天的任务或者放弃该任务 第i天的任务需要在ci号城市完成, ...
- 2021-12-15: 路径总和 III。给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。路径 不需要从根节点开
2021-12-15: 路径总和 III.给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目.路径 不需要从根节点开 ...
- WPF入门教程系列二十七 ——DataGrid使用示例MVVM模式(4)
WPF入门教程系列目录 WPF入门教程系列二--Application介绍 WPF入门教程系列三--Application介绍(续) WPF入门教程系列四--Dispatcher介绍 WPF入门教程系 ...
- 非 root 用户手动编译安装 GCC
我们知道,关于 GCC 在 CentOS 下通过 yum 安装默认版本号,CentOS 5 是 4.1.2:CentOS 6 是 4.4.7:CentOS 7 是 4.8.3.很多时候在编译安装软件都 ...
- 实例讲解Flink 流处理程序编程模型
摘要:在深入了解 Flink 实时数据处理程序的开发之前,先通过一个简单示例来了解使用 Flink 的 DataStream API 构建有状态流应用程序的过程. 本文分享自华为云社区<Flin ...
- STL-array(ACM)
1.C++ 11 出现的, C++98没有 2.可以作为数组元素 pair<array<int, 3>, int>pair<int a[3], int > 不能这样 ...
- XXE漏洞详解
XML外部实体注入--XXE漏洞详解 简单来说一下这个XXE漏洞,在这之前我也阅读了很多关于XXE漏洞的文章,发现有一小部分文章题目是 "XXE外部实体注入" 这样的字眼,我想这样 ...