场景:springboot网页点击缴费,弹出二维码,支付成功后回调服务器,保存订单信息。
1.先导入包,返回二维码链接,采用第三方包qrcode-utils生成图片。
com.github.binarywang
weixin-java-pay
4.0.0
org.projectlombok
lombok
provided
com.github.binarywang
qrcode-utils
1.1
2. 在后台获取配置信息,写在yml
3.写个属性类,读取yml文件
@Data
@ConfigurationProperties(prefix = "wx.pay")
public class WxPayProperties {
private String appId;
private String mchId;
private String mchKey;
private String subMchId;
private String certPath;
private String apiV3Key;
private String privateKeyPath;
private String privateCertPath;
private String notifyUrl;
}
4.写个配置类,把配置文件属性注入WxPayService
package com.ruoyi.web.controller.onlinepay.config;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.ruoyi.common.utils.StringUtils;
import lombok.AllArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConditionalOnClass(WxPayService.class)
@EnableConfigurationProperties(WxPayProperties.class)
@AllArgsConstructor
public class WxPayConfig {
private WxPayProperties properties;
@Bean
@ConditionalOnMissingBean
public WxPayService wxService() {
com.github.binarywang.wxpay.config.WxPayConfig payConfig = new com.github.binarywang.wxpay.config.WxPayConfig();
payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getCertPath()));
payConfig.setNotifyUrl(StringUtils.trimToNull(this.properties.getNotifyUrl()));
payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(false);
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}
5. 写个实现类WeChatService,实现类实现预支付wxPayService.unifiedOrder(wrequest)
public WxPayUnifiedOrderResult createUnifiedOrder(SysChargeVoucher sysChargeVoucher, HttpServletRequest request);
package com.ruoyi.web.controller.onlinepay.service.impl;
import cn.hutool.json.JSONObject;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.system.domain.SysChargeVoucher;
import com.ruoyi.web.controller.onlinepay.config.WxPayConfig;
import com.ruoyi.web.controller.onlinepay.service.WeChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
@Service
public class WeChatServiceImpl implements WeChatService {
@Autowired
private WxPayService wxPayService;
@Autowired(required=false)
private WxPayUnifiedOrderRequest orderRequest;
@Autowired
private WxPayConfig wxPayConfig;
@Override
public String createOrderInfo(SysChargeVoucher sysChargeVoucher,HttpServletRequest request) {
WxPayMwebOrderResult result = null;
try {
orderRequest.setOutTradeNo(sysChargeVoucher.getChargeBillId()+"");
orderRequest.setBody("我是商品描述");
orderRequest.setTotalFee(sysChargeVoucher.getAmount().multiply(new BigDecimal("100")).intValue());//金额需要扩大100倍:1代表支付时是0.01
orderRequest.setSpbillCreateIp(this.getAddrIp(request));
orderRequest.setProductId(sysChargeVoucher.getChargeVoucherId()+"");
orderRequest.setTradeType(WxPayConstants.TradeType.MWEB);// h5网页支付
result = wxPayService.createOrder(orderRequest);
} catch (WxPayException e) {
e.printStackTrace();
}
return result.getMwebUrl();
}
@Override
public WxPayUnifiedOrderResult createUnifiedOrder(SysChargeVoucher sysChargeVoucher, HttpServletRequest request) {
wxPayService= wxPayConfig.wxService();
WxPayUnifiedOrderResult rest=new WxPayUnifiedOrderResult();
try {
WxPayUnifiedOrderRequest wrequest = new WxPayUnifiedOrderRequest();
wrequest.setDeviceInfo("WEB");//设备号
wrequest.setBody("物业缴费");//商品描述
wrequest.setOutTradeNo(sysChargeVoucher.getDocumentNo()+"_"+sysChargeVoucher.getChargeVoucherId());//商户订单号
JSONObject map = new JSONObject();
map.put("conventionalChargeIds",sysChargeVoucher.getConventionalChargeIds());
map.put("meterChargeIds",sysChargeVoucher.getMeterChargeIds());
map.put("temporaryChargeIds",sysChargeVoucher.getTemporaryChargeIds());
map.put("apportionChargeIds",sysChargeVoucher.getApportionChargeIds());
wrequest.setDetail(map.toString());//商品详情
wrequest.setTotalFee(sysChargeVoucher.getAmount().multiply(new BigDecimal("100")).intValue());//总金额|分计
wrequest.setSpbillCreateIp(this.getAddrIp(request));//终端IP
wrequest.setTradeType("NATIVE");//交易类型
wrequest.setProductId(sysChargeVoucher.getDocumentNo()+"_"+sysChargeVoucher.getChargeVoucherId());//商品id
rest=wxPayService.unifiedOrder(wrequest);
} catch (WxPayException e) {
rest.setErrCodeDes(e.getErrCodeDes());
rest.setErrCode(e.getResultCode());
}
return rest;
}
private String getAddrIp(HttpServletRequest request){
return request.getRemoteAddr();
}
}
6.点击缴费,触发创建二维码
html
JS
var url = ctx + "pay/createQRCode";
$.ajax({
url: url,
type: "post",
dataType: "json",
data: data,
success: function (result) {
if(result.code==0){
$('#erCodeBut').trigger("click");
$('#img2').attr('src', 'data:image/png;base64,' + result.msg);
var p=$('#propertyUnitName').val();
var c=$('#customerName').val();
$('#tips').text("尊敬的"+c+"先生/女士,您名下单元:"+p+"的物业费用为:");
$('#wxamount').text(result.data.amount);
}else if(result.code==301){
alert(result.msg);
}else{
alert("生成二维码识别,请重试!");
}
}
});
后台请求
package com.ruoyi.web.controller.onlinepay.controller;
import com.github.binarywang.utils.qrcode.QrcodeUtils;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.service.*;
import com.ruoyi.web.controller.onlinepay.service.WeChatService;
import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.math.BigDecimal;
import java.util.List;
@RequestMapping("/pay")
@Controller
@AllArgsConstructor
public class WxPayController extends BaseController {
@Autowired
private ISysChargeVoucherService sysChargeVoucherService;
@Autowired
private ISysChargeBillService sysChargeBillService;
@Autowired
private ISysConventionalChargeService sysConventionalChargeService;
@Autowired
private ISysMeterChargeService sysMeterChargeService;
@Autowired
private ISysTemporaryChargeService sysTemporaryChargeService;
@Autowired
private ISysApportionChargeService sysApportionChargeService;
@Autowired
private ISysChargeVoucherDetailService sysChargeVoucherDetailService;
@Autowired
private WeChatService weChatService;
private WxPayService wxService;
@PostMapping("/createQRCode")
@ResponseBody
public AjaxResult createQRCode(SysChargeVoucher sysChargeVoucher,HttpServletRequest req){
SysChargeVoucher chargeVoucher=sysChargeVoucher.clone();
chargeVoucher.setDocumentNo(null);
chargeVoucher.setStatus("0");
List chargeList=sysChargeVoucherService.selectSysChargeVoucherList(chargeVoucher);
if(chargeList.size()==0){
sysChargeVoucher=this.addSysChargeVoucher(sysChargeVoucher);
}else{
sysChargeVoucher=chargeList.get(0);
}
if(sysChargeVoucher!=null&&sysChargeVoucher.getChargeVoucherId()!=null){
WxPayUnifiedOrderResult result = weChatService.createUnifiedOrder(sysChargeVoucher, req);
if (result != null && result.getCodeURL() != null) {
byte[] qrCodeBytes = QrcodeUtils.createQrcode(result.getCodeURL(), null);
String ercode = Base64.encodeBase64String(qrCodeBytes);
return AjaxResult.success(ercode, sysChargeVoucher);
} else if (result != null && result.getErrCode() != null) {
return AjaxResult.warn(result.getErrCodeDes());
}
}
return AjaxResult.error();
}
/**
* 读取支付结果通知
*
* @param xmlData
* @throws WxPayException
*/
@PostMapping("/getOrderNotifyResult")
public String getOrderNotifyResult(@RequestBody String xmlData, HttpServletRequest request, HttpServletResponse response) throws WxErrorException, WxPayException {
WxPayOrderNotifyResult orderNotifyResult = this.wxService.parseOrderNotifyResult(xmlData);
String noticeStr = null;
try {
BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
// 支付成功,商户处理后同步返回给微信参数
if (!orderNotifyResult.getResultCode().equals("SUCCESS")) {
// 支付失败, 记录流水失败
System.out.println("===============支付失败==============");
noticeStr = setXML("FAIL", "支付失败");
outputStream.write(noticeStr.getBytes());
outputStream.flush();
outputStream.close();
} else {
// TODO 处理你的业务,修改订单状态等
String outTradeNo= orderNotifyResult.getOutTradeNo();
String[] arr=outTradeNo.split("_");
SysChargeVoucher sysChargeVoucher =sysChargeVoucherService.selectSysChargeVoucherById(Long.parseLong(arr[1]));
updateSysChargeVoucher(sysChargeVoucher);
// 通知微信已经收到消息,不要再给我发消息了,否则微信会8连击调用本接口
noticeStr = setXML("SUCCESS", "支付成功");
outputStream.write(noticeStr.getBytes());
outputStream.flush();
outputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return noticeStr;
}
public String setXML(String return_code, String return_msg) {
return " ";
}
}