|
|
@@ -0,0 +1,143 @@
|
|
|
+package com.cyksj.service.cryptomus;
|
|
|
+
|
|
|
+import cn.hutool.core.codec.Base64;
|
|
|
+import cn.hutool.crypto.digest.MD5;
|
|
|
+import cn.hutool.http.HttpRequest;
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.cyksj.common.exception.BusinessRuntimeException;
|
|
|
+import com.cyksj.common.util.Codec;
|
|
|
+import com.cyksj.common.util.Jsons;
|
|
|
+import com.cyksj.enums.GatewayApiCode;
|
|
|
+import com.cyksj.model.entity.OrderDon;
|
|
|
+import com.cyksj.model.request.CryptomusPayReq;
|
|
|
+import com.cyksj.model.request.CryptomusRefundReq;
|
|
|
+import com.cyksj.model.request.OrderRefundReq;
|
|
|
+import com.cyksj.model.response.CryptomusPayRep;
|
|
|
+import com.cyksj.model.response.CryptomusRefundRep;
|
|
|
+import com.cyksj.model.response.CryptomusReturnRep;
|
|
|
+import com.cyksj.service.order.OrderDonService;
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.fasterxml.jackson.databind.node.ObjectNode;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.bouncycastle.crypto.digests.MD5Digest;
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author zwhui
|
|
|
+ * @date 2023/8/29 15:20
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Slf4j
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class CryptomusService {
|
|
|
+
|
|
|
+ private final OrderDonService orderDonService;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @Value("${cryptomus.shopId}")
|
|
|
+ private String shopId;
|
|
|
+
|
|
|
+ @Value("${cryptomus.shopKey}")
|
|
|
+ private String shopKey;
|
|
|
+
|
|
|
+ @Value("${cryptomus.host}")
|
|
|
+ private String host;
|
|
|
+
|
|
|
+
|
|
|
+ public String pay(Long orderId, String successUrl) throws Exception {
|
|
|
+ OrderDon orderDon = orderDonService.getById(orderId);
|
|
|
+ orderDon.setType(OrderDon.Type.CRYPTOMUS);
|
|
|
+ orderDonService.updateById(orderDon);
|
|
|
+ if (OrderDon.Status.hasPayment.equals(orderDon.getStatus())) {
|
|
|
+ throw new BusinessRuntimeException(GatewayApiCode.METADATA_SYSTEM_ERROR.getCode(),"The donation has been paid");
|
|
|
+ }
|
|
|
+ CryptomusPayReq cryptomusPay = new CryptomusPayReq();
|
|
|
+ cryptomusPay.setAmount(String.valueOf(orderDon.getMoney().divide(new BigDecimal(100), 2, RoundingMode.HALF_DOWN)));
|
|
|
+ cryptomusPay.setCurrency("USD");
|
|
|
+ cryptomusPay.setOrder_id(orderId.toString());
|
|
|
+ cryptomusPay.setUrl_callback(host + "/applets/order/cryptomus/notify");
|
|
|
+ cryptomusPay.setUrl_success(successUrl);
|
|
|
+ String json = Jsons.toJson(cryptomusPay);
|
|
|
+ String result = HttpRequest.post("https://api.cryptomus.com/v1/payment").header("merchant", shopId).header("sign", MD5.create().digestHex(Base64.encode(json) + shopKey)).body(json).execute().body();
|
|
|
+
|
|
|
+ return Jsons.parseObject(result, CryptomusPayRep.class).getResult().getUrl();
|
|
|
+ }
|
|
|
+
|
|
|
+ public void testPay(Long orderId, String successUrl) throws Exception {
|
|
|
+ OrderDon orderDon = orderDonService.getById(orderId);
|
|
|
+ orderDon.setType(OrderDon.Type.CRYPTOMUS);
|
|
|
+ orderDonService.updateById(orderDon);
|
|
|
+ if (OrderDon.Status.hasPayment.equals(orderDon.getStatus())) {
|
|
|
+ throw new BusinessRuntimeException(GatewayApiCode.METADATA_SYSTEM_ERROR.getCode(),"The donation has been paid");
|
|
|
+ }
|
|
|
+ CryptomusPayReq cryptomusPay = new CryptomusPayReq();
|
|
|
+ cryptomusPay.setAmount(String.valueOf(orderDon.getMoney().divide(new BigDecimal(100), 2, RoundingMode.HALF_DOWN)));
|
|
|
+ cryptomusPay.setCurrency("ETH");
|
|
|
+ cryptomusPay.setNetwork("eth");
|
|
|
+ cryptomusPay.setStatus("paid");
|
|
|
+ cryptomusPay.setOrder_id(orderId.toString());
|
|
|
+ cryptomusPay.setUrl_callback(host + "/applets/order/cryptomus/notify");
|
|
|
+ String json = Jsons.toJson(cryptomusPay);
|
|
|
+ String result = HttpRequest.post("https://api.cryptomus.com/v1/test-webhook/payment").header("merchant", shopId).header("sign", MD5.create().digestHex(Base64.encode(json) + shopKey)).body(json).execute().body();
|
|
|
+ System.out.println(result);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void notify(CryptomusReturnRep cryptomusReturnRep) throws Exception {
|
|
|
+ log.info("cryptomus 支付回调 用户信息:{}", cryptomusReturnRep);
|
|
|
+ //支付成功
|
|
|
+ if("paid".equals(cryptomusReturnRep.getStatus())){
|
|
|
+ String sign = cryptomusReturnRep.getSign();
|
|
|
+ ObjectMapper mapper = new ObjectMapper();
|
|
|
+ ObjectNode jsonNode = mapper.valueToTree(cryptomusReturnRep);
|
|
|
+ jsonNode.remove("sign");
|
|
|
+ String json = mapper.writeValueAsString(jsonNode);
|
|
|
+ String hash = MD5.create().digestHex(Base64.encode(json) + shopKey);
|
|
|
+ if (!sign.equals(hash)){
|
|
|
+ throw new BusinessRuntimeException(GatewayApiCode.METADATA_SYSTEM_ERROR.getCode(),"System error");
|
|
|
+ }
|
|
|
+ String orderId = cryptomusReturnRep.getOrderId();
|
|
|
+ String transationId = cryptomusReturnRep.getUuid();
|
|
|
+ String commission = cryptomusReturnRep.getCommission();
|
|
|
+ //更新订单支付状态
|
|
|
+ OrderDon orderDon = orderDonService.getById(orderId);
|
|
|
+ orderDon.setTransactionId(transationId);
|
|
|
+ orderDon.setPayTime(new Date());
|
|
|
+ orderDon.setAbroadTransactionFee(new BigDecimal(commission).multiply(BigDecimal.valueOf(100)));
|
|
|
+ orderDonService.orderNotify(orderDon);
|
|
|
+ log.info("支付成功订单:"+orderId+",支付交易号:"+transationId);
|
|
|
+ log.info("支付成功订单:"+orderId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public Boolean refund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
|
|
|
+ BigDecimal net = refundReq.getRefundMoney().subtract(orderDon.getAbroadTransactionFee());
|
|
|
+ log.info("cryptomus return order:{},money:{}",orderDon.getId(),net);
|
|
|
+ CryptomusRefundReq cryptomusRefundReq = new CryptomusRefundReq();
|
|
|
+ cryptomusRefundReq.setAddress(refundReq.getAddress());
|
|
|
+ cryptomusRefundReq.setUuid(orderDon.getTransactionId());
|
|
|
+ cryptomusRefundReq.setOrder_id(orderDon.getId().toString());
|
|
|
+ cryptomusRefundReq.setIs_subtract(false);
|
|
|
+ String json = Jsons.toJson(cryptomusRefundReq);
|
|
|
+ String result = HttpRequest.post("https://api.cryptomus.com/v1/payment/refund").header("merchant", shopId).header("sign", MD5.create().digestHex(Base64.encode(json) + shopKey)).body(json).execute().body();
|
|
|
+ CryptomusRefundRep cryptomusRefundRep = Jsons.parseObject(result, CryptomusRefundRep.class);
|
|
|
+ if (cryptomusRefundRep.getState() == 0){
|
|
|
+ orderDon.setStatus(OrderDon.Status.refund);
|
|
|
+ orderDonService.updateById(orderDon);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ log.info("paypal return refund:{}",cryptomusRefundRep);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|