雷蛇支付fixed

雷蛇支付验签

雷蛇支付1
This commit is contained in:
2025-01-07 13:44:04 +08:00
parent dab27e155d
commit d8011cdc56
7 changed files with 297 additions and 0 deletions

View File

@@ -487,6 +487,8 @@ public class Constant {
public static final String my_card = "MyCard";
// StartPay
public static final String start_pay = "start_pay";
// razer
public static final String razer = "razer";
}

View File

@@ -0,0 +1,17 @@
package com.accompany.payment.razer;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties("razer")
@Data
public class RazerPayConfig {
private String createUrl;//下单url
private String returnUrl;
private String callbackUrl;
private String applicationCode;
private String secretKey;
}

View File

@@ -0,0 +1,19 @@
package com.accompany.payment.razer;
import lombok.Data;
@Data
public class RazerPayResDTO {
private String applicationCode;
private String referenceId;
private String version;
private Long amount;
private String currencyCode;
private String paymentId;
private String paymentUrl;
private String hashType;
private String signature;
private String paymentStatusCode;
private String paymentStatusDate;
private Long virtualCurrencyAmount;
}

View File

@@ -0,0 +1,100 @@
package com.accompany.payment.razer;
import com.accompany.common.utils.HttpUtils;
import com.accompany.payment.model.ChargeProd;
import com.accompany.payment.model.ChargeRecord;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
@Slf4j
@Service
public class RazerPayService {
@Autowired
private RazerPayConfig razerPayConfig;
public RazerPayResDTO createOrder(ChargeRecord chargeRecord, ChargeProd chargeProd, String successUrl) {
try {
Map<String, String> formMap = new HashMap<>();
String applicationCode = razerPayConfig.getApplicationCode();
formMap.put("applicationCode", applicationCode);
String referenceId = chargeRecord.getChargeRecordId();
formMap.put("referenceId", referenceId);
String version = "v1";
formMap.put("version", version);
long amount = chargeRecord.getAmount();
formMap.put("amount", String.valueOf(amount));
String currencyCode = chargeProd.getLocalCurrencyCode();
formMap.put("currencyCode", currencyCode);
String returnUrl = successUrl;
formMap.put("returnUrl", returnUrl);
String callbackUrl = razerPayConfig.getCallbackUrl();
formMap.put("callbackUrl", callbackUrl);
Long customerId = chargeRecord.getUid();
formMap.put("customerId", String.valueOf(customerId));
String description = chargeProd.getChargeGoldNum() + "Gold";
formMap.put("description", description);
String hashType = "hmac-sha256";
formMap.put("hashType", hashType);
if (!"razer".equals(chargeRecord.getPaymentType())){
formMap.put("channelId",chargeRecord.getPaymentType());
}
String signStr = formatMapToSignStr(formMap);
String signature = signature(signStr);
formMap.put("signature", signature);
Map<String, String> headerMap = new HashMap<>();
headerMap.put("Content-Type", "application/x-www-form-urlencoded");
log.info("post :{}", JSON.toJSONString(formMap));
String resultBody = HttpUtils.doPost(razerPayConfig.getCreateUrl(), formMap, headerMap);
log.info("RazerPayService.createOrder resultBody:{}", resultBody);
RazerPayResDTO result = JSONObject.parseObject(resultBody, RazerPayResDTO.class);
return result;
} catch (NoSuchAlgorithmException e) {
log.error("RazerPayService.createOrder:e:{}", e);
} catch (InvalidKeyException e) {
log.error("RazerPayService.createOrder:e:{}", e);
} catch (IOException e) {
log.error("RazerPayService.createOrder:e:{}", e);
}
return new RazerPayResDTO();
}
public String formatMapToSignStr(Map<String, String> paramMap) {
Map tmpMap = paramMap;
List<Map.Entry<String, String>> infoIds = new ArrayList(tmpMap.entrySet());
Collections.sort(infoIds, (Comparator) (o1, o2) -> (((Map.Entry<String, Object>) o1).getKey()).toString().compareTo(((Map.Entry<String, Object>) o2).getKey()));
StringBuffer buf = new StringBuffer();
for (Map.Entry<String, String> item : infoIds) {
if ((!StringUtils.isEmpty(item.getKey()))
&& (!("signature".equals(item.getKey())))) {
buf.append(item.getValue());
}
}
return buf.toString();
}
public String signature(String signStr) throws NoSuchAlgorithmException, InvalidKeyException {
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(razerPayConfig.getSecretKey().getBytes(StandardCharsets.UTF_8), "HmacSHA256");
hmac.init(keySpec);
byte[] hmacBytes = hmac.doFinal(signStr.getBytes(StandardCharsets.UTF_8));
StringBuilder stringBuilder = new StringBuilder();
for(byte b : hmacBytes) {
stringBuilder.append(String.format("%02x",b));
}
return stringBuilder.toString();
}
}

View File

@@ -33,6 +33,11 @@ public class ChargeRecordService extends BaseService {
return chargeRecordMapper.selectByPrimaryKey(chargeRecordId);
}
public void updateChargeRecord(ChargeRecord record) {
record.setUpdateTime(new Date());
chargeRecordMapper.updateByPrimaryKey(record);
}
public List<ChargeRecord> listChargeRecordByPingXXId(List<String> pingxxIdList) {
ChargeRecordExample example = new ChargeRecordExample();
example.createCriteria().andPingxxChargeIdIn(pingxxIdList);

View File

@@ -0,0 +1,50 @@
package com.accompany.payment.strategy;
import com.accompany.common.constant.Constant;
import com.accompany.core.base.UidContextHolder;
import com.accompany.payment.annotation.PayChannelSupport;
import com.accompany.payment.constant.ChargeUserLimitConstant;
import com.accompany.payment.constant.PayConstant;
import com.accompany.payment.model.ChargeProd;
import com.accompany.payment.model.ChargeRecord;
import com.accompany.payment.payermax.PayermaxService;
import com.accompany.payment.payermax.dto.CreateOrderResDTO;
import com.accompany.payment.payermax.params.CreateOrderParams;
import com.accompany.payment.razer.RazerPayResDTO;
import com.accompany.payment.razer.RazerPayService;
import com.accompany.payment.service.ChargeUserLimitService;
import com.accompany.payment.utils.CommonPayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
@Service
@PayChannelSupport(Constant.ChargeChannel.razer)
public class RazerStrategy extends AbstractPayStrategy {
private final String SPILT_PREFIX = "-";
@Autowired
private ChargeUserLimitService chargeUserLimitService;
@Autowired
private RazerPayService razerPayService;
@Override
public Object pay(PayContext context) throws Exception {
chargeUserLimitService.chargeLimitCheck(UidContextHolder.get(), ChargeUserLimitConstant.LIMIT_TYPE_OF_H5);
ChargeRecord chargeRecord = context.getChargeRecord();
ChargeProd chargeProd = context.getChargeProd();
RazerPayResDTO orderRes = razerPayService.createOrder(chargeRecord, chargeProd, context.getSuccessUrl());
chargeRecord.setPingxxChargeId(orderRes.getPaymentId());
Map<String, Object> appMap = new HashMap<>();
appMap.put(PayConstant.H5_PAY_URL_FIELD, orderRes.getPaymentUrl());
appMap.put(PayConstant.H5_PAY_NICK_FIELD, context.getNick());
appMap.put(PayConstant.H5_PAY_ERBANNO_FIELD, context.getErbanNo());
return appMap;
}
}

View File

@@ -0,0 +1,104 @@
package com.accompany.business.controller.apppay;
import com.accompany.business.service.ChargeService;
import com.accompany.common.constant.Constant;
import com.accompany.common.status.BusiStatus;
import com.accompany.core.exception.ServiceException;
import com.accompany.payment.model.ChargeRecord;
import com.accompany.payment.razer.RazerPayService;
import com.accompany.payment.service.ChargeRecordService;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/payment/razer")
@Slf4j
public class RazerPayController {
@Autowired
private ChargeRecordService chargeRecordService;
@Autowired
private ChargeService chargeService;
@Autowired
private RazerPayService razerPayService;
@RequestMapping(value = "/callback", method = RequestMethod.POST)
public void callback(HttpServletRequest request) throws NoSuchAlgorithmException, InvalidKeyException, ParseException {
log.info("handle razerPay notification:request:{}", JSONObject.toJSONString(request.getParameterMap()));
// 创建一个Map来存储请求参数
Map<String, String> params = new HashMap<>();
// 获取所有参数名
Enumeration<String> paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
// 获取参数值
String paramValue = request.getParameter(paramName);
// 将参数名和值放入Map中
params.put(paramName, paramValue);
}
log.info("RazerPayController:params:{}", params);
String signStr = razerPayService.formatMapToSignStr(params);
String signature = razerPayService.signature(signStr);
String paramSignature = params.get("signature");
if (!signature.equals(paramSignature)) {
log.info("RazerPayController:signatureError,signStr:{},signature:{},paramSignature:{}", signStr, signature, paramSignature);
throw new ServiceException(BusiStatus.SERVERBUSY);
}
String chargeRecordId = params.get("referenceId");
ChargeRecord chargeRecordById =
chargeRecordService.getChargeRecordById(chargeRecordId);
if (chargeRecordById == null) {
log.info("RazerPayController empty charge, chargeId:{}", chargeRecordId);
return;
}
if (Constant.ChargeRecordStatus.finish.equals(chargeRecordById.getChargeStatus())) {
log.info("RazerPayController charge finish, chargeId:{}", chargeRecordId);
return;
}
if (!Constant.ChargeRecordStatus.create.equals(chargeRecordById.getChargeStatus())) {
log.info("RazerPayController charge_status fail, charge:{}", JSONObject.toJSONString(chargeRecordById));
return;
}
String paymentStatusCode = params.get("paymentStatusCode");
if ("00".equals(paymentStatusCode)) {
String amount = params.get("amount");
String currencyCode = params.get("currencyCode");
Long amountValue = Long.valueOf(amount);
if (!chargeRecordById.getAmount().equals(amountValue) || !chargeRecordById.getLocalCurrencyCode().equals(currencyCode)) {
log.info("RazerPayController amount fail, chargeRecordId:{},chargeAmount:{}, callBackAmound:{}",
chargeRecordId, chargeRecordById.getAmount(), amount);
return;
}
String paymentId = params.get("paymentId");
chargeRecordById.setLocalCurrencyCode(currencyCode);
chargeRecordById.setLocalAmount(amountValue);
chargeRecordById.setPingxxChargeId(paymentId);
String paymentStatusDate = params.get("paymentStatusDate");
chargeRecordById.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(paymentStatusDate));
chargeService.updateAppPayData(chargeRecordById);
} else {
chargeRecordById.setChargeStatus(Constant.ChargeRecordStatus.error);
chargeRecordById.setChargeDesc(paymentStatusCode);
chargeRecordService.updateChargeRecord(chargeRecordById);
}
log.info("end handle razer alipay notification");
}
}