支付模块-下单接口修改以及支付结果回溯接口修改
This commit is contained in:
parent
4760dba312
commit
efd0fa1e44
@ -1,6 +1,6 @@
|
|||||||
package com.fastbee.common.utils.pay;
|
package com.fastbee.common.utils.pay;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.io.IOException;
|
||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.InvalidAlgorithmParameterException;
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
@ -10,37 +10,26 @@ import javax.crypto.Cipher;
|
|||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.spec.GCMParameterSpec;
|
import javax.crypto.spec.GCMParameterSpec;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author xy-peng
|
|
||||||
*/
|
|
||||||
public class AesUtil {
|
public class AesUtil {
|
||||||
|
static final int KEY_LENGTH_BYTE = 32;
|
||||||
private static final String TRANSFORMATION = "AES/GCM/NoPadding";
|
static final int TAG_LENGTH_BIT = 128;
|
||||||
|
|
||||||
private static final int KEY_LENGTH_BYTE = 32;
|
|
||||||
private static final int TAG_LENGTH_BIT = 128;
|
|
||||||
|
|
||||||
private final byte[] aesKey;
|
private final byte[] aesKey;
|
||||||
|
|
||||||
public AesUtil(byte[] key) {
|
public AesUtil(byte[] key) {
|
||||||
if (key.length != KEY_LENGTH_BYTE) {
|
if (key.length != KEY_LENGTH_BYTE) {
|
||||||
throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
|
throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
|
||||||
}
|
}
|
||||||
this.aesKey = key;
|
this.aesKey = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
|
public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
|
||||||
throws GeneralSecurityException {
|
throws GeneralSecurityException, IOException {
|
||||||
try {
|
try {
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||||
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
|
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
|
||||||
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
|
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
|
||||||
|
|
||||||
Cipher cipher = Cipher.getInstance(TRANSFORMATION);
|
|
||||||
cipher.init(Cipher.DECRYPT_MODE, key, spec);
|
cipher.init(Cipher.DECRYPT_MODE, key, spec);
|
||||||
cipher.updateAAD(associatedData);
|
cipher.updateAAD(associatedData);
|
||||||
return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), StandardCharsets.UTF_8);
|
String result=new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
|
||||||
|
return result;
|
||||||
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.fastbee.common.utils.pay;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class RSAUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验签方法
|
||||||
|
* @param wechatpaySignature Wechatpay-Signature 响应头中的签名
|
||||||
|
* @param wechatpayTimestamp Wechatpay-Timestamp 响应头中的时间戳
|
||||||
|
* @param wechatpayNonce Wechatpay-Nonce 响应头中的随机串
|
||||||
|
* @param responseBody 应答报文主体
|
||||||
|
* @param publicKey 微信支付公钥(PEM 格式,去掉头尾并解码为二进制)
|
||||||
|
* @return 是否验签成功
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static boolean verifySignature(String wechatpaySignature,
|
||||||
|
String wechatpayTimestamp,
|
||||||
|
String wechatpayNonce,
|
||||||
|
String responseBody,
|
||||||
|
String publicKey) throws Exception {
|
||||||
|
// 构造验签名串:应答时间戳\n应答随机串\n应答报文主体\n
|
||||||
|
String message = wechatpayTimestamp + "\n" +
|
||||||
|
wechatpayNonce + "\n" +
|
||||||
|
responseBody + "\n";
|
||||||
|
|
||||||
|
// 解码微信支付公钥(Base64 格式)
|
||||||
|
byte[] publicKeyBytes = Base64.getDecoder().decode(publicKey);
|
||||||
|
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||||
|
PublicKey rsaPublicKey = keyFactory.generatePublic(keySpec);
|
||||||
|
|
||||||
|
// 初始化 Signature 对象,指定算法为 SHA256withRSA
|
||||||
|
Signature signature = Signature.getInstance("SHA256withRSA");
|
||||||
|
signature.initVerify(rsaPublicKey);
|
||||||
|
|
||||||
|
// 更新验签名串
|
||||||
|
signature.update(message.getBytes(StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
// 验证签名
|
||||||
|
byte[] signatureBytes = Base64.getDecoder().decode(wechatpaySignature);
|
||||||
|
return signature.verify(signatureBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
-----BEGIN PUBLIC KEY-----
|
||||||
|
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4zej1cqugGQtVSY2Ah8RMCKcr2UpZ8Npo+5Ja9xpFPYkWHaF1Gjrn3d5kcwAFuHHcfdc3yxDYx6+9grvJnCA2zQzWjzVRa3BJ5LTMj6yqvhEmtvjO9D1xbFTA2m3kyjxlaIar/RYHZSslT4VmjIatW9KJCDKkwpM6x/RIWL8wwfFwgz2q3Zcrff1y72nB8p8P12ndH7GSLoY6d2Tv0OB2+We2Kyy2+QzfGXOmLp7UK/pFQjJjzhSf9jxaWJXYKIBxpGlddbRZj9PqvFPTiep8rvfKGNZF9Q6QaMYTpTp/uKQ3YvpDlyeQlYe4rRFauH3mOE6j56QlYQWivknDX9VrwIDAQAB
|
||||||
|
-----END PUBLIC KEY-----
|
@ -3,12 +3,28 @@ package com.fastbee.common.utils.pay;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.security.KeyFactory;
|
import java.security.KeyFactory;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
public class wxPayConfig {
|
public class wxPayConfig {
|
||||||
|
|
||||||
|
|
||||||
|
// 获取微信支付公钥
|
||||||
|
public static String getPublicKey(String publicKeyPath) {
|
||||||
|
try {
|
||||||
|
// 读取私钥文件内容
|
||||||
|
String publicKeyContent = readFile(publicKeyPath);
|
||||||
|
// 去除私钥文件中的头尾信息
|
||||||
|
publicKeyContent = publicKeyContent.replace("-----BEGIN PUBLIC KEY-----", "")
|
||||||
|
.replace("-----END PUBLIC KEY-----", "")
|
||||||
|
.replaceAll("\\s+", "");
|
||||||
|
return publicKeyContent;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 获取商户私钥
|
// 获取商户私钥
|
||||||
public static PrivateKey getPrivateKey(String privateKeyPath) {
|
public static PrivateKey getPrivateKey(String privateKeyPath) {
|
||||||
|
@ -135,6 +135,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
.antMatchers("/system/district/tree").permitAll()
|
.antMatchers("/system/district/tree").permitAll()
|
||||||
.antMatchers("/sse/**").permitAll()
|
.antMatchers("/sse/**").permitAll()
|
||||||
.antMatchers("/common/upload").permitAll()
|
.antMatchers("/common/upload").permitAll()
|
||||||
|
.antMatchers("/pay/getresult").permitAll()
|
||||||
// 除上面外的所有请求全部需要鉴权认证
|
// 除上面外的所有请求全部需要鉴权认证
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
|
|
||||||
|
@ -5,69 +5,53 @@ import cn.hutool.json.JSONException;
|
|||||||
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONObject;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import cn.hutool.json.ObjectMapper;
|
import cn.hutool.json.ObjectMapper;
|
||||||
|
import com.dtflys.forest.annotation.Success;
|
||||||
import com.fastbee.common.core.controller.BaseController;
|
import com.fastbee.common.core.controller.BaseController;
|
||||||
import com.fastbee.common.core.domain.AjaxResult;
|
import com.fastbee.common.core.domain.AjaxResult;
|
||||||
import com.fastbee.common.utils.pay.AesUtil;
|
import com.fastbee.common.utils.pay.AesUtil;
|
||||||
import com.fastbee.common.wechat.WeChatLoginBody;
|
import com.fastbee.common.utils.pay.RSAUtil;
|
||||||
import com.fastbee.rechargecard.domain.NgUserRechargeRecords;
|
|
||||||
import com.fastbee.rechargecard.domain.dto.RechargecardUser;
|
|
||||||
import com.fastbee.rechargecard.domain.dto.WeChatRecharge;
|
import com.fastbee.rechargecard.domain.dto.WeChatRecharge;
|
||||||
import com.fastbee.rechargecard.domain.dto.WeChatRechargeBacktracking;
|
import com.fastbee.rechargecard.domain.dto.WeChatRechargeBacktracking;
|
||||||
import com.fastbee.rechargecard.service.INgUserRechargeRecordsService;
|
import com.fastbee.rechargecard.service.INgUserRechargeRecordsService;
|
||||||
import com.fastbee.rechargecard.service.IUserConsumptionDetailsService;
|
import com.fastbee.rechargecard.service.IUserConsumptionDetailsService;
|
||||||
import com.fastbee.rechargecard.service.IUserRechargeCardsService;
|
import com.fastbee.rechargecard.service.IUserRechargeCardsService;
|
||||||
|
import com.fastbee.rechargecard.service.IUserWechatPayService;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.client.utils.URIBuilder;
|
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.Signature;
|
import java.security.Signature;
|
||||||
import java.util.Base64;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import com.fastbee.common.utils.pay.wxPayConfig;
|
import com.fastbee.common.utils.pay.wxPayConfig;
|
||||||
|
|
||||||
import static cn.hutool.core.util.XmlUtil.xmlToMap;
|
import static cn.hutool.core.util.XmlUtil.xmlToMap;
|
||||||
import static com.fastbee.common.constant.Constants.LANGUAGE;
|
import static com.fastbee.common.constant.Constants.LANGUAGE;
|
||||||
|
import static com.fastbee.common.utils.pay.RSAUtil.verifySignature;
|
||||||
|
import static com.fastbee.rechargecard.service.impl.UserWechatPayServiceImpl.apiV3Key;
|
||||||
|
|
||||||
@Api(tags = "支付模块")
|
@Api(tags = "支付模块")
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/pay")
|
@RequestMapping("/pay")
|
||||||
public class WeChatPayController extends BaseController {
|
public class WeChatPayController extends BaseController {
|
||||||
/** 商户号 */
|
|
||||||
public static String mchId = "1531795301";
|
|
||||||
/** 商户API私钥文件路径 */
|
|
||||||
public static String privateKeyPath = "fastbee-common/src/main/java/com/fastbee/common/utils/pay/apiclient_key.pem";
|
|
||||||
/** 商户API证书序列号 */
|
|
||||||
public static String serial_no = "3075B63EF52666EDC3EAFC5D4FB35C02CE123A9C";
|
|
||||||
/** 商户APIV3密钥 */
|
|
||||||
public static String apiV3Key = "e85a203e8ca146102f5cd7ecff912580";
|
|
||||||
//微信小程序appid
|
|
||||||
public static String appId="wx308612d2a8423311";
|
|
||||||
//请求随机串
|
|
||||||
public static String nonce_str="";
|
|
||||||
//时间戳
|
|
||||||
public static String timeStamp="";
|
|
||||||
// 使用HttpClientBuilder创建CloseableHttpClient实例,采用默认配置
|
|
||||||
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private INgUserRechargeRecordsService ngUserRechargeRecordsService;
|
private INgUserRechargeRecordsService ngUserRechargeRecordsService;
|
||||||
@ -75,6 +59,8 @@ public class WeChatPayController extends BaseController {
|
|||||||
private IUserRechargeCardsService userRechargeCardsService;
|
private IUserRechargeCardsService userRechargeCardsService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private IUserConsumptionDetailsService userConsumptionDetailsService;
|
private IUserConsumptionDetailsService userConsumptionDetailsService;
|
||||||
|
@Autowired
|
||||||
|
private IUserWechatPayService userWechatPayService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信支付生成订单
|
* 微信支付生成订单
|
||||||
@ -83,164 +69,150 @@ public class WeChatPayController extends BaseController {
|
|||||||
@ApiOperation("生成订单")
|
@ApiOperation("生成订单")
|
||||||
@PostMapping("/order")
|
@PostMapping("/order")
|
||||||
public AjaxResult BuildOrder(@RequestBody WeChatRecharge recharge) throws Exception {
|
public AjaxResult BuildOrder(@RequestBody WeChatRecharge recharge) throws Exception {
|
||||||
|
System.out.println("生成订单");
|
||||||
String out_trade_no=UUID.randomUUID().toString().replace("-", "");
|
String out_trade_no=UUID.randomUUID().toString().replace("-", "");
|
||||||
while(ngUserRechargeRecordsService.SelectRechargeRecodeByRechargeCode(out_trade_no) !=null)
|
while(ngUserRechargeRecordsService.SelectRechargeRecodeByRechargeCode(out_trade_no) !=null)
|
||||||
{
|
{
|
||||||
out_trade_no=UUID.randomUUID().toString().replace("-", "");;
|
out_trade_no=UUID.randomUUID().toString().replace("-", "");;
|
||||||
}
|
}
|
||||||
|
//System.out.println(out_trade_no);
|
||||||
recharge.setRechargeCode(out_trade_no);
|
recharge.setRechargeCode(out_trade_no);
|
||||||
Map<String,String> result=CreateOrder(recharge);//生成订单
|
Map<String, String> result = userWechatPayService.CreateOrder(recharge); // 生成订单
|
||||||
|
|
||||||
|
//打印出返回前端的所有参数
|
||||||
|
// 获取键的集合
|
||||||
|
Set<String> keySet = result.keySet();
|
||||||
|
// 遍历键集合
|
||||||
|
for (String key : keySet) {
|
||||||
|
System.out.println(key + ": " + result.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
if(result.isEmpty())
|
if(result.isEmpty())
|
||||||
{
|
{
|
||||||
return toAjax("微信支付订单生成失败");
|
System.out.println("微信支付订单生成失败");
|
||||||
|
return error("微信支付订单生成失败");
|
||||||
}
|
}
|
||||||
|
System.out.println("微信支付订单生成成功");
|
||||||
|
|
||||||
//订单生成成功
|
//订单生成成功
|
||||||
int flag=ngUserRechargeRecordsService.insertNgUserRechargeRecordsWeChat(recharge);//插入用户充值记录表
|
int flag=ngUserRechargeRecordsService.insertNgUserRechargeRecordsWeChat(recharge);//插入用户充值记录表
|
||||||
flag=userConsumptionDetailsService.insertUserConsumptionDetailsWechat(recharge);//插入用户消费明细表
|
//flag=userConsumptionDetailsService.insertUserConsumptionDetailsWechat(recharge);//插入用户消费明细表
|
||||||
if(flag==1)
|
if(flag==1)
|
||||||
{
|
{
|
||||||
return success(result);
|
return success(result);
|
||||||
}
|
}
|
||||||
return toAjax("系统内部订单生成失败");
|
return error("系统内部订单生成失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/getresult")
|
@PostMapping("/getresult")
|
||||||
@ApiOperation("支付通知结果回溯")
|
@ApiOperation("支付通知结果回溯")
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
public String getResult(@RequestBody WeChatRechargeBacktracking backtracking) throws Exception {
|
public ResponseEntity<?> getResult(@RequestBody JSONObject jsonObject, HttpServletRequest request) throws Exception {//WeChatRechargeBacktracking backtracking
|
||||||
String algorithm=backtracking.getResource().getAlgorithm();
|
// 从HTTP请求头中获取微信签名和时间戳等值
|
||||||
String nonce=backtracking.getResource().getNonce();
|
System.out.println("微信回调开始---------");
|
||||||
String associated_data=backtracking.getResource().getAssociated_data();
|
String wechatpaySignature = request.getHeader("Wechatpay-Signature");//验签的签名值
|
||||||
String cliphertext=backtracking.getResource().getCliphertext();
|
String wechatpaySerial = request.getHeader("Wechatpay-Serial");//序列号
|
||||||
AesUtil aesUtil=new AesUtil(apiV3Key.getBytes("utf-8"));
|
String wechatpayTimestamp = request.getHeader("Wechatpay-Timestamp");//时间戳
|
||||||
//解密后的值
|
String wechatpayNonce = request.getHeader("Wechatpay-Nonce");//随机字符串
|
||||||
String decryptKey=aesUtil.decryptToString(associated_data.getBytes("utf-8"),nonce.getBytes("utf-8"),cliphertext);
|
String json=jsonObject.toString();
|
||||||
System.out.println("解密后的:"+decryptKey);
|
System.out.println("微信回调报文:{"+json+"}");
|
||||||
|
// 构建应答报文
|
||||||
|
Map<String, String> responseBody = new HashMap<>();
|
||||||
|
//解密jsonObject对象
|
||||||
|
String associated_data= (String) JSONUtil.getByPath(JSONUtil.parse(json),"resource.associated_data");//加密数据
|
||||||
|
String ciphertext=(String) JSONUtil.getByPath(JSONUtil.parse(json),"resource.ciphertext");//数据密文
|
||||||
|
System.out.println("ciphertext:"+ciphertext);
|
||||||
|
String nonce = (String) JSONUtil.getByPath(JSONUtil.parse(json), "resource.nonce");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验签字符串
|
||||||
|
* 应答时间戳\n
|
||||||
|
* 应答随机串\n
|
||||||
|
* 应答报文主体\n
|
||||||
|
*/
|
||||||
|
//String signStr=wechatpayTimestamp+"\n"+wechatpayNonce+"\n"+json+"\n";//验签字符串
|
||||||
|
// 使用微信支付公钥验签
|
||||||
|
/**
|
||||||
|
* 验签方法
|
||||||
|
* wechatpaySignature Wechatpay-Signature 响应头中的签名
|
||||||
|
* wechatpayTimestamp Wechatpay-Timestamp 响应头中的时间戳
|
||||||
|
* wechatpayNonce Wechatpay-Nonce 响应头中的随机串
|
||||||
|
* responseBody 应答报文主体
|
||||||
|
* publicKey 微信支付公钥(PEM 格式,去掉头尾并解码为二进制)
|
||||||
|
*/
|
||||||
|
/*String publicKey=wxPayConfig.getPublicKey(publicKeyPath);//读取并预处理后的微信支付公钥
|
||||||
|
boolean isVerified = verifySignature(wechatpaySignature, wechatpayTimestamp, wechatpayNonce, json, publicKey);
|
||||||
|
if (isVerified) {
|
||||||
|
System.out.println("签名验证成功");
|
||||||
|
} else {
|
||||||
|
System.out.println("签名验证失败");
|
||||||
|
return error("签名验证失败");
|
||||||
|
}*/
|
||||||
|
//使用apiv3key解密
|
||||||
|
String decryptData="";
|
||||||
|
try{
|
||||||
|
decryptData= new AesUtil(apiV3Key.getBytes(StandardCharsets.UTF_8)).decryptToString
|
||||||
|
(associated_data.getBytes(StandardCharsets.UTF_8),
|
||||||
|
nonce.getBytes(StandardCharsets.UTF_8),
|
||||||
|
ciphertext);
|
||||||
|
}catch (Exception e)
|
||||||
|
{
|
||||||
|
System.out.println("解密失败");
|
||||||
|
responseBody.put("code", "FAIL");
|
||||||
|
responseBody.put("message", "解密失败");
|
||||||
|
|
||||||
return decryptKey;
|
// 返回500状态码以及符合要求的应答报文
|
||||||
}
|
return new ResponseEntity<>(responseBody, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
//return error("解密失败");
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建订单,获取prepay_id和paySign
|
|
||||||
* @param recharge
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
public Map<String, String> CreateOrder(WeChatRecharge recharge) throws Exception{
|
|
||||||
System.out.println("CreateOrder");
|
|
||||||
//请求URL
|
|
||||||
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
|
|
||||||
Map<String,String> result=new HashMap<>();
|
|
||||||
|
|
||||||
Map<String,Object> reqdata=new HashMap<String,Object>();
|
|
||||||
Map<String,Object> amount=new HashMap<>();
|
|
||||||
Map<String,Object> payer=new HashMap<>();
|
|
||||||
amount.put("total",recharge.getTotal());
|
|
||||||
amount.put("currency",recharge.getCurrency());
|
|
||||||
payer.put("openid",recharge.getOpenId());
|
|
||||||
|
|
||||||
reqdata.put("amount",amount);
|
|
||||||
reqdata.put("appid",appId);
|
|
||||||
reqdata.put("mchid",mchId);
|
|
||||||
reqdata.put("description",recharge.getCardnumber()+recharge.getAmount().toString());
|
|
||||||
reqdata.put("out_trade_no",recharge.getRechargeCode());
|
|
||||||
reqdata.put("notify_url","https://1481109f.r3.cpolar.cn/pay/getresult");
|
|
||||||
reqdata.put("payer",payer);
|
|
||||||
String Signature=getSign(reqdata);
|
|
||||||
result.put("paySign",Signature);
|
|
||||||
String Authorization="WECHATPAY2-SHA256-RSA2048 mchid=\""+mchId+"\",nonce_str=\""+nonce_str+"\",signature=\""+Signature+"\",timestamp=\""+timeStamp+"\",serial_no=\""+serial_no+"\"";
|
|
||||||
|
|
||||||
StringEntity entity = new StringEntity(JSONUtil.toJsonStr(reqdata), "utf-8");
|
|
||||||
entity.setContentType("application/json");
|
|
||||||
httpPost.setEntity(entity);
|
|
||||||
httpPost.setHeader("Accept", "application/json");
|
|
||||||
httpPost.setHeader("Authorization",Authorization);
|
|
||||||
|
|
||||||
|
|
||||||
//完成签名并执行请求
|
|
||||||
CloseableHttpResponse response = httpClient.execute(httpPost);
|
|
||||||
try {
|
|
||||||
int statusCode = response.getStatusLine().getStatusCode();
|
|
||||||
if (statusCode == 200) {
|
|
||||||
// 假设responseEntity是包含JSON响应的字符串
|
|
||||||
String responseEntity = EntityUtils.toString(response.getEntity());
|
|
||||||
|
|
||||||
// 使用Hutool的JSONUtil解析JSON字符串
|
|
||||||
JSONObject jsonObject = JSONUtil.parseObj(responseEntity);
|
|
||||||
|
|
||||||
// 安全地获取prepay_id的值
|
|
||||||
String prepayId = jsonObject.getStr("prepay_id");
|
|
||||||
|
|
||||||
System.out.println("Prepay ID: " + prepayId);
|
|
||||||
result.put("prepay_id",prepayId);
|
|
||||||
System.out.println("success,return body = " + prepayId);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
} else if (statusCode == 204) {
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
|
|
||||||
throw new IOException("request failed");
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
response.close();
|
|
||||||
httpClient.close();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 生成签名
|
|
||||||
*/
|
|
||||||
public String getSign(Map<String,Object> reqBody) throws Exception {
|
|
||||||
//获取时间戳
|
|
||||||
|
|
||||||
String reqMethod="POST";
|
System.out.println("解密后的:"+decryptData);
|
||||||
String url="/v3/pay/transactions/jsapi";
|
if(decryptData==null)
|
||||||
/*String reqMethod="GET";
|
{
|
||||||
String url="/v3/refund/domestic/refunds/123123123123";*/
|
System.out.println("解密后值为空");
|
||||||
timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
|
responseBody.put("code", "FAIL");
|
||||||
//timeStamp="1554208460";
|
responseBody.put("message", "解密后值为空");
|
||||||
nonce_str= UUID.randomUUID().toString();
|
|
||||||
//nonce_str="593BEC0C930BF1AFEB40B4A08C8FB242";
|
|
||||||
String reqParam= JSONUtil.toJsonStr(reqBody);
|
|
||||||
|
|
||||||
/*HTTP请求方法\n
|
// 返回500状态码以及符合要求的应答报文
|
||||||
URL\n
|
return new ResponseEntity<>(responseBody, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
请求时间戳\n
|
//return error("解密后值为空");
|
||||||
请求随机串\n
|
}
|
||||||
请求报文主体\n
|
// 使用Hutool的JSONUtil解析JSON字符串
|
||||||
*/
|
JSONObject decryptJsonObject = JSONUtil.parseObj(decryptData);
|
||||||
String signStr=reqMethod+"\n"+url+"\n"+timeStamp+"\n"+nonce_str+"\n"+reqParam +"\n";
|
|
||||||
//String signStr=reqMethod+"\n"+url+"\n"+timeStamp+"\n"+nonce_str+"\n\n";
|
|
||||||
String sign=sign(signStr.getBytes("utf-8"));
|
|
||||||
|
|
||||||
/*//进行sha256
|
String result = decryptJsonObject.getStr("trade_state_desc");
|
||||||
String sha256HexSignStr = DigestUtil.sha256Hex(signStr);
|
String trade_state=decryptJsonObject.getStr("trade_state");
|
||||||
//在进行base64
|
if(result.isEmpty() || ! result.equals("支付成功") || !trade_state.equals("SUCCESS") )
|
||||||
String base64SignStr = Base64.getEncoder().encodeToString(sha256HexSignStr.getBytes());
|
{
|
||||||
*/
|
System.out.println("支付失败");
|
||||||
return sign;
|
responseBody.put("code", "FAIL");
|
||||||
|
responseBody.put("message", "支付失败");
|
||||||
|
|
||||||
|
// 返回500状态码以及符合要求的应答报文
|
||||||
|
return new ResponseEntity<>(responseBody, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
//return error("支付失败");
|
||||||
|
}
|
||||||
|
//支付成功后
|
||||||
|
JSONObject amount=decryptJsonObject.getJSONObject("amount");
|
||||||
|
BigDecimal payer_total=amount.getBigDecimal("payer_total");//支付金额
|
||||||
|
String rechargeCode=decryptJsonObject.getStr("out_trade_no");//订单号
|
||||||
|
int flag=userRechargeCardsService.updateUserRechargeWechat(rechargeCode,payer_total);
|
||||||
|
if(flag==1)
|
||||||
|
{
|
||||||
|
System.out.println("支付成功");
|
||||||
|
//return success("支付成功");
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
System.out.println("修改数据库失败");
|
||||||
|
responseBody.put("code", "FAIL");
|
||||||
|
responseBody.put("message", "修改数据库失败");
|
||||||
|
|
||||||
|
// 返回500状态码以及符合要求的应答报文
|
||||||
|
return new ResponseEntity<>(responseBody, HttpStatus.INTERNAL_SERVER_ERROR);
|
||||||
|
//return error("修改数据库失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成签名方法
|
|
||||||
* @param message
|
|
||||||
* @return
|
|
||||||
* @throws Exception
|
|
||||||
*/
|
|
||||||
private String sign(byte[] message) throws Exception{
|
|
||||||
Signature sign;
|
|
||||||
sign = Signature.getInstance("SHA256withRSA");
|
|
||||||
//这里需要一个PrivateKey类型的参数,就是商户的私钥。
|
|
||||||
//获取商户私钥——传商户私钥位置
|
|
||||||
PrivateKey privateKey = wxPayConfig.getPrivateKey(privateKeyPath);
|
|
||||||
sign.initSign(privateKey);
|
|
||||||
sign.update(message);
|
|
||||||
return Base64.getEncoder().encodeToString(sign.sign());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,10 @@ import lombok.Data;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class WeChatRechargeBacktracking {
|
public class WeChatRechargeBacktracking {
|
||||||
private String id;
|
private String id;//回调通知唯一编号
|
||||||
private String create_time;
|
private String create_time;//通知创建时间
|
||||||
private String resource_type;
|
private String resource_type;//资源数据类型
|
||||||
private String event_type;
|
private String event_type;//回调通知类型:TRANSACTION.SUCCESS
|
||||||
private String summary;
|
private String summary;//备注
|
||||||
private WeChatRechargeBacktrackingResource resource;
|
private WeChatRechargeBacktrackingResource resource;//通知资源数据
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,10 @@ import lombok.Data;
|
|||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class WeChatRechargeBacktrackingResource{
|
public class WeChatRechargeBacktrackingResource{
|
||||||
private String original_type;
|
private String original_type;//加密前的对象类型,transaction
|
||||||
private String algorithm;
|
private String algorithm;//加密算法类型
|
||||||
private String cliphertext;
|
private String ciphertext;//回调数据密文ciphertext
|
||||||
private String associated_data;
|
private String associated_data;//附加数据
|
||||||
private String nonce;
|
private String nonce;//随机串
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ public interface NgUserRechargeRecordsMapper
|
|||||||
* @param rechargeCode
|
* @param rechargeCode
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
|
@Select("select * from ng_user_recharge_records where recharge_code=#{rechargeCode}")
|
||||||
public NgUserRechargeRecords selectNgUserRechargeRecordsByRechargeCode(String rechargeCode);
|
public NgUserRechargeRecords selectNgUserRechargeRecordsByRechargeCode(String rechargeCode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,6 +4,7 @@ import java.util.List;
|
|||||||
import com.fastbee.rechargecard.domain.UserRechargeCards;
|
import com.fastbee.rechargecard.domain.UserRechargeCards;
|
||||||
import com.github.yulichang.base.MPJBaseMapper;
|
import com.github.yulichang.base.MPJBaseMapper;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,6 +35,7 @@ public interface UserRechargeCardsMapper extends MPJBaseMapper<UserRechargeCards
|
|||||||
* @param cardNumber
|
* @param cardNumber
|
||||||
* @return 用户充值卡
|
* @return 用户充值卡
|
||||||
*/
|
*/
|
||||||
|
@Select("select * from user_recharge_cards where card_number=#{cardNumber}")
|
||||||
public UserRechargeCards selectUserRechargeCardsByCardNumber(String cardNumber);
|
public UserRechargeCards selectUserRechargeCardsByCardNumber(String cardNumber);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +53,7 @@ public interface IUserRechargeCardsService
|
|||||||
* @param rechargeCode
|
* @param rechargeCode
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public int updateUserRechargeWechat(String rechargeCode);
|
public int updateUserRechargeWechat(String rechargeCode,BigDecimal payer_total) throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除用户充值卡
|
* 批量删除用户充值卡
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.fastbee.rechargecard.service;
|
||||||
|
|
||||||
|
import com.fastbee.rechargecard.domain.UserRechargeCards;
|
||||||
|
import com.fastbee.rechargecard.domain.dto.WeChatRecharge;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户微信支付Service接口
|
||||||
|
*/
|
||||||
|
public interface IUserWechatPayService {
|
||||||
|
/**
|
||||||
|
* 生成订单
|
||||||
|
* @param recharge
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String,String> CreateOrder(WeChatRecharge recharge) throws Exception;
|
||||||
|
}
|
@ -32,11 +32,13 @@ public class NgUserRechargeRecordsServiceImpl implements INgUserRechargeRecordsS
|
|||||||
NgUserRechargeRecords ngUserRechargeRecords=new NgUserRechargeRecords();
|
NgUserRechargeRecords ngUserRechargeRecords=new NgUserRechargeRecords();
|
||||||
ngUserRechargeRecords.setRechargeTime(DateUtils.getNowDate());
|
ngUserRechargeRecords.setRechargeTime(DateUtils.getNowDate());
|
||||||
ngUserRechargeRecords.setBalance(rechargecardUser.getAmount());
|
ngUserRechargeRecords.setBalance(rechargecardUser.getAmount());
|
||||||
|
ngUserRechargeRecords.setAmount(rechargecardUser.getAmount());
|
||||||
ngUserRechargeRecords.setType(1);//微信
|
ngUserRechargeRecords.setType(1);//微信
|
||||||
ngUserRechargeRecords.setStatus(0);//生成订单
|
ngUserRechargeRecords.setStatus(0);//生成订单
|
||||||
ngUserRechargeRecords.setAreaCode(String.valueOf(rechargecardUser.getAreacode()));
|
ngUserRechargeRecords.setAreaCode(String.valueOf(rechargecardUser.getAreacode()));
|
||||||
ngUserRechargeRecords.setCardNumber(String.valueOf(rechargecardUser.getCardnumber()));
|
ngUserRechargeRecords.setCardNumber(String.valueOf(rechargecardUser.getCardnumber()));
|
||||||
ngUserRechargeRecords.setRechargeCode(rechargecardUser.getRechargeCode());
|
ngUserRechargeRecords.setRechargeCode(rechargecardUser.getRechargeCode());
|
||||||
|
ngUserRechargeRecords.setSerialNumber(rechargecardUser.getDeviceNumber());
|
||||||
return ngUserRechargeRecordsMapper.insertNgUserRechargeRecords(ngUserRechargeRecords);
|
return ngUserRechargeRecordsMapper.insertNgUserRechargeRecords(ngUserRechargeRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,8 +214,9 @@ public class UserConsumptionDetailsServiceImpl implements IUserConsumptionDetail
|
|||||||
userConsumptionDetails.setPaymentStatus(0);
|
userConsumptionDetails.setPaymentStatus(0);
|
||||||
userConsumptionDetails.setPaymentMethod(recharge.getType());
|
userConsumptionDetails.setPaymentMethod(recharge.getType());
|
||||||
userConsumptionDetails.setPaymentTime(DateUtils.getNowDate());
|
userConsumptionDetails.setPaymentTime(DateUtils.getNowDate());
|
||||||
userConsumptionDetails.setStatus(0);
|
userConsumptionDetails.setStatus(2);
|
||||||
userConsumptionDetails.setCreateTime(DateUtils.getNowDate());
|
userConsumptionDetails.setCreateTime(DateUtils.getNowDate());
|
||||||
|
userConsumptionDetails.setDeviceNumber(recharge.getDeviceNumber());
|
||||||
return userConsumptionDetailsMapper.insertUserConsumptionDetails(userConsumptionDetails);
|
return userConsumptionDetailsMapper.insertUserConsumptionDetails(userConsumptionDetails);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -106,48 +106,73 @@ public class UserRechargeCardsServiceImpl implements IUserRechargeCardsService
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int updateUserRechargeWechat(String rechargeCode) {
|
public int updateUserRechargeWechat(String rechargeCode,BigDecimal payer_total) throws Exception {
|
||||||
|
|
||||||
|
|
||||||
|
//用户充值记录中订单信息状态更改为已支付
|
||||||
NgUserRechargeRecords ngUserRechargeRecords=new NgUserRechargeRecords();
|
NgUserRechargeRecords ngUserRechargeRecords=new NgUserRechargeRecords();
|
||||||
|
if(rechargeCode==null)
|
||||||
|
{
|
||||||
|
throw new Exception("订单编号为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(userRechargeRecordsMapper.selectNgUserRechargeRecordsByRechargeCode(rechargeCode)==null)
|
||||||
|
{
|
||||||
|
throw new Exception("订单信息不存在");
|
||||||
|
}
|
||||||
ngUserRechargeRecords=userRechargeRecordsMapper.selectNgUserRechargeRecordsByRechargeCode(rechargeCode);//查询订单信息
|
ngUserRechargeRecords=userRechargeRecordsMapper.selectNgUserRechargeRecordsByRechargeCode(rechargeCode);//查询订单信息
|
||||||
ngUserRechargeRecords.setStatus(1);//状态更改为已支付
|
ngUserRechargeRecords.setStatus(1);//状态更改为已支付
|
||||||
ngUserRechargeRecords.setRechargeCode(rechargeCode);
|
userRechargeRecordsMapper.updateNgUserRechargeRecords(ngUserRechargeRecords);
|
||||||
|
|
||||||
|
|
||||||
/* userConsumptionDetails.setCreateTime(DateUtils.getNowDate());
|
//用户充值卡中的余额更改
|
||||||
NgUserRechargeRecords ngUserRechargeRecords = NgUserRechargeRecords.builder()
|
String cardNumber=ngUserRechargeRecords.getCardNumber();//卡号
|
||||||
.userId(info.getUserId()).userName(info.getUserName())
|
BigDecimal balance=ngUserRechargeRecords.getAmount();//充值金额
|
||||||
.cardNumber(info.getCardNumber()).areaCode(rechargecardUser.getAreacode())
|
if(!cardNumber.isEmpty())
|
||||||
.type(rechargecardUser.getStatus()).amount(rechargecardUser.getNumber())
|
{
|
||||||
.balance(info.getBalance()).rechargeTime(DateUtils.getNowDate())
|
if(userRechargeCardsMapper.selectUserRechargeCardsByCardNumber(cardNumber)==null)
|
||||||
.rechargeCode(null).status(0).serialNumber(null).deviceNumber(null).projectId(null)
|
{
|
||||||
.deptId(null)
|
throw new Exception("用户信息不存在");
|
||||||
.areaCode(rechargecardUser.getAreacode())
|
}
|
||||||
.build();*/
|
UserRechargeCards rechargeCards=userRechargeCardsMapper.selectUserRechargeCardsByCardNumber(ngUserRechargeRecords.getCardNumber());
|
||||||
userRechargeRecordsMapper.updateNgUserRechargeRecordsWechat(ngUserRechargeRecords);
|
BigDecimal newBalance = rechargeCards.getBalance().add(balance);
|
||||||
/*RechargecardUser rechargecardUser=new RechargecardUser();
|
System.out.println(cardNumber+"的余额从"+rechargeCards.getBalance()+"变成了"+newBalance);
|
||||||
// 计算新的余额
|
rechargeCards.setBalance(newBalance);
|
||||||
BigDecimal newBalance = rechargecardUser.getAmount().add(info.getBalance());*/
|
userRechargeCardsMapper.updateUserRechargeCards(rechargeCards);
|
||||||
// 更新用户充值卡信息,包括新的余额
|
}else{
|
||||||
// info.setBalance(newBalance);
|
throw new Exception("卡号为空");
|
||||||
// info.setUpdateTime(DateUtils.getNowDate());
|
}
|
||||||
// info.setAreaCode(String.valueOf(rechargecardUser.getAreaCode()));
|
|
||||||
|
|
||||||
/*//构建主题
|
|
||||||
String topic ="hzlink/147/"+rechargecardUser.getDeviceNumber()+"/cmd/down";
|
|
||||||
|
//用户消费明细记录中状态更改为已支付
|
||||||
|
/*UserConsumptionDetails userConsumptionDetails=userConsumptionDetailsMapper.selectUserConsumptionDetailsBy();
|
||||||
|
userConsumptionDetails.setStatus(0);//更改为已支付
|
||||||
|
userConsumptionDetails.setPaymentStatus(2);//账单状态更改为已支付*/
|
||||||
|
|
||||||
|
String areaCode=ngUserRechargeRecords.getAreaCode();
|
||||||
|
|
||||||
|
//构建主题
|
||||||
|
String topic ="hzlink/147/"+ngUserRechargeRecords.getSerialNumber()+"/cmd/down";
|
||||||
//构建消息
|
//构建消息
|
||||||
Map<String,Object> param = new HashMap<>();
|
Map<String,Object> param = new HashMap<>();
|
||||||
//远程阀控
|
//远程阀控
|
||||||
param.put("cmd",1000);
|
param.put("cmd",1000);
|
||||||
Map<String,Object> data = new HashMap<>();
|
Map<String,Object> data = new HashMap<>();
|
||||||
data.put("orderNum", ngUserRechargeRecords.getId());
|
data.put("orderNum", rechargeCode);//订单号
|
||||||
data.put("cardNum",rechargecardUser.getCardnumber());
|
data.put("cardNum",cardNumber);//卡号
|
||||||
data.put("areaCode",rechargecardUser.getAreacode());
|
data.put("areaCode",areaCode);//区域号
|
||||||
data.put("investBalance",rechargecardUser.getAmount().doubleValue());
|
data.put("investBalance",balance);//充值的金额
|
||||||
data.put("investWater",rechargecardUser.getWater());
|
data.put("investWater",100);//充值的水量
|
||||||
|
|
||||||
param.put("data",data);
|
param.put("data",data);
|
||||||
pubMqttClient.publish(1,true,topic, JSONUtil.toJsonStr(param));*/
|
try{
|
||||||
|
//pubMqttClient.publish(1,true,topic, JSONUtil.toJsonStr(param));
|
||||||
|
}catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("消息发布失败");
|
||||||
|
}
|
||||||
|
|
||||||
// int i = userRechargeCardsMapper.updateUserRechargeCards(info);
|
// int i = userRechargeCardsMapper.updateUserRechargeCards(info);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,195 @@
|
|||||||
|
package com.fastbee.rechargecard.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.fastbee.common.utils.pay.wxPayConfig;
|
||||||
|
import com.fastbee.rechargecard.domain.dto.WeChatRecharge;
|
||||||
|
import com.fastbee.rechargecard.service.INgUserRechargeRecordsService;
|
||||||
|
import com.fastbee.rechargecard.service.IUserConsumptionDetailsService;
|
||||||
|
import com.fastbee.rechargecard.service.IUserRechargeCardsService;
|
||||||
|
import com.fastbee.rechargecard.service.IUserWechatPayService;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.Signature;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
@Service
|
||||||
|
public class UserWechatPayServiceImpl implements IUserWechatPayService {
|
||||||
|
|
||||||
|
|
||||||
|
/** 商户号 */
|
||||||
|
public static String mchId = "1531795301";
|
||||||
|
/** 商户API私钥文件路径 */
|
||||||
|
public static String privateKeyPath = "fastbee-common/src/main/java/com/fastbee/common/utils/pay/apiclient_key.pem";
|
||||||
|
/** 商户API证书序列号 */
|
||||||
|
public static String serial_no = "3075B63EF52666EDC3EAFC5D4FB35C02CE123A9C";
|
||||||
|
/** 商户APIV3密钥 */
|
||||||
|
public static String apiV3Key = "e85a203e8ca146102f5cd7ecff912580";
|
||||||
|
//微信小程序appid
|
||||||
|
public static String appId="wx308612d2a8423311";
|
||||||
|
//微信支付公钥地址
|
||||||
|
public static String publicKeyPath="fastbee-common/src/main/java/com/fastbee/common/utils/pay/wechat_public_key.pem";
|
||||||
|
@Override
|
||||||
|
/**
|
||||||
|
* 创建订单,获取prepay_id和paySign
|
||||||
|
* @param recharge
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public Map<String, String> CreateOrder(WeChatRecharge recharge) throws Exception {
|
||||||
|
System.out.println("CreateOrder");
|
||||||
|
//请求URL
|
||||||
|
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
|
||||||
|
Map<String,String> result=new HashMap<>();
|
||||||
|
|
||||||
|
Map<String,Object> reqdata=new HashMap<String,Object>();
|
||||||
|
Map<String,Object> amount=new HashMap<>();
|
||||||
|
Map<String,Object> payer=new HashMap<>();
|
||||||
|
amount.put("total",recharge.getTotal());
|
||||||
|
System.out.print(recharge.getTotal());
|
||||||
|
amount.put("currency",recharge.getCurrency());
|
||||||
|
payer.put("openid",recharge.getOpenId());
|
||||||
|
|
||||||
|
reqdata.put("amount",amount);
|
||||||
|
reqdata.put("appid",appId);
|
||||||
|
reqdata.put("mchid",mchId);
|
||||||
|
reqdata.put("description",recharge.getCardnumber()+recharge.getAmount().toString());
|
||||||
|
reqdata.put("out_trade_no",recharge.getRechargeCode());
|
||||||
|
reqdata.put("notify_url","https://46b411f6.r3.cpolar.cn/pay/getresult");//"\t\n" +
|
||||||
|
reqdata.put("payer",payer);
|
||||||
|
//String Signature=getSign(reqdata);
|
||||||
|
Map<String,String> info=getSign(reqdata);
|
||||||
|
String timeStamp=info.get("timeStamp");
|
||||||
|
String nonce_str=info.get("nonce_str");
|
||||||
|
|
||||||
|
result.put("timeStamp",timeStamp);
|
||||||
|
result.put("mchid",mchId);
|
||||||
|
result.put("signType","RSA");
|
||||||
|
result.put("nonceStr",nonce_str);
|
||||||
|
result.put("partnerid",mchId);
|
||||||
|
String Signature=info.get("sign");
|
||||||
|
|
||||||
|
String Authorization="WECHATPAY2-SHA256-RSA2048 mchid=\""+mchId+"\",nonce_str=\""+nonce_str+"\",signature=\""+Signature+"\",timestamp=\""+timeStamp+"\",serial_no=\""+serial_no+"\"";
|
||||||
|
|
||||||
|
StringEntity entity = new StringEntity(JSONUtil.toJsonStr(reqdata), "utf-8");
|
||||||
|
entity.setContentType("application/json");
|
||||||
|
httpPost.setEntity(entity);
|
||||||
|
httpPost.setHeader("Accept", "application/json");
|
||||||
|
httpPost.setHeader("Authorization",Authorization);
|
||||||
|
|
||||||
|
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
||||||
|
//完成签名并执行请求
|
||||||
|
CloseableHttpResponse response = httpClient.execute(httpPost);
|
||||||
|
try {
|
||||||
|
int statusCode = response.getStatusLine().getStatusCode();
|
||||||
|
if (statusCode == 200) {
|
||||||
|
// 假设responseEntity是包含JSON响应的字符串
|
||||||
|
String responseEntity = EntityUtils.toString(response.getEntity());
|
||||||
|
|
||||||
|
// 使用Hutool的JSONUtil解析JSON字符串
|
||||||
|
JSONObject jsonObject = JSONUtil.parseObj(responseEntity);
|
||||||
|
|
||||||
|
// 安全地获取prepay_id的值
|
||||||
|
String prepayId = jsonObject.getStr("prepay_id");
|
||||||
|
|
||||||
|
System.out.println("Prepay ID: " + prepayId);
|
||||||
|
result.put("prepay_id",prepayId);
|
||||||
|
result.put("paySign",getPaySign(prepayId,timeStamp,nonce_str));
|
||||||
|
System.out.println("success,return body = " + prepayId);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
} else if (statusCode == 204) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
System.out.println("failed,resp code = " + statusCode + ",return body = " + EntityUtils.toString(response.getEntity()));
|
||||||
|
throw new IOException("request failed");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
response.close();
|
||||||
|
httpClient.close();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} finally {
|
||||||
|
response.close();
|
||||||
|
httpClient.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 生成签名
|
||||||
|
*/
|
||||||
|
private Map<String,String> getSign(Map<String,Object> reqBody) throws Exception {
|
||||||
|
//获取时间戳
|
||||||
|
|
||||||
|
String reqMethod="POST";
|
||||||
|
String url="/v3/pay/transactions/jsapi";
|
||||||
|
/*String reqMethod="GET";
|
||||||
|
String url="/v3/refund/domestic/refunds/123123123123";*/
|
||||||
|
String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
|
//timeStamp="1554208460";
|
||||||
|
String nonce_str= UUID.randomUUID().toString();
|
||||||
|
//nonce_str="593BEC0C930BF1AFEB40B4A08C8FB242";
|
||||||
|
String reqParam= JSONUtil.toJsonStr(reqBody);
|
||||||
|
|
||||||
|
/*HTTP请求方法\n
|
||||||
|
URL\n
|
||||||
|
请求时间戳\n
|
||||||
|
请求随机串\n
|
||||||
|
请求报文主体\n
|
||||||
|
*/
|
||||||
|
String signStr=reqMethod+"\n"+url+"\n"+timeStamp+"\n"+nonce_str+"\n"+reqParam +"\n";
|
||||||
|
//String signStr=reqMethod+"\n"+url+"\n"+timeStamp+"\n"+nonce_str+"\n\n";
|
||||||
|
String sign=sign(signStr.getBytes("utf-8"));
|
||||||
|
Map<String,String> info=new HashMap<>();
|
||||||
|
info.put("timeStamp",timeStamp);
|
||||||
|
info.put("nonce_str",nonce_str);
|
||||||
|
info.put("sign",sign);
|
||||||
|
|
||||||
|
/*//进行sha256
|
||||||
|
String sha256HexSignStr = DigestUtil.sha256Hex(signStr);
|
||||||
|
//在进行base64
|
||||||
|
String base64SignStr = Base64.getEncoder().encodeToString(sha256HexSignStr.getBytes());
|
||||||
|
*/
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 生成前端所需签名
|
||||||
|
*/
|
||||||
|
private String getPaySign(String prepayId,String timeStamp,String nonce_str) throws Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用字段appId、timeStamp、nonceStr、package
|
||||||
|
*/
|
||||||
|
String signStr=appId+"\n"+timeStamp+"\n"+nonce_str+"\n"+"prepay_id="+prepayId+"\n";
|
||||||
|
String sign=sign(signStr.getBytes("utf-8"));
|
||||||
|
|
||||||
|
return sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成签名方法
|
||||||
|
* @param message
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private String sign(byte[] message) throws Exception{
|
||||||
|
Signature sign;
|
||||||
|
sign = Signature.getInstance("SHA256withRSA");
|
||||||
|
//这里需要一个PrivateKey类型的参数,就是商户的私钥。
|
||||||
|
//获取商户私钥——传商户私钥位置
|
||||||
|
PrivateKey privateKey = wxPayConfig.getPrivateKey(privateKeyPath);
|
||||||
|
sign.initSign(privateKey);
|
||||||
|
sign.update(message);
|
||||||
|
return Base64.getEncoder().encodeToString(sign.sign());
|
||||||
|
}
|
||||||
|
}
|
@ -76,10 +76,10 @@
|
|||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectNgUserRechargeRecordsByRechargeCode" parameterType="String" resultMap="NgUserRechargeRecordsResult">
|
<!--<select id="selectNgUserRechargeRecordsByRechargeCode" parameterType="String" resultMap="NgUserRechargeRecordsResult">
|
||||||
<include refid="selectNgUserRechargeRecordsVo"/>
|
<include refid="selectNgUserRechargeRecordsVo"/>
|
||||||
<where>
|
<where>
|
||||||
|
recharge_code = #{rechargeCode}
|
||||||
<if test="cardNumber != null and cardNumber != ''"> card_number = #{cardNumber}</if>
|
<if test="cardNumber != null and cardNumber != ''"> card_number = #{cardNumber}</if>
|
||||||
<if test="userId != null "> and user_id = #{userId}</if>
|
<if test="userId != null "> and user_id = #{userId}</if>
|
||||||
<if test="userName != null and userName != ''"> and user_name like concat('%', #{userName}, '%')</if>
|
<if test="userName != null and userName != ''"> and user_name like concat('%', #{userName}, '%')</if>
|
||||||
@ -88,14 +88,13 @@
|
|||||||
<if test="amount != null "> and amount = #{amount}</if>
|
<if test="amount != null "> and amount = #{amount}</if>
|
||||||
<if test="balance != null "> and balance = #{balance}</if>
|
<if test="balance != null "> and balance = #{balance}</if>
|
||||||
<if test="rechargeTime != null "> and recharge_time = #{rechargeTime}</if>
|
<if test="rechargeTime != null "> and recharge_time = #{rechargeTime}</if>
|
||||||
<if test="rechargeCode != null and rechargeCode != ''"> and recharge_code = #{rechargeCode}</if>
|
|
||||||
<if test="status != null "> and status = #{status}</if>
|
<if test="status != null "> and status = #{status}</if>
|
||||||
<if test="serialNumber != null and serialNumber != ''"> and serial_number = #{serialNumber}</if>
|
<if test="serialNumber != null and serialNumber != ''"> and serial_number = #{serialNumber}</if>
|
||||||
<if test="deviceNumber != null and deviceNumber != ''"> and device_number = #{deviceNumber}</if>
|
<if test="deviceNumber != null and deviceNumber != ''"> and device_number = #{deviceNumber}</if>
|
||||||
<if test="projectId != null "> and project_id = #{projectId}</if>
|
<if test="projectId != null "> and project_id = #{projectId}</if>
|
||||||
<if test="deptId != null "> and dept_id = #{deptId}</if>
|
<if test="deptId != null "> and dept_id = #{deptId}</if>
|
||||||
</where>
|
</where>
|
||||||
</select>
|
</select>-->
|
||||||
|
|
||||||
<select id="selectNgUserRechargeRecordsBySerialNumber" parameterType="NgUserRechargeRecords" resultMap="NgUserRechargeRecordsResult">
|
<select id="selectNgUserRechargeRecordsBySerialNumber" parameterType="NgUserRechargeRecords" resultMap="NgUserRechargeRecordsResult">
|
||||||
<include refid="selectNgUserRechargeRecordsVo"/>
|
<include refid="selectNgUserRechargeRecordsVo"/>
|
||||||
|
@ -58,10 +58,10 @@
|
|||||||
<include refid="selectUserRechargeCardsVo"/>
|
<include refid="selectUserRechargeCardsVo"/>
|
||||||
where card_number= #{cardnumber}
|
where card_number= #{cardnumber}
|
||||||
</select>
|
</select>
|
||||||
<select id="selectUserRechargeCardsByCardNumber" parameterType="String" resultMap="UserRechargeCardsResult">
|
<!--<select id="selectUserRechargeCardsByCardNumber" parameterType="String" resultMap="UserRechargeCardsResult">
|
||||||
<include refid="selectUserRechargeCardsVo"/>
|
<include refid="selectUserRechargeCardsVo"/>
|
||||||
where cardNumber = #{cardNumber}
|
where cardNumber = #{cardNumber}
|
||||||
</select>
|
</select>-->
|
||||||
|
|
||||||
<insert id="insertUserRechargeCards" parameterType="UserRechargeCards" useGeneratedKeys="true" keyProperty="id">
|
<insert id="insertUserRechargeCards" parameterType="UserRechargeCards" useGeneratedKeys="true" keyProperty="id">
|
||||||
insert into user_recharge_cards
|
insert into user_recharge_cards
|
||||||
|
Loading…
x
Reference in New Issue
Block a user