xiongzhu před 4 roky
rodič
revize
0235df3181

+ 117 - 1
src/main/java/com/izouma/nineth/service/SandPayService.java

@@ -13,6 +13,7 @@ import com.izouma.nineth.repo.GiftOrderRepo;
 import com.izouma.nineth.repo.MintOrderRepo;
 import com.izouma.nineth.repo.OrderRepo;
 import com.izouma.nineth.utils.DateTimeUtils;
+import com.izouma.nineth.utils.SnowflakeIdWorker;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.binary.Base64;
@@ -233,6 +234,121 @@ public class SandPayService {
     }
 
 
-    public void transfer(String name, String bank, BigDecimal amount) {
+    public JSONObject transfer(String name, String bank, BigDecimal amount) {
+        JSONObject request = new JSONObject();
+        DecimalFormat df = new DecimalFormat("000000000000", DecimalFormatSymbols.getInstance(Locale.US));
+        request.put("version", "01");                          //版本号
+        request.put("productId", "00000004");                  //产品ID
+        request.put("tranTime", DateTimeUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss"));                //交易时间
+        request.put("orderCode", new SnowflakeIdWorker(1, 1).nextId());                       //订单号
+        request.put("timeOut", DateTimeUtils.format(LocalDateTime.now().plusMinutes(3), "yyyyMMddHHmmss"));  //订单超时时间
+        request.put("tranAmt", df.format(amount.multiply(new BigDecimal("100"))));                           //金额
+        request.put("currencyCode", "156");                    //币种
+        request.put("accAttr", "0");                           //账户属性     0-对私   1-对公
+        request.put("accType", "4");                           //账号类型      3-公司账户  4-银行卡
+        request.put("accNo", bank);                            //收款人账户号
+        request.put("accName", name);                          //收款人账户名
+        request.put("provNo", "");                             //收款人开户省份编码
+        request.put("cityNo", "");                             //收款人开会城市编码
+        request.put("bankName", "");                           //收款账户开户行名称
+        request.put("bankType", "");                           //收款人账户联行号
+        request.put("remark", "消费");                          //摘要
+        request.put("payMode", "");                            //付款模式
+        request.put("channelType", "");                        //渠道类型
+        request.put("extendParams", "");                       //业务扩展参数
+        request.put("reqReserved", "");                        //请求方保留域
+        request.put("extend", "");                             //扩展域
+        request.put("phone", "");                              //手机号
+
+        String reqData = request.toJSONString();
+        log.info("请求数据:{}", reqData);
+
+        try {
+
+            String aesKey = RandomStringGenerator.getRandomStringByLength(16);
+            byte[] aesKeyBytes = aesKey.getBytes(StandardCharsets.UTF_8);
+
+            byte[] plainBytes = reqData.getBytes(StandardCharsets.UTF_8);
+            String encryptData = new String(Base64.encodeBase64(
+                    CryptoUtil.AESEncrypt(plainBytes, aesKeyBytes, "AES",
+                            "AES/ECB/PKCS5Padding", null)), StandardCharsets.UTF_8);
+
+            String sign = new String(Base64.encodeBase64(
+                    CryptoUtil.digitalSign(plainBytes, CertUtil.getPrivateKey(),
+                            "SHA1WithRSA")), StandardCharsets.UTF_8);
+
+            String encryptKey = new String(Base64.encodeBase64(
+                    CryptoUtil.RSAEncrypt(aesKeyBytes, CertUtil.getPublicKey(), 2048, 11,
+                            "RSA/ECB/PKCS1Padding")), StandardCharsets.UTF_8);
+
+
+            Map<String, String> reqMap = new HashMap<String, String>();
+            //整体报文格式
+            reqMap.put("transCode", "RTPM"); // 交易码
+            reqMap.put("accessType", "0"); // 接入类型
+            reqMap.put("merId", sandPayProperties.getMid()); // 合作商户ID	杉德系统分配,唯一标识
+            reqMap.put("encryptKey", encryptKey); // 加密后的AES秘钥
+            reqMap.put("encryptData", encryptData); // 加密后的请求/应答报文
+            reqMap.put("sign", sign); // 签名
+            reqMap.put("extend", ""); // 扩展域
+
+            String result;
+            try {
+                log.info("请求报文:{}", reqMap);
+                result = HttpClient.doPost("https://caspay.sandpay.com.cn/agent-main/openapi/agentpay",
+                        reqMap, 10000, 10000);
+                result = URLDecoder.decode(result, StandardCharsets.UTF_8);
+            } catch (IOException e) {
+                log.error(e.getMessage());
+                return null;
+            }
+
+            log.info("响应报文:{}", result);
+            Map<String, String> responseMap = SDKUtil.convertResultStringToMap(result);
+
+            String retEncryptKey = responseMap.get("encryptKey");
+            String retEncryptData = responseMap.get("encryptData");
+            String retSign = responseMap.get("sign");
+
+            log.debug("retEncryptKey:[{}]", retEncryptKey);
+            log.debug("retEncryptData:[{}]", retEncryptData);
+            log.debug("retSign:[{}]", retSign);
+
+            byte[] decodeBase64KeyBytes = Base64.decodeBase64(retEncryptKey
+                    .getBytes(StandardCharsets.UTF_8));
+
+            byte[] merchantAESKeyBytes = CryptoUtil.RSADecrypt(
+                    decodeBase64KeyBytes, CertUtil.getPrivateKey(), 2048, 11,
+                    "RSA/ECB/PKCS1Padding");
+
+            byte[] decodeBase64DataBytes = Base64.decodeBase64(retEncryptData.getBytes(StandardCharsets.UTF_8));
+
+            byte[] respDataBytes = CryptoUtil.AESDecrypt(decodeBase64DataBytes,
+                    merchantAESKeyBytes, "AES", "AES/ECB/PKCS5Padding", null);
+
+            String respData = new String(respDataBytes, StandardCharsets.UTF_8);
+            log.info("retData:[" + respData + "]");
+            System.out.println("响应data数据:" + respData);
+
+            byte[] signBytes = Base64.decodeBase64(retSign.getBytes(StandardCharsets.UTF_8));
+
+            boolean isValid = CryptoUtil.verifyDigitalSign(respDataBytes, signBytes,
+                    CertUtil.getPublicKey(), "SHA1WithRSA");
+
+            if (!isValid) {
+                log.error("verify sign fail.");
+                return null;
+            }
+            log.info("verify sign success");
+            System.out.println("verify sign success");
+
+            JSONObject respJson = JSONObject.parseObject(respData);
+            return respJson;
+
+        } catch (Exception e) {
+
+            log.error(e.getMessage());
+            return null;
+        }
     }
 }

+ 8 - 4
src/main/java/com/izouma/nineth/web/SandPayController.java

@@ -15,10 +15,8 @@ import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.rocketmq.spring.core.RocketMQTemplate;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -50,6 +48,12 @@ public class SandPayController {
         return "<html><body><a href=\"" + qrCode + "\">" + qrCode + "</a></body></html>";
     }
 
+    @PreAuthorize("hasRole('ADMIN')")
+    @GetMapping(value = "/testTransfer", produces = "text/html")
+    private Object testTransfer(@RequestParam String name, @RequestParam String bank, @RequestParam BigDecimal amount) {
+        return sandPayService.transfer(name, bank, amount);
+    }
+
     @PostMapping("/notify")
     public Object notifyOrder(HttpServletRequest req, HttpServletResponse resp) {
         String data = req.getParameter("data");

+ 2 - 2
src/test/java/com/izouma/nineth/CommonTest.java

@@ -15,6 +15,7 @@ import com.izouma.nineth.dto.SandPaySettle;
 import com.izouma.nineth.dto.UserWithdraw;
 import com.izouma.nineth.service.UserService;
 import com.izouma.nineth.utils.AESEncryptUtil;
+import com.izouma.nineth.utils.SnowflakeIdWorker;
 import com.izouma.nineth.utils.TokenUtils;
 import com.izouma.nineth.web.BaseController;
 import io.ipfs.api.IPFS;
@@ -627,7 +628,6 @@ public class CommonTest {
 
     @Test
     public void match() {
-        UserService.checkPasswordStrength("12345678aF[");
-        System.out.println(Pattern.matches("^[a-zA-Z0-9!@#$%^&*]+$", "[121213a123"));
+        System.out.println(String.format("%012d", new SnowflakeIdWorker(1,1).nextId()));
     }
 }