从零玩转系列之微信支付实战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 ...
随机推荐
- [python] Python类型提示总结
Python3.5 版本引入了类型提示(Type Hints),它允许开发者在代码中显式地声明变量.函数.方法等的类型信息.这种类型声明不会影响 Python 解释器的运行,但可以让 IDE 和静态分 ...
- 2021-09-17:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。进阶:你能尝试使用一趟扫描实现吗?
2021-09-17:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点.进阶:你能尝试使用一趟扫描实现吗? 福大大 答案2021-09-17: 双指针. 1.创建虚拟头节点preHea ...
- DataGridViewImageColumn 图片照片
Private Sub BT_PHOTOADDRESS_Click(sender As Object, e As EventArgs) Handles BT_PHOTOADDRESS.Click Di ...
- Midjourney|文心一格prompt教程[Text Prompt(上篇)]:品牌log、App、徽章、插画、头像场景生成,各种风格选择:科技风、运动风
Midjourney|文心一格prompt教程[Text Prompt(上篇)]:品牌log.App.徽章.插画.头像场景生成,各种风格选择:科技风.运动风 1.撰写 Text Prompt 注意事项 ...
- DP杂谈【持续更新中】
什么是DP? 推荐看一下. 正文 滚动数组优化 在一些空间贼小,时间还好的 DP 题目里,会用到优化空间的小技♂巧--滚动数组优化. 滚动数组,顾名思义,一个会滚动的数组,主要是怎样个滚法呢?接下来我 ...
- 【RocketMQ】NameServer总结
NameServer是一个注册中心,提供服务注册和服务发现的功能.NameServer可以集群部署,集群中每个节点都是对等的关系(没有像ZooKeeper那样在集群中选举出一个Master节点),节点 ...
- RabbitMQ 工作模式介绍
RabbitMQ 工作模式介绍 1.Hello World RabbitMQ 是一个消息代理:它接受并转发消息.您可以将其视为邮局:当您将要邮寄的邮件放入邮箱时,您可以确定信使最终会将邮件交付给您的收 ...
- 顶级生物信息学 RSS 订阅源
早在 2018 年的时候我在"生信草堂"的公众号上写过一篇关于 RSS 的文章<使用 RSS 打造你的科研资讯头条>,介绍了关于 RSS 的一些内容和如何使用 inor ...
- 让你的 conda “回滚”到以前版本的环境
我现在使用 Anaconda 作为我的主要 Python 发行版,同样,我们公司也将它用于所有开发人员机器以及他们的服务器.然而,前几天我在浏览一些论坛技术文章时遇到了一个我以前从未知道的 conda ...
- 【Java学习】 Spring的基础理解 IOC、AOP以及事务
一.简介 官网: https://spring.io/projects/spring-framework#overview 官方下载工具: https://repo.spring.io ...