fix: jinsha支付重新对接
This commit is contained in:
parent
44ae69e31f
commit
95db7f9e30
|
|
@ -31,8 +31,8 @@ public class PayController {
|
|||
*/
|
||||
@GetMapping("/jinsha-pay")
|
||||
@ApiOperation("jinsha请求支付")
|
||||
public AjaxResult jinShaPay(Long gearId) throws Exception {
|
||||
PayResVO payResVO = jinShaService.jinShaPay(gearId);
|
||||
public AjaxResult jinShaPay(Long gearId, String cardno, String cardname) throws Exception {
|
||||
PayResVO payResVO = jinShaService.jinShaPay(gearId, cardno, cardname);
|
||||
return AjaxResult.success(payResVO);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ public class JinShaBodyReq {
|
|||
|
||||
private String notify_url;
|
||||
|
||||
private String return_url;
|
||||
|
||||
private String sign;
|
||||
private String cardname;
|
||||
private String cardno;
|
||||
|
||||
/**
|
||||
* 档位ID
|
||||
|
|
|
|||
|
|
@ -8,8 +8,11 @@ public interface IJinShaService {
|
|||
|
||||
/**
|
||||
* 支付
|
||||
* @param gearId 档位ID
|
||||
* @param cardno 银行卡号
|
||||
* @param cardname 银行卡姓名
|
||||
*/
|
||||
PayResVO jinShaPay(Long gearId) throws Exception;
|
||||
PayResVO jinShaPay(Long gearId, String cardno, String cardname) throws Exception;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -48,10 +48,20 @@ public class JinShaService implements IJinShaService {
|
|||
@Autowired
|
||||
private IAiRechargeGiftGearService aiRechargeGiftGearService;
|
||||
@Autowired
|
||||
private IAiRechargeGiftService aiRechargeGiftService;
|
||||
@Autowired
|
||||
private IExchangeRateService exchangeRateService;
|
||||
|
||||
@Override
|
||||
public PayResVO jinShaPay(Long gearId) throws Exception {
|
||||
public PayResVO jinShaPay(Long gearId, String cardno, String cardname) throws Exception {
|
||||
|
||||
// 验证参数
|
||||
if (cardno == null || cardno.trim().isEmpty()) {
|
||||
throw new ServiceException("银行卡号不能为空", -1);
|
||||
}
|
||||
if (cardname == null || cardname.trim().isEmpty()) {
|
||||
throw new ServiceException("银行卡姓名不能为空", -1);
|
||||
}
|
||||
|
||||
//充值挡位查询
|
||||
AiRechargeGiftGear aiRechargeGiftGear = aiRechargeGiftGearService.selectAiRechargeGiftGearById(gearId);
|
||||
|
|
@ -62,62 +72,86 @@ public class JinShaService implements IJinShaService {
|
|||
// 使用汇率服务转换金额(从CNY转换为目标货币,默认INR)
|
||||
amount = exchangeRateService.convertAmount(amount, "USD", "INR");
|
||||
|
||||
JinShaBodyReq req = new JinShaBodyReq();
|
||||
req.setAppid(appId);
|
||||
req.setReturn_url(returnUrl + "/recharge");
|
||||
req.setNotify_url(notifyUrl + "/api/pay/jinsha-callBack");
|
||||
req.setAmount(amount);
|
||||
// 1. 配置请求参数
|
||||
TreeMap<String, Object> params = new TreeMap<>();
|
||||
params.put("appid", req.getAppid());
|
||||
// 生成订单号
|
||||
String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 8);
|
||||
String dateTime = new SimpleDateFormat("yyyyMMdd").format(new Date());
|
||||
String orderNo = dateTime + "js" + uuid;
|
||||
params.put("orderno", orderNo);
|
||||
params.put("amount", amount);
|
||||
params.put("notify_url", req.getNotify_url());
|
||||
params.put("return_url", req.getReturn_url());
|
||||
StringBuilder append = this.append(params);
|
||||
String sign = this.sign(append);
|
||||
String formData = append + "&sign=" + sign;
|
||||
// 2. 构建请求体(form-urlencoded 格式)
|
||||
RequestBody requestBody = RequestBody.create(
|
||||
MediaType.get("application/x-www-form-urlencoded;charset=utf-8"),
|
||||
formData
|
||||
);
|
||||
// 3. 构建 POST 请求
|
||||
|
||||
// 金额转换为int类型(去除小数部分)
|
||||
int amountInt = amount.intValue();
|
||||
|
||||
// 1. 配置签名参数(按照key排序,不包含notify_url和sign)
|
||||
TreeMap<String, Object> signParams = new TreeMap<>();
|
||||
signParams.put("appid", appId);
|
||||
signParams.put("amount", amountInt);
|
||||
signParams.put("orderno", orderNo);
|
||||
signParams.put("cardno", cardno);
|
||||
signParams.put("cardname", cardname);
|
||||
|
||||
// 2. 生成签名
|
||||
String sign = this.generateSign(signParams);
|
||||
|
||||
// 3. 构建请求参数(使用FormBody.Builder自动处理URL编码)
|
||||
FormBody.Builder formBuilder = new FormBody.Builder();
|
||||
formBuilder.add("appid", appId);
|
||||
formBuilder.add("amount", String.valueOf(amountInt));
|
||||
formBuilder.add("orderno", orderNo);
|
||||
formBuilder.add("cardno", cardno);
|
||||
formBuilder.add("cardname", cardname);
|
||||
formBuilder.add("notify_url", notifyUrl + "/api/pay/jinsha-callBack");
|
||||
formBuilder.add("sign", sign);
|
||||
RequestBody requestBody = formBuilder.build();
|
||||
// 5. 构建 POST 请求
|
||||
Request request = new Request.Builder()
|
||||
.url(url + "/api/pay")
|
||||
// .header("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
|
||||
.header("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
|
||||
.post(requestBody)
|
||||
.build();
|
||||
// 4. 发送请求并获取响应
|
||||
// 6. 发送请求并获取响应
|
||||
Response response = OkHttpUtils.newCall(request).execute();
|
||||
ResponseBody body = response.body();
|
||||
if (null == body) {
|
||||
log.error("kada支付请求的响应异常");
|
||||
throw new Exception("kadapay responsebody is null");
|
||||
log.error("jinsha支付请求的响应异常");
|
||||
throw new Exception("jinshapay responsebody is null");
|
||||
}
|
||||
JinShaBodyRes jinShaBodyRes = objectMapper.readValue(body.string(), JinShaBodyRes.class);
|
||||
String responseBody = body.string();
|
||||
log.info("jinsha支付请求响应: {}", responseBody);
|
||||
JinShaBodyRes jinShaBodyRes = objectMapper.readValue(responseBody, JinShaBodyRes.class);
|
||||
|
||||
// 检查响应code,0表示成功,其他值表示失败
|
||||
Integer code = jinShaBodyRes.getCode();
|
||||
if (code == null || code != 0) {
|
||||
String msg = jinShaBodyRes.getMsg();
|
||||
log.error("jinsha支付请求失败,code: {}, msg: {}", code, msg);
|
||||
throw new ServiceException(msg != null ? msg : "支付请求失败", code != null ? code : -1);
|
||||
}
|
||||
|
||||
// 创建充值管理
|
||||
AiUser userInfo = aiUserService.getUserInfo(SecurityUtils.getAiUserId());
|
||||
AiRecharge aiRecharge = new AiRecharge();
|
||||
aiRecharge.setOrderNum(orderNo);
|
||||
aiRecharge.setUserId(SecurityUtils.getAiUserId());
|
||||
aiRecharge.setAmount(amount);
|
||||
aiRecharge.setGearId(req.getGearId());
|
||||
aiRecharge.setGearId(gearId);
|
||||
aiRecharge.setGearAmount(aiRechargeGiftGear.getRechargeAmount());
|
||||
aiRecharge.setSource(userInfo.getSource());
|
||||
AiRechargeGift aiRechargeGift = aiRechargeGiftService.selectAiRechargeGiftById(aiRechargeGiftGear.getRechargeId());
|
||||
aiRecharge.setPayType(aiRechargeGift.getPayType());
|
||||
// jinsha支付成功返回后,不需要支付URL,订单状态由回调更新
|
||||
aiRechargeService.insertAiRecharge(aiRecharge);
|
||||
|
||||
PayResVO payResVO = new PayResVO();
|
||||
payResVO.setOrderNo(orderNo);
|
||||
payResVO.setPayUrl(jinShaBodyRes.getData().getPayurl());
|
||||
// jinsha支付成功后不需要跳转支付页面,直接返回订单号
|
||||
return payResVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public AjaxResult jinShaCall(JinShaBodyCall req) {
|
||||
log.info("jinsha支付回调,订单号: {}, 状态: {}", req.getOrderno(), req.getStatus());
|
||||
|
||||
// 验证签名
|
||||
TreeMap<String, Object> params = new TreeMap<>();
|
||||
params.put("status", req.getStatus());
|
||||
params.put("orderno", req.getOrderno());
|
||||
|
|
@ -126,14 +160,58 @@ public class JinShaService implements IJinShaService {
|
|||
StringBuilder append = this.append(params);
|
||||
String sign = this.sign(append);
|
||||
if (!sign.equals(req.getSign())) {
|
||||
log.error("支付回调签名错误 {}", req.getOrderno());
|
||||
return AjaxResult.error();
|
||||
}
|
||||
//充值成功处理
|
||||
aiRechargeService.addRecharge(req.getOrderno());
|
||||
return AjaxResult.success();
|
||||
log.error("jinsha支付回调签名错误,订单号: {}, 期望签名: {}, 实际签名: {}",
|
||||
req.getOrderno(), sign, req.getSign());
|
||||
return AjaxResult.error("签名验证失败");
|
||||
}
|
||||
|
||||
// 处理订单状态
|
||||
// status:0=>处理中, status:1=>成功, status:2=>失败
|
||||
Integer status = req.getStatus();
|
||||
if (status == null) {
|
||||
log.error("jinsha支付回调状态为空,订单号: {}", req.getOrderno());
|
||||
return AjaxResult.error("状态为空");
|
||||
}
|
||||
|
||||
if (status == 1) {
|
||||
// 充值成功处理
|
||||
log.info("jinsha支付成功,订单号: {}", req.getOrderno());
|
||||
aiRechargeService.addRecharge(req.getOrderno());
|
||||
return AjaxResult.success();
|
||||
} else if (status == 2) {
|
||||
// 支付失败
|
||||
log.warn("jinsha支付失败,订单号: {}", req.getOrderno());
|
||||
// 这里可以添加失败处理逻辑,比如更新订单状态为失败
|
||||
return AjaxResult.success();
|
||||
} else {
|
||||
// 处理中(status:0)
|
||||
log.info("jinsha支付处理中,订单号: {}", req.getOrderno());
|
||||
return AjaxResult.success();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成签名
|
||||
* 按照文档要求:key=value&key=value&...&secret=secret,然后MD5
|
||||
*/
|
||||
private String generateSign(TreeMap<String, Object> sortedParams) {
|
||||
StringBuilder paramSb = new StringBuilder();
|
||||
for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
// 拼接格式:key=value&
|
||||
paramSb.append(key).append("=").append(value).append("&");
|
||||
}
|
||||
// 最后添加secret
|
||||
paramSb.append("secret=").append(secret);
|
||||
String signSource = paramSb.toString();
|
||||
log.debug("jinsha签名源字符串: {}", signSource);
|
||||
return Md5Utils.hash(signSource);
|
||||
}
|
||||
|
||||
/**
|
||||
* 旧的签名方法(回调使用)
|
||||
*/
|
||||
private StringBuilder append(TreeMap<String, Object> sortedParams) {
|
||||
StringBuilder paramSb = new StringBuilder();
|
||||
for (Map.Entry<String, Object> entry : sortedParams.entrySet()) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue