WeChatMiniProgramRemoteServiceImpl.java 6.92 KB
package com.zteits.pay.biz.wx;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.clouds.common.constants.CodeValKindEnum;
import com.clouds.common.constants.CodeValueEnum;
import com.clouds.common.constants.RedisKeyEnum;
import com.clouds.common.oss.base.OssClientService;
import com.clouds.common.oss.fastdfs.FastDFSOssClientWrapper;
import com.clouds.common.utils.HttpClientUtils;
import com.clouds.common.utils.ResultUtils;
import com.clouds.common.utils.WxConfigUtil;
import com.clouds.common.utils.image.ImageBase64Util;
import com.clouds.common.utils.wx.AccessToken;
import com.clouds.common.utils.wx.AccessTokenUtil;
import com.zteits.clouds.api.apibase.bean.BizResult;
import com.zteits.clouds.api.apibase.constants.BasicEnum;
import com.zteits.clouds.api.apibase.constants.ErrorType;
import com.zteits.clouds.api.apibase.constants.PayTypeEnum;
import com.zteits.clouds.api.apibase.exception.BizException;
import com.zteits.clouds.api.dto.pay.TdCAcctNoSecretDTO;
import com.zteits.clouds.api.dto.pay.param.GetWxUnlimitedQrCodeRequest;
import com.zteits.clouds.api.dto.sys.DataDicKindDetailDTO;
import com.zteits.clouds.api.dto.sys.SysOrgAppIdDTO;
import com.zteits.clouds.api.dto.sys.param.DataDicKindDetailRequest;
import com.zteits.clouds.api.dto.sys.param.SysOrgAppIdQueryRequest;
import com.zteits.clouds.api.service.pay.wx.WeChatMiniProgramRemoteService;
import com.zteits.clouds.api.service.sys.DataDictionaryService;
import com.zteits.clouds.api.service.sys.SysOrgAppIdService;
import com.zteits.pay.biz.AccountRechargeServiceImpl;
import com.zteits.pay.dao.TdBWxConfigDao;
import com.zteits.pay.domain.TdBWxConfig;
import com.zteits.pay.util.FastDFSClientWrapper;
import groovy.util.logging.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: Tom
 * @Date: 2022/8/30 14:26
 * @Description:
 */
@Service
public class WeChatMiniProgramRemoteServiceImpl implements WeChatMiniProgramRemoteService {
    private static final Logger logger = LoggerFactory.getLogger(WeChatMiniProgramRemoteServiceImpl.class);

    /**
     * 获取小程序码,适用于需要的码数量极多的业务场景。通过该接口生成的小程序码,永久有效,数量暂无限制。URL
     */
    private final String GETUNLIMITED = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?";

    @Autowired
    private FastDFSClientWrapper fastDFSClientWrapper;

    @Autowired
    private TdBWxConfigDao tdBWxConfigDao;

    @Autowired
    private SysOrgAppIdService sysOrgAppIdService;

    @Autowired
    private DataDictionaryService dataDictionaryService;


    @Override
    public BizResult<String> getUnlimitedQrCodeUrl(GetWxUnlimitedQrCodeRequest request) {
        if (request == null || request.getOrgId() == null || StringUtils.isBlank(request.getScene())){
            return new BizResult<>(ErrorType.PARAMM_NULL, "参数为空");
        }

        SysOrgAppIdQueryRequest sysRequest = new SysOrgAppIdQueryRequest();
        sysRequest.setOrgId(request.getOrgId());
        sysRequest.setPayType(PayTypeEnum.WXAPPLETS.getValue());
        sysRequest.setSysCode(BasicEnum.SYS_CODE.getValue());
        BizResult<SysOrgAppIdDTO> appIdDTOBizResult = sysOrgAppIdService.querySysOrgAppIdByOrgIdAndPayType(sysRequest);
        SysOrgAppIdDTO sysOrgAppIdDTO = appIdDTOBizResult.getData();

        TdBWxConfig tdBWxConfig = tdBWxConfigDao.queryWxConfigByAppId(sysOrgAppIdDTO.getPayAppId());

        //微信小程序appId
        String wxAppId = tdBWxConfig.getAppid();
        //微信小程序appsecret
        String wxAppSecret = tdBWxConfig.getAppSecret();

        byte[] body = this.getUnlimitedForBytes(wxAppId,wxAppSecret, request.getScene());
        if (body == null || body.length == 0) {
            logger.info("获取二维码失败,失效accessToken,重新调用");
            AccessTokenUtil.deleteAccessToken(wxAppId);
            body = this.getUnlimitedForBytes(wxAppId,wxAppSecret, request.getScene());
            if (body == null || body.length == 0) {
                logger.info("新的accessToken获取二维码依旧失效,抛异常");
            }
        }
        //上传图片到OSS
        String url = "";
        try {
            url = fastDFSClientWrapper.uploadBase64Pic(ImageBase64Util.encode(body), ".jpg",request.getOrgId(),"wx");
        } catch (Exception e) {
            logger.error("图片上传阿里云失败", e);
        }

        logger.info("图片完整地址:{}", url);
        return new BizResult<>(url);
    }

    /**
     * 调用微信生成二维码,获取bytes
     *
     * @return
     */
    private byte[] getUnlimitedForBytes(String wxAppId, String wxAppSecret, String scene) {
        DataDicKindDetailRequest dataDicKindDetailRequest = new DataDicKindDetailRequest();
        dataDicKindDetailRequest.setCodeKind(CodeValKindEnum.WX_MINI_CONFIG.name());
        dataDicKindDetailRequest.setSysCode(BasicEnum.SYS_CODE.getValue());
        BizResult<List<DataDicKindDetailDTO>> bizResult = dataDictionaryService.getDataDictionaryKindDetails(dataDicKindDetailRequest);
        List<DataDicKindDetailDTO> dataDicKindDetailDTOS = ResultUtils.getBizResultData(bizResult);
        if (CollectionUtils.isEmpty(dataDicKindDetailDTOS)) {
            throw new BizException(ErrorType.SYS_CODE_NOT_CONFIG, "字典表未配置" + CodeValKindEnum.WX_MINI_CONFIG.name(), false);
        }
        Map<String, String> map = dataDicKindDetailDTOS.stream().collect(Collectors.toMap(DataDicKindDetailDTO::getCodeValue, DataDicKindDetailDTO::getCodeValueName));

        //要打开的小程序版本。正式版为 release(默认值),体验版为 trial,开发版为 develop
        String envVersion = map.get(CodeValueEnum.WX_MINI_ENV_VERSION.name());
        //page
        String page = map.get(CodeValueEnum.WX_MINI_CHARGE_PAGE.name());
        //获取accessToken
        wxAppSecret = WxConfigUtil.decode(wxAppSecret);
        AccessToken token = AccessTokenUtil.getToken(wxAppId, wxAppSecret);
        String accessToken = token.getAccessToken();
        //生成二维码
        String url = GETUNLIMITED + "access_token=" + accessToken;
        JSONObject params = new JSONObject();
        params.put("scene", scene);
        if (StringUtils.isNotEmpty(envVersion)) {
            //不传递,默认release
            params.put("env_version", envVersion);
        }
        if (StringUtils.isNotEmpty(page)) {
            params.put("page", page);
        }
        params.put("check_path", false);

        HttpClientUtils client = new HttpClientUtils();
        byte[] body = client.post(url, params.toJSONString());
        return body;
    }

}