spring?boot+vue實現(xiàn)JSAPI微信支付的完整步驟
微信支付
最近公司要在微信公眾號上做一個活動預報名,活動的門票等需要在微信中支付。
微信支付前的準備
微信支付需要一個微信支付商務號(https://pay.weixin.qq.com/index.php/apply/applyment_home/guide_normal),請自行去商務平臺申請。商務號申請完后,需要在 “微信公眾號平臺–>微信支付” 中接入。接入成功后還需要在 “微信公眾號平臺–>設置–>公眾號設置–>功能設置” 中將你的域名設置好,域名格式:http://baidu.com/ ,并將你的服務器ip設置成白名單,設置好之后 就可以開始開發(fā)微信支付了,

后臺開發(fā)
話不多說,直接上代碼吧,如果想細了解的請看官方文檔
控制層
@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); // 商戶訂單號(唯一) 我是用當前時間戳+隨意數(shù)字生成的
parameterMap.put("fee_type", "CNY"); //貨幣類型 CNY:人民幣
parameterMap.put("total_fee", total_fee); // 總金額 分為單位
parameterMap.put("notify_url", wxnotify); // 支付成功后的回調(diào)地址 填你
parameterMap.put("trade_type", "JSAPI");//JSAPI--JSAPI支付(或小程序支付)、NATIVE--Native支付、APP--app支付,MWEB--H5支付,不同trade_type決定了調(diào)起支付的方式
//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");
// 生成支付簽名 參數(shù)值的參數(shù)按照參數(shù)名ASCII碼從小到大排序(字典序)
String sign = PayCommonUtil.createSign("UTF-8", parameterMap);
parameterMap.put("sign", sign);
System.out.println(parameterMap);
// 微信的統(tǒng)一下單接口 需要將集合中的參數(shù) 拼接成<xml></xml> 格式
String requestXML = PayCommonUtil.getRequestXml(parameterMap);
System.out.println(requestXML);
// 調(diào)用微信的統(tǒng)一下單接口
String result = PayCommonUtil.httpsRequest(
"https://api.mch.weixin.qq.com/pay/unifiedorder", "POST",
requestXML);
// 返回的數(shù)據(jù)是 xml 格式的數(shù)據(jù)
System.out.println(result);
Map<String, Object> map = null;
try {
// 微信統(tǒng)一下單接口返回的數(shù)據(jù) 也是xml 格式的 所以需要把它轉(zhuǎn)成map 集合,因為我們只需要當中的一個統(tǒng)一下單編號 prepay_id
map = PayCommonUtil.doXMLParse(result);
// 時間戳 需要轉(zhuǎn)換成秒
map.put("timestamp", System.currentTimeMillis() / 1000);
// 二次簽名 微信支付簽名需要簽名兩次,第一次是用來獲取統(tǒng)一下單的訂單號
if ("SUCCESS".equals(map.get("result_code"))) {
SortedMap<String, Object> map2 = new TreeMap<String, Object>();
// 第二次支付簽名的 參數(shù) 需要將 第一次簽名中的 訂單號帶入簽名中
map2.put("appId", map.get("appid"));
map2.put("timeStamp", map.get("timestamp"));
//這邊的隨機字符串必須是第一次生成sign時,微信返回的隨機字符串,不然支付時會報簽名錯誤
map2.put("nonceStr", map.get("nonce_str"));
// 訂單詳情擴展字符串 統(tǒng)一下單接口返回的prepay_id參數(shù)值,提交格式如:prepay_id=***
map2.put("package", "prepay_id=" + map.get("prepay_id"));
// 簽名方式 要和第一次簽名方式一直
map2.put("signType", "MD5");
// 支付簽名
String sign2 = PayCommonUtil.createSign("UTF-8", map2);
// 將你前端需要的數(shù)據(jù) 放在集合中
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);
// 返回給前端的集合數(shù)據(jù)
maps.put("status", 200);
maps.put("msg", "統(tǒng)一下單成功!");
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;
}
工具類(參考這個網(wǎng)址,或者使用微信官方提供的那個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);
// 將支付用戶加入數(shù)據(jù)庫中 保存
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();
}
}
微信支付就到此結(jié)束了。
總結(jié)
到此這篇關(guān)于spring boot+vue實現(xiàn)JSAPI微信支付的文章就介紹到這了,更多相關(guān)springboot vue實現(xiàn)微信支付內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot集成PostgreSQL并設置最大連接數(shù)
本文主要介紹了SpringBoot集成PostgreSQL并設置最大連接數(shù),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-11-11
談談Java利用原始HttpURLConnection發(fā)送POST數(shù)據(jù)
這篇文章主要給大家介紹java利用原始httpUrlConnection發(fā)送post數(shù)據(jù),設計到httpUrlConnection類的相關(guān)知識,感興趣的朋友跟著小編一起學習吧2015-10-10
詳解SpringBoot中異步請求的實現(xiàn)與并行執(zhí)行
這篇文章主要為大家詳細介紹了在SpringBoot中如何是實現(xiàn)異步請求、并行執(zhí)行,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-02-02
SpringBoot集成WebSocket的兩種方式(JDK內(nèi)置版和Spring封裝版)
這篇文章主要介紹了SpringBoot集成WebSocket的兩種方式,這兩種方式為JDK內(nèi)置版和Spring封裝版,本文結(jié)合示例代碼給大家介紹的非常詳細,需要的朋友可以參考下2023-06-06

