微信支付

文档地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1 

 封装的工具类

package com.qf.fmall.utils;import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.HttpRequest;
import org.apache.shiro.crypto.hash.Md5Hash;import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;public class WeixinPayUtils {public static final  String orderSubmit="https://api.mch.weixin.qq.com/pay/unifiedorder";public static final  String orderQueryUrl="https://api.mch.weixin.qq.com/pay/orderquery";public static final String appkey="sbNCm1JnevqI36LrEaxFwcaT0hkGxFnC";public static void main(String[] args) {String s = weixinPay("sadsadasa", "wqeqweqeq");System.out.println(s);}public static String weixinPay(String oid,String describe){//1. 组织请求map,必传字段如下//这里可有序可以无序,但是计算签名的时候必须有序,规定!按Key排序TreeMap<String, String> treeMap = new TreeMap<>();treeMap.put("appid","wx632c8f211f8122c6");//商户的应用IDtreeMap.put("mch_id","1497984412"); //商户号treeMap.put("notify_url","http://47.118.45.73:8080/pay/callback"); // 商户提供的回调地址String randomstr = UUID.randomUUID().toString().replaceAll("-", ""); //生成随机数treeMap.put("nonce_str",randomstr); // 长度32个字符的随机字符串,干扰项treeMap.put("body",describe); // 订单描述信息treeMap.put("out_trade_no",oid); // 订单编号treeMap.put("total_fee","1");  // 1 分钱treeMap.put("trade_type","NATIVE"); // 支付类型treeMap.put("fee_type","CNY"); // 币种treeMap.put("sign_type","MD5"); // 签名算法//计算签名String tempString = treeMap.toString().replace("{", "").replace("}", "").replace(", ","&")+"&key="+appkey;String sign = new Md5Hash(tempString).toHex().toUpperCase();treeMap.put("sign",sign);//map转XML字符串String xml = XmlUtil.mapToXmlStr(treeMap);//用Hutool工具类发送post请求String result = HttpRequest.post(orderSubmit).body(xml).execute().body();// xml str ----> mapMap<String, Object> resultMap = XmlUtil.xmlToMap(result);String url = (String) resultMap.get("code_url");return  url;}public static String queryStatus(String orderId) {//1. 组织请求map,必传字段如下//这里可有序可以无序,但是计算签名的时候必须有序,规定!按Key排序TreeMap<String, String> treeMap = new TreeMap<>();treeMap.put("appid","wx632c8f211f8122c6");//商户的应用IDtreeMap.put("mch_id","1497984412"); //商户号String randomstr = UUID.randomUUID().toString().replaceAll("-", ""); //生成随机数treeMap.put("nonce_str",randomstr); // 长度32个字符的随机字符串,干扰项treeMap.put("out_trade_no",orderId); // 订单编号treeMap.put("sign_type","MD5"); // 签名算法//计算签名String tempString = treeMap.toString().replace("{", "").replace("}", "").replace(", ","&")+"&key="+appkey;String sign = new Md5Hash(tempString).toHex().toUpperCase();treeMap.put("sign",sign);//map转XML字符串String xml = XmlUtil.mapToXmlStr(treeMap);//用Hutool工具类发送post请求String result = HttpRequest.post(orderQueryUrl).body(xml).execute().body();// xml str ----> mapMap<String, Object> resultMap = XmlUtil.xmlToMap(result);String trade_state = (String) resultMap.get("trade_state");return  trade_state;}
}

controller

package com.qf.fmall.controller;import com.qf.fmall.common.ResultVo;
import com.qf.fmall.entity.Orders;
import com.qf.fmall.service.IOrdersService;
import com.qf.fmall.utils.FmallConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.Arrays;
import java.util.HashMap;/*** <p>* 订单  前端控制器* </p>** @author jmj* @since 2023-08-24*/
@RestController
@RequestMapping("/order")
@CrossOrigin
@Slf4j
public class OrdersController {@Autowiredprivate IOrdersService ordersService;@PostMapping("/add")public ResultVo add(Integer[] cids,@RequestBody Orders orders) throws Exception {log.info("入参为:cid={},orders={}", Arrays.toString(cids),orders);HashMap<String,Object> map= ordersService.addOrder(cids,orders);return ResultVo.vo(FmallConstants.SUCCESS_CODE,FmallConstants.SUCCESS_MSG,map);}@GetMapping("/status/{orderId}")public ResultVo status(@PathVariable("orderId") String orderId){log.info("入参为:orderId={}",orderId);String s=   ordersService.status(orderId);log.info("传回来的状态:{}",s);return ResultVo.vo(FmallConstants.SUCCESS_CODE,FmallConstants.SUCCESS_MSG,s);}}

service

package com.qf.fmall.service.impl;import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qf.fmall.entity.*;
import com.qf.fmall.mapper.OrdersMapper;
import com.qf.fmall.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qf.fmall.utils.WeixinPayUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;/*** <p>* 订单  服务实现类* </p>** @author jmj* @since 2023-08-24*/
@Service
@Slf4j
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrdersService {@Autowiredprivate IShoppingCartService shoppingCartService;@Autowiredprivate IProductSkuService iProductSkuService;@Autowiredprivate IProductService iProductService;@Autowiredprivate IOrderItemService iOrderItemService;@Transactional(rollbackFor = Exception.class)@Overridepublic synchronized HashMap<String, Object> addOrder(Integer[] cids, Orders orders) throws Exception {//1. 查询用户购物车中的对应的商品套餐库存量是否还足够List<Map<String, Object>> shoppingcars = shoppingCartService.listMaps(new QueryWrapper<ShoppingCart>().select("sku_id  skuId, SUM(`cart_num`) `sum`").in("cart_id", cids).groupBy("sku_id"));log.info("查出来的购物车按ID分类计算的集合为{}",shoppingcars);TreeSet<String> productIds = new TreeSet<>();//查出购物车中所有的productIdfor (Map<String, Object> shoppingcar : shoppingcars) {ProductSku one = iProductSkuService.getOne(new QueryWrapper<ProductSku>().eq("sku_id", shoppingcar.get("skuId")));productIds.add(one.getProductId());Integer stock = one.getStock();Double cartNum = (Double) shoppingcar.get("sum");if (cartNum>stock){throw new Exception("库存不足,购买失败");}
//             减少库存one.setStock((stock-cartNum.intValue()));iProductSkuService.updateById(one);}//过了这个循环没有抛异常,就可以往下走,说明库存够//2. 生成唯一的订单编号String orderId = UUID.randomUUID().toString().replace("-", "");orders.setOrderId(orderId);//3. 生成订单主表(orders表)中的数据orders.setCreateTime(new Date());//创建时间orders.setUpdateTime(new Date());//修改时间// 产品名称:untitled用逗号隔开//先查Product产品IDStringBuilder builder = new StringBuilder();for (String productId : productIds) {//查出每个产品中的名字,放到字符串缓冲流中,并用逗号拼接builder.append(iProductService.getOne(new QueryWrapper<Product>().eq("product_id",productId)).getProductName());builder.append(",");}//删除最后一个逗号,拼接转化为字符串String untitled = builder.deleteCharAt(builder.length() - 1).toString();orders.setUntitled(untitled);// 订单的状态,初始值1,待付款 statusorders.setStatus("1");//待付款// 逻辑删除状态,初始值为0 delete_statusorders.setDeleteStatus(0);log.info("生成的order对象为:{}",orders);//将对象添加到订单表里this.save(orders);//4. 生成订单明细表的数据 (OrderItem表)//有几个cid就有几个定单ArrayList<OrderItem> orderItems = new ArrayList<>();for (Integer cartId : cids) {OrderItem orderItem = new OrderItem();String orderItemId = UUID.randomUUID().toString().replace("-", "");//设置32位随机数作为ItemId 放入orderItem对象里orderItem.setItemId(orderItemId);//订单Id注入orderItem.setOrderId(orders.getOrderId());//查一下购物车 idShoppingCart shoppingCart = shoppingCartService.getOne(new QueryWrapper<ShoppingCart>().eq("cart_id", cartId));ProductSku productSku = iProductSkuService.getOne(new QueryWrapper<ProductSku>().eq("sku_id", shoppingCart.getSkuId()));Product product = iProductService.getOne(new QueryWrapper<Product>().eq("product_id", productSku.getProductId()));//查一下产品对象//注入产品IDorderItem.setProductId(productSku.getProductId());orderItem.setProductName(product.getProductName());orderItem.setProductImg(productSku.getSkuImg());orderItem.setSkuId(productSku.getSkuId());orderItem.setSkuName(productSku.getSkuName());orderItem.setProductPrice(new BigDecimal(productSku.getSellPrice()));orderItem.setBuyCounts(Integer.parseInt(shoppingCart.getCartNum()));orderItem.setTotalAmount(new BigDecimal(productSku.getSellPrice()*Integer.parseInt(shoppingCart.getCartNum())));//转换时间SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");orderItem.setBasketDate(format.parse(shoppingCart.getCartTime()));orderItem.setIsComment(0);log.info("每个订单详情对象:{}",orderItem);//保存到集合orderItems.add(orderItem);}//5. 保存订单到数据库log.info("添加到数据库的订单集合对象:{}",orderItems);iOrderItemService.saveBatch(orderItems);//清空购物车List<Integer> list = Arrays.asList(cids);shoppingCartService.removeBatchByIds(list);//6. 跟微信支付平台交互,获取可以支付的urlString url = WeixinPayUtils.weixinPay(orders.getOrderId(),orders.getUntitled());log.info("url:{}",url);//7. 组织返回的map数据HashMap<String, Object> map = new HashMap<>();map.put("orderId",orders.getOrderId());map.put("productNames",orders.getUntitled());map.put("payUrl",url);return map;}@Overridepublic String status(String orderId) {//1.掉微信支付的查询订单状态接口,获取订单状态String status= WeixinPayUtils.queryStatus(orderId);//2.如果支付成功了,需要修改订单表中的订单状态和支付时间if (status.equals("SUCCESS")){Orders orders = new Orders();orders.setOrderId(orderId);orders.setStatus("2");updateById(orders);return "2";}return "-1";}}

封装工具类

pom

<!--   微信支付 sdk (sdk用来简化调用的工具包)   --><dependency><groupId>com.github.wxpay</groupId><artifactId>wxpay-sdk</artifactId><version>0.0.3</version></dependency></dependencies>

 WxSdkUtils

package com.qf.fmall2302.wxpay;import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConfig;import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;public class WxSdkUtils {public String getPayUrl(String orderid,String desc,Long amount) throws Exception {// 创建sdk的核心对象WXPay wxPay = new WXPay(new MyWxConfig());HashMap<String, String> map = new HashMap<>();String randomstr = UUID.randomUUID().toString().replaceAll("-", "");map.put("nonce_str",randomstr); // 长度32个字符的随机字符串,干扰项map.put("body",desc); // 订单描述信息map.put("out_trade_no",orderid); // 订单编号map.put("total_fee","1");  // 1 分钱map.put("trade_type","NATIVE"); // 支付类型map.put("fee_type","CNY"); // 币种map.put("notify_url","http://47.118.45.73:8080/pay/callback"); // 商户提供的回调地址map.put("sign_type","MD5"); // 签名算法Map<String, String> result = wxPay.unifiedOrder(map);return result.get("code_url");}public static String queryStatus(String orderid) throws Exception {WXPay wxPay = new WXPay(new MyWxConfig());HashMap<String, String> map = new HashMap<>();map.put("out_trade_no",orderid);Map<String, String> result = wxPay.orderQuery(map);return result.get("trade_state");}public static void main(String[] args) throws Exception {String orderid = "202308241617987";WXPay wxPay = new WXPay(new MyWxConfig());HashMap<String, String> map = new HashMap<>();map.put("out_trade_no",orderid);Map<String, String> result = wxPay.orderQuery(map);System.out.println(result);}}

MyWxConfig implements WXPayConfig 

package com.qf.fmall2302.wxpay;import com.github.wxpay.sdk.WXPayConfig;import java.io.InputStream;public class MyWxConfig implements WXPayConfig {public static final String appid = "wx632c8f211f8122c6";public static final String mch_id = "1497984412";public static final String appkey = "sbNCm1JnevqI36LrEaxFwcaT0hkGxFnC";@Overridepublic String getAppID() {return appid;}@Overridepublic String getMchID() {return mch_id;}@Overridepublic String getKey() {return appkey;}@Overridepublic InputStream getCertStream() {return null;}@Overridepublic int getHttpConnectTimeoutMs() {return 0;}@Overridepublic int getHttpReadTimeoutMs() {return 0;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/105830.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

情人节特别篇:用c++弹奏音乐“海阔天空”与“孤勇者”

W...Y的主页 &#x1f495; 代码库分享 &#x1f60a; 目录 孤勇者 海阔天空 今天是2023年8月22日七夕情人节&#xff0c;但是对我来说就是再普通不过的日子。我相信有很多人期待这一天的到来&#xff0c;和自己的对象出去享受快乐时光。但是我只有一个人独孤的度过短暂的时…

freertos之任务调度算法

介绍 所谓调度算法&#xff0c;就是怎么确定哪个就绪态的任务可以切换为运行状态。 通过配置文件FreeRTOSConfig.h的三个配置项来配置调度算法&#xff1a;configUSE_PREEMPTION &#xff08;是否抢占&#xff09; configUSE_TIME_SLICING &#xff08;是否轮转&#xff09; c…

分布式事务(7):SpringCloud2.0整合LCN

目前LCN版本已经升级为4.0了,但是官方没有SpringCloud2.0的demo案例。 因为LCN本身是开源的,有些大神对LCN框架源码做修改,可以支持SpringCloud2.0版本。 下载地址:https://download.csdn.net/download/u013938578/88251904 1 下载LCN服务端源码 https://download.csdn.…

day-27 代码随想录算法训练营(19)回溯part03

39.组合总和 分析&#xff1a;同一个数可以选多次&#xff0c;但是不能有重复的答案&#xff1b; 思路&#xff1a;横向遍历&#xff0c;纵向递归&#xff08;不同的是递归的时候不需要跳到下一个位置&#xff0c;因为同一个数可以选多次&#xff09; class Solution { publ…

基于python+pyqt的opencv汽车分割系统

目录 一、实现和完整UI视频效果展示 主界面&#xff1a; 识别结果界面&#xff1a; 查看分割处理过程图片界面&#xff1a; 二、原理介绍&#xff1a; 加权灰度化 ​编辑 二值化 滤波降噪处理 锐化处理 边缘特征提取 图像分割 完整演示视频&#xff1a; 完整代码链…

4.14 tcp_tw_reuse 为什么默认是关闭的?

开启 tcp_tw_reuse 参数可以快速复用处于 TIME_WAIT 状态的 TCP 连接时&#xff0c;相当于缩短了 TIME_WAIT 状态的持续时间。 tcp_tw_reuse 是什么&#xff1f; TIME_WAIT 状态的持续时间是 60 秒&#xff0c;这意味着这 60 秒内&#xff0c;客户端一直会占用着这个端口。端…

springboot定时任务:同时使用定时任务和websocket报错

背景 项目使用了websocket,实现了消息的实时推送。后来项目需要一个定时任务&#xff0c;使用org.springframework.scheduling.annotation的EnableScheduling注解来实现&#xff0c;启动项目之后报错 Bean com.alibaba.cloud.sentinel.custom.SentinelAutoConfiguration of t…

11.Oracle中rollup函数详解

【基本介绍】 【格式】&#xff1a;group by rollup(字段1,字段2,字段3,...,字段n) 【说明】&#xff1a;rollup主要用于分组汇总&#xff0c;如果rollup中有n个字段&#xff0c;则会分别按【字段1】、【字段1,字段2】&#xff0c;【字段1,字段2,字段3】&#xff0c;...&#…

uniapp,使用canvas制作一个签名版

先看效果图 我把这个做成了页面&#xff0c;没有做成组件&#xff0c;因为之前我是配合uview-plus的popup弹出层使用的&#xff0c;这种组件好像是没有生命周期的&#xff0c;第一次打开弹出层可以正常写字&#xff0c;但是关闭之后再打开就不会显示绘制的线条了&#xff0c;还…

【Linux应用部署篇】在CSDN云IDE平台部署Etherpad文档编辑器

【Linux应用部署篇】在CSDN云IDE平台部署Etherpad文档编辑器 一、CSDN云IDE平台介绍1.1 CSDN云IDE平台简介1.2 CSDN云IDE平台特点 二、本次实践介绍2.1 本次实践介绍2.2 Etherpad简介 三、登录CSDN云IDE平台3.1 登录CSDN开发云3.2 登录云IDE3.3 新建工作空间3.4 进入工作空间 四…

Spring(aop介绍,底层实现,jdk代理,cglib代理)

02-aop简介-aop的作用及其优势_哔哩哔哩_bilibili 122 1、Spring的aop介绍 1.1aop是一种技术&#xff0c;aop是在运行之间执行的&#xff0c;他可以完成程序功能之间的松耦合&#xff0c;动态代理的作用也等同于Aop的作用&#xff1a;他提供了相应的封装&#xff0c;Aop是面向…

unity 模型显示在UI上 并交互(点击、旋转、缩放)

项目工程&#xff1a;unity模型显示在UI上并交互&#xff08;点击、旋转、缩放&#xff09;资源-CSDN文库 1.在Assets创建 Render Texture&#xff08;下面会用到&#xff09;&#xff0c;根据需要设置Size 2.创建UIRawImage&#xff0c;并把Render Texture赋上 3.创建相机&am…

SSL/CA 证书及其相关证书文件(pem、crt、cer、key、csr)

数字证书是网络世界中的身份证&#xff0c;数字证书为实现双方安全通信提供了电子认证。数字证书中含有密钥对所有者的识别信息&#xff0c;通过验证识别信息的真伪实现对证书持有者身份的认证。数字证书可以在网络世界中为互不见面的用户建立安全可靠的信任关系&#xff0c;这…

vue实现表格的动态高度

需求:表格能够根据窗口的大小自动适配页面高度 防抖和节流函数的使用场景是当需要对频繁触发的事件进行限制时,例如: 防抖函数常用于限制用户在短时间内多次触发某一事件,例如搜索框输入并搜索,当用户一直在输入时,我们可以使用防抖函数来避免多次请求搜索结果,减轻服…

切换Debian的crontab的nano编辑器

Debian的crontab默认的编辑器是nano&#xff0c;用起来很不习惯,怎么才能转回vim呢? 用以下命令便可&#xff1a; #update-alternatives --config editor 出现以下所示的界面&#xff1a; 而后选择8使用/usr/bin/vim就能够了。 PS&#xff1a;若是你发现你的定时没有生效&…

【Python编程】将同一种图片分类到同一文件夹中

一、数据结构如下&#xff1a; 二、编程工具&#xff1a;Jupyter-Notebook 三、代码&#xff1a; import os import cv2 import shutilpath0os.getcwd()\\apple\\RGB path1os.getcwd()\\apple\\tof_confidence path2os.getcwd()\\apple\\tof_depth path3os.getcwd()\\apple\\…

【Adobe After Effects】关于ae点击空格不会播放反而回退一帧的解决方案

最近玩ae的时候遇见了一个小问题&#xff0c;就是有时候敲空格&#xff0c;视频没办法播放&#xff0c;反而会回退一帧&#xff0c;经过摸索发现了一个解决办法&#xff1a; 点击编辑---首选项 然后选择“音频硬件” 然后选择正确的默认输出&#xff0c;点击确定即可

Visual Studio 2022的MFC框架——WinMain函数

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;今天我们来重新审视一下Visual Studio 2022下开发工具的MFC框架知识。 大家还记得创建Win32应用程序是怎么弄的吗&#xff1f; Win32应用程序的建立到运行是有一个个关系分明的步骤的&#xff1a; 1.进入W…

AURIX TriCore内核架构学习笔记

名词缩写 ISA - Instruction Set Architecture&#xff0c;指令集架构PC - Program Counter, holds the address of the instruction that is currently runningGPRs - 32 General Purpose RegistersPSW - Program Status WordPCXI - Previous Context InformationCSA - Conte…

腾讯云服务器价格表大全_轻量服务器_CVM云服务器报价明细

腾讯云服务器租用费用表&#xff1a;轻量应用服务器2核2G4M带宽112元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;2核4G5M带宽756元三年、云服务器CVM S5实例2核2G配置280.8元一年、GPU服务器GN10Xp实例145元7天&#xff0c;腾讯云服务器网长期更新腾讯云轻量…