|
|
@@ -6,8 +6,13 @@ import cn.hutool.core.date.DateTime;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
import cn.hutool.core.util.RandomUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.crypto.digest.DigestAlgorithm;
|
|
|
+import cn.hutool.crypto.digest.Digester;
|
|
|
import cn.hutool.extra.servlet.ServletUtil;
|
|
|
import cn.hutool.http.Header;
|
|
|
+import cn.hutool.http.HttpUtil;
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.cyksj.common.EnvCommonService;
|
|
|
@@ -16,6 +21,7 @@ import com.cyksj.common.exception.BusinessRuntimeException;
|
|
|
import com.cyksj.common.i18n.I18nMessageUtil;
|
|
|
import com.cyksj.common.snowflake.Sequence;
|
|
|
import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
|
|
|
+import com.cyksj.common.util.Codec;
|
|
|
import com.cyksj.common.util.Jsons;
|
|
|
import com.cyksj.common.util.SmsUtil;
|
|
|
import com.cyksj.common.util.StringUtil;
|
|
|
@@ -27,12 +33,11 @@ import com.cyksj.mapper.manage.coupon.CouponMapper;
|
|
|
import com.cyksj.mapper.manage.coupon.CouponSkuMapper;
|
|
|
import com.cyksj.mapper.manage.coupon.CouponUserMapper;
|
|
|
import com.cyksj.mapper.manage.distribute.*;
|
|
|
-import com.cyksj.model.dto.ChatGPTPlusPurchaseLimitDto;
|
|
|
-import com.cyksj.model.dto.CouponPopularizeDto;
|
|
|
-import com.cyksj.model.dto.OrderDonPostDataDto;
|
|
|
+import com.cyksj.model.dto.*;
|
|
|
import com.cyksj.model.entity.*;
|
|
|
import com.cyksj.model.manage.views.GroupsRelationView;
|
|
|
import com.cyksj.model.manage.views.OrderDonView;
|
|
|
+import com.cyksj.model.request.OrderAttach;
|
|
|
import com.cyksj.model.request.OrderPayRequest;
|
|
|
import com.cyksj.model.views.CouponNewUserView;
|
|
|
import com.cyksj.model.views.CouponUserView;
|
|
|
@@ -59,6 +64,7 @@ import com.ejlchina.searcher.util.MapUtils;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.dao.DuplicateKeyException;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
@@ -66,10 +72,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Optional;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
* @author chan
|
|
|
@@ -1663,4 +1667,102 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
|
|
|
userPlatDistributeRate.setSecondRate(secondRate);
|
|
|
return userPlatDistributeRate;
|
|
|
}
|
|
|
+
|
|
|
+ @Value("${v5pay.merchantNo}")
|
|
|
+ private String merchantNo;
|
|
|
+
|
|
|
+ @Value("${v5pay.appKey}")
|
|
|
+ private String appKey;
|
|
|
+
|
|
|
+ @Value("${v5pay.appSecret}")
|
|
|
+ private String appSecret;
|
|
|
+
|
|
|
+ @Value("${v5pay.apiUrl}")
|
|
|
+ private String apiUrl;
|
|
|
+
|
|
|
+ @Value("${v5pay.callbackUrl}")
|
|
|
+ private String callbackUrl;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String v5Pay(Long orderId,String successUrl) throws Exception {
|
|
|
+ OrderDon orderDon = this.getById(orderId);
|
|
|
+ Objects.requireNonNull(orderDon, "订单不存在!");
|
|
|
+
|
|
|
+ orderDon.setType(OrderDon.Type.V5_PAY);
|
|
|
+ this.updateById(orderDon);
|
|
|
+
|
|
|
+ OrderAttach attach = new OrderAttach();
|
|
|
+ attach.setO(orderDon.getId());
|
|
|
+ String att = Codec.DoBase64.custom()
|
|
|
+ .setData(Jsons.toJson(attach)).encodeAsText();
|
|
|
+ callbackUrl = callbackUrl + "/"+envCommonService.getPort()+"/"+envCommonService.getApi()+"/applets/order/v5pay/notify";
|
|
|
+ V5payPayment v5payPayment = new V5payPayment().setMerchantNo(merchantNo).setAppKey(appKey).setSysCountryCode("MY").setCurrency("MYR")
|
|
|
+ .setOrderNo(orderDon.getOrderNo()).setAmount(orderDon.getMoney().divide(BigDecimal.valueOf(100),2, RoundingMode.HALF_DOWN))
|
|
|
+ .setMerchantParam(att).setCallbackUrl(callbackUrl).setRedirectUrl(successUrl);
|
|
|
+ v5payPayment.setSign(generateSignature(v5payPayment,appSecret));
|
|
|
+ String result = HttpUtil.post(apiUrl+"/cgi/cashier/v2/payin",Jsons.toJson(v5payPayment));
|
|
|
+ log.info("v5pay result:{}",result);
|
|
|
+ JSONObject jsonObject = JSONUtil.parseObj(result);
|
|
|
+ if (!"1000".equals(jsonObject.getStr("code"))){
|
|
|
+ throw new BusinessRuntimeException(GatewayApiCode.METADATA_SYSTEM_ERROR.getCode(),GatewayApiCode.METADATA_SYSTEM_ERROR.getMsg());
|
|
|
+ }
|
|
|
+ return jsonObject.getStr("checkoutUrl");
|
|
|
+ }
|
|
|
+
|
|
|
+ public static String generateSignature(V5payPayment payment, String secretKey) {
|
|
|
+ Map<String, String> params = new TreeMap<>();
|
|
|
+
|
|
|
+ params.put("merchantNo", payment.getMerchantNo());
|
|
|
+ params.put("appKey", payment.getAppKey());
|
|
|
+ params.put("orderNo", payment.getOrderNo());
|
|
|
+ params.put("amount", payment.getAmount().toPlainString());
|
|
|
+ params.put("merchantParam", payment.getMerchantParam());
|
|
|
+ params.put("email", payment.getEmail());
|
|
|
+ params.put("mobile", payment.getMobile());
|
|
|
+ params.put("name", payment.getName());
|
|
|
+ params.put("callbackUrl", payment.getCallbackUrl());
|
|
|
+ params.put("redirectUrl", payment.getRedirectUrl());
|
|
|
+
|
|
|
+ // 拼接非空参数
|
|
|
+ String plainText = params.entrySet().stream()
|
|
|
+ .filter(entry -> entry.getValue() != null && !entry.getValue().isEmpty())
|
|
|
+ .map(entry -> entry.getKey() + "=" + entry.getValue())
|
|
|
+ .collect(Collectors.joining("&"));
|
|
|
+
|
|
|
+ // 拼接 secretKey
|
|
|
+ String signTemp = plainText + secretKey;
|
|
|
+
|
|
|
+ // 使用 MD5 加密
|
|
|
+ Digester md5 = new Digester(DigestAlgorithm.MD5);
|
|
|
+
|
|
|
+ return md5.digestHex(signTemp);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void v5PayNotiry(V5payDto v5payDto) throws Exception {
|
|
|
+ log.info("v5pay 回调成功 :{}",v5payDto);
|
|
|
+ if (!"success".equals(v5payDto.getMessage())){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String attach = Codec.DoBase64.custom().setData(v5payDto.getMerchantParam()).decodeAsText();
|
|
|
+
|
|
|
+ OrderAttach orderV2Attach = Jsons.parseObject(attach, OrderAttach.class);
|
|
|
+ //更新订单支付状态
|
|
|
+ Long orderId = orderV2Attach.getO();
|
|
|
+ OrderDon orderDon = this.getById(orderId);
|
|
|
+ if (orderDon == null){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (orderDon.getStatus().equals(OrderDon.Status.hasPayment)) {
|
|
|
+ log.info("已回调,重复修改状态 id:{}", orderDon.getId());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String transactionId = v5payDto.getTransactionId();
|
|
|
+ orderDon.setTransactionId(transactionId);
|
|
|
+ orderDon.setPayTime(new Date());
|
|
|
+ orderDon.setAbroadTransactionFee(new BigDecimal(v5payDto.getFee()));
|
|
|
+ orderNotify(orderDon);
|
|
|
+ log.info("支付成功订单:"+orderId+",支付交易号:"+transactionId);
|
|
|
+ log.info("支付成功订单:"+orderId);
|
|
|
+ }
|
|
|
}
|