微信公众号支付(统一下单、支付结果通知、查询订单)

news/2025/2/28 14:16:45/

最近做的项目涉及到微信公众号的支付,翻遍文档和查阅众多资料后,记一下自己整的过程:

1.先看的官方文档,把DEMO下载下来,发现都是要证书的,继续看文档,API列表

2.还是看文档,参数,坑最多的地方,这里需要在工具类里边先配置几个东西,需要在公众号的账号和商户号里面预先设置好

公众号AppId 微信支付商户号 微信支付API秘钥

微信支付通知URL 我用的是内网穿透工具 nat300 映射的已备案域名

3.调用微信统一下单的接口,微信只接收XML格式的字符串,返回的也是XML格式的字符串,主要代码如下:

/*** 微信公众号支付统一下单* @param req* @param request* @return* @throws Exception*/@Overridepublic ServiceResult<Object> unifiedorder(WxOrderReq req, HttpServletRequest request, String openId) {Map<String, String> paraMap = new HashMap<String, String>();paraMap.put("appid", WXPayConfig.APP_ID);paraMap.put("mch_id", WXPayConfig.MCH_ID);paraMap.put("nonce_str", WXPayUtil.generateNonceStr());   //随机字符串,长度要求在32位以内。paraMap.put("body", req.getIntroduce());paraMap.put("out_trade_no", orderNumber);paraMap.put("total_fee", req.getSum().multiply(new BigDecimal(100)).stripTrailingZeros().toPlainString());  //订单总金额,单位为分paraMap.put("spbill_create_ip", IpUtil.getIpAddr(request));paraMap.put("notify_url", WXPayConfig.NOTIFY_URL);paraMap.put("trade_type", WXPayConfig.TRADE_TYPE_JSAPI);paraMap.put("openid", openId);Map<String, String> payMap = new HashMap<String, String>();try {String sign = WXPayUtil.generateSignature(paraMap, WXPayConfig.KEY);//签名,将所有的请求参数按照ASCII字典排序后,按照规定格式拼接成字符串,再使用MD5加密后生成paraMap.put("sign", sign);// 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorderString url = WXPayConfig.UNIFIED_ORDER_URL;String xml = WXPayUtil.mapToXml(paraMap);//将map转成xml格式的 字符串(微信只接受xml格式的字符串)String xmlStr = HttpKit.post(url, xml); //请求微信统一下单接口(微信只返回xml格式的字符串)Map<String, String> map = WXPayUtil.xmlToMap(xmlStr); //将xml格式的字符串转成 map//xmlStr.indexOf("SUCCESS") != -1if (!map.get("return_code").equals("SUCCESS")) {return ServiceResult.newFailure(new CodeMsg(-1,"调用接口失败!!!!!!"));}// 微信生成的预支付会话标识,该值有效期为2小时String prepay_id = map.get("prepay_id");payMap.put("appId", WXPayConfig.APP_ID);payMap.put("timeStamp", String.valueOf(WXPayUtil.getCurrentTimestamp()));payMap.put("nonceStr", WXPayUtil.generateNonceStr());payMap.put("signType", WXPayConfig.SIGNTYPE);payMap.put("package", "prepay_id=" + prepay_id);String paySign = WXPayUtil.generateSignature(payMap, WXPayConfig.KEY);payMap.put("paySign", paySign);payMap.put("outTradeNo",orderNumber);} catch (Exception e) {e.printStackTrace();}//新增订单业务return ServiceResult.newSuccess(payMap);}

 

4.支付结果通知,这个接口是在工具类中配置好的 微信支付通知url

/*** 支付结果通知* @param request* @param response*/public ServiceResult<Object> getWeChatPayReturn(HttpServletRequest request,  HttpServletResponse response){String resSuccessXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";String resFailXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";String resXml = "";try {InputStream inStream = request.getInputStream();ByteArrayOutputStream outSteam = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = inStream.read(buffer)) != -1) {outSteam.write(buffer, 0, len);}WXPayUtil.getLogger().info("wxnotify:微信支付----start----");// 获取微信调用我们notify_url的返回信息String result = new String(outSteam.toByteArray(), "utf-8");WXPayUtil.getLogger().info("wxnotify:微信支付----result----=" + result);// 关闭流outSteam.close();inStream.close();// xml转换为mapMap<String, String> resultMap = WXPayUtil.xmlToMap(result);boolean isSuccess = false;if (WXPayConstants.SUCCESS.equalsIgnoreCase(resultMap.get("return_code"))){WXPayUtil.getLogger().info("wxnotify:微信支付----返回成功");if (WXPayUtil.isSignatureValid(resultMap,WXPayConfig.KEY)){// 订单处理 操作 orderconroller 的回写操作?WXPayUtil.getLogger().info("wxnotify:微信支付----验证签名成功");// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.resXml = resSuccessXml;isSuccess = true;} else {WXPayUtil.getLogger().error("wxnotify:微信支付----判断签名错误");}} else {WXPayUtil.getLogger().error("wxnotify:支付失败,错误信息:" + resultMap.get("return_msg"));resXml = resFailXml;}// 回调方法,处理业务 - 修改订单支付状态WXPayUtil.getLogger().info("wxnotify:微信支付回调:修改的订单===>" + resultMap.get("out_trade_no"));
//            logger.info("resultMap::::::",resultMap);ServiceResult<Object> updateResult = orderService.updateOrderState(resultMap.get("out_trade_no"));if (updateResult.success()){WXPayUtil.getLogger().info("wxnotify:微信支付回调:修改订单支付状态成功");} else {WXPayUtil.getLogger().error("wxnotify:微信支付回调:修改订单支付状态失败");}} catch (Exception e) {e.printStackTrace();}finally {try {// 处理业务完毕BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());out.write(resXml.getBytes());out.flush();out.close();} catch (IOException e) {WXPayUtil.getLogger().error("wxnotify:支付回调发布异常:out:", e);}}return ServiceResult.newSuccess(resXml);}

 

5.查询订单  根据订单号向微信发起请求 得知该订单的状态

/*** 查询订单* @param req* @return* @throws Exception*/@Overridepublic ServiceResult<Object> orderQuery(OrderQueryReq req) {String trade_state = null;String accessToken = req.getAccessToken();ObjectResult<User> userByToken = authFeignService.getUserByToken(accessToken);User data = userByToken.getData();if (data == null) {return ServiceResult.newFailure(CodeMsg.ERROR_ACCESS_TOKEN);}Map<String, String> paraMap = new HashMap<String, String>();paraMap.put("appid",WXPayConfig.APP_ID);paraMap.put("mch_id",WXPayConfig.MCH_ID);paraMap.put("nonce_str",WXPayUtil.generateNonceStr());   //随机字符串,长度要求在32位以内。paraMap.put("out_trade_no",req.getOutTradeNo());try {String sign = WXPayUtil.generateSignature(paraMap, WXPayConfig.KEY);//签名,将所有的请求参数按照ASCII字典排序后,按照规定格式拼接成字符串,再使用MD5加密后生成paraMap.put("sign", sign);// 查询订单 https://api.mch.weixin.qq.com/pay/orderqueryString url = WXPayConfig.ORDER_QUERY;String xml = WXPayUtil.mapToXml(paraMap);//将map转成xml格式的 字符串(微信只接受xml格式的字符串)String xmlStr = HttpKit.post(url, xml); //请求微信查询订单接口(微信只返回xml格式的字符串)Map<String, String> map = WXPayUtil.xmlToMap(xmlStr); //将xml格式的字符串转成 mapSystem.err.println(map);trade_state = map.get("trade_state");}catch (Exception e){e.printStackTrace();}//SUCCESS—支付成功 REFUND—转入退款 NOTPAY—未支付 CLOSED—已关闭 REVOKED—已撤销(付款码支付)// USERPAYING--用户支付中(付款码支付) PAYERROR--支付失败(其他原因,如银行返回失败)if ("SUCCESS".equals(trade_state)){return ServiceResult.newSuccess(0);}if ("REFUND".equals(trade_state)){return ServiceResult.newSuccess("转入退款");}if ("NOTPAY".equals(trade_state)){return ServiceResult.newSuccess("未支付");}if ("CLOSED".equals(trade_state)){return ServiceResult.newSuccess("已关闭");}if ("REVOKED".equals(trade_state)){return ServiceResult.newSuccess("已撤销(付款码支付)");}if ("USERPAYING".equals(trade_state)){return ServiceResult.newSuccess("用户支付中(付款码支付)");}if ("PAYERROR".equals(trade_state)){return ServiceResult.newSuccess("支付失败");}return ServiceResult.newSuccess(trade_state);}

 

比较懒,所以就直接放的代码了,欢迎大家交流指正 tansky1995@gmail.com


http://www.ppmy.cn/news/705660.html

相关文章

网上商城系统支付方式如何配置?支付方式有哪些

众所周知&#xff0c;网购平台中的会员支付、商家收款绝大部分是通过第三方支付平台(微信、支付宝、银联...)进行交易&#xff0c;而一款网上商城系统中集成的支付接口也是多样化的&#xff0c;如&#xff1a;支付宝(电脑网站)、支付宝(手机网站)、微信支付(扫码支付)、微信支付…

微信支付常见错误和统一下单错误码详情

微信支付常见错误和统一下单错误码详情 微信支付常见问题描述及解决方法微信调用统一下单接口&#xff0c;当result_codeFAIL时&#xff0c;错误代码及错误描述参考链接&#xff1a; 微信支付常见问题描述及解决方法 序号问题错误描述解决方法1此公众号并没有这些scope的权限&…

三网折扣话费充值接口文档

话费充值接口文档 接口版本&#xff1a;1.0 ―、引言 文档概述 本文档提供话费充值接口规范说明&#xff0c;提供一整套的完整的接入示例(http 接口)供商户参 考&#xff0c;可以帮助商户开发人员快速完成接口开发与联调&#xff0c;实现与话费充值系统的交易互联。 公司官网&a…

【电路原理学习笔记】第2章:电压、电流和电阻:2.1 原子结构

第2章&#xff1a;电压、电流和电阻 2.1 原子结构 元素&#xff1a;不能用化学方法分解成更简单形式的物质称为元素。原子&#xff1a;原子是体现元素特性的最小粒子。原子核&#xff1a;原子核由质子和中子组成&#xff0c;质子带有正电荷&#xff0c;中子呈中性。电子带有负…

vue3+ts+elementui制作精美的课表

使用vue3tselementui 如何制作出精美的课表呢&#xff0c; 最终效果图如下: 直接上代码&#xff1a; 这里直接把封装成一个课表的组件&#xff1a; <script setup lang"ts"> import { ref, watch, onMounted } from "vue"; import IconText from …

3分钟看懂电动汽车“刹车”这件事!

特斯拉“刹车门”频频热搜&#xff0c; 我们抛开争执聊聊科普。 逆姐3分钟带你说说汽车“刹车”这件事&#xff0c; 燃油车和电动车到底啥区别&#xff1f;

智能电动车无线外设规范

1、电动自行车无线外设规范的意义 电动自行车是一个常见的交通工具&#xff0c;多年发展下来&#xff0c;形成了多个较为标准的零部件&#xff0c;通过组装这些零部件&#xff0c;即可拼装成&#xff0c;常见的电动车零部件包括&#xff1a; 机械类&#xff1a;车架&#xff0…

自动驾驶系列(十)编写电动车ROS节点(刹车)

一、硬件控制协议 对于不同的设备&#xff0c;底层的通讯方式都不一致&#xff0c;因此需要根据具体硬件具体分析。本系统 采用了1个CAN盒子控制转向&#xff0c;1路DA控制油门&#xff0c;另外一路DA控制刹车。 1&#xff0c;转向协议 CAN协议获取当前状态的帧ID是0x322,发送…