美文网首页技能拓展springboot
基于spring boot 的 app端微信支付

基于spring boot 的 app端微信支付

作者: Raral | 来源:发表于2021-04-14 18:07 被阅读0次

    基于spring boot 的 app微信支付

    微信申请支付平台

    1. 根据需求提供材料,完成账户注册流程


      wx011.jpg
      wx022.jpg
      wx03.png
      wx055.jpg
    1. 在当前账户下申请支付功能
    • JSAPI支付
    • Native支付
    • H5支付


      wx04.png

    相关所有支付类型


    wx_config04.png
    1. 查看对应的支付配置


      wx_config011.jpg
    2. AppId账户管理,核心配置参数

    app应用


    wx_config022.jpg

    小程序应用


    wx_config033.jpg
    1. 接入文档
      https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml
    2. 流程图


      wx_pay.png

    springboot 接入app支付

    controller

    @Log4j2
    @RequestMapping("/api/ocs/we-chat/pay")
    @RestController
    public class ApiOcsWeChatPayController extends BaseController {
    
        @Autowired
        private IApiWeChatPayService apiWeChatPayService;
    
        /**
         * 微信APP支付 获取预支付id
         * @param request
         * @param response
         * @return
         * @throws Exception
         */
        @PostMapping("/prepay")
        public AjaxResult prepayOrder(HttpServletRequest request, HttpServletResponse response  )throws Exception{
            TenPayRes tenPayRes = apiWeChatPayService.prepayOrder(request, response);
            if (tenPayRes==null) {
                return AjaxResult.error("失败,请重试");
            }
            return AjaxResult.success("成功",tenPayRes);
        }
    
    
        /** app 微信支付校验 */
        @PostMapping("/notify")
        public void notifyRechargeOrder(HttpServletRequest request, HttpServletResponse response)throws Exception{
            boolean b = apiWeChatPayService.notifyRechargeOrder(request, response);
        }
    
    }
    
    //app端需要的参数
    public class TenPayRes implements Serializable {
    
         /** appid */
         private String appId;
         /** 签名 */
         private String sign;
         /** 预支付交易会话标识 */
         private String prepayId;
         /** 商户id */
         private String partnerId;
         /** 随机字符串 */
         private String nonceStr;
         /** 时间戳 */
         private String timeStamp;
         /** 支付方式 */
         private String packageValue;
    }
    

    service

    @Service
    public class ApiWeChatPayServiceImpl implements IApiWeChatPayService {
    
    
        @Autowired
        private IOcsRechargeOrderService rechargeOrderService;
    
    
    
        /**
         *  app 微信支付  获取预支付id
         * @param request
         * @param response
         * @return
         */
        @Override
        public TenPayRes prepayOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
            //1. 微信支付工具类
            PrepayIdRequestHandler prepayReqHandler = new PrepayIdRequestHandler(request, response);
            //2. 获取该业务相关信息
            // 2.1 用户id
            String userId = request.getParameter("userId");
            // 2.2 订单总金额
            String totalFee =request.getParameter("orderAmount");
            BigDecimal total_fees = new BigDecimal(totalFee).multiply(new BigDecimal(100));
            int total_fee = total_fees.intValue();
            // 2.3 订单编号
            String out_trade_no = request.getParameter("orderCode");
            Long aLong = Long.valueOf(out_trade_no);
            QueryWrapper<OcsRechargeOrder> wrapper = new QueryWrapper<>();
            wrapper.eq("code", aLong).eq("user_id", userId);
            //3. 自己业务 可以省略不写
            OcsRechargeOrder one = rechargeOrderService.getOne(wrapper);
            Integer userType = one.getUserType();
            String appId=null;
            String appSecrrt=null;
            if (userType==0){
                appId=WeChatPayStatic.APP_IDS;
                appSecrrt=WeChatPayStatic.APP_SECRETS;
            }else if(userType==1){
                appId=WeChatPayStatic.APP_ID;
                appSecrrt=WeChatPayStatic.APP_SECRET;
            }
    
            //4.关键 ----------------- 微信支付 参数封装  生成签名-------------
            //微信开发平台应用ID
            prepayReqHandler.setParameter("appid", appId);
            //商品描述
            prepayReqHandler.setParameter("body", WeChatPayStatic.BODY);
            //微信支付商户号
            prepayReqHandler.setParameter("mch_id", WeChatPayStatic.MCH_ID);
            String nonce_str = WXUtil.getNonceStr();
            //随机字符串
            prepayReqHandler.setParameter("nonce_str", nonce_str);
            //微信服务器回调通知url :目的就是微信那边支付成功或者失败后的回调地址,在这里 可以进行自己业务操作(异步的)
            prepayReqHandler.setParameter("notify_url", WeChatPayStatic.NOTIFY_URLS);
            prepayReqHandler.setParameter("out_trade_no", out_trade_no);
            //获取到客户端IP地址
            prepayReqHandler.setParameter("spbill_create_ip", request.getRemoteAddr());
            String timestamp = WXUtil.getTimeStamp();
            //时间戳
            prepayReqHandler.setParameter("time_start", timestamp);
            // System.out.println(String.valueOf(total_fee));
            //订单总金额
            prepayReqHandler.setParameter("total_fee", String.valueOf(total_fee));
            prepayReqHandler.setParameter("trade_type", "APP");
    
            /**
             * 注意签名(sign)的生成方式,具体见官方文档(传参都要参与生成签名,且参数名按照字典序排序,最后接上APP_KEY,转化成大写)
             */
            String signsss=prepayReqHandler.createMD5Sign(WeChatPayStatic.APP_KEY);
            prepayReqHandler.setParameter("sign", signsss);//签名
            prepayReqHandler.setGateUrl(WeChatPayStatic.GATEURL);//支付入口参数
            //获取prepayid
            String prepayid = prepayReqHandler.sendPrepay().get("prepay_id");
    
            if (prepayid != null && !prepayid.equals("")) {
                String signs = "appid=" + appId + "&noncestr=" + nonce_str + "&package=Sign=WXPay&partnerid="
                        + WeChatPayStatic.PARTNER_ID + "&prepayid=" + prepayid + "&timestamp=" + timestamp
                        + "&key="+WeChatPayStatic.APP_KEY;
    
                TenPayRes tenPayRes = new TenPayRes();
                tenPayRes.setAppId(appId);
                tenPayRes.setSign(Md5Encrypt.MD5Encode(signs, "utf8").toUpperCase());
                tenPayRes.setPartnerId(WeChatPayStatic.PARTNER_ID);
                tenPayRes.setPrepayId(prepayid);
                tenPayRes.setNonceStr(nonce_str);
                tenPayRes.setTimeStamp(timestamp);
                tenPayRes.setPackageValue("Sign=WXPay");
                return tenPayRes;
            }
    
            return null;
        }
    
        /**
         *  验签
         * @param request
         * @param response
         * @return
         * @throws Exception
         */
        @Override
        public boolean notifyRechargeOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
            //获取信息流
            response.reset();
            PrintWriter writer = response.getWriter();
            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);
            }
            outSteam.close();
            inStream.close();
            String result = new String(outSteam.toByteArray(), "utf-8");
            Map<String, String> map = null;
            try {
                /**
                 * 解析微信通知返回的信息
                 */
                map = XMLUtil.doXMLParse(result);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            String rnc = map.get("return_code");
            String rtc = map.get("result_code");
            if ("SUCCESS".equals(rnc)) {
                SortedMap<String,String> sort=new TreeMap<String,String>(map);
                String signss=sort.get("sign");
                String signs= XMLUtil.createSign(sort);
                if(!signs.equals(signss)){
                    throw new Exception("微信回调参数签名不合法");
                }
                if ("SUCCESS".equals(rtc)){
                    //业务校验
                    // 订单编号
                    String orderCode = map.get("out_trade_no");
                    Long orderCodes = Long.valueOf(orderCode);
                    // 支付编号
                    String payCode = map.get("transaction_id");
                    // 支付金额
                    String total_fee = map.get("total_fee");
                    boolean b = rechargeOrderService.checkRecharge(orderCodes, total_fee, 2);
                    if(!b){
                        throw new Exception("金额不符");
                    }
                    // 支付完成 更新订单状态
                    int payType=2;
                    BigDecimal money = new BigDecimal(total_fee).divide(new BigDecimal("100"));
                    String paymentAmount = money.toString();
                    boolean flag = rechargeOrderService.updateRechargeOrder(orderCodes, payType, payCode, paymentAmount,new Date());
                    String notifyStr = XMLUtil.setXML("SUCCESS", "OK");
                    writer.write(notifyStr);
                    writer.flush();
                }
    
            }
    
            return false;
        }
    }
    

    dao

    utils

    
    
    public class PrepayIdRequestHandler extends RequestHandler {
    
        public PrepayIdRequestHandler(HttpServletRequest request,
                                      HttpServletResponse response) {
            super( request, response );
        }
    
    
        public String createMD5Sign(String Appkeys) {
    
    
            StringBuffer sb = new StringBuffer();
            Set es = super.getAllParameters().entrySet();
            Iterator it = es.iterator();
            while (it.hasNext()) {
                Map.Entry entry = (Map.Entry) it.next();
                String k = (String) entry.getKey();
                String v = (String) entry.getValue();
                sb.append( k + "=" + v + "&" );
            }
            String params = sb.append( "key=" + Appkeys ).substring( 0 );
            String sign = Md5Encrypt.MD5Encode( params, "utf8" );
            return sign.toUpperCase();
        }
    
        /**
         * 提交预支付
         *
         * @return
         * @throws Exception
         */
        public Map<String,String> sendPrepay() throws Exception {
            TenpayHttpClient httpClient = this.callHP();
            Map<String, String> map = new HashMap<>();
            String prepayid = "";
            String resContent = "";
            if (httpClient != null) {
                resContent = httpClient.getResContent();
                System.out.println( "获取prepayid的返回值:" + resContent );
                map= XMLUtil.doXMLParse( resContent );
    
            }
            return map;
        }
    
        //获取沙箱密钥
    
    
        public String getShaKey() throws Exception {
            TenpayHttpClient httpClient = this.callHP();
            String SignKey = "";
            String resContent = "";
            if (httpClient != null) {
                resContent = httpClient.getResContent();
                System.out.println( "获取SignKey的返回值:" + resContent );
                Map<String, String> map = XMLUtil.doXMLParse( resContent );
                if (map.containsKey( "sandbox_signkey" )) {
                    SignKey = map.get( "sandbox_signkey" );
                }
            }
            return SignKey;
        }
    
        public TenpayHttpClient callHP() {
            String SignKey = "";
            Set es = super.getAllParameters().entrySet();
            Iterator it = es.iterator();
            StringBuffer sb = new StringBuffer( "<xml>" );
            while (it.hasNext()) {
                Map.Entry entry = (Map.Entry) it.next();
                String k = (String) entry.getKey();
                String v = (String) entry.getValue();
                sb.append( "<" + k + ">" + v + "</" + k + ">" );
            }
            sb.append( "</xml>" );
            String params = sb.substring( 0 );//截取字符串
    
            System.out.println( "请求参数:" + params );
            String requestUrl = super.getGateUrl();
            System.out.println( "请求url:" + requestUrl );
            TenpayHttpClient httpClient = new TenpayHttpClient();
            httpClient.setReqContent( requestUrl );
            Boolean b = httpClient.callHttpPost( requestUrl, params );
            if (b) {
                return httpClient;
            } else {
                return null;
            }
        }
    
    }
    
    

    参考文献

    https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_5_2.shtml
    https://blog.csdn.net/xiaxl/article/details/108851372

    相关文章

      网友评论

        本文标题:基于spring boot 的 app端微信支付

        本文链接:https://www.haomeiwen.com/subject/dsdllltx.html