微信支付

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

微信支付_第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 treeMap = new TreeMap<>();
        treeMap.put("appid","wx632c8f211f8122c6");//商户的应用ID
        treeMap.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 ----> map
        Map resultMap = XmlUtil.xmlToMap(result);
        String url = (String) resultMap.get("code_url");
        return  url;


    }


    public static String queryStatus(String orderId) {
        //1. 组织请求map,必传字段如下
        //这里可有序可以无序,但是计算签名的时候必须有序,规定!按Key排序
        TreeMap treeMap = new TreeMap<>();
        treeMap.put("appid","wx632c8f211f8122c6");//商户的应用ID
        treeMap.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 ----> map
        Map 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;

/**
 * 

* 订单 前端控制器 *

* * @author jmj * @since 2023-08-24 */ @RestController @RequestMapping("/order") @CrossOrigin @Slf4j public class OrdersController { @Autowired private IOrdersService ordersService; @PostMapping("/add") public ResultVo add(Integer[] cids,@RequestBody Orders orders) throws Exception { log.info("入参为:cid={},orders={}", Arrays.toString(cids),orders); HashMap 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.*;

/**
 * 

* 订单 服务实现类 *

* * @author jmj * @since 2023-08-24 */ @Service @Slf4j public class OrdersServiceImpl extends ServiceImpl implements IOrdersService { @Autowired private IShoppingCartService shoppingCartService; @Autowired private IProductSkuService iProductSkuService; @Autowired private IProductService iProductService; @Autowired private IOrderItemService iOrderItemService; @Transactional(rollbackFor = Exception.class) @Override public synchronized HashMap addOrder(Integer[] cids, Orders orders) throws Exception { //1. 查询用户购物车中的对应的商品套餐库存量是否还足够 List> shoppingcars = shoppingCartService.listMaps(new QueryWrapper().select("sku_id skuId, SUM(`cart_num`) `sum`").in("cart_id", cids).groupBy("sku_id")); log.info("查出来的购物车按ID分类计算的集合为{}",shoppingcars); TreeSet productIds = new TreeSet<>();//查出购物车中所有的productId for (Map shoppingcar : shoppingcars) { ProductSku one = iProductSkuService.getOne(new QueryWrapper().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产品ID StringBuilder builder = new StringBuilder(); for (String productId : productIds) { //查出每个产品中的名字,放到字符串缓冲流中,并用逗号拼接 builder.append(iProductService.getOne(new QueryWrapper().eq("product_id",productId)).getProductName()); builder.append(","); } //删除最后一个逗号,拼接转化为字符串 String untitled = builder.deleteCharAt(builder.length() - 1).toString(); orders.setUntitled(untitled); // 订单的状态,初始值1,待付款 status orders.setStatus("1");//待付款 // 逻辑删除状态,初始值为0 delete_status orders.setDeleteStatus(0); log.info("生成的order对象为:{}",orders); //将对象添加到订单表里 this.save(orders); //4. 生成订单明细表的数据 (OrderItem表) //有几个cid就有几个定单 ArrayList 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()); //查一下购物车 id ShoppingCart shoppingCart = shoppingCartService.getOne(new QueryWrapper().eq("cart_id", cartId)); ProductSku productSku = iProductSkuService.getOne(new QueryWrapper().eq("sku_id", shoppingCart.getSkuId())); Product product = iProductService.getOne(new QueryWrapper().eq("product_id", productSku.getProductId())); //查一下产品对象 //注入产品ID orderItem.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 list = Arrays.asList(cids); shoppingCartService.removeBatchByIds(list); //6. 跟微信支付平台交互,获取可以支付的url String url = WeixinPayUtils.weixinPay(orders.getOrderId(),orders.getUntitled()); log.info("url:{}",url); //7. 组织返回的map数据 HashMap map = new HashMap<>(); map.put("orderId",orders.getOrderId()); map.put("productNames",orders.getUntitled()); map.put("payUrl",url); return map; } @Override public 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


        
            com.github.wxpay
            wxpay-sdk
            0.0.3
        
    

 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 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 result = wxPay.unifiedOrder(map);
        return result.get("code_url");
    }

    public static String queryStatus(String orderid) throws Exception {
        WXPay wxPay = new WXPay(new MyWxConfig());
        HashMap map = new HashMap<>();
        map.put("out_trade_no",orderid);
        Map 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 map = new HashMap<>();
        map.put("out_trade_no",orderid);
        Map 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";

    @Override
    public String getAppID() {
        return appid;
    }

    @Override
    public String getMchID() {
        return mch_id;
    }

    @Override
    public String getKey() {
        return appkey;
    }

    @Override
    public InputStream getCertStream() {
        return null;
    }

    @Override
    public int getHttpConnectTimeoutMs() {
        return 0;
    }

    @Override
    public int getHttpReadTimeoutMs() {
        return 0;
    }
}

你可能感兴趣的:(SpringBoot,微信)