|
@@ -2,13 +2,11 @@ package com.ruoyi.web.work.wxpay;
|
|
|
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
import cn.hutool.http.ContentType;
|
|
|
-import cn.hutool.json.JSONArray;
|
|
|
import cn.hutool.json.JSONUtil;
|
|
|
import com.alibaba.fastjson2.JSONObject;
|
|
|
import com.ijpay.core.IJPayHttpResponse;
|
|
|
import com.ijpay.core.enums.AuthTypeEnum;
|
|
|
import com.ijpay.core.enums.RequestMethodEnum;
|
|
|
-import com.ijpay.core.kit.AesUtil;
|
|
|
import com.ijpay.core.kit.HttpKit;
|
|
|
import com.ijpay.core.kit.PayKit;
|
|
|
import com.ijpay.core.kit.WxPayKit;
|
|
@@ -16,21 +14,25 @@ import com.ijpay.core.utils.DateTimeZoneUtil;
|
|
|
import com.ijpay.wxpay.WxPayApi;
|
|
|
import com.ijpay.wxpay.enums.WxDomainEnum;
|
|
|
import com.ijpay.wxpay.enums.v3.BasePayApiEnum;
|
|
|
-import com.ijpay.wxpay.enums.v3.CertAlgorithmTypeEnum;
|
|
|
import com.ijpay.wxpay.model.v3.Amount;
|
|
|
import com.ijpay.wxpay.model.v3.Payer;
|
|
|
import com.ijpay.wxpay.model.v3.UnifiedOrderModel;
|
|
|
import com.ruoyi.common.annotation.Log;
|
|
|
-import com.ruoyi.common.config.RuoYiConfig;
|
|
|
import com.ruoyi.common.core.domain.AjaxResult;
|
|
|
import com.ruoyi.common.enums.BusinessType;
|
|
|
import com.ruoyi.common.exception.ServiceException;
|
|
|
+import com.ruoyi.common.utils.SecurityUtils;
|
|
|
import com.ruoyi.web.work.api.config.BaseController;
|
|
|
+import com.ruoyi.web.work.domain.Company;
|
|
|
import com.ruoyi.web.work.domain.Pay;
|
|
|
+import com.ruoyi.web.work.domain.Recharge;
|
|
|
import com.ruoyi.web.work.domain.User;
|
|
|
+import com.ruoyi.web.work.domain.dto.CompanyPayDto;
|
|
|
import com.ruoyi.web.work.domain.dto.PayDto;
|
|
|
+import com.ruoyi.web.work.domain.dto.PayStateDto;
|
|
|
import com.ruoyi.web.work.service.ICompanyService;
|
|
|
import com.ruoyi.web.work.service.IPayService;
|
|
|
+import com.ruoyi.web.work.service.IRechargeService;
|
|
|
import com.ruoyi.web.work.service.IUserService;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
@@ -40,14 +42,10 @@ import org.springframework.web.bind.annotation.*;
|
|
|
import javax.annotation.Resource;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
-import java.io.ByteArrayInputStream;
|
|
|
-import java.io.File;
|
|
|
-import java.io.FileWriter;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
import java.security.cert.X509Certificate;
|
|
|
import java.util.HashMap;
|
|
|
-import java.util.List;
|
|
|
import java.util.Map;
|
|
|
|
|
|
@RestController
|
|
@@ -62,115 +60,63 @@ public class WxPayController extends BaseController {
|
|
|
private IUserService userService;
|
|
|
|
|
|
@Autowired
|
|
|
- private ICompanyService companyService;
|
|
|
+ private IRechargeService rechargeService;
|
|
|
|
|
|
@Autowired
|
|
|
private IPayService payService;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private ICompanyService companyService;
|
|
|
+
|
|
|
/**
|
|
|
* PC扫码支付
|
|
|
*
|
|
|
* @param dto
|
|
|
* @return
|
|
|
*/
|
|
|
- @Log(title = "在线扫码支付", businessType = BusinessType.PAY)
|
|
|
- @PostMapping("/pay")
|
|
|
+ @Log(title = "微信充值", businessType = BusinessType.PAY)
|
|
|
+ @PostMapping("/companyPay")
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
- public AjaxResult pay(@Validated @RequestBody PayDto dto) {
|
|
|
+ public AjaxResult companyPay(@Validated @RequestBody CompanyPayDto dto) {
|
|
|
try {
|
|
|
String orderNum = PayKit.generateStr();
|
|
|
UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel();
|
|
|
unifiedOrderModel.setAppid(wxPayV3Bean.getAppId());
|
|
|
unifiedOrderModel.setMchid(wxPayV3Bean.getMchId());
|
|
|
- unifiedOrderModel.setDescription("测试支付");
|
|
|
+ unifiedOrderModel.setDescription("企业账户充值");
|
|
|
unifiedOrderModel.setOut_trade_no(orderNum);
|
|
|
unifiedOrderModel.setTime_expire(DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3));
|
|
|
- unifiedOrderModel.setAttach("爱心捐款");
|
|
|
- unifiedOrderModel.setNotify_url(wxPayV3Bean.getDomain().concat("/app/wxPay/payNotify"));
|
|
|
- unifiedOrderModel.setAmount(new Amount().setTotal(1));
|
|
|
+ unifiedOrderModel.setAttach("企业账户充值");
|
|
|
+ unifiedOrderModel.setNotify_url(wxPayV3Bean.getDomain().concat("/app/wxPay/companyNotify"));
|
|
|
+ unifiedOrderModel.setAmount(new Amount().setTotal(dto.getMoney().multiply(new BigDecimal(100)).intValue()));
|
|
|
IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.NATIVE_PAY.toString(), wxPayV3Bean.getMchId(), getSerialNumber(), null, wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(unifiedOrderModel), AuthTypeEnum.RSA.getCode());
|
|
|
boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
|
|
|
if (response.getStatus() == 200 && verifySignature) {
|
|
|
//保存订单信息
|
|
|
- /* Donate donate = new Donate();
|
|
|
- BeanUtils.copyProperties(dto, donate);
|
|
|
- donate.setState(0);
|
|
|
- donate.setOrderNum(orderNum);
|
|
|
- donateService.save(donate);*/
|
|
|
- return AjaxResult.success("成功", response.getBody());
|
|
|
+ Recharge recharge = new Recharge();
|
|
|
+ recharge.setCompanyId(SecurityUtils.getLoginUser().getUser().getCompanyId());
|
|
|
+ recharge.setState(0);
|
|
|
+ recharge.setType(1);
|
|
|
+ recharge.setIdent(dto.getIdent());
|
|
|
+ recharge.setNums(orderNum);
|
|
|
+ recharge.setMoney(dto.getMoney());
|
|
|
+ recharge.setVersion(System.currentTimeMillis());
|
|
|
+ recharge.setOpBy(SecurityUtils.getLoginUser().getUser().getNickName());
|
|
|
+ recharge.setUserId(SecurityUtils.getLoginUser().getUser().getUserId());
|
|
|
+ if (!rechargeService.save(recharge)) {
|
|
|
+ return AjaxResult.error("充值失败,请联系平台或者转账充值");
|
|
|
+ }
|
|
|
+ return AjaxResult.success(response.getBody());
|
|
|
}
|
|
|
- return AjaxResult.error("系统异常");
|
|
|
+ return AjaxResult.error("支付异常,请联系平台或者转账充值");
|
|
|
} catch (Exception e) {
|
|
|
- throw new ServiceException("系统异常");
|
|
|
+ throw new ServiceException(e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- @GetMapping("/get")
|
|
|
- public AjaxResult v3Get() {
|
|
|
- // 获取平台证书列表
|
|
|
- try {
|
|
|
- IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.GET, WxDomainEnum.CHINA.toString(), CertAlgorithmTypeEnum.getCertSuffixUrl(CertAlgorithmTypeEnum.RSA.getCode()), wxPayV3Bean.getMchId(), getSerialNumber(), null, wxPayV3Bean.getKeyPath(), "", AuthTypeEnum.RSA.getCode());
|
|
|
- Map<String, List<String>> headers = response.getHeaders();
|
|
|
- String timestamp = response.getHeader("Wechatpay-Timestamp");
|
|
|
- String nonceStr = response.getHeader("Wechatpay-Nonce");
|
|
|
- String serialNumber = response.getHeader("Wechatpay-Serial");
|
|
|
- String signature = response.getHeader("Wechatpay-Signature");
|
|
|
-
|
|
|
- String body = response.getBody();
|
|
|
- int status = response.getStatus();
|
|
|
-
|
|
|
- int isOk = 200;
|
|
|
- if (status == isOk) {
|
|
|
- cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(body);
|
|
|
- JSONArray dataArray = jsonObject.getJSONArray("data");
|
|
|
- // 默认认为只有一个平台证书
|
|
|
- cn.hutool.json.JSONObject encryptObject = dataArray.getJSONObject(0);
|
|
|
- cn.hutool.json.JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate");
|
|
|
- String associatedData = encryptCertificate.getStr("associated_data");
|
|
|
- String cipherText = encryptCertificate.getStr("ciphertext");
|
|
|
- String nonce = encryptCertificate.getStr("nonce");
|
|
|
- String algorithm = encryptCertificate.getStr("algorithm");
|
|
|
- String serialNo = encryptObject.getStr("serial_no");
|
|
|
- final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, algorithm, new File(RuoYiConfig.getUploadPath() + "/platformCert.pem").toString());
|
|
|
- // 根据证书序列号查询对应的证书来验证签名结果
|
|
|
- boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
|
|
|
- System.out.println("verifySignature:"+verifySignature);
|
|
|
- }
|
|
|
- return AjaxResult.success(body);
|
|
|
- } catch (Exception e) {
|
|
|
- System.out.println("asd:" + e.getMessage());
|
|
|
- e.printStackTrace();
|
|
|
- return AjaxResult.error();
|
|
|
- }
|
|
|
+ @GetMapping("/payState")
|
|
|
+ public AjaxResult payState(@Validated PayStateDto dto) {
|
|
|
+ return AjaxResult.success(rechargeService.selectByIdent(dto.getIdent()) == null ? false : true);
|
|
|
}
|
|
|
-
|
|
|
- private String savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath) {
|
|
|
- try {
|
|
|
- String key3 = wxPayV3Bean.getApiKey3();
|
|
|
- String publicKey;
|
|
|
- if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) {
|
|
|
- publicKey = PayKit.sm4DecryptToString(key3, cipherText, nonce, associatedData);
|
|
|
- } else {
|
|
|
- AesUtil aesUtil = new AesUtil(wxPayV3Bean.getApiKey3().getBytes(StandardCharsets.UTF_8));
|
|
|
- // 平台证书密文解密
|
|
|
- // encrypt_certificate 中的 associated_data nonce ciphertext
|
|
|
- publicKey = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), nonce.getBytes(StandardCharsets.UTF_8), cipherText);
|
|
|
- }
|
|
|
- if (StrUtil.isNotEmpty(publicKey)) {
|
|
|
- System.out.println("publicKey:" + publicKey);
|
|
|
- // 保存证书
|
|
|
- FileWriter writer = new FileWriter(certPath);
|
|
|
- writer.write(publicKey);
|
|
|
- // 获取平台证书序列号
|
|
|
- X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes()));
|
|
|
- return certificate.getSerialNumber().toString(16).toUpperCase();
|
|
|
- }
|
|
|
- return "";
|
|
|
- } catch (Exception e) {
|
|
|
- return e.getMessage();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* @param dto
|
|
|
* @return
|
|
@@ -189,11 +135,9 @@ public class WxPayController extends BaseController {
|
|
|
unifiedOrderModel.setAmount(new Amount().setTotal(dto.getMoney().multiply(new BigDecimal(100)).intValue()));
|
|
|
unifiedOrderModel.setNotify_url(wxPayV3Bean.getDomain().concat("/app/wxPay/payNotify"));
|
|
|
unifiedOrderModel.setPayer(new Payer().setOpenid(getUser().getOpenId()));
|
|
|
- System.out.println("asd:" + getSerialNumber());
|
|
|
IJPayHttpResponse response = WxPayApi.v3(RequestMethodEnum.POST, WxDomainEnum.CHINA.toString(), BasePayApiEnum.JS_API_PAY.toString(), wxPayV3Bean.getMchId(), getSerialNumber(), null, wxPayV3Bean.getKeyPath(), JSONUtil.toJsonStr(unifiedOrderModel));
|
|
|
System.out.println("统一下单响应:" + response);
|
|
|
boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath());
|
|
|
- System.out.println("verifySignature:" + verifySignature);
|
|
|
if (response.getStatus() == 200 && verifySignature) {
|
|
|
String body = response.getBody();
|
|
|
JSONObject jsonObject = JSONObject.parseObject(body);
|
|
@@ -212,7 +156,6 @@ public class WxPayController extends BaseController {
|
|
|
}
|
|
|
return AjaxResult.error("支付异常,请联系平台");
|
|
|
} catch (Exception e) {
|
|
|
- e.printStackTrace();
|
|
|
throw new ServiceException(e.getMessage());
|
|
|
}
|
|
|
}
|
|
@@ -227,12 +170,6 @@ public class WxPayController extends BaseController {
|
|
|
String serialNo = request.getHeader("Wechatpay-Serial");
|
|
|
String signature = request.getHeader("Wechatpay-Signature");
|
|
|
String result = HttpKit.readData(request);
|
|
|
- System.out.println("timestamp:" + timestamp);
|
|
|
- System.out.println("nonce:" + nonce);
|
|
|
- System.out.println("serialNo:" + serialNo);
|
|
|
- System.out.println("serialNo2:" + getSerialNumber());
|
|
|
- System.out.println("signature:" + signature);
|
|
|
- //serialNo=getSerialNumber();
|
|
|
// 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
|
|
|
JSONObject res = JSONObject.parseObject(WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, wxPayV3Bean.getApiKey3(), wxPayV3Bean.getPlatformCertPath()));
|
|
|
System.out.println("支付通知明文:" + res.toJSONString());
|
|
@@ -251,6 +188,51 @@ public class WxPayController extends BaseController {
|
|
|
response.setStatus(500);
|
|
|
map.put("code", "ERROR");
|
|
|
map.put("message", "支付失败");
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ response.setStatus(500);
|
|
|
+ map.put("code", "ERROR");
|
|
|
+ map.put("message", "签名错误");
|
|
|
+ }
|
|
|
+ response.setHeader("Content-type", ContentType.JSON.toString());
|
|
|
+ response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
|
|
|
+ response.flushBuffer();
|
|
|
+ } catch (Exception e) {
|
|
|
+ throw new ServiceException(e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ @PostMapping(value = "/companyNotify")
|
|
|
+ public void companyNotify(HttpServletRequest request, HttpServletResponse response) {
|
|
|
+ Map<String, String> map = new HashMap<>(12);
|
|
|
+ try {
|
|
|
+ String timestamp = request.getHeader("Wechatpay-Timestamp");
|
|
|
+ String nonce = request.getHeader("Wechatpay-Nonce");
|
|
|
+ String serialNo = request.getHeader("Wechatpay-Serial");
|
|
|
+ String signature = request.getHeader("Wechatpay-Signature");
|
|
|
+ String result = HttpKit.readData(request);
|
|
|
+ // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号
|
|
|
+ JSONObject res = JSONObject.parseObject(WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, wxPayV3Bean.getApiKey3(), wxPayV3Bean.getPlatformCertPath()));
|
|
|
+ System.out.println("支付通知明文:" + res.toJSONString());
|
|
|
+ if (res != null && res.getString("trade_state").equals("SUCCESS")) {
|
|
|
+ //业务处理,更新订单信息
|
|
|
+ Recharge recharge = rechargeService.selectByNums(res.getString("out_trade_no"));
|
|
|
+ if (recharge != null && recharge.getState() == 0) {
|
|
|
+ recharge.setState(1);
|
|
|
+ Company company = companyService.getById(recharge.getCompanyId());
|
|
|
+ company.setMoney(company.getMoney().add(recharge.getMoney()));
|
|
|
+ if (rechargeService.updateById(recharge) && companyService.updateById(company)) {
|
|
|
+ response.setStatus(200);
|
|
|
+ map.put("code", "SUCCESS");
|
|
|
+ map.put("message", "SUCCESS");
|
|
|
+ } else {
|
|
|
+ response.setStatus(500);
|
|
|
+ map.put("code", "ERROR");
|
|
|
+ map.put("message", "支付失败");
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
@@ -262,9 +244,7 @@ public class WxPayController extends BaseController {
|
|
|
response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
|
|
|
response.flushBuffer();
|
|
|
} catch (Exception e) {
|
|
|
- e.printStackTrace();
|
|
|
- System.out.println("msg:" + e.getMessage());
|
|
|
- throw new ServiceException("系统异常");
|
|
|
+ throw new ServiceException(e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
|