spring boot+vue实现JSAPI微信支付的完整步骤
作者:晨曦哦 发布时间:2023-07-31 13:39:26
标签:springboot,微信支付,vue
微信支付
最近公司要在微信公众号上做一个活动预报名,活动的门票等需要在微信中支付。
微信支付前的准备
微信支付需要一个微信支付商务号(https://pay.weixin.qq.com/index.php/apply/applyment_home/guide_normal),请自行去商务平台申请。商务号申请完后,需要在 “微信公众号平台–>微信支付” 中接入。接入成功后还需要在 “微信公众号平台–>设置–>公众号设置–>功能设置” 中将你的域名设置好,域名格式:http://baidu.com/ ,并将你的服务器ip设置成白名单,设置好之后 就可以开始开发微信支付了,
后台开发
话不多说,直接上代码吧,如果想细了解的请看官方文档
微信支付
控制层
@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中的微信工具类)怎么选择,看你个人
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


猜你喜欢
- Java基本概念JDK包含了不少Java开发相关命令。如,javac、java、javap、javaw、javadoc。虽然现在的Java开
- Service翻译成中文是服务,熟悉Windows 系统的同学一定很熟悉了。A
- 前言在平时的项目开发中,mybatis应用非常广泛,但一般都是直接CRUD类型sql的执行。本片博客主要说明一个另类的操作,注入sql,并使
- 业务场景我们知道在使用PageHelper分页插件时,会对执行PageHelper.startPage(pageNum, pageSize)
- 前文本章是关于Java流程控制语句的最全汇总,本篇为汇总中篇。流程是人们生活中不可或缺的一部分,它表示人们每天都在按照一定的流程做事。比如出
- 前言之前在SpringBoot项目中一直使用的是SpringFox提供的Swagger库,上了下官网发现已经有接近两年没出新版本了!前几天升
- 前言SSL Socket通讯是对socket的扩展,增加Socket通讯的数据安全性,SSL认证分为单向和双向认证。单向认证只认证服务器端的
- 因为在准备讲Maven用Maven Helper插件的时候,在网上学习,发现资料很少,我就把自己研究的配置分享给大家!!IDEA(本人用的2
- Lambda,希腊字母λ,在C#编程语言中,被引入为Lambda表达式,表示为匿名函数(匿名方法)。编程时离不开函数,
- 本文实例为大家分享了android音乐播放器的具体代码,供大家参考,具体内容如下话不多说先上效果前言写这个音乐播放器实在是迫不得已。因为我们
- Android透明状态栏只有在4.4之后有。在代码中加入下面几行代码即可实现来源:http://www.cnblogs.com/wangxi
- for循环语句重复执行语句,直到条件变为 false。语法for ( init-expression ; cond-expression ;
- 本文实例讲述了Android编程入门之HelloWorld项目目录结构。分享给大家供大家参考,具体如下:我们介绍了如何搭建Android开发
- 本文实例讲述了linux环境下java程序打包成简单的hello world输出jar包。分享给大家供大家参考,具体如下:1. linux必
- 一、前言Android实现圆角矩形,圆形或者椭圆等图形,一般主要是个自定义View加上使用Xfermode实现的。实现圆角图片的方法其实不少
- 使用@Async异步调用方法Async简介异步方法调用使用场景:处理日志、发送邮件、短信......spring中提供了@Async来实现异
- 前言在真实的项目开发中,使用SpringBoot可以说非常普遍了,而在框架整合中,与数据库的交互无外乎使用jpa,mybatis,mybat
- 说明:在填写表数据时当输入完一个文本框后,输入下一个文本框时需要用Tab键切换,但是有的人喜欢用Enter键切换下一个,此方法是Enter取
- 前言本文主要给大家介绍的是java虚拟机的故障处理工具,文中提到这些工具包括:名称主要作用jpsJVM process Status Too
- 我就废话不多说了,大家还是直接看代码吧~package c10; import java.util.Scanner; public clas