一、前言

从零玩转系列之微信支付实战PC端支付微信取消接口搭建 | 技术创作特训营第一期

halo各位大佬很久没更新了最近在搞微信支付,因商户号审核了我半个月和小程序认证也找了资料并且将商户号和小程序进行关联,至此微信支付Native支付完成.此篇文章过长我将分几个阶段的文章发布(项目源码都有,小程序和PC端)

在此之前已经更新了微信支付开篇、微信支付安全、微信实战基础框架搭建、本次更新为微信支付实战PC端接口搭建,实战篇分为几个章节因为代码量确实有点多哈.

本次项目使用技术栈

后端: SpringBoot3.1.x、Mysql8.0、MybatisPlus

前端: Vue3、Vite、ElementPlus

小程序: Uniapp、Uview

一、取消订单接口

场景

  1. 用户下单完毕后未支付 可进行取消订单
  2. 订单超时支付系统自动取消订单

修改 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 订单编号直接发送取消完成

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

本文章仓库WeChatPayScaffolding

【写作提纲】

I. 前言

A. 通过前言表达我每次的文章内容是什么东西

II. 取消订单接口实现

A. 集结生活之中的场景来解析他的逻辑

III. 查询订单接口实现

A. 完善取消订单接口当中已经实现了的功能

IV. 测试

A. 通过测试用例一步步排查编写是否存在BUG

从零玩转系列之微信支付实战PC端支付微信取消接口搭建 | 技术创作特训营第一期的更多相关文章

  1. 微信开放平台PC端扫码登录功能个人总结

    最近公司给我安排一个微信登录的功能,需求是这样的: 1.登录授权 点击二维码图标后,登录界面切换为如下样式(二维码),微信扫描二维码并授权,即可成功登录:    若当前账号未绑定微信账号,扫描后提示“ ...

  2. c#版在pc端发起微信扫码支付

    等了好久,微信官方终于发布了.net的demo. 主要代码: /** * 生成直接支付url,支付url有效期为2小时,模式二 * @param productId 商品ID * @return 模式 ...

  3. 【微信开发】PC端 微信扫码支付成功之后自动跳转

    场景: PC端   微信扫码支付 结果: 支付成功 自动跳转 实现思路: 支付二维码页面,写ajax请求支付状态,请求到结果,无论成功还是失败,都跳转到相应的结果页面 具体实现方法: html部分: ...

  4. 前端:微信支付和支付宝支付在pc端和h5页面中的应用

    1:h5微信支付 使用的是https://pay.weixin.qq.com/wiki/doc/api/index.html  中的 (1):公司需要首先要配置公众号微信支付地址和测试白名单(支付的时 ...

  5. Java SpringMVC实现PC端网页微信扫码支付完整版

    一:前期微信支付扫盲知识 前提条件是已经有申请了微信支付功能的公众号,然后我们需要得到公众号APPID和微信商户号,这个分别在微信公众号和微信支付商家平台上面可以发现.其实在你申请成功支付功能之后,微 ...

  6. 【weixin】微信支付---Native支付模式二(PC端支付大多采用此模式)

    [模式二]:商户后台系统调用微信支付[统一下单API]生成预付交易,将接口返回的链接生成二维码,用户扫码后输入密码完成支付交易.注意:该模式的预付单有效期为2小时,过期后无法支付 模式二与模式一相比, ...

  7. pc端用微信扫一扫实现微信第三方登陆

    官方文档链接 第一步:获取AppID  AppSecret (微信开发平台申请PC端微信登陆)   第二步:生成扫描二维码,获取code https://open.weixin.qq.com/conn ...

  8. 支付宝pc端支付接入PHP实现

    引入支付宝接口 放入一个插件库中,方便管理 创建支付类 1.发起支付 public function init() { $order_id = $_REQUEST['order_id']; $orde ...

  9. Python接入支付宝进行PC端支付

    1.  支付宝开放平台登录,使用支付宝账号登录 https://open.alipay.com/platform/home.htm 2.选择沙箱模式 [支付宝提供了测试环境] https://docs ...

  10. PC端网站微信扫码登录

    需求分析:用户通过扫描我们网页的二维码,如果已经绑定我们平台的账户,即成功进入首页,否则提示先绑定个人微信账号. 1.绑定微信账号:是通过关注微信公众号实现绑定个人微信账号.首先通过后台接口获取到ti ...

随机推荐

  1. Selenium - 元素定位(2) - XPATH进阶

    Selenium - 元素定位 XPATH 定位进阶 元素示例 属性定位 # xpath 通过id属性定位 driver.find_element_by_xpath("//*[@id='kw ...

  2. 安装vue cli3以及配置环境 镜像下载

    安装vue cli3以及配置环境 镜像下载 1.下载安装Node.js 安装vue cli3之前需要先安装Node.js,方便对vue进行下载 node.js的下载与安装方法在隔壁哟 地址:https ...

  3. 利用简单的IO操作实现M3U8文件之间的合并

    先上代码: 1 @SneakyThrows //合并操作,最终文件不包含结束标识,方便多次合并 2 private static void mergeM3U8File(String source, S ...

  4. ET介绍——组件式设计(优化版的ECS)

    组件式设计 在代码复用和组织数据方面,面向对象可能是大家第一反应.面向对象三大特性继承,封装,多态,在一定程度上能解决不少代码复用,数据复用的问题.不过面向对象不是万能的,它也有极大的缺陷: 1. 数 ...

  5. Create Vite App 支持 OpenTiny 啦🎉

    大家好,我是 Kagol,个人公众号:前端开源星球. 一个月前,日日自新写了一篇介绍 Create Vite App 开源项目的文章: 基于vite 4.x 快速搭建开箱即用,高度可定制化模版脚手架 ...

  6. IT入门深似海,入门到放弃你学废了嘛

    我一直觉得IT行业 程序员行业.甚至觉得程序员人群 是一个特殊存在的群体. 入门到放弃,是真的,IT门槛高嘛. 其实吧,IT编程门槛,是有的,但是对于感兴趣的,想学习IT编程同学来说,也是一件容易事情 ...

  7. 代码随想录算法训练营Day16二叉树|104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度  222.完全二叉树的节点个数

    代码随想录算法训练营 代码随想录算法训练营Day16二叉树|104.二叉树的最大深度 559.n叉树的最大深度 111.二叉树的最小深度  222.完全二叉树的节点个数 104.二叉树的最大深度 题目 ...

  8. 【python基础】复杂数据类型-列表类型(数值列表)

    1.数值列表 列表非常适合用于存储数字集合,而python提供了很多工具,可帮助我们高速地处理数字列表. 1.1 range函数 python的range函数能够轻松的生成连续一系列数字. 其语法格式 ...

  9. Galaxy 生信平台(四):邮件与管理员配置

    前几天看到中山大学和国家基因库合作开发的 Translatome Workbench 翻译组学可视化在线数据分析平台 (db.cngb.org/galaxy/) 的推送信息,也上去看了一下,工具和教程 ...

  10. 【快应用】addEventListener()方法无法监听动画事件

    ​[关键词] 动画监听.动态改变 [问题背景] Style中设置动画样式,然后在onshow生命周期中调用addEventListener()方法去监听动画事件,无法监听到,该方法无任何回调返回 问题 ...