spring boot+vue实现JSAPI微信支付的完整步骤

作者:晨曦哦 时间:2023-07-31 13:39:26 

微信支付

最近公司要在微信公众号上做一个活动预报名,活动的门票等需要在微信中支付。

微信支付前的准备

微信支付需要一个微信支付商务号(https://pay.weixin.qq.com/index.php/apply/applyment_home/guide_normal),请自行去商务平台申请。商务号申请完后,需要在 “微信公众号平台–>微信支付” 中接入。接入成功后还需要在 “微信公众号平台–>设置–>公众号设置–>功能设置” 中将你的域名设置好,域名格式:http://baidu.com/ ,并将你的服务器ip设置成白名单,设置好之后 就可以开始开发微信支付了,

spring boot+vue实现JSAPI微信支付的完整步骤

后台开发

话不多说,直接上代码吧,如果想细了解的请看官方文档

微信支付

控制层

@RequestMapping(value = "/wxpay", produces = MediaType.APPLICATION_JSON_VALUE)  
@ResponseBody
public Map<String, Object> weixinPrePay(@RequestBody Pay pay,HttpServletRequest request) throws Exception  {
   Map<String,Object> maps = new HashMap<String,Object>();
   // 前端传值总是会多一个: 后台截取掉 这个看情况 可能你不存在这种情况的
   pay.setOpenid(pay.getOpenid().substring(0, pay.getOpenid().length()-1));
   System.out.println(pay.getOpenid());
   // 前端传来的金额  后台需要将它变成 元
   Double prices = pay.getPrice()*100;
   Integer total_fee = prices.intValue();
       System.out.println(prices+"----"+pay.getPrice()+"----"+total_fee);
   // 生成唯一订单号
   Integer out_trade_no = (int) (System.currentTimeMillis() / 1000+970516);
       SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();  
       parameterMap.put("appid", Parm.APPID);  //微信公众号的appid
       parameterMap.put("mch_id", Parm.MCH_ID/*PayCommonUtil.MCH_ID*/);  //商户号
       parameterMap.put("device_info", "WEB");  
       parameterMap.put("nonce_str", randomString);  // 随机字符串
       parameterMap.put("body", "cheshi"); // 商品描述
       parameterMap.put("out_trade_no", out_trade_no);  // 商户订单号(唯一) 我是用当前时间戳+随意数字生成的
       parameterMap.put("fee_type", "CNY");  //货币类型 CNY:人民币
       parameterMap.put("total_fee", total_fee);   // 总金额  分为单位
       parameterMap.put("notify_url", wxnotify);   // 支付成功后的回调地址 填你
       parameterMap.put("trade_type", "JSAPI");//JSAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付,不同trade_type决定了调起支付的方式
       //trade_type为JSAPI是 openid为必填项
       parameterMap.put("openid", ASEUtil.AESdecrypt(pay.getOpenid()));
       // 加密格式  MD5 微信底层默认加密是HMAC-SHA256  具体你可以去看微信的支付底层代码(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1)
       parameterMap.put("sign_type", "MD5");
       // 生成支付签名 参数值的参数按照参数名ASCII码从小到大排序(字典序)
       String sign = PayCommonUtil.createSign("UTF-8", parameterMap);  
       parameterMap.put("sign", sign);  
       System.out.println(parameterMap);
       // 微信的统一下单接口 需要将集合中的参数 拼接成<xml></xml> 格式
       String requestXML = PayCommonUtil.getRequestXml(parameterMap);  
       System.out.println(requestXML);  
       // 调用微信的统一下单接口
       String result = PayCommonUtil.httpsRequest(  
               "https://api.mch.weixin.qq.com/pay/unifiedorder", "POST",  
               requestXML);  
       // 返回的数据是 xml 格式的数据
       System.out.println(result);  
       Map<String, Object> map = null;  
       try {  
           // 微信统一下单接口返回的数据 也是xml 格式的  所以需要把它转成map 集合,因为我们只需要当中的一个统一下单编号 prepay_id
           map = PayCommonUtil.doXMLParse(result);
           // 时间戳 需要转换成秒
           map.put("timestamp", System.currentTimeMillis() / 1000);
           // 二次签名 微信支付签名需要签名两次,第一次是用来获取统一下单的订单号
           if ("SUCCESS".equals(map.get("result_code"))) {
           SortedMap<String, Object> map2 = new TreeMap<String, Object>();
           // 第二次支付签名的 参数 需要将 第一次签名中的 订单号带入签名中
               map2.put("appId", map.get("appid"));
               map2.put("timeStamp", map.get("timestamp"));
               //这边的随机字符串必须是第一次生成sign时,微信返回的随机字符串,不然支付时会报签名错误
               map2.put("nonceStr", map.get("nonce_str"));
               // 订单详情扩展字符串 统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=***
               map2.put("package", "prepay_id=" + map.get("prepay_id"));
               // 签名方式 要和第一次签名方式一直
               map2.put("signType", "MD5");
               // 支付签名
               String sign2 = PayCommonUtil.createSign("UTF-8", map2);
               // 将你前端需要的数据 放在集合中
               Map<String,Object> payInfo = new HashMap<String,Object>();
               payInfo.put("appId", map.get("appid"));
               payInfo.put("timeStamp", map.get("timestamp"));
               payInfo.put("nonceStr", map.get("nonce_str"));
               payInfo.put("prepay_id",map.get("prepay_id"));
               payInfo.put("signType", "MD5");
               payInfo.put("paySign", sign2);
               // 返回给前端的集合数据
               maps.put("status", 200);
               maps.put("msg", "统一下单成功!");
               maps.put("data", payInfo);
           }else {
           maps.put("status", 500);
               maps.put("msg", "服务器忙,请稍后再试");
               maps.put("data", null);
           }
       } catch (JDOMException e) {  
           // TODO Auto-generated catch block  
           e.printStackTrace();  
       } catch (IOException e) {  
           // TODO Auto-generated catch block  
           e.printStackTrace();  
       }
       return maps;
   }

工具类(参考这个网址,或者使用微信官方提供的那个demo中的微信工具类)怎么选择,看你个人

spring boot+vue实现JSAPI微信支付的完整步骤

vue前端

// 微信支付
   onBridgeReady() {
     let that = this;
     let param = {
       openid: sessionStorage.getItem("openid"),  // 当前用户微信的openid
       price: that.ruleForm.price  // 应付金额
     };
     // 后台支付签名接口
     weixinPrePay(param).then(ref => {
       console.log(ref.data);
       if (ref.data.status == 200) {
         WeixinJSBridge.invoke(
           "getBrandWCPayRequest",
           {
             appId: ref.data.data.appId, // 微信的appid
             timeStamp: ref.data.data.timeStamp, //时间戳
             nonceStr: ref.data.data.nonceStr, //随机串
             package: "prepay_id=" + ref.data.data.prepay_id,  // 订单号
             signType: "MD5", //微信签名方式:
             paySign: ref.data.data.paySign //微信签名
           },
           function(res) {
             if (res.err_msg == "get_brand_wcpay_request:ok") {
               // 使用以上方式判断前端返回,微信团队郑重提示:
               //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
               var equipments = "";
               if (that.ruleForm.region === 1) {
                 equipments = "单人套餐(门票一张,帐篷一顶)";
               } else {
                 equipments = "双人套餐(门票两张,帐篷一顶)";
               }
               let params = {
                 SysUser: {
                   name: that.ruleForm.username,
                   mobile: that.ruleForm.phone,
                   openid: sessionStorage.getItem("openid")
                 },
                 Info_id: that.ruleForm.info,
                 Participants: that.ruleForm.numbers,
                 Equipments: equipments,
                 price: that.ruleForm.price
               };
               console.log(params);
               // 将支付用户加入数据库中 保存
               insertForecast(params).then(ref => {
                 if (ref.data.status == 200) {
                   that.$router.push({
                     path: "/ForeacstList"
                   });
                 } else {
                   that.$message.error("预报名失败");
                 }
               });
             } else {
               that.$message.error("支付失败,请重新支付");
             }
           }
         );
       } else {
         that.$message.error(ref.data.msg);
       }
     });
   },
   // 微信支付
   WeixinJs() {
     console.log(this.ruleForm.price);
     if (typeof WeixinJSBridge == "undefined") {
       if (document.addEventListener) {
         document.addEventListener(
           "WeixinJSBridgeReady",
           onBridgeReady,
           false
         );
       } else if (document.attachEvent) {
         document.attachEvent("WeixinJSBridgeReady", onBridgeReady);
         document.attachEvent("onWeixinJSBridgeReady", onBridgeReady);
       }
     } else {
       this.onBridgeReady();
     }
   }

微信支付就到此结束了。

来源:https://blog.csdn.net/qq_36731585/article/details/101676422

标签:springboot,微信支付,vue
0
投稿

猜你喜欢

  • Java nacos动态配置实现流程详解

    2021-06-04 19:18:30
  • java开发实现五子棋游戏

    2021-09-07 12:41:32
  • 实现Android studio设置自动导包及自动导包快捷键

    2022-03-22 00:05:26
  • springboot集成elasticsearch7的图文方法

    2022-05-15 19:46:11
  • 基于synchronized修饰静态和非静态方法

    2021-10-30 06:58:03
  • Android Dispatchers.IO线程池深入刨析

    2022-12-13 16:20:31
  • jpa多数据源时Hibernate配置自动生成表不生效的解决

    2023-04-24 06:19:55
  • Java 重入锁和读写锁的具体使用

    2023-09-10 11:06:54
  • 基于SpringBoot核心原理(自动配置、事件驱动、Condition)

    2023-08-23 01:46:31
  • java如何去除图片中的白色背景

    2022-04-17 00:07:14
  • java spring mvc处理器映射器介绍

    2021-11-22 01:01:35
  • Unity 按钮事件封装操作(EventTriggerListener)

    2022-07-08 10:07:08
  • Android中使用 AutoCompleteTextView 实现手机号格式化附带清空历史的操作

    2021-07-05 17:08:43
  • spring boot thymeleaf 图片上传web项目根目录操作步骤

    2023-11-23 10:50:46
  • C#反射(Reflection)详解

    2022-09-16 22:58:11
  • svn 清理失败 (cleanup 失败) 的快速解决方法

    2022-10-25 11:22:40
  • Android AndBase框架使用封装好的函数完成Http请求(三)

    2021-09-15 09:49:56
  • Java多线程之条件对象Condition

    2021-09-25 15:15:30
  • Java Socket编程服务器响应客户端实例代码

    2023-08-09 03:25:51
  • C# SendInput 模拟鼠标操作的实现方法

    2022-03-15 00:07:25
  • asp之家 软件编程 m.aspxhome.com