|
@@ -2,11 +2,13 @@ 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;
|
|
@@ -14,15 +16,23 @@ 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.web.work.api.config.BaseController;
|
|
|
+import com.ruoyi.web.work.domain.Pay;
|
|
|
+import com.ruoyi.web.work.domain.User;
|
|
|
import com.ruoyi.web.work.domain.dto.PayDto;
|
|
|
+import com.ruoyi.web.work.service.ICompanyService;
|
|
|
+import com.ruoyi.web.work.service.IPayService;
|
|
|
+import com.ruoyi.web.work.service.IUserService;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.validation.annotation.Validated;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
@@ -30,10 +40,14 @@ import org.springframework.web.bind.annotation.*;
|
|
|
import javax.annotation.Resource;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
-import java.beans.Transient;
|
|
|
+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
|
|
@@ -42,9 +56,16 @@ public class WxPayController extends BaseController {
|
|
|
@Resource
|
|
|
WxPayBean wxPayV3Bean;
|
|
|
|
|
|
+ private String serialNo;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ private IUserService userService;
|
|
|
|
|
|
- private String serialNo;
|
|
|
+ @Autowired
|
|
|
+ private ICompanyService companyService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IPayService payService;
|
|
|
|
|
|
/**
|
|
|
* PC扫码支付
|
|
@@ -52,15 +73,11 @@ public class WxPayController extends BaseController {
|
|
|
* @param dto
|
|
|
* @return
|
|
|
*/
|
|
|
- @Log(title = "在线捐赠", businessType = BusinessType.PAY)
|
|
|
+ @Log(title = "在线扫码支付", businessType = BusinessType.PAY)
|
|
|
@PostMapping("/pay")
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public AjaxResult pay(@Validated @RequestBody PayDto dto) {
|
|
|
try {
|
|
|
- /* Project project = projectService.getById(dto.getProjectId());
|
|
|
- if (project == null) {
|
|
|
- return AjaxResult.error("捐赠项目不存在");
|
|
|
- }*/
|
|
|
String orderNum = PayKit.generateStr();
|
|
|
UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel();
|
|
|
unifiedOrderModel.setAppid(wxPayV3Bean.getAppId());
|
|
@@ -87,59 +104,122 @@ public class WxPayController extends BaseController {
|
|
|
throw new ServiceException("系统异常");
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ @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();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ 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
|
|
|
*/
|
|
|
@PostMapping("/jsApiPay")
|
|
|
- @Transient
|
|
|
- public AjaxResult jsApiPay() {
|
|
|
+ public AjaxResult jsApiPay(@Validated @RequestBody PayDto dto) {
|
|
|
try {
|
|
|
-/* if (StringUtils.isEmpty(dto.getOpenId())) {
|
|
|
- return AjaxResult.error("openId不能为空");
|
|
|
- }
|
|
|
- Project project = projectService.getById(dto.getProjectId());
|
|
|
- if (project == null) {
|
|
|
- return AjaxResult.error("捐赠项目不存在");
|
|
|
- }*/
|
|
|
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.setAmount(new Amount().setTotal(1));
|
|
|
+ unifiedOrderModel.setAttach("账户充值");
|
|
|
+ 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);
|
|
|
- if (response.getStatus() == 200) {
|
|
|
+ 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);
|
|
|
Map<String, String> map = WxPayKit.jsApiCreateSign(wxPayV3Bean.getAppId(), jsonObject.getString("prepay_id"), wxPayV3Bean.getKeyPath());
|
|
|
- //保存支付订单
|
|
|
- /* Donate donate = new Donate();
|
|
|
- BeanUtils.copyProperties(dto, donate);
|
|
|
- donate.setState(0);
|
|
|
- donate.setOrderNum(orderNum);
|
|
|
- donateService.save(donate);*/
|
|
|
+ //保存支付订单记录
|
|
|
+ Pay pay = new Pay();
|
|
|
+ pay.setUserId(getUser().getId());
|
|
|
+ pay.setMoney(dto.getMoney());
|
|
|
+ pay.setState(0);
|
|
|
+ pay.setVersion(System.currentTimeMillis());
|
|
|
+ pay.setNums(orderNum);
|
|
|
+ if (!payService.save(pay)) {
|
|
|
+ return AjaxResult.error("充值失败,请联系平台");
|
|
|
+ }
|
|
|
return AjaxResult.success(map);
|
|
|
}
|
|
|
- return AjaxResult.error("系统异常222");
|
|
|
+ return AjaxResult.error("支付异常,请联系平台");
|
|
|
} catch (Exception e) {
|
|
|
- System.out.println("asd:"+e.getMessage());
|
|
|
e.printStackTrace();
|
|
|
- throw new ServiceException("系统异常");
|
|
|
+ throw new ServiceException(e.getMessage());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- @Log(title = "在线捐赠通知", businessType = BusinessType.PAY)
|
|
|
+ @Transactional
|
|
|
@PostMapping(value = "/payNotify")
|
|
|
- public void payNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
|
|
|
+ public void payNotify(HttpServletRequest request, HttpServletResponse response) {
|
|
|
Map<String, String> map = new HashMap<>(12);
|
|
|
try {
|
|
|
String timestamp = request.getHeader("Wechatpay-Timestamp");
|
|
@@ -147,19 +227,32 @@ 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());
|
|
|
if (res != null && res.getString("trade_state").equals("SUCCESS")) {
|
|
|
-/* Donate donate = donateService.selectByOrderNum(res.getString("out_trade_no"));
|
|
|
- if (donate != null) {
|
|
|
- donate.setState(1);
|
|
|
- donateService.clearCache();
|
|
|
- donateService.updateById(donate);
|
|
|
- response.setStatus(200);
|
|
|
- map.put("code", "SUCCESS");
|
|
|
- map.put("message", "SUCCESS");
|
|
|
- }*/
|
|
|
+ //业务处理,更新订单信息
|
|
|
+ Pay pay = payService.selectByNums(res.getString("out_trade_no"));
|
|
|
+ if (pay != null && pay.getState() == 0) {
|
|
|
+ pay.setState(1);
|
|
|
+ User user = userService.getById(pay.getUserId());
|
|
|
+ user.setMoney(user.getMoney().add(pay.getMoney()));
|
|
|
+ if (payService.updateById(pay) && userService.updateById(user)) {
|
|
|
+ response.setStatus(200);
|
|
|
+ map.put("code", "SUCCESS");
|
|
|
+ map.put("message", "SUCCESS");
|
|
|
+ } else {
|
|
|
+ response.setStatus(500);
|
|
|
+ map.put("code", "ERROR");
|
|
|
+ map.put("message", "支付失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
} else {
|
|
|
response.setStatus(500);
|
|
|
map.put("code", "ERROR");
|
|
@@ -169,6 +262,8 @@ 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("系统异常");
|
|
|
}
|
|
|
}
|