文档控制台
文档首页/
Paynicorn 支付/
API 文档/
服务端接入示例代码/

服务端接入示例代码

更新时间:2024.06.25 09:52:42

服务端接入示例代码

以下代码示例帮助商户的服务端研发快速完成 H5 支付收银台的接入工作。

在线支付

预下单

package com.platform.horizonservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.platform.horizonservice.constants.ResultCode;
import com.platform.horizonservice.feign.PaynicornCpFeignClient;
import com.platform.horizonservice.feign.model.CommonRequest;
import com.platform.horizonservice.feign.model.CommonResponse;
import com.platform.horizonservice.feign.model.TradePaymentRequest;
import com.platform.horizonservice.feign.model.TradePaymentResponse;
import com.platform.horizonservice.pojo.dto.TopUpPaymentDto;
import com.platform.horizonservice.pojo.vo.TopUpPaymentResult;
import com.platform.horizonservice.service.ITopUpTradePrePayService;
import com.platform.horizonservice.util.PaynicornSignUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;

import javax.annotation.Resource;

/**
 * @author simon.sheng
 * @version 1.0.0
 * @since 1.8.0
 */
@Service("TopUpTradePrePayService")
@Slf4j
public class TopUpTradePrePayServiceImpl implements ITopUpTradePrePayService {

    private static final String TXN_ID = "txnId";
    private static final String CODE = "code";
    private static final String MESSAGE = "message";
    private static final String STATUS = "status";
    private static final String WEB_URL = "webUrl";
    private static final String STEP_STATUS = "stepStatus";
    @Resource
    private PaynicornCpFeignClient cpGatewayFeignClient;
    @Value("${paynicorn.pay.mobile.topUp.appKey}")
    private String paynicornPayMobileAppKey;
    @Value("${paynicorn.pay.mobile.topUp.privateKey}")
    private String paynicornPayMobilePrivateKey;

    @Override
    public TopUpPaymentResult raisePrePay(TopUpPaymentDto topUpPaymentDto) {
        TopUpPaymentResult resultVo;
        String cpOrderId = topUpPaymentDto.getOrderId();
        String currency = topUpPaymentDto.getCurrency();
        String countryCode = topUpPaymentDto.getCountryCode();
        String amount = topUpPaymentDto.getAmount();
        String appKey = topUpPaymentDto.getAppKey();
        String orderDesc = topUpPaymentDto.getOrderDesc();

        if (StringUtils.isBlank(cpOrderId)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "CP_ORDER_ID", cpOrderId);
            return resultVo;
        }

        if (StringUtils.isBlank(amount)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "AMOUNT", amount);
            return resultVo;
        }

        if (StringUtils.isBlank(currency)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "CURRENCY", currency);
            return resultVo;
        }

        if (StringUtils.isBlank(countryCode)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "COUNTRY_CODE", countryCode);
            return resultVo;
        }

        if (StringUtils.isBlank(appKey)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "APP_KEY", appKey);
            return resultVo;
        }

        if (StringUtils.isBlank(orderDesc)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "ORDER_DESCRIPTION", orderDesc);
            return resultVo;
        }

        JSONObject payResultJson = raisePaymentRequest(topUpPaymentDto);
        resultVo = standardizedResponse(payResultJson);
        return resultVo;
    }

    private JSONObject raisePaymentRequest(TopUpPaymentDto topUpPaymentDto) {
        String id = topUpPaymentDto.getId();
        String cpOrderId = topUpPaymentDto.getOrderId();

        try {
            TradePaymentRequest requestBody = new TradePaymentRequest();
            BeanUtils.copyProperties(topUpPaymentDto, requestBody);
            requestBody.setOrderDescription(topUpPaymentDto.getOrderDesc()); //必填
            requestBody.setPayByLocalCurrency(false); //TRADE用本位币发起预下单,不用美金!

            String appKey = paynicornPayMobileAppKey;
            String appSecret = paynicornPayMobilePrivateKey;
            CommonRequest commonRequest = PaynicornSignUtils.generateCommReq(requestBody, appKey, appSecret);

            return postForTradePayment(requestBody, commonRequest, appSecret, cpOrderId, id);
        } catch (Exception e) {
            log.error(id, cpOrderId, e.getMessage(), e);
        }
        return null;

    }

    private JSONObject postForTradePayment(TradePaymentRequest requestBody, CommonRequest commonRequest, String appSecret, String cpOrderId, String id) {

        JSONObject resBody = new JSONObject();
        try {
            log.info("top-up prePay postForTradePayment in, requestBody:{}, cpOrderId:{}, id:{}", JSON.toJSONString(requestBody), cpOrderId, id);
            CommonResponse commonResponse = cpGatewayFeignClient.raisePayment(commonRequest);
            log.info("top-up prePay postForTradePayment out, responseCode:{}, cpOrderId:{}, commonResponse:{}", commonResponse.getResponseCode(), cpOrderId, JSON.toJSONString(commonResponse));

            if (!"000000".equals(commonResponse.getResponseCode())) {
                resBody.put(CODE, commonResponse.getResponseCode());
                resBody.put(MESSAGE, commonResponse.getResponseMessage());
                resBody.put(STEP_STATUS, 400);
                return resBody;
            }

            TradePaymentResponse tradeResponse = PaynicornSignUtils.decodeCommResp(commonResponse, appSecret, TradePaymentResponse.class);
            log.info("top-up prePay postForTradePayment out responseCode:{}, cpOrderId:{}, tradeResponse:{}", commonResponse.getResponseCode(), cpOrderId, JSON.toJSONString(tradeResponse));
            if (null == tradeResponse) {
                return null;
            } else {
                resBody.put(STEP_STATUS, 200);
                resBody.put(STATUS, tradeResponse.getStatus());
                resBody.put(CODE, tradeResponse.getCode());
                resBody.put(MESSAGE, tradeResponse.getMessage());
                resBody.put(TXN_ID, tradeResponse.getTxnId());
                resBody.put(WEB_URL, tradeResponse.getWebUrl());
            }
            return resBody;
        } catch (HttpServerErrorException e) {
            HttpStatus httpStatus = e.getStatusCode();
            JSONObject errorBody = JSON.parseObject(e.getResponseBodyAsString());
            if (null != errorBody) {
                resBody.put(STEP_STATUS, httpStatus.value());
                resBody.put(CODE, httpStatus.value());
                resBody.put(MESSAGE, "5XX TRADE Exception");
            }
            log.info("top-up prePay postForTradePayment 500 error. request:{},status:{},response:{},resBody:{},cpOrderId:{},id:{}", JSON.toJSONString(requestBody), httpStatus.value(), errorBody, resBody, cpOrderId, id);
            return resBody;
        } catch (HttpClientErrorException e) {
            HttpStatus httpStatus = e.getStatusCode();
            JSONObject errorBody = JSON.parseObject(e.getResponseBodyAsString());
            if (null != errorBody) {
                resBody.put(STEP_STATUS, httpStatus.value());
                resBody.put(CODE, httpStatus.value());
                resBody.put(MESSAGE, "4XX TRADE Exception");
            }
            log.info("top-up prePay postForTradePayment 400 error raise.postFortop-up new prePay is exception: status:{},body:{},error:{}, cpOrderId:{},id:{}", httpStatus.value(), errorBody, e.getMessage(), cpOrderId, id, e);
            return resBody;
        } catch (ResourceAccessException e) {
            String errorBody = e.getMessage();
            resBody.put(STEP_STATUS, 500);
            resBody.put(CODE, "SP_TIMEOUT_ERROR");
            resBody.put(MESSAGE, "TRADE SP_NETWORK_TIMEOUT_ERROR");
            log.info("top-up prePay resourceAccess exception,requestBody:{},resBody:{},cpOrderId:{},id:{}, error:{}", JSON.toJSONString(requestBody), resBody, cpOrderId, id, errorBody);
            return resBody;
        } catch (Exception e) {
            log.error("top-up prePay unknown exception: body:{},cpOrderId:{},id:{},error:{},", JSON.toJSONString(requestBody), cpOrderId, id, e.getMessage(), e);
        }
        return null;
    }

    private TopUpPaymentResult standardizedResponse(JSONObject payResultJson) {
        TopUpPaymentResult resultVo;
        ResultCode resultCode = ResultCode.FAILED;
        if (null == payResultJson) {
            resultVo = new TopUpPaymentResult(ResultCode.SP_RAISE_RESULT_EMPTY);
            resultVo.setCode("trade raise failed");
            resultVo.setMessage("trade raisePrePay returns NULL");
            return resultVo;
        }

        String txnId = payResultJson.getString(TXN_ID);
        String code = payResultJson.getString(CODE);
        String message = payResultJson.getString(MESSAGE);
        String status = payResultJson.getString(STATUS);
        String webUrl = payResultJson.getString(WEB_URL);
        if ("-1".equalsIgnoreCase(status)) {
            resultCode = ResultCode.PROCESSING;
        } else if ("1".equalsIgnoreCase(status)) {
            resultCode = ResultCode.SUCCESS;
        }

        resultVo = new TopUpPaymentResult(resultCode);
        resultVo.setTxnId(txnId);
        resultVo.setResult(status);
        resultVo.setCode(code);
        resultVo.setMessage(message);
        resultVo.setWebUrl(webUrl); //1.3 预下单结束,如果直连返回了渠道方收银台,则直接返回
        return resultVo;
    }

}

查询支付订单状态

package com.platform.horizonservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.platform.horizonservice.constants.ResultCode;
import com.platform.horizonservice.feign.PaynicornCpFeignClient;
import com.platform.horizonservice.feign.model.CommonRequest;
import com.platform.horizonservice.feign.model.CommonResponse;
import com.platform.horizonservice.feign.model.TradeQueryRequest;
import com.platform.horizonservice.feign.model.TradeQueryResponse;
import com.platform.horizonservice.pojo.dto.TopUpQueryDto;
import com.platform.horizonservice.pojo.vo.TopUpQueryResult;
import com.platform.horizonservice.service.ITopUpTradePrePayService;
import com.platform.horizonservice.util.PaynicornSignUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;

import javax.annotation.Resource;

/**
 * @author simon.sheng
 * @version 1.0.0
 * @since 1.8.0
 */
@Service("TopUpTradeQueryService")
@Slf4j
public class TopUpTradeQueryServiceImpl implements ITopUpTradePrePayService {

    private static final String TXN_ID = "txnId";
    private static final String CODE = "code";
    private static final String MESSAGE = "message";
    private static final String STATUS = "status";
    private static final String COMPLETE_TIME = "completeTime";
    private static final String STEP_STATUS = "stepStatus";
    @Resource
    private PaynicornCpFeignClient cpGatewayFeignClient;
    @Value("${paynicorn.pay.mobile.topUp.appKey}")
    private String paynicornPayMobileAppKey;
    @Value("${paynicorn.pay.mobile.topUp.privateKey}")
    private String paynicornPayMobilePrivateKey;

    @Override
    public TopUpQueryResult query(TopUpQueryDto topUpQueryDto) {
        TopUpQueryResult resultVo;
        String cpOrderId = topUpQueryDto.getOrderId();
        String appKey = topUpQueryDto.getAppKey();
        String txnType = topUpQueryDto.getTxnType();

        if (StringUtils.isBlank(cpOrderId)) {
            resultVo = new TopUpQueryResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "CP_ORDER_ID", cpOrderId);
            return resultVo;
        }

        if (StringUtils.isBlank(appKey)) {
            resultVo = new TopUpQueryResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "APP_KEY", appKey);
            return resultVo;
        }

        if (StringUtils.isBlank(txnType)) {
            resultVo = new TopUpQueryResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "TXN_TYPE", txnType);
            return resultVo;
        }

        JSONObject queryResultJson = queryPaymentRequest(topUpQueryDto);
        resultVo = standardizedResponse(queryResultJson);
        return resultVo;
    }

    private JSONObject queryPaymentRequest(TopUpQueryDto topUpQueryDto) {
        String id = topUpQueryDto.getId();
        String cpOrderId = topUpQueryDto.getOrderId();

        try {
            TradeQueryRequest requestBody = new TradeQueryRequest();
            BeanUtils.copyProperties(topUpQueryDto, requestBody);

            String appKey = paynicornPayMobileAppKey;
            String appSecret = paynicornPayMobilePrivateKey;
            CommonRequest commonRequest = PaynicornSignUtils.generateCommReq(requestBody, appKey, appSecret);

            return postForTradeQuery(commonRequest, requestBody, appSecret, cpOrderId, id);
        } catch (Exception e) {
            log.error(id, cpOrderId, e.getMessage(), e);
        }
        return null;

    }

    private JSONObject postForTradeQuery(CommonRequest commonRequest, TradeQueryRequest requestBody, String appSecret, String cpOrderId, String id) {

        JSONObject resBody = new JSONObject();
        try {
            log.info("top-up postForTradeQuery in, requestBody:{}, cpOrderId:{}, id:{}", JSON.toJSONString(requestBody), cpOrderId, id);
            CommonResponse commonResponse = cpGatewayFeignClient.queryPayment(commonRequest);
            log.info("top-up postForTradeQuery out, responseCode:{}, cpOrderId:{}, commonResponse:{}", commonResponse.getResponseCode(), cpOrderId, JSON.toJSONString(commonResponse));

            if (!"000000".equals(commonResponse.getResponseCode())) {
                resBody.put(CODE, commonResponse.getResponseCode());
                resBody.put(MESSAGE, commonResponse.getResponseMessage());
                resBody.put(STEP_STATUS, 400);
                return resBody;
            }

            TradeQueryResponse tradeResponse = PaynicornSignUtils.decodeCommResp(commonResponse, appSecret, TradeQueryResponse.class);
            log.info("top-up postForTradeQuery out responseCode:{}, cpOrderId:{}, tradeResponse:{}", commonResponse.getResponseCode(), cpOrderId, JSON.toJSONString(tradeResponse));

            if (null == tradeResponse) {
                return null;
            } else {
                resBody.put(STEP_STATUS, 200);
                resBody.put(STATUS, tradeResponse.getStatus());
                resBody.put(CODE, tradeResponse.getCode());
                resBody.put(MESSAGE, tradeResponse.getMessage());
                resBody.put(TXN_ID, tradeResponse.getTxnId());
                resBody.put(COMPLETE_TIME, tradeResponse.getCompleteTime());
                return resBody;
            }
        } catch (HttpServerErrorException e) {
            String response = e.getResponseBodyAsString();
            HttpStatus httpStatus = e.getStatusCode();
            JSONObject responseJSON = JSON.parseObject(response);
            if (null != responseJSON) {
                resBody.put(STEP_STATUS, httpStatus.value());
                resBody.put(CODE, httpStatus.value());
                resBody.put(MESSAGE, "5XX TRADE Exception");
            }
            log.info("top-up 500 error. postForTradeQuery request:{},status:{},response:{},resBody:{},cpOrderId:{},id:{}", requestBody, httpStatus.value(), response, resBody, cpOrderId, id);
            return resBody;
        } catch (HttpClientErrorException e) {
            HttpStatus httpStatus = e.getStatusCode();
            JSONObject errorBody = JSON.parseObject(e.getResponseBodyAsString());
            if (null != errorBody) {
                resBody.put(STEP_STATUS, httpStatus.value());
                resBody.put(CODE, httpStatus.value());
                resBody.put(MESSAGE, "4XX TRADE Exception");
            }
            log.info("top-up 400 error.postForTradeQuery is exception: status:{},body:{},error:{}, cpOrderId:{},id:{}", httpStatus.value(), errorBody, e.getMessage(), cpOrderId, id, e);
            return resBody;
        } catch (ResourceAccessException e) {
            String errorBody = e.getMessage();
            resBody.put(STEP_STATUS, 500);
            resBody.put(CODE, "SP_TIMEOUT_ERROR");
            resBody.put(MESSAGE, "TRADE SP_NETWORK_TIMEOUT_ERROR");
            log.info("top-up query resourceAccess exception,requestBody:{},error:{},resBody:{},cpOrderId:{},id:{}", requestBody, errorBody, resBody, cpOrderId, id);
            return resBody;
        } catch (Exception e) {
            log.error("top-up unknown error query.postForTradeQuery is exception: body:{},error:{},cpOrderId:{},id:{}", requestBody, e.getMessage(), cpOrderId, id, e);
        }
        return null;
    }

    private TopUpQueryResult standardizedResponse(JSONObject payResultJson) {
        TopUpQueryResult resultVo;
        ResultCode resultCode;
        if (null == payResultJson) {
            resultVo = new TopUpQueryResult(ResultCode.UNKNOWN);
            resultVo.setCode("trade query failed");
            resultVo.setMessage("trade query returns NULL");
            return resultVo;
        }

        String txnId = payResultJson.getString(TXN_ID);
        String code = payResultJson.getString(CODE);
        String message = payResultJson.getString(MESSAGE);
        String status = payResultJson.getString(STATUS);
        String completeTime = payResultJson.getString(COMPLETE_TIME);

        if ("0".equalsIgnoreCase(status)) {
            resultCode = ResultCode.FAILED;
        } else if ("1".equalsIgnoreCase(status)) {
            resultCode = ResultCode.SUCCESS;
        } else {
            resultCode = ResultCode.PROCESSING;
        }

        resultVo = new TopUpQueryResult(resultCode);
        resultVo.setTxnId(txnId);
        resultVo.setResult(status);
        resultVo.setCode(code);
        resultVo.setMessage(message);
        resultVo.setCompleteTime(completeTime);
        return resultVo;
    }

}

接受回调通知

# CALLBACK SAMPLE
root@paynicorn-trade-694fb6dfb4-n77cv:/# curl --location 'https://mehndi-india.shalltry.com/mehndi/payment/manage/pay-back' \
> --header 'Content-Type: application/json' \
> --data '{"content":"eyJhbW91bnQiOiIxMDAiLCJjb2RlIjoiMDAwMCIsImNvdW50cnlDb2RlIjoiUEsiLCJjdXJyZW5jeSI6IlBLUiIsIm1lc3NhZ2UiOiJzdWNjZXNzIiwib3JkZXJJZCI6Ijc2ODg0MjY1Nzk5OTg4MDE5MiIsInBheU1ldGhvZCI6Ik1PQ0siLCJwcmljaW5nQW1vdW50IjoiMTAwIiwicHJpY2luZ0N1cnJlbmN5IjoiUEtSIiwic3RhdHVzIjoiMSIsInR4bklkIjoiMTI0MjEwNDM5Nzg3MTU0NjcifQ==","sign":"a72c3d33f7cf285470bf8f13a0adad05"}'
//秘文解析
String content = JSON.parseObject(body).getString("content");
if (StringUtils.isBlank(content)) {
    return new TopUpCallbackResult(ResultCode.TRADE_CALLBACK_DATA_INVALID);
}
String decodeContent = new String(Base64.decodeBase64(content.getBytes()));
log.info("top-up trade payment callback decodeContent:{}", decodeContent);

TopUpCallbackDto callbackDto = new TopUpCallbackDto();
callbackDto.setBody(decodeContent);


packagpackage com.platform.horizonservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.platform.horizonservice.constants.ResultCode;
import com.platform.horizonservice.pojo.dto.TopUpCallbackDto;
import com.platform.horizonservice.pojo.vo.TopUpCallbackResult;
import com.platform.horizonservice.service.ITopUpTradePrePayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service("TopUpTradeCallbackService")
@Slf4j
public class TopUpTradeCallbackServiceImpl implements ITopUpTradePrePayService {

    private static final String STATUS = "status";
    private static final String TXN_ID = "txnId";
    private static final String CODE = "code";
    private static final String MESSAGE = "message";

    public TopUpCallbackResult getUniqueTransactionId(TopUpCallbackDto callbackDto) {
        log.info("top-up trade callback getUniqueTransactionId callbackDto: {}", JSON.toJSONString(callbackDto));

        JSONObject callback = JSON.parseObject(callbackDto.getBody());
        String txnId = callback.getString(TXN_ID);

        TopUpCallbackResult callbackResult = new TopUpCallbackResult(ResultCode.SUCCESS);
        callbackResult.setPspNo(txnId);
        log.info("top-up trade callback getUniqueTransactionId callbackResult:{}, txnId:{}", JSON.toJSONString(callbackResult), txnId);
        return callbackResult;
    }

    @Override
    public TopUpCallbackResult callback(TopUpCallbackDto callbackDto) {
        //ok
        log.info("top-up trade callback request:{}", JSON.toJSONString(callbackDto));
        TopUpCallbackResult callbackResult;

        try {
            JSONObject callback = JSON.parseObject(callbackDto.getBody());
            String txnId = callback.getString(TXN_ID);
            String code = callback.getString(CODE);
            String message = callback.getString(MESSAGE);
            String status = callback.getString(STATUS);
            String spResponseData = "success_" + txnId;

            if ("1".equals(status)) {
                callbackResult = new TopUpCallbackResult(ResultCode.SUCCESS);
                callbackResult.setPspNo(txnId);
                callbackResult.setCode(code);
                callbackResult.setMessage(message);
                callbackResult.setBody(spResponseData);
                return callbackResult;
            } else if ("0".equals(status)) {
                callbackResult = new TopUpCallbackResult(ResultCode.FAILED);
                callbackResult.setPspNo(txnId);
                callbackResult.setCode(code);
                callbackResult.setMessage(message);
                callbackResult.setBody(spResponseData);
                return callbackResult;
            } else {
                callbackResult = new TopUpCallbackResult(ResultCode.UNKNOWN);
                callbackResult.setPspNo(txnId);
                callbackResult.setCode(code);
                callbackResult.setMessage(message);
            }
        } catch (Exception e) {
            log.error("top-up trade callback return null. callbackDto:{}, error:{}", JSON.toJSONString(callbackDto), e.getMessage(), e);
        }
        return null;
    }
}

话费充值

充值下单

package com.platform.horizonservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.i18n.phonenumbers.NumberParseException;
import com.google.i18n.phonenumbers.PhoneNumberUtil;
import com.google.i18n.phonenumbers.Phonenumber;
import com.platform.horizonservice.constants.ResultCode;
import com.platform.horizonservice.constants.TopUpTypeEnum;
import com.platform.horizonservice.feign.PaynicornCpFeignClient;
import com.platform.horizonservice.feign.model.*;
import com.platform.horizonservice.pojo.dto.TopUpMobileDto;
import com.platform.horizonservice.pojo.vo.TopUpPaymentResult;
import com.platform.horizonservice.service.ITopUpMobilePayService;
import com.platform.horizonservice.util.PaynicornSignUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Objects;

import static com.platform.horizonservice.constants.CommonConstants.MOBILE_TOP_UP;

/**
 * @author simon.sheng
 * @version 1.0.0
 * @since 1.8.0
 */
@Service("TopUpMobilePayService")
@Slf4j
public class TopUpMobilePayServiceImpl implements ITopUpMobilePayService {

    private static final String SP_TXN_ID = "transId";
    private static final String CODE = "code";
    private static final String MESSAGE = "message";
    private static final String STEP_STATUS = "stepStatus";
    private final PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
    @Resource
    private PaynicornCpFeignClient cpGatewayFeignClient;
    @Value("${paynicorn.pay.mobile.topUp.appKey}")
    private String paynicornPayMobileAppKey;
    @Value("${paynicorn.pay.mobile.topUp.privateKey}")
    private String paynicornPayMobilePrivateKey;

    @Override
    public TopUpPaymentResult raise(TopUpMobileDto topUpMobileDto) {
        TopUpPaymentResult resultVo;
        String cpOrderId = topUpMobileDto.getOrderId();
        String subOrderId = topUpMobileDto.getSubOrderId();
        String currency = topUpMobileDto.getCurrency();
        String countryCode = topUpMobileDto.getCountryCode();
        String amount = topUpMobileDto.getAmount();

        if (StringUtils.isBlank(cpOrderId)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "CP_ORDER_ID", cpOrderId);
            return resultVo;
        }

        if (StringUtils.isBlank(subOrderId)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "SUB_ORDER_ID", cpOrderId);
            return resultVo;
        }

        if (StringUtils.isBlank(amount)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "AMOUNT", amount);
            return resultVo;
        }

        if (StringUtils.isBlank(currency)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "CURRENCY", currency);
            return resultVo;
        }

        if (StringUtils.isBlank(countryCode)) {
            resultVo = new TopUpPaymentResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "COUNTRY_CODE", countryCode);
            return resultVo;
        }

        JSONObject payResultJson = raiseTopUpMobileRequest(topUpMobileDto);
        resultVo = standardizedResponse(payResultJson);
        return resultVo;
    }

    private JSONObject raiseTopUpMobileRequest(TopUpMobileDto topUpMobileDto) {
        String cpOrderId = topUpMobileDto.getOrderId();
        String subOrderId = topUpMobileDto.getSubOrderId();

        try {
            String appKey = paynicornPayMobileAppKey;
            String appSecret = paynicornPayMobilePrivateKey;
            String countryCode = topUpMobileDto.getCountryCode();
            String operatorCode = topUpMobileDto.getOperatorCode();
            String customerPhone = topUpMobileDto.getNationalPhoneNo();
            String amountLocal = topUpMobileDto.getAmount();
            Phonenumber.PhoneNumber phoneNo;
            try {
                phoneNo = phoneUtil.parse(customerPhone, countryCode);
                customerPhone = String.valueOf(phoneNo.getNationalNumber()).replaceAll("-", "").replaceAll(" ", "");
                if (!"0".equals(customerPhone.substring(0, 1))) {
                    customerPhone = "0" + customerPhone;
                }
            } catch (NumberParseException e) {
                log.error("top-up mobile PhoneNumberParse Exception, customerPhone:{},cpOrderId:{},subOrderId:{}", customerPhone, cpOrderId, subOrderId);
            }

            TradeMobileTopUpRequest request = new TradeMobileTopUpRequest();
            request.setAppKey(appKey);
            request.setTransId(subOrderId);
            request.setCountryCode(countryCode);
            request.setOperatorCode(operatorCode);
            request.setBizType(TopUpTypeEnum.MOBILE_TOP_UP.desc);
            request.setBenefitNo(customerPhone);
            request.setAmount(new BigDecimal(amountLocal));
            request.setMemo(MOBILE_TOP_UP);

            CommonRequest commonRequest = PaynicornSignUtils.generateCommReq(request, appKey, appSecret);

            JSONObject response = postForMobileTopUp(request, commonRequest, appSecret, cpOrderId, subOrderId);
            log.info("top-up mobile raiseOrder.cpOrderId:{},subOrderId:{},response:{}", cpOrderId, subOrderId, response);
            return response;
        } catch (Exception e) {
            log.error(cpOrderId, e.getMessage(), e);
        }
        return null;

    }

    private JSONObject postForMobileTopUp(TradeMobileTopUpRequest request, CommonRequest commonRequest, String appSecret, String cpOrderId, String subOrderId) {

        JSONObject resBody = new JSONObject();
        try {
            log.info("top-up postForMobileTopUp in, requestBody:{}, cpOrderId:{},subOrderId:{}", JSON.toJSONString(request), cpOrderId, subOrderId);
            CommonResponse commonResponse = cpGatewayFeignClient.raiseTopUpV3(commonRequest);
            log.info("top-up postForMobileTopUp out responseCode:{}, cpOrderId:{}, subOrderId:{}, commonResponse:{}", commonResponse.getResponseCode(), cpOrderId, subOrderId, JSON.toJSONString(commonResponse));

            if (!"000000".equals(commonResponse.getResponseCode())) {
                resBody.put(CODE, commonResponse.getResponseCode());
                resBody.put(MESSAGE, commonResponse.getResponseMessage());
                resBody.put(STEP_STATUS, 400);
                return resBody;
            }

            TradeMobileTopUpResponse tradeResponse = PaynicornSignUtils.decodeCommResp(commonResponse, appSecret, TradeMobileTopUpResponse.class);
            log.info("top-up postForMobileTopUp out responseCode:{}, cpOrderId:{}, subOrderId:{}, tradeResponse:{}", commonResponse.getResponseCode(), cpOrderId, subOrderId, JSON.toJSONString(tradeResponse));
            TradeMobileTopUpResult result = Objects.requireNonNull(tradeResponse).getResult();
            if (null == result) {
                resBody.put(CODE, tradeResponse.getCode());
                resBody.put(MESSAGE, tradeResponse.getMsg());
                resBody.put(STEP_STATUS, 500);
            } else {
                resBody.put(CODE, result.getStatusCode()); //0 processing, 1 success, 2 failed
                resBody.put(MESSAGE, result.getDescription());
                resBody.put(SP_TXN_ID, result.getOrderId());
                resBody.put(STEP_STATUS, 200);
            }
            return resBody;
        } catch (HttpServerErrorException e) {
            String response = e.getResponseBodyAsString();
            HttpStatus httpStatus = e.getStatusCode();
            JSONObject responseJSON = JSON.parseObject(response);
            if (null != responseJSON) {
                resBody.put(STEP_STATUS, httpStatus.value());
                resBody.put(CODE, httpStatus.value());
                resBody.put(MESSAGE, "5XX TRADE Exception");
            }
            log.info("top-up 500 error postForMobileTopUp request:{},status:{},response:{},resBody:{},cpOrderId:{},subOrderId:{}", JSON.toJSONString(request), httpStatus.value(), response, resBody, cpOrderId, subOrderId);
            return resBody;
        } catch (HttpClientErrorException e) {
            HttpStatus httpStatus = e.getStatusCode();
            JSONObject errorBody = JSON.parseObject(e.getResponseBodyAsString());
            if (null != errorBody) {
                resBody.put(STEP_STATUS, httpStatus.value());
                resBody.put(CODE, httpStatus.value());
                resBody.put(MESSAGE, "4XX TRADE Exception");
            }
            log.info("top-up 400 error postForMobileTopUp is exception: status:{},body:{},error:{}, cpOrderId:{},subOrderId:{}", httpStatus.value(), errorBody, e.getMessage(), cpOrderId, subOrderId);
            return resBody;
        } catch (ResourceAccessException e) {
            String errorBody = e.getMessage();
            resBody.put(STEP_STATUS, 500);
            resBody.put(CODE, "SP_TIMEOUT_ERROR");
            resBody.put(MESSAGE, "TRADE SP_NETWORK_TIMEOUT_ERROR");
            log.info("top-up postForMobileTopUp resourceAccess exception,requestBody:{},error:{},resBody:{},cpOrderId:{},subOrderId:{}", JSON.toJSONString(request), errorBody, resBody, cpOrderId, subOrderId);
            return resBody;
        } catch (Exception e) {
            log.error("top-up postForMobileTopUp unknown exception: body:{},error:{},cpOrderId:{},subOrderId:{}", JSON.toJSONString(request), e.getMessage(), cpOrderId, subOrderId, e);
        }
        return null;
    }

    private TopUpPaymentResult standardizedResponse(JSONObject payResultJson) {
        TopUpPaymentResult resultVo;
        ResultCode resultCode = ResultCode.FAILED;
        if (null == payResultJson) {
            resultVo = new TopUpPaymentResult(ResultCode.SP_RAISE_RESULT_EMPTY);
            resultVo.setCode("sp raise failed");
            resultVo.setMessage("sp raiseMobileTopUpRequest returns NULL");
            return resultVo;
        }

        String spTxnId = payResultJson.getString(SP_TXN_ID);
        String code = payResultJson.getString(CODE);
        String message = payResultJson.getString(MESSAGE);
        if (StringUtils.isNotBlank(spTxnId) && !code.equalsIgnoreCase("2")) {
            resultCode = ResultCode.PROCESSING;
        }

        resultVo = new TopUpPaymentResult(resultCode);
        resultVo.setCode(code);
        resultVo.setMessage(message);
        resultVo.setSpTxnId(spTxnId);
        return resultVo;
    }
}

查询话费订单

package com.platform.horizonservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.platform.horizonservice.constants.ResultCode;
import com.platform.horizonservice.feign.PaynicornCpFeignClient;
import com.platform.horizonservice.feign.model.*;
import com.platform.horizonservice.pojo.dto.TopUpMobileQueryDto;
import com.platform.horizonservice.pojo.vo.TopUpQueryResult;
import com.platform.horizonservice.service.ITopUpMobilePayService;
import com.platform.horizonservice.util.PaynicornSignUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.ResourceAccessException;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @author simon.sheng
 * @version 1.0.0
 * @since 1.8.0
 */
@Service("TopUpMobileQueryService")
@Slf4j
public class TopUpMobileQueryServiceImpl implements ITopUpMobilePayService {

    private static final String CODE = "code";
    private static final String MESSAGE = "message";
    private static final String STEP_STATUS = "stepStatus";
    @Resource
    private PaynicornCpFeignClient cpGatewayFeignClient;
    @Value("${paynicorn.pay.mobile.topUp.appKey}")
    private String paynicornPayMobileAppKey;
    @Value("${paynicorn.pay.mobile.topUp.privateKey}")
    private String paynicornPayMobilePrivateKey;


    @Override
    public TopUpQueryResult query(TopUpMobileQueryDto topUpMobileQueryDto) {
        TopUpQueryResult resultVo;
        String cpOrderId = topUpMobileQueryDto.getOrderId();
        String subOrderId = topUpMobileQueryDto.getSubOrderId();

        if (StringUtils.isBlank(cpOrderId)) {
            resultVo = new TopUpQueryResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "CP_ORDER_ID", cpOrderId);
            return resultVo;
        }

        if (StringUtils.isBlank(subOrderId)) {
            resultVo = new TopUpQueryResult(ResultCode.CLIENT_PARAMETER_ILLEGAL, "SUB_ORDER_ID", cpOrderId);
            return resultVo;
        }

        JSONObject queryResultJson = queryTopUpRequest(topUpMobileQueryDto);
        resultVo = standardizedResponse(queryResultJson);
        return resultVo;
    }

    private JSONObject queryTopUpRequest(TopUpMobileQueryDto topUpMobileQueryDto) {
        String cpOrderId = topUpMobileQueryDto.getOrderId();
        String subOrderId = topUpMobileQueryDto.getSubOrderId();

        try {
            String appKey = paynicornPayMobileAppKey;
            String appSecret = paynicornPayMobilePrivateKey;

            TradeMobileTopUpQuery request = new TradeMobileTopUpQuery();
            request.setAppKey(appKey);
            request.setTransId(subOrderId);

            CommonRequest commonRequest = PaynicornSignUtils.generateCommReq(request, appKey, appSecret);

            JSONObject response = postForMobileTopUpQuery(request, commonRequest, appSecret, cpOrderId, subOrderId);
            log.info("top-up mobile query. cpOrderId:{},subOrderId:{},response:{}", cpOrderId, subOrderId, response);
            return response;
        } catch (Exception e) {
            log.error(cpOrderId, e.getMessage(), e);
        }
        return null;
    }

    private JSONObject postForMobileTopUpQuery(TradeMobileTopUpQuery request, CommonRequest commonRequest, String appSecret, String cpOrderId, String subOrderId) {

        JSONObject resBody = new JSONObject();
        try {
            log.info("top-up query postForMobileTopUpQuery in, requestBody:{}, cpOrderId:{}", JSON.toJSONString(request), cpOrderId);
            CommonResponse commonResponse = cpGatewayFeignClient.queryTopUpV3(commonRequest);
            log.info("top-up query postForMobileTopUpQuery out responseCode:{}, cpOrderId:{}, subOrderId:{}, commonResponse:{}", commonResponse.getResponseCode(), cpOrderId, subOrderId, JSON.toJSONString(commonResponse));

            if (!"000000".equals(commonResponse.getResponseCode())) {
                resBody.put(CODE, commonResponse.getResponseCode());
                resBody.put(MESSAGE, commonResponse.getResponseMessage());
                resBody.put(STEP_STATUS, 400);
                return resBody;
            }

            TradeMobileTopUpQueryResponse tradeResponse = PaynicornSignUtils.decodeCommResp(commonResponse, appSecret, TradeMobileTopUpQueryResponse.class);
            log.info("top-up query postForMobileTopUpQuery out responseCode:{}, cpOrderId:{}, subOrderId:{}, tradeResponse:{}", commonResponse.getResponseCode(), cpOrderId, subOrderId, JSON.toJSONString(tradeResponse));
            TradeMobileTopUpQueryResult result = Objects.requireNonNull(tradeResponse).getResult();
            if (null == result) {
                resBody.put(CODE, tradeResponse.getCode());
                resBody.put(MESSAGE, tradeResponse.getMsg());
                resBody.put(STEP_STATUS, 500);
            } else {
                resBody.put(CODE, result.getStatusCode());
                resBody.put(MESSAGE, result.getDescription());
                resBody.put(STEP_STATUS, 200);
            }
            return resBody;
        } catch (HttpServerErrorException e) {
            String response = e.getResponseBodyAsString();
            HttpStatus httpStatus = e.getStatusCode();
            JSONObject responseJSON = JSON.parseObject(response);
            if (null != responseJSON) {
                resBody.put(STEP_STATUS, httpStatus.value());
                resBody.put(CODE, httpStatus.value());
                resBody.put(MESSAGE, "5XX TRADE Exception");
            }
            log.info("top-up query 500 error postForMobileTopUpQuery request:{},status:{},response:{},resBody:{},cpOrderId:{},subOrderId:{}", JSON.toJSONString(request), httpStatus.value(), response, resBody, cpOrderId, subOrderId);
            return resBody;
        } catch (HttpClientErrorException e) {
            HttpStatus httpStatus = e.getStatusCode();
            JSONObject errorBody = JSON.parseObject(e.getResponseBodyAsString());
            if (null != errorBody) {
                resBody.put(STEP_STATUS, httpStatus.value());
                resBody.put(CODE, httpStatus.value());
                resBody.put(MESSAGE, "4XX TRADE Exception");
            }
            log.info("top-up query 400 error postForMobileTopUpQuery is exception: status:{},body:{},error:{}, cpOrderId:{}, subOrderId:{}", httpStatus.value(), errorBody, e.getMessage(), cpOrderId, subOrderId);
            return resBody;
        } catch (ResourceAccessException e) {
            String errorBody = e.getMessage();
            resBody.put(STEP_STATUS, 500);
            resBody.put(CODE, "SP_TIMEOUT_ERROR");
            resBody.put(MESSAGE, "TRADE SP_NETWORK_TIMEOUT_ERROR");
            log.info("top-up query postForMobileTopUpQuery resourceAccess exception,requestBody:{},error:{},resBody:{},cpOrderId:{},subOrderId:{}", JSON.toJSONString(request), errorBody, resBody, cpOrderId, subOrderId);
            return resBody;
        } catch (Exception e) {
            log.error("top-up query postForMobileTopUpQuery unknown exception: body:{},cpOrderId:{},subOrderId:{},error:{}", JSON.toJSONString(request), cpOrderId, subOrderId, e.getMessage(), e);
        }
        return null;
    }

    private TopUpQueryResult standardizedResponse(JSONObject payResultJson) {
        TopUpQueryResult resultVo;
        ResultCode resultCode = ResultCode.FAILED;
        if (null == payResultJson) {
            resultVo = new TopUpQueryResult(ResultCode.UNKNOWN);
            resultVo.setCode("sp query raise failed");
            resultVo.setMessage("sp queryMobileTopUpRequest returns NULL");
            return resultVo;
        }

        String code = payResultJson.getString(CODE);
        String message = payResultJson.getString(MESSAGE);

        //0: 充值处理中,1: 充值成功,2:充值失败
        if ("0".equalsIgnoreCase(code)) {
            resultCode = ResultCode.PROCESSING;
        } else if ("1".equalsIgnoreCase(code)) {
            resultCode = ResultCode.SUCCESS;
        }

        resultVo = new TopUpQueryResult(resultCode);
        resultVo.setCode(code);
        resultVo.setMessage(message);
        return resultVo;
    }
}


接受回调通知

ppackage com.platform.horizonservice.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.platform.horizonservice.constants.ResultCode;
import com.platform.horizonservice.pojo.dto.TopUpCallbackDto;
import com.platform.horizonservice.pojo.vo.TopUpCallbackResult;
import com.platform.horizonservice.service.ITopUpMobilePayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service("TopUpMobileCallbackService")
@Slf4j
public class TopUpMobileCallbackServiceImpl implements ITopUpMobilePayService {

    private static final String STATUS = "status";
    private static final String SP_TXN_ID = "orderNo";
    private static final String CP_ORDER_ID = "originOrderNo";
    private static final String TOP_UP_SUCCESS = "TOP_UP_SUCCESS";
    private static final String TOP_UP_FAILED = "TOP_UP_FAILED";
    private static final String TOP_UP_PENDING = "TOP_UP_PENDING";


    public TopUpCallbackResult getUniqueTransactionId(TopUpCallbackDto callbackDto) {
        log.info("top-up mobile sp callback getUniqueTxnId callbackDto: {}", JSON.toJSONString(callbackDto));

        JSONObject callback = JSON.parseObject(callbackDto.getBody());
        String subOrderId = callback.getString(CP_ORDER_ID);

        TopUpCallbackResult callbackResult = new TopUpCallbackResult(ResultCode.SUCCESS);
        callbackResult.setRequestNo(subOrderId);
        log.info("top-up mobile sp callback getUniqueTxnId callbackResult:{}, subOrderId:{}", JSON.toJSONString(callbackResult), subOrderId);
        return callbackResult;
    }

    @Override
    public TopUpCallbackResult callback(TopUpCallbackDto callbackDto) {
        log.info("top-up mobile sp callback request:{}", JSON.toJSONString(callbackDto));
        TopUpCallbackResult callbackResult;

        try {
            JSONObject callback = JSON.parseObject(callbackDto.getBody());
            String spTxnId = callback.getString(SP_TXN_ID);
            String status = callback.getString(STATUS);
            String spResponseData = "success";

            if ("1".equals(status)) {
                callbackResult = new TopUpCallbackResult(ResultCode.SUCCESS);
                callbackResult.setPspNo(spTxnId);
                callbackResult.setCode(TOP_UP_SUCCESS);
                callbackResult.setMessage(TOP_UP_SUCCESS);
                callbackResult.setBody(spResponseData);
                return callbackResult;
            } else if ("2".equals(status)) {
                callbackResult = new TopUpCallbackResult(ResultCode.FAILED);
                callbackResult.setPspNo(spTxnId);
                callbackResult.setCode(TOP_UP_FAILED);
                callbackResult.setMessage(TOP_UP_FAILED);
                callbackResult.setBody(spResponseData);
                return callbackResult;
            } else {
                callbackResult = new TopUpCallbackResult(ResultCode.UNKNOWN);
                callbackResult.setPspNo(spTxnId);
                callbackResult.setCode(TOP_UP_PENDING);
                callbackResult.setMessage(TOP_UP_PENDING);
            }
        } catch (Exception e) {
            log.error("top-up mobile sp callback return null. callbackDto:{}, error:{}", JSON.toJSONString(callbackDto), e.getMessage(), e);
        }
        return null;
    }
}

密钥签名

本代码示例同时适用于在线支付和话费充值过程中所需要的密钥签名过程。

/*Top Secret*/
package com.platform.horizonservice.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.platform.horizonservice.feign.model.CommonRequest;
import com.platform.horizonservice.feign.model.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Base64Utils;

import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author heng.hu
 * @date 2019-06-13
 */
@Slf4j
public final class PaynicornSignUtils {

    /**
     * Instantiation is not allowed
     */
    private PaynicornSignUtils() {
    }

    /**
     * generate signature
     */
    public static String sign(String content, String salt) {
        String source = content + salt;
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("md5");
        } catch (NoSuchAlgorithmException e) {
            log.error("paynicorn trade sign fail.", e);
            return null;
        }
        byte[] text = source.getBytes(StandardCharsets.UTF_8);
        return Hex.encodeHexString(messageDigest.digest(text));
    }

    public static boolean verify(String content, String sign, String salt) {
        return sign.equals(sign(content, salt));
    }

    /**
     * Encrypt request
     *
     */
    public static CommonRequest generateCommReq(Object bizReq, String appKey, String secret) {
        String strBizReq = JSON.toJSONString(bizReq);
        log.info("paynicorn trade raise request bizReq:{}", strBizReq);
        String content = new String(Base64Utils.encode(strBizReq.getBytes(StandardCharsets.UTF_8)));
        String sign = sign(content, secret);

        CommonRequest commonRequest = CommonRequest.builder().content(content).sign(sign).appKey(appKey).build();
        log.info("paynicorn trade raise request comReq:{}", commonRequest.toString());
        return commonRequest;
    }

    /**
     * DecodeEncrypt request
     *
     */
    public static <T> T decodeCommResp(CommonResponse commonResponse, String secret, Class<T> clazz) {
        if (!verify(commonResponse.getContent(), commonResponse.getSign(), secret)) {
            log.warn("paynicorn trade decode verify fail.");
            return null;
        }

        String strBizResp = new String(Base64Utils.decode(commonResponse.getContent().getBytes()), StandardCharsets.UTF_8);
        log.info("paynicorn trade decode strBizResp:{}", strBizResp);
        return JSON.parseObject(strBizResp, clazz);
    }

}

查询美元汇率

package com.platform.horizonservice.cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.platform.horizonservice.feign.PaynicornCpFeignClient;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author heng.hu 拉取交易当天费率
 */
@Component
public class RateCache {
    @Resource
    private PaynicornCpFeignClient paynicornCpFeignClient;
    /**
     * 最新汇率 USD
     */
    LoadingCache<String, Map<String, BigDecimal>> cache = Caffeine.newBuilder()
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build(p -> {
                Map<String, BigDecimal> map = new HashMap<>();
                LinkedHashMap currencyList = (LinkedHashMap) paynicornCpFeignClient.queryAllCurrency().get("quotes");
                if (!CollectionUtils.isEmpty(currencyList)) {
                    currencyList.forEach((k, v) -> {
                        map.put(String.valueOf(k).substring(3), new BigDecimal(String.valueOf(v)));
                    });
                }
                return map;
            });
    LoadingCache<String, Map<String, BigDecimal>> currencyCache = Caffeine.newBuilder()
            .expireAfterWrite(1, TimeUnit.HOURS)
            .build(p -> {
                Map<String, BigDecimal> map = new HashMap<>();
                LinkedHashMap currencyList = (LinkedHashMap) paynicornCpFeignClient.queryAllCurrencyByDate(p).get("quotes");
                if (!CollectionUtils.isEmpty(currencyList)) {
                    currencyList.forEach((k, v) -> {
                        map.put(String.valueOf(k), new BigDecimal(String.valueOf(v)));
                    });
                } else {
                    return getCurrencyAll();
                }
                return map;
            });
    public Map<String, BigDecimal> getCurrencyAll() {
        return cache.get("CURRENCY_ALL");
    }
    public Map<String, BigDecimal> getCurrencyDate(String date) {
        return currencyCache.get(date);
    }
}

/**
 * 币种转换 - USDNGN
 **/
private void fillOrderData(List<AggregationOrder> orderList) {
    for (AggregationOrder order : orderList) {
        Map<String, BigDecimal> currencyDate = rateCache.getCurrencyDate(order.getOrderTime()); //查询下单当日的美金费率

        if ("AHA".equals(order.getCurrency())) {
            //AHA/美金 = 100/1
            order.setAmountSumUsd(
                    Strings.isNullOrEmpty(String.valueOf(order.getAmountSumLocal())) ? new BigDecimal("0.00") :
                            order.getAmountSumLocal().divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP));
        } else if ("USD".equals(order.getCurrency())) {
            order.setAmountSumUsd(order.getAmountSumLocal());
        } else {
            String usdKey = "USD" + order.getCurrency();
            if (currencyDate.containsKey(usdKey)) {
                //美金汇率
                order.setAmountSumUsd(
                        Strings.isNullOrEmpty(String.valueOf(order.getAmountSumLocal())) ? new BigDecimal("0.00") :
                                order.getAmountSumLocal().divide(currencyDate.get(usdKey), 2, BigDecimal.ROUND_HALF_UP)
                );
            } else {
                log.info("fillOrderData >> currency-exchange orderCurrency:{} not exist. exchangeTime:{}", order.getCurrency(), order.getOrderTime());
            }
        }
    }
}