SpringBoot+Vue實現(xiàn)微信掃碼支付、退款功能
<dependency><groupId>com.github.wxpay</groupId><artifactId>wxpay-sdk</artifactId><version>0.0.3</version></dependency>
在配置類添加申請的商家號信息
#關聯(lián)的公眾號appidweixin.pay.appid=wxXXXXXXX#商戶號weixin.pay.partner=XXXXXXXXX#商戶keyweixin.pay.partnerkey=XXXXXXXXXX
添加微信生成二維碼service
public class WeiXinServiceImpl implements WeiXinService {private PaymentInfoService paymentInfoService;private OrderInfoService orderInfoService;private WeiXinService weiXinService;//生成支付的二維碼public Map createNative(Long orderId) {//支付記錄表添加數(shù)據(jù)//根據(jù)單號查詢訂單相關信息OrderInfo orderInfo = orderInfoService.getById(orderId);if (orderInfo == null){throw new OrderException(20001,"訂單不存在");}//添加訂單狀態(tài)paymentInfoService.savePaymentInfo(orderInfo,PaymentTypeEnum.WEIXIN.getStatus());//調用微信接口返回二維碼try {//2 調用微信接口,得到二維碼地址等信息//封裝傳遞微信地址參數(shù)Map paramMap = new HashMap();paramMap.put("appid", ConstantPropertiesUtils.APPID); //公眾號idparamMap.put("mch_id", ConstantPropertiesUtils.PARTNER); //商戶號paramMap.put("nonce_str", WXPayUtil.generateNonceStr()); //隨機字符串,調用工具類Date reserveDate = orderInfo.getReserveDate();String reserveDateString = new DateTime(reserveDate).toString("yyyy/MM/dd");String body = reserveDateString + "就診"+ orderInfo.getDepname();paramMap.put("body", body);//掃碼后手機顯示內容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"); //終端ipparamMap.put("notify_url", "http://xxxxxxxxx");//回調地址paramMap.put("trade_type", "NATIVE"); //二維碼類型//請求微信生成二維碼接口HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");//設置post請求相關參數(shù)//微信支付要求傳遞參數(shù)xml格式//把封裝map集合變成xml,加密處理,傳輸String xml = WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY);client.setXmlParam(xml);//支持https協(xié)議client.setHttps(true);//發(fā)送client.post();//調用微信接口,返回數(shù)據(jù),xml格式的數(shù)據(jù)String resultXml = client.getContent();System.out.println("微信二維碼:"+resultXml);//把xml格式數(shù)據(jù)轉換mapMap<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,"生成二維碼失敗");}}}
控制層
public class WeixinController {private WeiXinService weixinPayService;/*** 下單 生成二維碼*/public R createNative(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" ="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//調用接口weixinApi.createNative(this.orderId).then(response => {this.payObj = response.dataif(this.payObj.codeUrl == '') {this.dialogPayVisible = falsethis.$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文件,所以需要轉換
//調用微信接口查詢支付狀態(tài)@Overridepublic 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 調用微信接口,傳遞數(shù)據(jù),設置參數(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)
public Result queryPayStatus(Long orderId) {//調用查詢接口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),處理支付結果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.p12weixinservice中
//退款@Overridepublic 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 調用微信退款接口//封裝微信接口需要數(shù)據(jù)Map<String,String> paramMap = new HashMap<>(8);paramMap.put("appid",ConstantPropertiesUtils.APPID); //公眾賬號IDparamMap.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ù)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;}

入骨相思知不知
玲瓏骰子安紅豆



入我相思門,知我相思苦,長相思兮長相憶,短相思兮無窮極。



評論
圖片
表情
