字节跳动小程序

access_token管理、图片审核

@Service
public class ToutiaoService {
    @Value("${tt.getTokenUrl}")
    private String getTokenUrl;

    @Value("${tt.appId}")
    private String appId;

    @Value("${tt.appSecret}")
    private String appSecret;

    @Value("${tt.imgCensorUrl}")
    private String imgCensorUrl;

    private String accessToken;

    private Date tokenExpire;

    @Autowired
    private RestTemplate restTemplate;

    public String fetchToken() {
        String urlStr = String.format(getTokenUrl, appId, appSecret);
        TtAccess ttAccess = restTemplate.getForObject(urlStr, TtAccess.class);
        if(ttAccess.getError() > 0){
            throw new RestfulException(ttAccess.getErrmsg());
        }
        accessToken = ttAccess.getAccess_token();
        long duration = ttAccess.getExpires_in() - 300;
        tokenExpire = new Date(System.currentTimeMillis() + duration * 1000);
        return accessToken;
    }

    public String getAccessToken() {
        if (accessToken == null || tokenExpire == null || tokenExpire.before(new Date())) {
            fetchToken();
        }
        return accessToken;
    }

    public boolean censor(MultipartFile file) throws IOException {
        String base64Img = new BASE64Encoder().encode(file.getBytes());  // 图片base64编码,不用加文件名或格式信息
        base64Img = base64Img.replaceAll("[\\s*\t\n\r]", "");  // 去掉Base64里的换行符
        String token = this.getAccessToken();
        TtRequest request = new TtRequest(appId, token);
        request.setImage_data(base64Img);

        TtResponse ttResponse = restTemplate.postForObject(imgCensorUrl, request, TtResponse.class);
        if(ttResponse.getError() == 0){
            List<TtResponse.Predict> predicts = ttResponse.getPredicts();
            for (TtResponse.Predict predict : predicts){
                if(predict.isHit()){
                    return true;
                }
            }
        }
        if(ttResponse.getError() == 2){
            this.fetchToken();
        }
        return false;
    }
}

支付相关

@Service
public class TtPayService {
    @Value("${tt.appId}")
    private String appId;

    @Value("${tt.salt}")
    private String salt;

    @Value("${tt.placeOrderUrl}")
    private String placeOrderUrl;

    @Value("${tt.callbackToken}")
    private String ttCallbackToken;

    @Value("${tt.orderQueryUrl}")
    private String orderQueryUrl;

    @Autowired
    private RestTemplate restTemplate;

    /* 统一下单 */
    public JSONObject unifiedOrder(TtPay ttPay) throws DocumentException {
        ttPay.setValid_time(7200);
        List<String> values = new ArrayList<>();
        values.add(ttPay.getOut_order_no());
        values.add(String.valueOf(ttPay.getTotal_amount()));
        values.add(ttPay.getSubject());
        values.add(ttPay.getBody());
        values.add(String.valueOf(ttPay.getValid_time()));
        String sign = this.sign(values);    // 签名
        ttPay.setSign(sign);
        ttPay.setApp_id(appId);

        String jsonStr = restTemplate.postForObject(placeOrderUrl, ttPay, String.class);
        JSONObject response = JSON.parseObject(jsonStr);
        response = this.preTreatResponse(response);  // 处理响应
        return response;
    }

    /* 支付通知处理 */
    public String ttPayNotify(String request) {
        JSONObject jsonObject = JSONObject.parseObject(request);
        if (!jsonObject.getString("type").equals("payment")) {
            return ttPayService.notifySuccess();
        }
        ttPayService.notifyValidate(jsonObject);
        jsonObject = JSONObject.parseObject(jsonObject.getString("msg"));
        long tradeNum = jsonObject.getLongValue("cp_orderno");
        /* 从数据库里查询订单,并处理订单 */
        return ttPayService.notifySuccess();
    }

    /* 查询订单 */
    public JSONObject queryOrder(String out_order_no) throws DocumentException {
        List<String> values = new ArrayList<>();
        values.add(out_order_no);
        String sign = this.sign(values);    // 签名

        JSONObject request = new JSONObject();
        request.put("out_order_no", out_order_no);
        request.put("sign", sign);
        request.put("app_id", appId);

        String jsonStr = restTemplate.postForObject(orderQueryUrl, request.toJSONString(), String.class);
        JSONObject response = JSON.parseObject(jsonStr);
        response = this.preTreatResponse(response);  // 处理响应
        return response;
    }

    /* 校验 支付通知 */
    public void notifyValidate(JSONObject jsonObject) {
        List<String> keys = new ArrayList(jsonObject.keySet());
        List<String> values = new ArrayList<>();
        for (String key : keys) {
            if (key.equals("msg_signature") || key.equals("type")) {
                continue;
            }
            values.add(jsonObject.getString(key));
        }
        values.add(ttCallbackToken);
        Collections.sort(values);  // 字典排序

        String ttSign = jsonObject.getString("msg_signature");
        String mySign = DigestUtils.sha1Hex(String.join("", values));
        if (!ttSign.equals(mySign)) {                        // 校验签名
            throw new RestfulException("签名不正确");
        }
    }

    /* 签名 */
    public String sign(List<String> values) {
        values.add(salt);
        Collections.sort(values);  // 字典排序
        String sign = StringUtils.join(values, "&");
        return DigestUtils.md5Hex(sign);  // MD5 摘要
    }

/* 预处理响应 */
    public JSONObject preTreatResponse(JSONObject jsonObject) throws DocumentException {
        int err_no = jsonObject.getIntValue("err_no");
        if (err_no != 0) {
            throw new RestfulException(err_no, jsonObject.getString("err_tips"));
        }
        return jsonObject;
    }

    public String notifySuccess() {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("err_no", 0);
        jsonObject.put("err_tips", "success");
        return jsonObject.toJSONString();
    }
}
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,100评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,308评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事?!?“怎么了?”我有些...
    开封第一讲书人阅读 159,718评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,275评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,376评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,454评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,464评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,248评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,686评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,974评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,150评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,817评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,484评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,140评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,374评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,012评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,041评论 2 351

推荐阅读更多精彩内容