package org.yangyuan.pay.core.common; import org.apache.commons.lang3.StringUtils; import org.yangyuan.pay.bean.AliTrade; import org.yangyuan.pay.bean.TradeStatus; import org.yangyuan.pay.bean.WxTrade; import org.yangyuan.pay.bean.common.Trade; import org.yangyuan.pay.bean.common.TradeToken; import org.yangyuan.pay.config.CommonConfig; import org.yangyuan.pay.core.*; import org.yangyuan.pay.exception.RefundException; import org.yangyuan.pay.util.PayDateUtil; import redis.clients.jedis.Jedis; import java.util.Date; /** * 支付统一调度器定义抽象实现 * @author yangyuan * @date 2017年5月9日 */ public abstract class AbstractPayManager implements PayManager{ /** * 用户订单数量模板 */ private static final String TRADE_COUNT_KEY_TMPL = "service:pay:manager:trade_count:{type}:{uuid}"; /** * 支付业务核心 * <br> * 这里之所以用静态,是为了减少内存占用,这些核心类线程安全,在内存中只保留一份即可,即永久代中。 */ private static final AliMobilePay aliMobilePay = new AliMobilePay(); private static final AliWebPcPay aliWebPcPay = new AliWebPcPay(); private static final AliWebMobilePay aliWebMobilePay = new AliWebMobilePay(); private static final AliQrcodePay aliQrcodePay = new AliQrcodePay(); private static final WxMobilePay wxMobilePay = new WxMobilePay(); private static final WxWebPcPay wxWebPcPay = new WxWebPcPay(); private static final WxWebMobilePay wxWebMobilePay = new WxWebMobilePay(); private static final WxQrcodePay wxQrcodePay = new WxQrcodePay(); private static final WxJsSdkPay wxJsSdkPay = new WxJsSdkPay(); /** * 获取一个新的<b>支付订单号</b>(注意<b>业务订单号</b>和<b>支付订单号</b>的概念区别!项目中所有的商户订单号均为支付订单号) * * <p>格式定义:</p> * * <pre> * 固定16位。 * 假设<b>支付订单号</b>为:00ba00ix1sob0001 * * +------------------------------------+------------------+----------------+------------------------+--------------------+---------------------+----------------------------------+ * | 00 | b | a | 0 | 0 | ix1sob | 0001 | * +------------------------------------+------------------+----------------+------------------------+--------------------+---------------------+----------------------------------+ * | 从2017年起至现在的年数,32进制表示 | 月份,32进制表示 | 日,32进制表示 | 订单号类型,32进制表示 | 保留位,32进制表示 | 用户唯一id,固定6位 | 该用户当日创建订单数量,32进制表示 | * +------------------------------------+------------------+----------------+------------------------+--------------------+---------------------+----------------------------------+ * </pre> * * @param uuid 用户唯一id * * @return 支付订单号 */ public String newTradeNo(String uuid){ Jedis redis = null; try { redis = CommonConfig.getJedisPool().getResource(); StringBuilder builder = new StringBuilder(16); Date date = new Date(); String key = TRADE_COUNT_KEY_TMPL.replace("{type}", getTradeType()) .replace("{uuid}", uuid); int count = redis.incr(key).intValue(); if(count == 1){ int ttl = (int)((PayDateUtil.getIntegralEndTime(date).getTime() - date.getTime())/1000l); redis.expire(key, ttl); } int year = Integer.parseInt(PayDateUtil.format(date, "yyyy")); year = year - 2017; int month = Integer.parseInt(PayDateUtil.format(date, "MM")); if(month > 9){ month = month + 87; }else{ month = month + 48; } int day = Integer.parseInt(PayDateUtil.format(date, "dd")); if(day > 9){ day = day + 87; }else{ day = day + 48; } builder.append(StringUtils.leftPad(Integer.toString(year, 32), 2, "0")); builder.append((char) month); builder.append((char) day); /** * 类型 */ builder.append(getTradeType()); /** * 保留位 */ builder.append(0); /** * 用户唯一id */ builder.append(uuid); /** * 数量 */ builder.append(StringUtils.leftPad(Integer.toString(count, 32), 4, "0")); return builder.toString(); } finally { if(redis != null){ redis.close(); redis = null; } } } /** * 获取订单类型 * <br> * 长度1位,32进制表示法,即:0~v * @return 订单类型 */ public abstract String getTradeType(); /** * 获取当前支付调度器对应的支付适配器 * @return */ public abstract AbstractPayAdaptor getPayAdaptor(); /** * 订单状态分发 * @param status */ public void doTradeStatus(TradeStatus status){ getPayAdaptor().doTradeStatus(status); } /** * 匹配订单类型 * @param outTradeNo 商户订单号 * @return */ public boolean matches(String outTradeNo){ return outTradeNo.substring(4, 5).equals(getTradeType()); } @Override public <T> TradeToken<T> mobilePay(Trade trade) { if(trade instanceof AliTrade){ return (TradeToken<T>) aliMobilePay.pay((AliTrade) trade); } if(trade instanceof WxTrade){ return (TradeToken<T>) wxMobilePay.pay((WxTrade) trade); } throw new IllegalArgumentException("[移动支付]不支持的订单类型[" + trade.getClass().getSimpleName() + "]"); } @Override public <T> TradeToken<T> webPcPay(Trade trade) { if(trade instanceof AliTrade){ return (TradeToken<T>) aliWebPcPay.pay((AliTrade) trade); } if(trade instanceof WxTrade){ return (TradeToken<T>) wxWebPcPay.pay((WxTrade) trade); } throw new IllegalArgumentException("[电脑网页支付]不支持的订单类型[" + trade.getClass().getSimpleName() + "]"); } @Override public <T> TradeToken<T> webMobilePay(Trade trade) { if(trade instanceof AliTrade){ return (TradeToken<T>) aliWebMobilePay.pay((AliTrade) trade); } if(trade instanceof WxTrade){ return (TradeToken<T>) wxWebMobilePay.pay((WxTrade) trade); } throw new IllegalArgumentException("[手机网页支付]不支持的订单类型[" + trade.getClass().getSimpleName() + "]"); } @Override public <T> TradeToken<T> qrcodePay(Trade trade) { if(trade instanceof AliTrade){ return (TradeToken<T>) aliQrcodePay.pay((AliTrade) trade); } if(trade instanceof WxTrade){ return (TradeToken<T>) wxQrcodePay.pay((WxTrade) trade); } throw new IllegalArgumentException("[扫码支付]不支持的订单类型[" + trade.getClass().getSimpleName() + "]"); } @Override public <T> TradeToken<T> jsSdkPay(Trade trade) { if(trade instanceof AliTrade){ throw new IllegalArgumentException("[JS-SDK支付]支付宝不支持该支付方式"); } if(trade instanceof WxTrade){ return (TradeToken<T>) wxJsSdkPay.pay((WxTrade) trade); } throw new IllegalArgumentException("[JS-SDK支付]不支持的订单类型[" + trade.getClass().getSimpleName() + "]"); } @Override public void refund(Trade trade) throws RefundException { if(trade instanceof AliTrade){ aliMobilePay.refund((AliTrade) trade); return; } if(trade instanceof WxTrade){ wxMobilePay.refund((WxTrade) trade); return; } throw new IllegalArgumentException("[退款]不支持的订单类型[" + trade.getClass().getSimpleName() + "]"); } @Override public TradeStatus status(Trade trade) { if(trade instanceof AliTrade){ return aliMobilePay.status((AliTrade) trade); } if(trade instanceof WxTrade){ return wxMobilePay.status((WxTrade) trade); } throw new IllegalArgumentException("[订单状态查询]不支持的订单类型[" + trade.getClass().getSimpleName() + "]"); } }