SpringBoot整合Vue實現(xiàn)微信掃碼支付以及微信退款功能詳解
直接上代碼,在order模塊添加依賴
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
在配置類添加申請的商家號信息
#關(guān)聯(lián)的公眾號appid weixin.pay.appid=wxXXXXXXX #商戶號 weixin.pay.partner=XXXXXXXXX #商戶key weixin.pay.partnerkey=XXXXXXXXXX
添加微信生成二維碼service
@Service
public class WeiXinServiceImpl implements WeiXinService {
@Autowired
private PaymentInfoService paymentInfoService;
@Autowired
private OrderInfoService orderInfoService;
@Autowired
private WeiXinService weiXinService;
//生成支付的二維碼
@Override
public Map createNative(Long orderId) {
//支付記錄表添加數(shù)據(jù)
//根據(jù)單號查詢訂單相關(guān)信息
OrderInfo orderInfo = orderInfoService.getById(orderId);
if (orderInfo == null){
throw new OrderException(20001,"訂單不存在");
}
//添加訂單狀態(tài)
paymentInfoService.savePaymentInfo(orderInfo,PaymentTypeEnum.WEIXIN.getStatus());
//調(diào)用微信接口返回二維碼
try {
//2 調(diào)用微信接口,得到二維碼地址等信息
//封裝傳遞微信地址參數(shù)
Map paramMap = new HashMap();
paramMap.put("appid", ConstantPropertiesUtils.APPID); //公眾號id
paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER); //商戶號
paramMap.put("nonce_str", WXPayUtil.generateNonceStr()); //隨機(jī)字符串,調(diào)用工具類
Date reserveDate = orderInfo.getReserveDate();
String reserveDateString = new DateTime(reserveDate).toString("yyyy/MM/dd");
String body = reserveDateString + "就診"+ orderInfo.getDepname();
paramMap.put("body", body);//掃碼后手機(jī)顯示內(nèi)容
paramMap.put("out_trade_no", orderInfo.getOutTradeNo()); //訂單流水號
//paramMap.put("total_fee", order.getAmount().multiply(new BigDecimal("100")).longValue()+"");
paramMap.put("total_fee", "1");//TODO 為了測試 支付金額
paramMap.put("spbill_create_ip", "127.0.0.1"); //終端ip
paramMap.put("notify_url", "http://xxxxxxxxx");//回調(diào)地址
paramMap.put("trade_type", "NATIVE"); //二維碼類型
//請求微信生成二維碼接口
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
//設(shè)置post請求相關(guān)參數(shù)
//微信支付要求傳遞參數(shù)xml格式
//把封裝map集合變成xml,加密處理,傳輸
String xml = WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY);
client.setXmlParam(xml);
//支持https協(xié)議
client.setHttps(true);
//發(fā)送
client.post();
//調(diào)用微信接口,返回數(shù)據(jù),xml格式的數(shù)據(jù)
String resultXml = client.getContent();
System.out.println("微信二維碼:"+resultXml);
//把xml格式數(shù)據(jù)轉(zhuǎn)換map
Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXml);
Map map = new HashMap<>();
map.put("orderId", orderId);
map.put("totalFee", orderInfo.getAmount());
map.put("resultCode", resultMap.get("result_code"));
map.put("codeUrl", resultMap.get("code_url")); //微信二維碼地址
return map;
} catch (Exception e) {
e.printStackTrace();
throw new orderException(20001,"生成二維碼失敗");
}
}
}
控制層
@RestController
@RequestMapping("/api/order/weixin")
public class WeixinController {
@Autowired
private WeiXinService weixinPayService;
/**
* 下單 生成二維碼
*/
@GetMapping("/createNative/{orderId}")
public R createNative(
@ApiParam(name = "orderId", value = "訂單id", required = true)
@PathVariable("orderId") Long orderId) {
Map map = weixinPayService.createNative(orderId);
return R.ok().data(map);
}
}
前端微信支付二維碼,wx.js定義方法
createNative(orderId) {
return request({
url: `/api/order/weixin/createNative/${orderId}`,
method: 'get'
})
}
顯示二維碼需要前端安裝插件 安裝npm install vue-qriously
訂單詳情頁,修改order/show.vue組件
import weixinApi from '@/api/yygh/wx'
<!-- 微信支付彈出框 -->
<el-dialog :visible.sync="dialogPayVisible" style="text-align: left" :append-to-body="true" width="500px" @close="closeDialog">
<div class="container">
<div class="operate-view" style="height: 350px;">
<div class="wrapper wechat">
<div>
<qriously :value="payObj.codeUrl" :size="220"/>
<div style="text-align: center;line-height: 25px;margin-bottom: 40px;">
請使用微信掃一掃<br/>
掃描二維碼支付
</div>
</div>
</div>
</div>
</div>
</el-dialog>
//生成二維碼
pay() {
//彈框
this.dialogPayVisible = true
//調(diào)用接口
weixinApi.createNative(this.orderId).then(response => {
this.payObj = response.data
if(this.payObj.codeUrl == '') {
this.dialogPayVisible = false
this.$message.error("支付錯誤")
} else {
//每隔3秒查詢一次支付狀態(tài)
this.timer = setInterval(()=>{
this.queryPayStatus(this.orderId)
},3000)
}
})
},
查詢訂單支付狀態(tài),添加定時器方法,每隔3秒去查詢一次支付狀態(tài),api
queryPayStatus(orderId) {
return request({
url: `/api/order/weixin/queryPayStatus/${orderId}`,
method: 'get'
})
},
后端,weixinservice封裝信息請求微信提供的接口,判斷是否支付成功,因為微信返回的是xml文件,所以需要轉(zhuǎn)換
//調(diào)用微信接口查詢支付狀態(tài)
@Override
public Map queryPayStatus(Long orderId, String paymentType) {
//1 根據(jù)orderId查詢訂單信息
OrderInfo orderInfo = orderInfoService.getById(orderId);
if(orderInfo == null) {
throw new orderException(20001,"訂單不存在");
}
try {
//2 封裝微信接口需要數(shù)據(jù)
Map paramMap = new HashMap<>();
paramMap.put("appid", ConstantPropertiesUtils.APPID);
paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);
paramMap.put("out_trade_no", orderInfo.getOutTradeNo());
paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
//3 調(diào)用微信接口,傳遞數(shù)據(jù),設(shè)置參數(shù)
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
client.setXmlParam(WXPayUtil.generateSignedXml(paramMap,ConstantPropertiesUtils.PARTNERKEY));
client.setHttps(true);
client.post();
//4 獲取微信接口返回數(shù)據(jù)
String xml = client.getContent();
System.out.println("支付狀態(tài)返回xml: "+xml);
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
return resultMap;
} catch (Exception e) {
e.printStackTrace();
throw new orderException(20001,"查詢失敗");
}
}
支付成功后,更新狀態(tài)
控制層,查詢狀態(tài)
@ApiOperation(value = "查詢支付狀態(tài)")
@GetMapping("/queryPayStatus/{orderId}")
public Result queryPayStatus(
@ApiParam(name = "orderId", value = "訂單id", required = true)
@PathVariable("orderId") Long orderId) {
//調(diào)用查詢接口
Map<String, String> resultMap = weixinPayService.queryPayStatus(orderId, PaymentTypeEnum.WEIXIN.name());
if (resultMap == null) {//出錯
return Result.fail().message("支付出錯");
}
if ("SUCCESS".equals(resultMap.get("trade_state"))) {//如果成功
//更改訂單狀態(tài),處理支付結(jié)果
String out_trade_no = resultMap.get("out_trade_no");
paymentInfoService.paySuccess(out_trade_no, PaymentTypeEnum.WEIXIN.getStatus(), resultMap);
return Result.ok().message("支付成功");
}
return Result.ok().message("支付中");
}
退款
退款與支付唯一不同的是需要在下載微信提供的退款證書,下載好后通過配置文件加載退款證書路徑
weixin.cert=C:\\apiclient_cert.p12
weixinservice中
//退款
@Override
public Boolean refund(Long orderId) {
//1 根據(jù)訂單號查詢訂單支付記錄信息
QueryWrapper<PaymentInfo> wrapper = new QueryWrapper<>();
wrapper.eq("order_id",orderId);
PaymentInfo paymentInfo = paymentInfoService.getOne(wrapper);
//2 TODO 添加退款信息到退款表
try {
//3 調(diào)用微信退款接口
//封裝微信接口需要數(shù)據(jù)
Map<String,String> paramMap = new HashMap<>(8);
paramMap.put("appid",ConstantPropertiesUtils.APPID); //公眾賬號ID
paramMap.put("mch_id",ConstantPropertiesUtils.PARTNER); //商戶編號
paramMap.put("nonce_str",WXPayUtil.generateNonceStr());
paramMap.put("transaction_id",paymentInfo.getTradeNo()); //微信訂單號
paramMap.put("out_trade_no",paymentInfo.getOutTradeNo()); //商戶訂單編號
paramMap.put("out_refund_no","tk"+paymentInfo.getOutTradeNo()); //商戶退款單號
// paramMap.put("total_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
// paramMap.put("refund_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+"");
paramMap.put("total_fee","1");
paramMap.put("refund_fee","1");
//設(shè)置接口和參數(shù)
HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");
client.setXmlParam(WXPayUtil.generateSignedXml(paramMap,ConstantPropertiesUtils.PARTNERKEY));
client.setHttps(true);
client.setCert(true);//退款證書
client.setCertPassword(ConstantPropertiesUtils.PARTNER);//證書密碼 商戶key
//發(fā)送post請求
client.post();
//4、返回退款數(shù)據(jù)
String xml = client.getContent();
Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}總結(jié)
到此這篇關(guān)于SpringBoot整合Vue實現(xiàn)微信掃碼支付以及微信退款功能的文章就介紹到這了,更多相關(guān)SpringBoot整合Vue微信掃碼支付退款內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決JAVA非對稱加密不同系統(tǒng)加密結(jié)果不一致的問題
這篇文章主要介紹了解決JAVA非對稱加密不同系統(tǒng)加密結(jié)果不一致的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-10-10
SpringBoot+Spring Security無法實現(xiàn)跨域的解決方案
這篇文章主要介紹了SpringBoot+Spring Security無法實現(xiàn)跨域的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
Java反射機(jī)制詳解_動力節(jié)點Java學(xué)院整理
Java 反射機(jī)制。通俗來講呢,就是在運行狀態(tài)中,我們可以根據(jù)“類的部分已經(jīng)的信息”來還原“類的全部的信息”。這篇文章給大家詳細(xì)介紹了java反射機(jī)制的知識,感興趣的朋友一起看看吧2017-06-06

