| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731 |
- package com.izouma.nineth.service;
- import cn.com.sandpay.cashier.sdk.*;
- import com.alibaba.fastjson.JSONObject;
- import com.izouma.nineth.config.Constants;
- import com.izouma.nineth.config.GeneralProperties;
- import com.izouma.nineth.config.RedisKeys;
- import com.izouma.nineth.config.SandPayProperties;
- import com.izouma.nineth.dto.PayQuery;
- import com.izouma.nineth.enums.PayStatus;
- import com.izouma.nineth.exception.BusinessException;
- import com.izouma.nineth.repo.AuctionOrderRepo;
- 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.MD5Util;
- import com.izouma.nineth.utils.SnowflakeIdWorker;
- import lombok.AllArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.codec.binary.Base64;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.stereotype.Service;
- import java.io.IOException;
- import java.math.BigDecimal;
- import java.math.RoundingMode;
- import java.net.URLDecoder;
- import java.net.URLEncoder;
- import java.nio.charset.StandardCharsets;
- import java.text.DecimalFormat;
- import java.text.DecimalFormatSymbols;
- import java.text.SimpleDateFormat;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- import java.util.*;
- import java.util.concurrent.TimeUnit;
- @Service
- @AllArgsConstructor
- @Slf4j
- public class SandPayService {
- private final OrderRepo orderRepo;
- private final GiftOrderRepo giftOrderRepo;
- private final SandPayProperties sandPayProperties;
- private final MintOrderRepo mintOrderRepo;
- private final SnowflakeIdWorker snowflakeIdWorker;
- private final GeneralProperties generalProperties;
- private final AuctionOrderRepo auctionOrderRepo;
- private final RedisTemplate<String, Object> redisTemplate;
- public static String paddingOrderId(String orderId) {
- if (orderId != null && orderId.length() < 12) {
- StringBuilder orderIdBuilder = new StringBuilder(orderId);
- for (int i = orderIdBuilder.length(); i < 12; i++) {
- orderIdBuilder.insert(0, "0");
- }
- orderId = orderIdBuilder.toString();
- }
- return orderId;
- }
- public static String getReqTime() {
- return DateTimeUtils.format(LocalDateTime.now(), "yyyyMMddHHmmss");
- }
- public static String getTimeout(int seconds) {
- return DateTimeUtils.format(LocalDateTime.now().plusSeconds(seconds), "yyyyMMddHHmmss");
- }
- public static String getTimeout(LocalDateTime createTime, int seconds) {
- return DateTimeUtils.format(Optional.ofNullable(createTime).orElse(LocalDateTime.now())
- .plusSeconds(seconds), "yyyyMMddHHmmss");
- }
- public static String convertAmount(BigDecimal amount) {
- DecimalFormat df = new DecimalFormat("000000000000", DecimalFormatSymbols.getInstance(Locale.US));
- return df.format(amount.multiply(new BigDecimal("100")));
- }
- public static JSONObject requestServer(JSONObject header, JSONObject body, String reqAddr) {
- Map<String, String> reqMap = new HashMap<String, String>();
- JSONObject reqJson = new JSONObject();
- reqJson.put("head", header);
- reqJson.put("body", body);
- String reqStr = reqJson.toJSONString();
- String reqSign;
- // 签名
- try {
- reqSign = new String(Base64.encodeBase64(CryptoUtil.digitalSign(reqStr.getBytes(StandardCharsets.UTF_8),
- CertUtil.getPrivateKey(), "SHA1WithRSA")));
- } catch (Exception e) {
- log.error(e.getMessage());
- return null;
- }
- //整体报文格式
- reqMap.put("charset", "UTF-8");
- reqMap.put("data", reqStr);
- reqMap.put("signType", "01");
- reqMap.put("sign", reqSign);
- reqMap.put("extend", "");
- String result;
- try {
- log.info("请求报文:\n{}", JSONObject.toJSONString(reqJson, true));
- result = HttpClient.doPost(reqAddr, reqMap, 30000, 30000);
- result = URLDecoder.decode(result, StandardCharsets.UTF_8);
- } catch (IOException e) {
- log.error(e.getMessage());
- return null;
- }
- Map<String, String> respMap = SDKUtil.convertResultStringToMap(result);
- String respData = respMap.get("data");
- String respSign = respMap.get("sign");
- // 验证签名
- boolean valid;
- try {
- valid = CryptoUtil.verifyDigitalSign(respData.getBytes(StandardCharsets.UTF_8),
- Base64.decodeBase64(respSign), CertUtil.getPublicKey(), "SHA1WithRSA");
- if (!valid) {
- log.error("verify sign fail.");
- return null;
- }
- log.info("verify sign success");
- JSONObject respJson = JSONObject.parseObject(respData);
- if (respJson != null) {
- log.info("响应码:[{}]", respJson.getJSONObject("head").getString("respCode"));
- log.info("响应描述:[{}]", respJson.getJSONObject("head").getString("respMsg"));
- log.info("响应报文:\n{}", JSONObject.toJSONString(respJson, true));
- } else {
- log.error("服务器请求异常!!!");
- }
- return respJson;
- } catch (Exception e) {
- log.error(e.getMessage());
- return null;
- }
- }
- public String pay(String orderId, String subject, BigDecimal amount, LocalDateTime expireAt, String type) {
- String pOrderId = paddingOrderId(orderId);
- JSONObject extend = new JSONObject();
- extend.put("type", type);
- extend.put("orderId", pOrderId);
- extend.put("id", pOrderId);
- JSONObject header = new JSONObject();
- header.put("version", "1.0"); //版本号
- header.put("method", "sandpay.trade.precreate"); //接口名称:统一下单并支付
- header.put("productId", "00000006"); //产品编码
- header.put("mid", sandPayProperties.getMid()); //商户号
- header.put("accessType", "1"); //接入类型设置为普通商户接入
- header.put("channelType", "07"); //渠道类型:07-互联网 08-移动端
- header.put("reqTime", getReqTime()); //请求时间
- JSONObject body = new JSONObject();
- body.put("payTool", "0401"); //支付工具: 固定填写0401
- body.put("orderCode", pOrderId); //商户订单号
- body.put("totalAmount", convertAmount(amount)); //订单金额 12位长度,精确到分
- //body.put("limitPay", "5"); //限定支付方式 送1-限定不能使用贷记卡 送4-限定不能使用花呗 送5-限定不能使用贷记卡+花呗
- body.put("subject", subject); //订单标题
- body.put("body", subject); //订单描述
- body.put("txnTimeOut", getTimeout(expireAt, 0)); //订单超时时间
- body.put("notifyUrl", sandPayProperties.getNotifyUrl()); //异步通知地址
- body.put("bizExtendParams", ""); //业务扩展参数
- body.put("merchExtendParams", ""); //商户扩展参数
- body.put("extend", extend.toJSONString()); //扩展域
- JSONObject res = requestServer(header, body, "https://cashier.sandpay.com.cn/qr/api/order/create");
- String respCode = res.getJSONObject("head").getString("respCode");
- if ("000000".equals(respCode)) {
- redisTemplate.opsForValue()
- .set(RedisKeys.PAY_TMP + orderId, Constants.PayChannel.SAND, 1, TimeUnit.DAYS);
- return "alipays://platformapi/startapp?saId=10000007&qrcode="
- + res.getJSONObject("body").getString("qrCode");
- }
- String msg = res.getJSONObject("head").getString("respMsg");
- throw new BusinessException(Constants.PAY_ERR_MSG, msg);
- }
- public String payQuick(String orderId, String subject, BigDecimal amount, LocalDateTime expireAt,
- String type, String returnUrl) {
- String pOrderId = paddingOrderId(orderId);
- JSONObject extend = new JSONObject();
- extend.put("type", type);
- extend.put("orderId", pOrderId);
- extend.put("id", pOrderId);
- JSONObject header = new JSONObject();
- header.put("version", "1.0"); //版本号
- header.put("method", "sandpay.trade.pay"); //接口名称:统一下单
- header.put("mid", sandPayProperties.getMid()); //商户号
- header.put("accessType", "1"); //接入类型设置为平台商户接入 //接入类型设置为普通商户接入
- header.put("channelType", "07"); //渠道类型:07-互联网 08-移动端
- header.put("reqTime", getReqTime()); //请求时间
- header.put("productId", "00000008"); //产品编码
- JSONObject body = new JSONObject();
- body.put("orderCode", pOrderId); //商户订单号
- body.put("totalAmount", convertAmount(amount)); //订单金额
- body.put("subject", subject); //订单标题
- body.put("body", subject); //订单描述
- body.put("txnTimeOut", getTimeout(expireAt, 0)); //订单超时时间
- body.put("clientIp", "192.168.22.55"); //客户端IP
- body.put("limitPay", ""); //限定支付方式 送1-限定不能使用贷记卡送 4-限定不能使用花呗 送5-限定不能使用贷记卡+花呗
- body.put("notifyUrl", sandPayProperties.getNotifyUrl()); //异步通知地址
- body.put("frontUrl", returnUrl); //前台通知地址
- body.put("storeId", ""); //商户门店编号
- body.put("terminalId", ""); //商户终端编号
- body.put("operatorId", ""); //操作员编号
- body.put("clearCycle", ""); //清算模式
- body.put("royaltyInfo", ""); //分账信息
- body.put("riskRateInfo", ""); //风控信息域
- body.put("bizExtendParams", ""); //业务扩展参数
- body.put("merchExtendParams", ""); //商户扩展参数
- body.put("extend", extend.toJSONString()); //扩展域
- body.put("payMode", "sand_h5"); //支付模式
- JSONObject res = requestServer(header, body, "https://cashier.sandpay.com.cn/gateway/api/order/pay");
- String respCode = res.getJSONObject("head").getString("respCode");
- if ("000000".equals(respCode)) {
- redisTemplate.opsForValue()
- .set(RedisKeys.PAY_TMP + orderId, Constants.PayChannel.SAND, 1, TimeUnit.DAYS);
- return res.getJSONObject("body").getString("credential");
- }
- String msg = res.getJSONObject("head").getString("respMsg");
- throw new BusinessException(Constants.PAY_ERR_MSG, msg);
- }
- public String payQuickBind(String orderId, String subject, BigDecimal amount, LocalDateTime expireAt,
- String type, String returnUrl, Long userId, String name, String idNo) {
- String pOrderId = paddingOrderId(orderId);
- SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
- Calendar calendar = Calendar.getInstance();
- String createTime = sdf.format(calendar.getTime());
- calendar.add(Calendar.HOUR, 1);
- String endTime = sdf.format(calendar.getTime());
- String version = "10";
- String mer_no = sandPayProperties.getMid();
- //key1
- String mer_key = "fvLh4EEoJPJEkqg+6s3B8sTRVREAyVAxS34+5JGiJOmIFnIrnfD1k/KiUYo5Nfb7tBx0jj9HOI0=";
- UUID uuid = UUID.randomUUID();
- String mer_order_no = uuid.toString().replaceAll("-", "");
- String notify_url = sandPayProperties.getNotifyUrl();
- String order_amt = amount.toPlainString();
- //"userId":"用户在商户下唯一标识 1-10位","userName":"证件姓名","idCard":"18位身份证号码"
- String pay_extra = "{\"userId\":\"" + userId + "\",\"userName\":\"" + name + "\",\"idCard\":\"" + idNo + "\"}";
- //md5key
- String key = "KvKQYXhwvkoQRAiQN2IzVSaecqYFP8emDHJrLettbShZsd8k/V2OU/myAV6My/qeotZ8K0WG8ifDzgelCexY7517gmF7SqFUcyuKgSC+HFNmn14C4iy9JRy0NvsSJRjgMzZWAhrwNL5ixuz+UKFTiw==";
- JSONObject extend = new JSONObject();
- extend.put("type", type);
- extend.put("orderId", pOrderId);
- extend.put("id", pOrderId);
- Map<String, String> map = new LinkedHashMap<>();
- map.put("accsplit_flag", "NO");
- map.put("create_ip", "127_0_0_1");
- map.put("create_time", createTime);
- map.put("extend", extend.toJSONString());
- // if(!(gh_static_url==null||"".equals(gh_static_url)))map.put("gh_static_url",gh_static_url);;
- map.put("mer_key", mer_key);
- map.put("mer_no", mer_no);
- map.put("mer_order_no", mer_order_no);
- map.put("notify_url", notify_url);
- map.put("order_amt", order_amt);
- map.put("pay_extra", pay_extra);
- map.put("return_url", returnUrl);
- map.put("sign_type", "MD5");
- map.put("store_id", "000000");
- map.put("version", version);
- map.put("key", key);
- // map.put("extend", "aaa");
- // map.put("expire_time",endTime);
- // map.put("goods_name",goods_name);
- // map.put("product_code","02010006");
- // map.put("clear_cycle","0");
- String signature = "";
- for (String s : map.keySet()) {
- if (!(map.get(s) == null || map.get(s).equals(""))) {
- signature += s + "=";
- signature += map.get(s) + "&";
- }
- }
- signature = signature.substring(0, signature.length() - 1);
- String sign = MD5Util.encode(signature).toUpperCase();
- //url
- return "https://sandcash.mixienet.com.cn/pay/h5/quicktopup?" +
- "version=" + version +
- "&mer_no=" + mer_no +
- "&mer_key=" + URLEncoder.encode(mer_key, StandardCharsets.UTF_8) +
- "&mer_order_no=" + mer_order_no +
- "&create_time=" + createTime +
- "&expire_time=" + getTimeout(expireAt, 0) +
- "&extend=" + URLEncoder.encode(extend.toJSONString(), StandardCharsets.UTF_8) +
- "&order_amt=" + order_amt +
- "¬ify_url=" + URLEncoder.encode(notify_url, StandardCharsets.UTF_8) +
- "&return_url=" + URLEncoder.encode(returnUrl, StandardCharsets.UTF_8) +
- "&create_ip=127_0_0_1" +
- "&goods_name=" + URLEncoder.encode(subject, StandardCharsets.UTF_8) +
- "&store_id=000000" +
- "&product_code=06030003" +
- "&clear_cycle=3" +
- "&pay_extra=" + URLEncoder.encode(pay_extra, StandardCharsets.UTF_8) +
- "&meta_option=%5B%7B%22s%22%3A%22Android%22,%22n%22%3A%22wxDemo%22,%22id%22%3A%22com.pay.paytypetest%22,%22sc%22%3A%22com.pay.paytypetest%22%7D%5D" +
- "&accsplit_flag=NO" +
- "&jump_scheme=" +
- // "&gh_static_url="+gh_static_url+""+
- "&sign_type=MD5" +
- "&key=" + URLEncoder.encode(key, StandardCharsets.UTF_8) +
- "&sign=" + sign;
- }
- public JSONObject query(String orderId) {
- orderId = paddingOrderId(orderId);
- JSONObject header = new JSONObject();
- header.put("version", "1.0"); //版本号
- header.put("method", "sandpay.trade.query"); //接口名称:订单查询
- header.put("productId", "00000006"); //产品编码
- header.put("mid", sandPayProperties.getMid()); //商户号
- header.put("accessType", "1"); //接入类型设置为普通商户接入
- header.put("channelType", "07"); //渠道类型:07-互联网 08-移动端
- header.put("reqTime", getReqTime()); //请求时间
- JSONObject body = new JSONObject();
- body.put("orderCode", orderId);
- body.put("extend", ""); //扩展域
- return requestServer(header, body, "https://cashier.sandpay.com.cn/qr/api/order/query");
- }
- public JSONObject refund(String orderId, BigDecimal amount) {
- orderId = paddingOrderId(orderId);
- JSONObject header = new JSONObject();
- header.put("version", "1.0"); //版本号
- header.put("method", "sandpay.trade.refund"); //接口名称:退货
- header.put("productId", "00000006"); //产品编码
- header.put("mid", sandPayProperties.getMid()); //商户号
- header.put("accessType", "1"); //接入类型设置为普通商户接入
- header.put("channelType", "07"); //渠道类型:07-互联网 08-移动端
- header.put("reqTime", getReqTime()); //请求时间
- JSONObject body = new JSONObject();
- body.put("orderCode", snowflakeIdWorker.nextId()); //商户订单号
- body.put("oriOrderCode", paddingOrderId(orderId)); //原交易订单号
- body.put("refundAmount", convertAmount(amount)); //退货金额
- body.put("refundReason", "退款"); //退货原因
- body.put("notifyUrl", sandPayProperties.getNotifyUrl()); //异步通知地址
- body.put("extend", "");
- return requestServer(header, body, "https://cashier.sandpay.com.cn/qr/api/order/refund");
- }
- public JSONObject transfer(String id, String name, String bank, BigDecimal amount, String phone) {
- 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", getReqTime()); //交易时间
- request.put("orderCode", id); //订单号
- request.put("timeOut", getTimeout(180)); //订单超时时间
- 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", 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, 300000, 300000);
- 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;
- }
- }
- public JSONObject queryTransfer(String tranTime, String orderId) {
- JSONObject request = new JSONObject();
- request.put("version", "01"); // 版本号
- request.put("productId", "00000004"); // 产品ID
- request.put("tranTime", tranTime); // 查询订单的交易时间
- request.put("orderCode", orderId); // 要查询的订单号
- 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", "ODQU"); // 交易码
- reqMap.put("accessType", "0"); // 接入类型
- reqMap.put("merId", sandPayProperties.getMid()); // 合作商户ID 杉德系统分配,唯一标识
- reqMap.put("plId", null);
- 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/queryOrder",
- reqMap, 300000, 300000);
- 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;
- }
- }
- public PayQuery payQuery(String orderId) {
- JSONObject res = query(orderId);
- PayQuery query = new PayQuery(Constants.PayChannel.SAND);
- String respCode = res.getJSONObject("head").getString("respCode");
- if ("000000".equals(respCode)) {
- query.setExist(true);
- JSONObject body = res.getJSONObject("body");
- query.setMsg(body.getString("orderMsg") + " " + body.getString("oriRespMsg"));
- query.setAmount(new BigDecimal(body.getString("totalAmount"))
- .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
- query.setTransactionId(body.getString("payOrderCode"));
- if (StringUtils.isNotEmpty(body.getString("payTime"))) {
- query.setPayTime(LocalDateTime.parse(body.getString("payTime"), DateTimeFormatter.ofPattern("yyyyMMddHHmmss")));
- }
- if (StringUtils.isNotEmpty(body.getString("oriOrderCode"))) {
- query.setOrderId(body.getString("oriOrderCode"));
- }
- switch (body.getString("orderStatus")) {
- case "00":
- query.setStatus(PayStatus.SUCCESS);
- break;
- case "01":
- query.setStatus(PayStatus.PENDING);
- break;
- case "02":
- query.setStatus(PayStatus.FAIL);
- break;
- case "03":
- query.setStatus(PayStatus.CANCEL);
- break;
- case "04":
- query.setStatus(PayStatus.REFUNDED);
- break;
- case "05":
- query.setStatus(PayStatus.REFUNDING);
- break;
- }
- } else {
- query.setExist(false);
- query.setMsg(res.getString("msg"));
- }
- return query;
- }
- public BigDecimal balance() {
- JSONObject request = new JSONObject();
- request.put("version", "01"); //版本号
- request.put("productId", "00000004"); //产品ID
- request.put("tranTime", getReqTime()); //交易时间
- request.put("orderCode", snowflakeIdWorker.nextId()); //订单号
- 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", "MBQU"); // 交易码
- 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/queryBalance",
- reqMap, 300000, 300000);
- 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.getBigDecimal("balance").divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
- } catch (Exception e) {
- log.error(e.getMessage());
- return null;
- }
- }
- }
|