CashierOrderToken.java 3.92 KB
package com.diligrp.cashier.boss.domain;

import com.diligrp.cashier.boss.Constants;
import com.diligrp.cashier.boss.exception.BossServiceException;
import com.diligrp.cashier.shared.ErrorCode;
import com.diligrp.cashier.shared.security.Base62Cipher;
import com.diligrp.cashier.shared.security.HexUtils;
import com.diligrp.cashier.shared.util.JsonUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

public class CashierOrderToken {
    // 商户号
    private Long mchId;
    // 交易ID
    private String tradeId;
    // 收银台类型
    private Integer cashierType;
    // 业务系统用户标识
    private String userId;
    // 页面回调地址
    private String redirectUrl;

    public static String encode(Long tokenId, SecretKeySpec secretKey) {
        try {
            String payload = Base62Cipher.encodeLong(tokenId);
            Mac mac = Mac.getInstance(Constants.TOKEN_SIGN_ALGORITHM);
            mac.init(secretKey);

            byte[] bytes = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8));
            String signature = HexUtils.encodeHexStr(bytes).substring(0, Constants.TOKEN_SIGN_LENGTH);
            payload = payload + signature;
            return payload;
        }  catch (Exception ex) {
            throw new BossServiceException(ErrorCode.ILLEGAL_ARGUMENT_ERROR, "Failed to generate order token");
        }
    }

    public static long decode(String token, SecretKeySpec secretKey) {
        if (token == null || token.length() <= Constants.TOKEN_SIGN_LENGTH) {
            throw new BossServiceException(ErrorCode.ILLEGAL_ARGUMENT_ERROR, "Invalid order token");
        }

        String payload = token.substring(0, token.length() - Constants.TOKEN_SIGN_LENGTH);
        String signature = token.substring(token.length() - Constants.TOKEN_SIGN_LENGTH);
        String tokenSign;
        try {
            Mac mac = Mac.getInstance(Constants.TOKEN_SIGN_ALGORITHM);
            mac.init(secretKey);
            byte[] bytes = mac.doFinal(payload.getBytes(StandardCharsets.UTF_8));
            tokenSign = HexUtils.encodeHexStr(bytes).substring(0, Constants.TOKEN_SIGN_LENGTH);
        } catch (Exception ex) {
            throw new BossServiceException(ErrorCode.OPERATION_NOT_ALLOWED, "Invalid order token");
        }

        if (!Objects.equals(signature, tokenSign)) {
            throw new BossServiceException(ErrorCode.OPERATION_NOT_ALLOWED, "Invalid order token signature");
        }
        return Base62Cipher.decodeLong(payload);
    }

    public static CashierOrderToken decodeCashierOrder(String payload) {
        if (payload != null) {
            return JsonUtils.fromJsonString(payload, CashierOrderToken.class);
        }
        return null;
    }

    public CashierOrderToken() {
    }

    public CashierOrderToken(Long mchId, String tradeId, Integer cashierType, String userId, String redirectUrl) {
        this.mchId = mchId;
        this.tradeId = tradeId;
        this.cashierType = cashierType;
        this.userId = userId;
        this.redirectUrl = redirectUrl;
    }

    public Long getMchId() {
        return mchId;
    }

    public void setMchId(Long mchId) {
        this.mchId = mchId;
    }

    public String getTradeId() {
        return tradeId;
    }

    public void setTradeId(String tradeId) {
        this.tradeId = tradeId;
    }

    public Integer getCashierType() {
        return cashierType;
    }

    public void setCashierType(Integer cashierType) {
        this.cashierType = cashierType;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getRedirectUrl() {
        return redirectUrl;
    }

    public void setRedirectUrl(String redirectUrl) {
        this.redirectUrl = redirectUrl;
    }

    @Override
    public String toString() {
        return JsonUtils.toJsonString(this);
    }
}