前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >微信开放平台之第三方平台开发,一整套流程

微信开放平台之第三方平台开发,一整套流程

原创
作者头像
悟空码字
修改于 2021-02-01 02:59:22
修改于 2021-02-01 02:59:22
2.3K00
代码可运行
举报
运行总次数:0
代码可运行

假如说,有多个业务,功能模式相同的公众号/小程序,如果只是小程序开发,那是不是需要复制多套代码,改appid信息,在微信公众号后台,配置域名服务器以及密钥等繁琐的信息,每改一个提交发布一次,进行重复的步骤。随着要维护的公众号/小程序数量逐步增加,需要投入的资源以及成本也随之增加。

有没有想过,只需要开发一套公众号/小程序代码,以之为模板,再来一套后台管理系统,把在微信公众号后台做的那些事都搬到我们自己的系统中。来一个业务相同的小程序,只需要管理员授权后,只要在我们的系统中点点几个按钮,就可以把小程序发布上线,一次开发供 N 个公众号使用,提供标准化的接口服务来满足业务的基础需求。通过扫描二维码授权给平台,帮助 N 多个公众号代实现业务,不再需要理解繁琐参数设置,并且密码不提供给开发者,保证安全,真正做到解放运营同学和开发的双手,有更多的时间去谈女朋友,那该多好。没错,微信第三方平台开发就是来帮你节省更多时间去把妹的神器。

概述

微信公众平台-第三方平台(简称第三方平台)开放给所有通过开发者资质认证后的开发者使用。在得到公众号或小程序运营者(简称运营者)授权后,第三方平台开发者可以通过调用微信开放平台的接口能力,为公众号或小程序的运营者提供账号申请、小程序创建、技术开发、行业方案、活动营销、插件能力等全方位服务。同一个账号的运营者可以选择多家适合自己的第三方为其提供产品能力或委托运营。

从业务特征上来说,第三方平台必须如图所示

从具体的业务场景上说,第三方平台包括以下场景:

  1. 提供行业解决方案,如针对电商行业的解决方案,或针对旅游行业的解决方案等;
  2. 行业:(横向)提供更加专业的运营能力,精细化运营用户公众号或小程序;
  3. 功能:(纵向)对公众平台功能的优化,如专门优化图文消息视觉样式和排版的工具,或专门定制的 CRM 用户管理功能,或功能强大的小程序插件等。

接入第三方开发的前提是要有微信开放平台应用,详细创建步骤请参考

https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/how_to_apply.htm

1、获取验证票据

验证票据(component_verify_ticket),在第三方平台创建审核通过后,微信服务器会向其 ”授权事件接收URL” 每隔 10 分钟以 POST 的方式推送 component_verify_ticket

接收 POST 请求后,只需直接返回字符串 success。为了加强安全性,postdata 中的 xml 将使用服务申请时的加解密 key 来进行加密,在收到推送后需进行解密。

代码语言:javascript
代码运行次数:0
运行
复制
public void saveTicket(HttpServletRequest request, HttpServletResponse response) throws IOException {
  String msgSignature = request.getParameter("msg_signature");// 微信加密签名
  String timeStamp = request.getParameter("timestamp");// 时间戳    
  String nonce = request.getParameter("nonce"); // 随机数  
  BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream(),"UTF-8"));
  StringBuffer sb = new StringBuffer();
  String line = null;
  while ((line = br.readLine()) != null) {
    sb = sb.append(line);
  }
  String postData = sb.toString();
  try {
    AuthorizedUtils.saveComponentVerifyTicket(msgSignature, timeStamp, nonce, postData);
  } catch (Exception e) {
    logger.error("系统异常", e);
  } finally {
    // 响应消息
    PrintWriter out = response.getWriter();
    out.print("success");
  }
}

2、获取令牌

令牌(component_access_token)是第三方平台接口的调用凭据。令牌的获取是有限制的,每个令牌的有效期为 2 小时,请自行做好令牌的管理,在令牌快过期时(比如1小时50分),重新调用接口获取。

代码语言:javascript
代码运行次数:0
运行
复制
public static ComponentToken getComponentToken(String ticket) {
    
RedisService<ComponentToken> redisService = RedisService.load();

ComponentToken componentToken = redisService.load(ComponentToken.COMPONENTTOKEN_ID, ComponentToken.class);  
if (componentToken == null) {
  String encryptAppId = ThirdPlat.PLAT_APPID;
  String appId = EnDecryptUtil.d3esDecode(encryptAppId);
  String encryptSecret = ThirdPlat.PLAT_SECRET;
  String secret = EnDecryptUtil.d3esDecode(encryptSecret);
      
  String requestUrl = AuthAccessUrl.COMPONENT_ACCESS_URL;
  Map<String, String> map = new HashMap<>(); 
  map.put("component_appid", appId); //第三方平台appid
  map.put("component_appsecret", secret); //第三方平台appsecret
  map.put("component_verify_ticket", ticket); 
  String outputStr = JSONObject.toJSONString(map);
  logger.warn("请求数据"+outputStr);
  JSONObject jsonObject = HttpRequestUtils.httpRequest(requestUrl, "POST", outputStr);
    if (null != jsonObject) {
    long expires = System.currentTimeMillis() + 7200;
    try{
      expires = System.currentTimeMillis() + jsonObject.getIntValue("expires_in");        
    }catch (Exception e) {
    }
    try {
      componentToken = new ComponentToken();
      componentToken.setComponentAccessToken(jsonObject.getString("component_access_token"));
      componentToken.setExpiresIn(expires);
      redisService.save(componentToken, ComponentToken.class);
    } catch (Exception e) {
      componentToken = null;
      logger.error("系统异常", e);
    }
  }
} else {
  long sysTime = System.currentTimeMillis();
  if (sysTime >= componentToken.getExpiresIn()) {
    redisService.delete(ComponentToken.COMPONENTTOKEN_ID, ComponentToken.class);
    componentToken = getComponentToken(ticket);
  }else{
  }
}
return componentToken;
}

3、快速创建小程序

快速创建小程序接口优化了小程序注册认证的流程,能帮助第三方平台迅速拓展线下商户,拓展商户的服务范围,占领小程序线下商业先机。采用法人人脸识别方式替代小额打款等认证流程,极大的减轻了小程序主体、类目资质信息收集的人力成本。第三方平台只需收集法人姓名、法人微信、企业名称、企业代码信息这四个信息,便可以向企业法人下发一条模板消息来采集法人人脸信息,完成全部注册、认证流程。以及法人收到创建成功后的小程序APPID时,同时下发模板消息给法人,提示法人进行邮箱和密码的设置,便于后续法人登陆小程序控制台进行管理。

通过该接口创建小程序默认为“已认证”。为降低接入小程序的成本门槛,通过该接口创建的小程序无需交 300 元认证费。

代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult fastRegister(String merchantId) {
  Merchant merchant = merchantService.getById(merchantId);
  if (merchant == null) {
      logger.warn("快速创建小程序---->失败,merchant为null");
      return AjaxResult.error("快速创建小程序失败,merchant为null",null);
  } else {
      RedisService<ComponentVerifyTicket> redisService = RedisService.load();
      ComponentVerifyTicket componentVerifyTicket = redisService.load(ComponentVerifyTicket.COMPONENT_VERIFY_TICKET_ID,
              ComponentVerifyTicket.class);
    if (componentVerifyTicket == null) {
        logger.warn("快速创建小程序---->失败,component_verify_ticket为null");
        return AjaxResult.error("快速创建小程序失败,component_verify_ticket为null",null);
    } else {
        ComponentToken componentToken = AuthorizedUtils.getComponentToken(componentVerifyTicket.getComponentVerifyTicket());
        RegisterWeappOut out = new RegisterWeappOut();
        out.setName(merchant.getName())
                .setCode(merchant.getCode())
                .setCode_type(merchant.getCodeType())
                .setLegal_persona_wechat(merchant.getLegalPersonaWechat())
                .setLegal_persona_name(merchant.getLegalPersonaName())
                .setComponent_phone(merchant.getComponentPhone());
        JSONObject obj = BaseUtils.createRegisterWeapp(componentToken,out);
        if (obj.getInteger("errcode") == 0 && "ok".equalsIgnoreCase(obj.getString("errmsg"))) {
            return AjaxResult.success();
        } else {
            return AjaxResult.error(obj.getInteger("errcode"),obj.getString("errmsg"));
        }
    }
}
} 

4、获取预授权码

预授权码(pre_auth_code)是第三方平台方实现授权托管的必备信息,每个预授权码有效期为 10 分钟。需要先获取令牌才能调用。

代码语言:javascript
代码运行次数:0
运行
复制
public static String getPreAuthCode(String ticket) {
ComponentToken componentToken = getComponentToken(ticket);
String encryptAppId = ThirdPlat.PLAT_APPID;
String appId = EnDecryptUtil.d3esDecode(encryptAppId);
String url = AuthAccessUrl.PRE_AUTH_CODE_URL + componentToken.getComponentAccessToken();
Map<String, String> map = new HashMap<String, String>();
map.put("component_appid", appId);
    JSONObject jsonObject = HttpRequestUtils.httpRequest(url, "POST", JSONObject.toJSONString(map));   
return jsonObject.getString("pre_auth_code");
}

5、引导商户授权获取授权信息

第三方服务商构建授权链接放置自己的网站,用户点击后,弹出授权页

代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult getMchWebAuthUrl(@PathVariable("id") String id) {
RedisService<ComponentVerifyTicket> redisService = RedisService.load();
ComponentVerifyTicket componentVerifyTicket = redisService.load(ComponentVerifyTicket.COMPONENT_VERIFY_TICKET_ID,
    ComponentVerifyTicket.class);
if(componentVerifyTicket == null){
  return AjaxResult.error("引入用户进入授权页失败,component_verify_ticket为null",null);
}else{
  String preAuthCode = AuthorizedUtils.getPreAuthCode(componentVerifyTicket.getComponentVerifyTicket());
  String encryptAppId = ThirdPlat.PLAT_APPID;
  String appId = EnDecryptUtil.d3esDecode(encryptAppId);
  String auth_type = ThirdPlat.AUTH_TYPE;
  String requestUrl = AuthAccessUrl.WEB_AUTH_URL;
  try {
    requestUrl = requestUrl.replace("COMPONENT_APPID", appId).replace("PRE_AUTH_CODE", preAuthCode)
        .replace("REDIRECT_URI", URLEncoder.encode(ThirdPlat.REDIRECT_URI.replace("MERCHANTID", id),"UTF-8")).replace("AUTH_TYPE", auth_type);
  } catch (UnsupportedEncodingException e) {
    e.printStackTrace();
  }
  logger.warn("步骤2:引入用户进入授权页---->成功,url为:" + requestUrl);
  return AjaxResult.success("操作成功",requestUrl);
  
}
}

6、设置小程序基本信息

设置小程序名称,当名称没有命中关键词,则直接设置成功;当名称命中关键词,需提交证明材料,并需要审核。修改小程序的头像。修改功能介绍。修改小程序隐私设置,即修改是否可被搜

代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult setBasicInfo(BasicInfo basicInfo) throws IOException {
  Merchant merchant = merchantService.getById(basicInfo.getMerchantId());
  if (merchant == null) {
      logger.warn("设置基本信息---->失败,merchant为null");
      return AjaxResult.error("设置基本信息失败,merchant为null",null);
  } else {
      AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
      //修改头像
      if (StringUtils.isNotEmpty(basicInfo.getHeadImage())) {
          UploadIn uli = new UploadIn();
          uli.setType("image").setUrlPath(basicInfo.getHeadImage());
          JSONObject uploadJson = BaseUtils.upload(info,uli);
          String mediaId = uploadJson.getString("media_id");
          ModifyHeadImageIn mhi = new ModifyHeadImageIn();
          mhi.setHead_img_media_id(mediaId).setX1("0").setY1("0").setX2("1").setY2("1");
          JSONObject obj = BaseUtils.modifyHeadImage(info,mhi);
          if (!obj.getInteger(ResStatus.ERRCODE).equals(ResStatus.CODE) || !ResStatus.MSG.equalsIgnoreCase(obj.getString(ResStatus.ERRMSG))) {
              return AjaxResult.error(obj.getInteger(ResStatus.ERRCODE),obj.getString(ResStatus.ERRMSG));
          } else {
              merchant.setAppletsHeadImg(basicInfo.getHeadImage());
          }
      }
      //修改名称
      if (StringUtils.isNotEmpty(basicInfo.getNickname())) {
          UploadIn uli = new UploadIn();
          uli.setType("image").setUrlPath(merchant.getBusinessLicense());
          JSONObject uploadJson = BaseUtils.upload(info,uli);
          String mediaId = uploadJson.getString("media_id");
          SetNicknameIn sni = new SetNicknameIn();
          sni.setNick_name(basicInfo.getNickname());
          sni.setLicense(mediaId);
          JSONObject obj = BaseUtils.setNickname(info,sni);
          if (!obj.getInteger(ResStatus.ERRCODE).equals(ResStatus.CODE) || !ResStatus.MSG.equalsIgnoreCase(obj.getString(ResStatus.ERRMSG))) {
              return AjaxResult.error(obj.getInteger(ResStatus.ERRCODE),obj.getString(ResStatus.ERRMSG));
          } else {
              merchant.setAppletsName(basicInfo.getNickname());
              if (obj.containsKey("audit_id") && StringUtils.isNotEmpty(obj.getString("audit_id"))) {
                  merchant.setAuditId(obj.getString("audit_id"));
              }
          }
      }
      //修改功能介绍
      if (StringUtils.isNotEmpty(basicInfo.getSignature())) {
          ModifySignatureIn msi = new ModifySignatureIn();
          msi.setSignature(basicInfo.getSignature());
          JSONObject obj = BaseUtils.modifySignature(info, msi);
          if (!obj.getInteger(ResStatus.ERRCODE).equals(ResStatus.CODE) || !ResStatus.MSG.equalsIgnoreCase(obj.getString(ResStatus.ERRMSG))) {
              return AjaxResult.error(obj.getInteger(ResStatus.ERRCODE),obj.getString(ResStatus.ERRMSG));
          } else {
              merchant.setAppletsSignature(basicInfo.getSignature());
          }
      }
      //修改隐私设置,即修改是否可被搜索
      if (StringUtils.isNotEmpty(basicInfo.getStatus())) {
          SearchStatusIn ssi = new SearchStatusIn();
          ssi.setStatus(basicInfo.getStatus());
          JSONObject obj = BaseUtils.changeWxaSearchStatus(info, ssi);
          if (!obj.getInteger(ResStatus.ERRCODE).equals(ResStatus.CODE) || !ResStatus.MSG.equalsIgnoreCase(obj.getString(ResStatus.ERRMSG))) {
              return AjaxResult.error(obj.getInteger(ResStatus.ERRCODE),obj.getString(ResStatus.ERRMSG));
          } else {
              merchant.setSearchStatus(basicInfo.getStatus());
          }
      }
      merchantService.updateById(merchant);
      return AjaxResult.success();
  }
}

7、支付授权

即填写商户号和商户号密钥,以及上传p12证书

8、设置服务器域名

授权给第三方的小程序,其服务器域名只可以为第三方平台的服务器,当小程序通过第三方平台发布代码上线后,小程序原先自己配置的服务器域名将被删除,只保留第三方平台的域名,所以第三方平台在代替小程序发布代码之前,需要调用接口为小程序添加第三方平台自身的域名。 

注意:

  1. 需要先将域名登记到第三方平台的小程序服务器域名中,才可以调用接口进行配置。
  2. 最多可以添加1000个合法服务器域名;其中,Request域名、Socket域名、Uploadfile域名、Download域名、Udp域名的设置数量均最大支持200个。
  3. 每月可提交修改申请50次。
代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult modifyDomain(ModifyDomain modifyDomain) {
  Merchant merchant = merchantService.getById(modifyDomain.getMerchantId());
  if (merchant == null) {
      logger.warn("设置服务器域名---->失败,merchant为null");
      return AjaxResult.error("设置服务器域名失败,merchant为null",null);
  } else {
      AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
      ModifyDomainOut out = new ModifyDomainOut();
      out.setAction(modifyDomain.getAction());
      String[] requests = modifyDomain.getRequestdomain().split(",");
      List<String> requestList = Arrays.asList(requests);
      out.setRequestdomain(requestList);
      String[] wsrequests = modifyDomain.getWsrequestdomain().split(",");
      List<String> wsrequestList = Arrays.asList(wsrequests);
      out.setWsrequestdomain(wsrequestList);
      String[] uploads = modifyDomain.getUploaddomain().split(",");
      List<String> uploadList = Arrays.asList(uploads);
      out.setUploaddomain(uploadList);
      String[] downloads = modifyDomain.getDownloaddomain().split(",");
      List<String> downloadsList = Arrays.asList(downloads);
      out.setDownloaddomain(downloadsList);
      JSONObject obj = BaseUtils.modifyDomain(info, out);
      if("0".equals(obj.getString("errcode")) && "ok".equalsIgnoreCase(obj.getString("errmsg"))){
          return AjaxResult.success();
      } else {
          return AjaxResult.error(obj.getInteger("errcode"),obj.getString("errmsg"));
      }
  }
}

9、设置业务域名

授权给第三方的小程序,其业务域名只可以为第三方平台的服务器,当小程序通过第三方发布代码上线后,小程序原先自己配置的业务域名将被删除,只保留第三方平台的域名,所以第三方平台在代替小程序发布代码之前,需要调用接口为小程序添加业务域名。

注意:

  1. 需要先将业务域名登记到第三方平台的小程序业务域名中,才可以调用接口进行配置。
  2. 为授权的小程序配置域名时支持配置子域名,例如第三方登记的业务域名如为 qq.com,则可以直接将 qq.com 及其子域名(如 xxx.qq.com)也配置到授权的小程序中。
  3. 最多可以添加100个业务域名。
代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult webviewDomain(WebviewDomain webviewDomain) {
  Merchant merchant = merchantService.getById(webviewDomain.getMerchantId());
  if (merchant == null) {
      logger.warn("设置业务域名---->失败,merchant为null");
      return AjaxResult.error("设置业务域名失败,merchant为null",null);
  } else {
      AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
      SetWebViewDomainOut out = new SetWebViewDomainOut();
      out.setAction(webviewDomain.getAction());
      String[] webviews = webviewDomain.getWebviewdomain().split(",");
      List<String> webviewList = Arrays.asList(webviews);
      out.setWebviewdomain(webviewList);
      JSONObject obj = BaseUtils.setWebViewDomain(info, out);
      if("0".equals(obj.getString("errcode")) && "ok".equalsIgnoreCase(obj.getString("errmsg"))){
          return AjaxResult.success();
      } else {
          return AjaxResult.error(obj.getInteger("errcode"),obj.getString("errmsg"));
      }
  }
}

10、上传小程序代码

第三方平台需要先将草稿添加到代码模板库,或者从代码模板库中选取某个代码模板,得到对应的模板 id(template_id);然后调用本接口可以为已授权的小程序上传代码。

代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult commit(CommitModel model) {
  Merchant merchant = merchantService.selectMerchantById(model.getMerchantId());
  if (merchant == null) {
      logger.warn("上传代码---->失败,merchant为null");
      return AjaxResult.error("上传代码,merchant为null",null);
  }
  AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
  CommitIn commitIn = new CommitIn();
  String value = model.getValue();
  String[] items = value.split("_");
  String version = items[2];
  commitIn.setTemplate_id(items[0])
          .setUser_desc(items[1])
          .setUser_version(version);

  //第三方自定义的配置
  JSONObject obj = new JSONObject();
  obj.put("extAppid", merchant.getAppid());
  Map<String, Object> map = new HashMap<>();
  map.put("merchantId", model.getMerchantId());
  map.put("userVersion", commitIn.getUser_version());
  obj.put("ext", map);
  map = new HashMap<>();
  Map<String, Object> maps = new HashMap<>();
  maps.put("pages/index/index", map);
  obj.put("extPages", maps);
  commitIn.setExt_json(JSONObject.toJSONString(obj));
  //接受微信返回的数据
  obj = CodeUtils.commit(info, commitIn);
  if("0".equals(obj.getString("errcode")) && "ok".equalsIgnoreCase(obj.getString("errmsg"))){
      AppletsRelease ar = appletsReleaseService.getOne(new LambdaQueryWrapper<AppletsRelease>()
              .eq(AppletsRelease::getMerchantId,merchant.getId()));
      if(ar == null){
          ar = new AppletsRelease();
          ar.setMerchantId(model.getMerchantId()).setHistoryversion(version);
      } else{
          ar.setHistoryversion(version);
      }
      appletsReleaseService.saveOrUpdate(ar);
      return AjaxResult.success();
  } else {
      return AjaxResult.error(obj.getInteger("errcode"),obj.getString("errmsg"));
  }
}

11、成员管理

第三方平台在帮助旗下授权的小程序提交代码审核之前,可先让小程序运营者体验,体验之前需要将运营者的个人微信号添加到该小程序的体验者名单中。 

注意: 如果运营者同时也是该小程序的管理员,则无需绑定,管理员默认有体验权限。

代码语言:javascript
代码运行次数:0
运行
复制
/**
* 绑定体验者
* @parambindTester
* @return
*/
@Override
public AjaxResult bindTester(BindTester bindTester) {
  Merchant merchant = merchantService.getById(bindTester.getMerchantId());
  if (merchant == null) {
      logger.warn("绑定体验者---->失败,merchant为null");
      return AjaxResult.error("绑定体验者失败,merchant为null",null);
  } else {
      AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
      JSONObject obj = MemberUtils.bindTester(info, bindTester.getWechatId());
      if("0".equals(obj.getString("errcode")) && "ok".equalsIgnoreCase(obj.getString("errmsg"))){
      AppletsTester at = new AppletsTester();
        at.setMerchantId(bindTester.getMerchantId()).setWechatId(bindTester.getWechatId()).setUserStr(obj.getString("userstr"));
        appletsTesterService.insertAppletsTester(at);
        return AjaxResult.success();
    } else {
        return AjaxResult.error(obj.getInteger("errcode"),obj.getString("errmsg"));
    }
}
}

/**
* 解除体验者
* @paramtesterIds
* @return
*/
@Override
public AjaxResult unbindTester(Long[] testerIds) {
  for (Long id : testerIds) {
      AppletsTester tester = appletsTesterService.getById(id);
      if (tester == null) {
          logger.warn("解除体验者---->失败,tester为null");
          return AjaxResult.error("解除体验者,tester为null",null);
      }
      Merchant merchant = merchantService.getById(tester.getMerchantId());
      if (merchant == null) {
          logger.warn("解除体验者---->失败,merchant为null");
          return AjaxResult.error("解除体验者,merchant为null",null);
          }
        AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
        JSONObject obj = MemberUtils.unbindTester(info, tester.getWechatId());
        if("0".equals(obj.getString("errcode")) && "ok".equalsIgnoreCase(obj.getString("errmsg"))){
            appletsTesterService.removeById(id);
        } else {
            return AjaxResult.error(obj.getInteger("errcode"),obj.getString("errmsg"));
        }
    }
    return AjaxResult.success();
}

12、获取体验版二维码

代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult getQrcode(String merchantId) {
  Merchant merchant = merchantService.getById(merchantId);
  if (merchant == null) {
      logger.warn("获取体验二维码---->失败,merchant为null");
      return AjaxResult.error("获取体验二维码,merchant为null",null);
  }
  AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
  String qrcodeUrl =  CodeUtils.getQrcode(info, "pages/index/index");
  return AjaxResult.success("操作成功",qrcodeUrl);
}

13、提交审核

代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult submitAudit(SubmitAudit submit) {
  Merchant merchant = merchantService.getById(submit.getMerchantId());
  if (merchant == null) {
      logger.warn("获取体验二维码---->失败,merchant为null");
      return AjaxResult.error("获取体验二维码,merchant为null", null);
  }
  AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
  List<String> categorys = submit.getCategory();
  submit.setFirst_id(categorys.get(0).split("-")[0])
          .setFirst_class(categorys.get(0).split("-")[1])
          .setSecond_id(categorys.get(1).split("-")[0])
          .setSecond_class(categorys.get(1).split("-")[1])
          .setTag(submit.getTag().replace(",", " "));
  List<SubmitAudit> submits = new ArrayList<>();
  submits.add(submit);
  JSONObject sa = CodeUtils.submitAudit(info, submits);
  if (sa.getInteger(ResStatus.ERRCODE).equals(ResStatus.CODE) && ResStatus.MSG.equalsIgnoreCase(sa.getString(ResStatus.ERRMSG))) {
      JSONObject obj = CodeUtils.getAuditStatus(info, sa.getString("auditid"));
      if (obj.getInteger(ResStatus.ERRCODE).equals(ResStatus.CODE) && ResStatus.MSG.equalsIgnoreCase(obj.getString(ResStatus.ERRMSG))) {
          AppletsRelease ar = appletsReleaseService.getOne(new LambdaQueryWrapper<AppletsRelease>()
                  .eq(AppletsRelease::getMerchantId,merchant.getId()));
          if (ar == null) {
              return AjaxResult.error("请先上传代码");
          }
          ar.setMerchantId(submit.getMerchantId())
                  .setAuditId(sa.getString("auditid"))
                  .setStatus(obj.getString("status"))
                  .setRemark(obj.getString("screenshot"));
          if (AppletsRelease.STATUS_0.equals(ar.getStatus())) {
              ar.setRemark(AppletsRelease.MSG_0);
          } else if (AppletsRelease.STATUS_1.equals(ar.getStatus())) {
              ar.setReason(obj.getString("reason"))
                      .setScreenshot(obj.getString("screenshot"))
                      .setRemark(AppletsRelease.MSG_1);
          } else if (AppletsRelease.STATUS_2.equals(ar.getStatus())) {
              ar.setRemark(AppletsRelease.MSG_2);
          } else if (AppletsRelease.STATUS_3.equals(ar.getStatus())) {
              ar.setRemark(AppletsRelease.MSG_3);
          } else if (AppletsRelease.STATUS_4.equals(ar.getStatus())) {
              ar.setRemark(AppletsRelease.MSG_4);
          }
          appletsReleaseService.updateById(ar);
          return AjaxResult.success();
      } else {
          return AjaxResult.error(obj.getInteger(ResStatus.ERRCODE), obj.getString(ResStatus.ERRMSG));
      }
  } else {
      return AjaxResult.error(sa.getInteger(ResStatus.ERRCODE), sa.getString(ResStatus.ERRMSG));
  }
}

14、审核撤回

注意: 单个帐号每天审核撤回次数最多不超过 1 次,一个月不超过 10 次。

代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult undoCodeAudit(String[] ids) {
  StringBuilder sb = new StringBuilder();
  for (String id : ids) {
      Merchant merchant = merchantService.getById(id);
      AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
      JSONObject obj = CodeUtils.undoCodeAudit(info);
      if (obj.getInteger(ResStatus.ERRCODE).equals(ResStatus.CODE) && ResStatus.MSG.equalsIgnoreCase(obj.getString(ResStatus.ERRMSG))) {
          AppletsRelease ar = appletsReleaseService.getOne(new LambdaQueryWrapper<AppletsRelease>()
                  .eq(AppletsRelease::getMerchantId,merchant.getId()));
          ar.setStatus(AppletsRelease.MSG_3);
          appletsReleaseService.updateById(ar);
      } else{
          sb.append(merchant.getName()+",");
      }
  }
  if (sb.length() == 0) {
      return AjaxResult.success();
  } else {
      String name = sb.substring(0, sb.length()-1);
      return AjaxResult.error(name+"审核撤回失败");
  }
}

15、发布已通过审核的小程序

代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult releaseApplets(String[] ids) {
  StringBuilder sb = new StringBuilder();
  for (String id : ids) {
      Merchant merchant = merchantService.getById(id);
      AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
      JSONObject obj = CodeUtils.release(info);
      if (obj.getInteger(ResStatus.ERRCODE).equals(ResStatus.CODE) && ResStatus.MSG.equalsIgnoreCase(obj.getString(ResStatus.ERRMSG))) {
          AppletsRelease ar = appletsReleaseService.getOne(new LambdaQueryWrapper<AppletsRelease>()
                  .eq(AppletsRelease::getMerchantId,merchant.getId()));
          ar.setStatus(AppletsRelease.STATUS_5);
          appletsReleaseService.updateById(ar);
      } else{
          sb.append(merchant.getName()+",");
      }
  }
  if (sb.length() == 0) {
      return AjaxResult.success();
  } else {
      String name = sb.substring(0, sb.length()-1);
      return AjaxResult.error(name+"发布失败");
  }
}

16、小程序版本回退

注意:

  1. 如果没有上一个线上版本,将无法回退
  2. 只能向上回退一个版本,即当前版本回退后,不能再调用版本回退接口
代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult revertCodeRelease(String[] ids) {
  StringBuilder sb = new StringBuilder();
  for (String id : ids) {
      Merchant merchant = merchantService.getById(id);
      AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
      JSONObject obj = CodeUtils.revertCodeRelease(info);
      if (!(obj.getInteger(ResStatus.ERRCODE).equals(ResStatus.CODE) && ResStatus.MSG.equalsIgnoreCase(obj.getString(ResStatus.ERRMSG)))) {
          sb.append(merchant.getName()+",");
      }
  }
  if (sb.length() == 0) {
      return AjaxResult.success();
  } else {
      String name = sb.substring(0, sb.length()-1);
      return AjaxResult.error(null,name+"审核撤回失败");
  }
}

17、获取小程序码

代码语言:javascript
代码运行次数:0
运行
复制
public AjaxResult getMiniQrcode(@PathVariable("merchantId") String merchantId) {
  Merchant merchant = merchantService.getById(merchantId);
  if (merchant == null) {
      logger.warn("获取小程序码---->失败,merchant为null");
      return AjaxResult.error("获取小程序码,merchant为null",null);
  }
  String qrcode;
  if (StringUtils.isNotEmpty(merchant.getAppletImage())) {
      qrcode = merchant.getAppletImage();
  } else {
      AuthorizationInfo info = AuthorizedUtils.getAuthorizationInfo(merchant.getAppid());
      qrcode = WxUtils.getMiniQrcode(merchantId, "pages/index/index", "merchant", "miniQrcode", info.getAuthorizer_access_token());
      merchant.setAppletImage(qrcode);
      merchantService.updateById(merchant);
  }
  return AjaxResult.success("操作成功",qrcode);
}

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
10个最佳ES6特性
为了保证可读性,本文采用意译而非直译,并且对源代码进行了大量修改。另外,本文版权归原作者所有,翻译仅用于学习。
疯狂的技术宅
2019/03/28
5060
require和import的区别
CommonJs 规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的 exports属性(即module.exports)是对外的接口,加载某个模块,其实是加载该模块的module.exports属性。
木子星兮
2020/07/16
1.2K0
前端MVC Vue2学习总结(七)——ES6与Module模块化、Vue-cli脚手架搭建、开发、发布项目与综合示例
使用vue-cli可以规范项目,提高开发效率,但是使用vue-cli时需要一些ECMAScript6的知识,特别是ES6中的模块管理内容,本章先介绍ES6中的基础与模块化的内容再使用vue-cli开发vue项目。 一、ECMAScript6概要 ECMAScript是一种由Ecma国际(前身为欧洲计算机制造商协会,英文名称是European Computer Manufacturers Association)通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaSc
张果
2018/03/30
1.8K0
前端MVC Vue2学习总结(七)——ES6与Module模块化、Vue-cli脚手架搭建、开发、发布项目与综合示例
前端模块化详解(完整版)
在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀,此时在JS方面就会考虑使用模块化规范去管理。 本文内容主要有理解模块化,为什么要模块化,模块化的优缺点以及模块化规范,并且介绍下开发中最流行的CommonJS, AMD, ES6、CMD规范。本文试图站在小白的角度,用通俗易懂的笔调介绍这些枯燥无味的概念,希望诸君阅读后,对模块化编程有个全新的认识和理解!
Nealyang
2019/09/29
1.4K0
前端模块化详解(完整版)
深入理解 ES Module
Module是ES6 出现的一个新的语法,提供一种将 JavaScript 程序拆分为可按需导入的单独模块的机制。在未出现之前,我们可能使用 commonjs等模块规范。随着ES Module的普及和推广,浏览器已经支持原生的模块规范。
前端知知
2022/09/29
4400
深入理解 ES Module
前端模块化详解(完整版)
上例子通过jquery方法将页面的背景颜色改成红色,所以必须先引入jQuery库,就把这个库当作参数传入。这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显。
小生方勤
2019/06/01
2.2K0
前端模块化的今生
众所周知,早期 JavaScript 原生并不支持模块化,直到 2015 年,TC39 发布 ES6,其中有一个规范就是 ES modules(为了方便表述,后面统一简称 ESM)。但是在 ES6 规范提出前,就已经存在了一些模块化方案,比如 CommonJS(in Node.js)、AMD。ESM 与这些规范的共同点就是都支持导入(import)和导出(export)语法,只是其行为的关键词也一些差异。
ConardLi
2019/12/17
7170
前端模块化-CommonJS,AMD,CMD,ES6
随着 JavaScript 工程越来越大,团队协作不可避免,为了更好地对代码进行管理和测试,模块化的概念逐渐引入前端。模块化可以降低协同开发的成本,减少代码量,同时也是“高内聚,低耦合”的基础。
李振
2021/11/26
4340
模块化的一些小研究
我们知道最常见的模块化方案有CommonJS、AMD、CMD、ES6,AMD规范一般用于浏览器,异步的,因为模块加载是异步的,js解释是同步的,所以有时候导致依赖还没加载完毕,同步的代码运行结束;CommonJS规范一般用于服务端,同步的,因为在服务器端所有文件都存储在本地的硬盘上,传输速率快而且稳定。
lhyt
2022/09/21
3530
50 种 ES6 模块,面试被问麻了
快来免费体验ChatGpt plus版本的,我们出的钱 体验地址:https://chat.waixingyun.cn可以加入网站底部技术群,一起找bug,...
前端小智@大迁世界
2024/02/12
2280
50 种 ES6 模块,面试被问麻了
Vue学习-ES6的模块化实现
在实际编写js脚本时,可能会遇到多个js脚本中变量或函数重复命名的情况,如果全部为全局变量,则在使用的时候会产生很多麻烦。因此出现了模块化的概念,即可以把每一个js脚本当作一个独立的模块,不同模块间的内容互不干扰,这样在实际使用起来的时候会避免很多不必要的麻烦。
花猪
2022/02/17
4200
Javascript模块化详解
前端的发展日新月异,前端工程的复杂度也不可同日而语。原始的开发方式,随着项目复杂度提高,代码量越来越多,所需加载的文件也越来越多,这个时候就需要考虑如下几个问题:
Clearlove
2021/03/11
6500
Javascript模块化详解
【译】开始在web使用JS Modules
原文说的JS modules,实际上指的是ES6的模块化特性,通过<script type="module">可以实现不经过打包直接在浏览器中import/export,此玩法确实让人眼前一亮。
elson
2018/07/04
2K0
【译】开始在web使用JS Modules
五分钟带你回顾前端模块化发展史
CSS 早在 2.1 的版本就提出了 @import 来实现模块化,但是 JavaScript 直到 ES6 才出现官方的模块化方案 ES Module。尽管早期 JavaScript 语言规范上不支持模块化,但这并没有阻止 JavaScript 的发展。官方没有模块化标准,那么我们就自己动手创建标准。社区里的前辈们创建并实现了规范,这些规范便是前端模块化发展之路上智慧的结晶。
童欧巴
2020/03/30
8920
五分钟带你回顾前端模块化发展史
javaScript模块化解析「建议收藏」
上面说提到的结构,就是模块;按照这种结构划分开发程序的过程,就是模块化开发的过程;
全栈程序员站长
2022/11/15
5200
javaScript模块化解析「建议收藏」
模块化的一些小研究0.前言1.script标签引入2.AMD与CMD3.CommonJS与ES64.循环依赖5.webpack是如何处理模块化的
我们知道最常见的模块化方案有CommonJS、AMD、CMD、ES6,AMD规范一般用于浏览器,异步的,因为模块加载是异步的,js解释是同步的,所以有时候导致依赖还没加载完毕,同步的代码运行结束;CommonJS规范一般用于服务端,同步的,因为在服务器端所有文件都存储在本地的硬盘上,传输速率快而且稳定。
lhyt
2018/10/31
1.3K0
【译】开始在web中使用JS Modules
原文:《Using JavaScript modules on the web》 https://developers.google.com/web/fundamentals/primers/modules 译者序 JS modules,即ES6的模块化特性,通过 <scripttype="modules">可以实现不经过打包直接在浏览器中import/export,此玩法确实让人眼前一亮。 先看看 <scripttype="modules">的兼容性。目前只有较新版本的chrome/firefox/saf
QQ音乐前端团队
2018/08/12
1.2K0
【THE LAST TIME】深入浅出 JavaScript 模块化
随着互联网的发展,前端开发也变的越来越复杂,从一开始的表单验证到现在动不动上千上万行代码的项目开发,团队协作就是我们不可避免的工作方式,为了更好地管理功能逻辑,模块化的概念也就渐渐产生了。
Nealyang
2020/01/14
7190
【THE LAST TIME】深入浅出 JavaScript 模块化
【前端】:模块化 - 打包技术
ES modules export live bindings, not values, so values can be changed after they are initially imported as per.
WEBJ2EE
2020/09/01
1.5K0
【前端】:模块化 - 打包技术
[译]ES6 模块化入门
在 ES6 之前,我们已经知道了 RequireJS,AngularJS 的依赖注入,以及 CommonJS,具体可以看笔者的上一篇文章《JS模块化历史简介》。当我们学习 ES6 的模块化,就会发现它的发展深受 CommonJS 的影响。通过这篇文章,我们将看到 export 和 import 语句,以及 ES6 模块是怎么与 CommonJS 模块兼容的。
savokiss
2019/11/06
8450
相关推荐
10个最佳ES6特性
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档