SpringBoot整合Vue实现微信扫码支付以及微信退款功能详解

网友投稿 495 2022-07-31


直接上代码,在order模块添加依赖

com.github.wxpay

wxpay-sdk

0.0.3

在配置类添加申请的商家号信息

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) {

//支付记录表添加数据

//根据单号查询订单相关信息

OrderInfo orderInfo = orderInfoService.getById(orderId);

if (orderInfo == null){

throw new OrderException(20001,"订单不存在");

}

//添加订单状态

paymentInfoService.savePaymentInfo(orderInfo,PaymentTypeEnum.WEIXIN.getStatus());

//调用微信接口返回二维码

try {

//2 调用微信接口,得到二维码地址等信息

//封装传递微信地址参数

Map paramMap = new HashMap();

paramMap.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"); //终端ip

paramMap.put("notify_url", "http://xxxxxxxxx");//回调地址

paramMap.put("trade_type", "NATIVE"); //二维码类型

//请求微信生成二维码接口

HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");

//设置post请求相关参数

//微信支付要求传递参数xml格式

//把封装map集合变成xml,加密处理,传输

String xml = WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY);

client.setXmlParam(xml);

//支持https协议

client.setHttps(true);

//发送

client.post();

//调用微信接口,返回数据,xml格式的数据

String resultXml = client.getContent();

System.out.println("微信二维码:"+resultXml);

//把xml格式数据转换map

Map 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'

请使用微信扫一扫

扫描二维码支付

//生成二维码

pay() {

//弹框

this.dialogPayVisible = true

//调用接口

weixinApi.createNative(this.orderId).then(response => {

this.payObj = response.data

if(this.payObj.codeUrl == '') {

this.dialogPayVisible = false

this.$message.error("支付错误")

} else {

//每隔3秒查询一次支付状态

this.timer = setInterval(()=>{

this.queryPayStatus(this.orderId)

},3000)

}

})

},

查询订单支付状态,添加定时器方法,每隔3秒去查询一次支付状态,api

queryPayStatus(orderId) {

return request({

url: `/api/order/weixin/queryPayStatus/${orderId}`,

method: 'get'

})

},

后端,weixinservice封装信息请求微信提供的接口,判断是否支付成功,因为微信返回的是xml文件,所以需要转换

//调用微信接口查询支付状态

@Override

public Map queryPayStatus(Long orderId, String paymentType) {

//1 根据orderId查询订单信息

OrderInfo orderInfo = orderInfoService.getById(orderId);

if(orderInfo == null) {

throw new orderException(20001,"订单不存在");

}

try {

//2 封装微信接口需要数据

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 调用微信接口,传递数据,设置参数

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 获取微信接口返回数据

String xml = client.getContent();

System.out.println("支付状态返回xml: "+xml);

Map resultMap = WXPayUtil.xmlToMap(xml);

return resultMap;

} catch (Exception e) {

e.printStackTrace();

throw new orderException(20001,"查询失败");

}

}

支付成功后,更新状态

控制层,查询状态

@ApiOperation(value = "查询支付状态")

@GetMapping("/queryPayStatus/{orderId}")

public Result queryPayStatus(

@ApiParam(name = "orderId", value = "订单id", required = true)

@PathVariable("orderId") Long orderId) {

//调用查询接口

Map resultMap = weixinPayService.queryPayStatus(orderId, PaymentTypeEnum.WEIXIN.name());

if (resultMap == null) {//出错

return Result.fail().message("支付出错");

}

if ("SUCCESS".equals(resultMap.get("trade_state"))) {//如果成功

//更改订单状态,处理支付结果

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 根据订单号查询订单支付记录信息

QueryWrapper wrapper = new QueryWrapper<>();

wrapper.eq("order_id",orderId);

PaymentInfo paymentInfo = paymentInfoService.getOne(wrapper);

//2 TODO 添加退款信息到退款表

try {

//3 调用微信退款接口

//封装微信接口需要数据

Map 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");

//设置接口和参数

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

//发送post请求

client.post();

//4、返回退款数据

String xml = client.getContent();

Map resultMap = WXPayUtil.xmlToMap(xml);

} catch (Exception e) {

e.printStackTrace();

}

return null;

}

总结


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Springboot并发调优之大事务和长连接(springboot 并发调优)
下一篇:Java HashMap中除了死循环之外的那些问题
相关文章

 发表评论

暂时没有评论,来抢沙发吧~