我们在搭建小程序第三方平台过程发现官方提供的有很多接口,但不是每个接口都需要开发者用代码去实现。比如代码包管理的删除接口,就可以通过登录open.weixin.qq.com里,在列表看着更加详细的代码包版本介绍通过官方提供的界面就可以删除。即如果不是特殊需要,此接口可以不做开发。
那么我们搭建一个小程序服务商第三方平台需要哪些必要的功能模块呢?
必备功能模块概况
首先用一张图总概括下搭建一个mvp小程序服务商第三方平台必备的开发功能模块
第三方平台权限集
先用一张图表明第三方平台账号在授权后可用的权限集的部分。
只有平台先申请某一个权限,经过审核且全网发布后,旗下小程序才能在授权时选择某权限。有以下等 A>=B, B>=C;也就是第三方平台即使有每个微信提供的每个权限集,通过管理员授权后也不一定有全部权权限。原因:
1 单一授权被授权给其他第三方平台账号,或管理员授权时选择不把某一个权限授权给平台。比如开发和代码管理权限集
2 旗下小程序自身主体资质性质自带,不能拥有某个api权限。案例参考3
3 最终授权成功的权限集里,每个权限下都有多个api,所以在用某个api前需要看是由有权限。比如开发和代码管理权限集下,setwebviewdomain这个api不支持个人主体资质的appid调用
4 授权成功后,用token就可以用第三方平台提供的api代调用实现业务,或代调用小程序开发文档的api(标志参数需要access_token)里的接口,来实现产品开发。
授权及回调域名验证
####### 说明 #######
发起域名必须要在合法登记的域名名单内,且用户授权同意后的跳转url必须要在资料登记。体现在第三方平台创建时的以下两项配置中。
① 授权发起页域名
② 授权事件接收URL
授权回调URL源码
public void ProcessRequest(HttpContext context)
{
Request = context.Request;
Response = context.Response;
string signature = Request.QueryString["signature"];
string msg_signature = Request.QueryString["msg_signature"];
string timestamp = Request.QueryString["timestamp"];
string nonce = Request.QueryString["nonce"];
#region Response body
// 微信并不会因为返回失败就再发送一次消息,相反如果不返回success, 微信会延迟推送
string ResMsg = "success";
if (Request.HttpMethod == "POST")
{
using (Stream stream = Request.InputStream)
{
Byte[] postBytes = new Byte[stream.Length];
stream.Read(postBytes, 0, (Int32)stream.Length);
string postString = Encoding.UTF8.GetString(postBytes);
if (postString.Contains("<AppId>"))
{
XElement xdoc = XElement.Parse(postString);
CurAppID = xdoc.Element("AppId").Value.Trim();
LoadAppInfo(CurAppID);
string postStringXmlSrc = string.Empty;
Tencent.WXBizMsgCrypt wxcpt = new Tencent.WXBizMsgCrypt(CurAppToken, CurAppEncodingAESKey, CurAppID);
int ret = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postString, ref postStringXmlSrc);
if (ret == 0)
{
xdoc = XElement.Parse(postStringXmlSrc);
if (xdoc != null)
{
string InfoType = xdoc.Element("InfoType").Value.Trim();
if (InfoType == "component_verify_ticket")
{
string componentVerifyTicket = xdoc.Element("ComponentVerifyTicket").Value.Trim();
WeixinDataHelper.UpdateComponentVerifyTicket(CurAppID, componentVerifyTicket);
}
else if (InfoType == "unauthorized")
{
string authorizedAppId = xdoc.Element("AuthorizerAppid").Value.Trim();
WeixinDataHelper.Unauthorized(CurAppID, authorizedAppId);
}
else
{
// 微信平台上填写的授权URL 目前就支持这两种 InfoType
}
}
}
}
}
}
else if (Request.HttpMethod == "GET")
{
ResMsg = Request.QueryString["echostr"];
}
ResponseEnd(ResMsg);
#endregion
}
各种票据有效性维护机制
1 授权后得到授权码(authorization_code )
需要用授权码去调用接口换取令牌,并保存。
2 获取令牌和刷新令牌
用授权码获得令牌authorizer_access_token和刷新令牌authorizer_refresh_token。 需要保存令牌和刷新令牌。
3 刷新令牌authorizer_access_token
用刷新令牌定期去微信网关拉取令牌,维持令牌的有效性,保证后期代实现接口时令牌有效性。约1h左右的时间去刷新一次令牌。刷新令牌服务需要有重试机制,因为瞬时网络原因会返回失败,需要重试。
消息与事件处理平台
1 第三方平台component_verify_ticke更新
平台审核通过后,每隔10分钟定时推送一次component_verify_ticket,开发者需要保存在数据库。再授权场景获取预授权码时需要用到这个有效的ticket。
2 授权状态变更(成功,变更,取消)
3 代码审核通知消息
4 注意:
① 这里的消息时加密的需要先解密。
② 有开发者反馈说不知道返回信息时旗下哪个appid,这里补充下,appid是再请求头的request参数里直接返回的。
③ 消息与通知解密部分代码
public void ProcessRequest(HttpContext context)
{
HttpRequest Request = context.Request;
HttpResponse Response = context.Response;
// 所属的已授权公众号的appid
string AppID = Request.QueryString["AppID"];
string reqSignature = Request.QueryString["signature"];
string reqMsgSignature = Request.QueryString["msg_signature"];
string reqTimestamp = Request.QueryString["timestamp"];
string reqNonce = Request.QueryString["nonce"];
if (string.IsNullOrEmpty(AppID) || !WeixinHelper.ValidateWeixinInterface(reqSignature, WeixinResources.ComponentAppToken, reqTimestamp, reqNonce))
{
ResponseEnd(Response, string.Empty,AppID);
return;
}
if (AppID == WeixinResources.AutoTestAppID)
{
string _tmsg = new WeixinAutoTestHandler(Request, Response, WeixinResources.ComponentAppID).GetMsg();
ResponseEnd(Response, _tmsg,AppID);
return;
}
#region Response body
string ResMsg = string.Empty;
if (Request.HttpMethod == "POST")
{
using (Stream stream = Request.InputStream)
{
Byte[] postBytes = new Byte[stream.Length];
stream.Read(postBytes, 0, (Int32)stream.Length);
string postString = Encoding.UTF8.GetString(postBytes);
string Msg = string.Empty;
// 解密
Tencent.WXBizMsgCrypt wxcpt = new Tencent.WXBizMsgCrypt(WeixinResources.ComponentAppToken, WeixinResources.ComponentAppEncodingAESKey, WeixinResources.ComponentAppID);
int ret = 0;
ret = wxcpt.DecryptMsg(reqMsgSignature, reqTimestamp, reqNonce, postString, ref Msg);
if (ret != 0)
{
ResponseEnd(Response, string.Empty,AppID);
return;
}
// 生成响应消息
string resMsg = WeixinHelper.ReturnMessageAsThirdPlatform(AppID, Msg);
// 加密消息
string EncryptMsg = string.Empty;
ret = wxcpt.EncryptMsg(resMsg, reqTimestamp, reqNonce, ref EncryptMsg);
if (ret != 0)
{
EncryptMsg = string.Empty;
}
ResMsg = EncryptMsg;
}
}
else if (Request.HttpMethod == "GET")
{
ResMsg = Request.QueryString["echostr"];
}
ResponseEnd(Response, ResMsg,AppID);
#endregion
}
public static string ReturnMessageAsThirdPlatform(string AppID, string requestMsg)
{
string responseContent = string.Empty;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(requestMsg);
XmlNode MsgType = xmlDoc.SelectSingleNode("/xml/MsgType");
if (MsgType != null)
{
switch (MsgType.InnerText)
{
case "event":
responseContent = EventHandleAsThirdPlatform(AppID, xmlDoc); //事件处理
break;
case "text":
case "image":
case "voice":
case "video":
case "shortvideo":
case "location":
responseContent = TextHandleAsThirdPlatform(AppID, xmlDoc); //消息处理
break;
default:
break;
}
}
return responseContent;
}
代小程序域名设置机制
1 小程序服务器域名
为授权小程序设置服务器域名
requestdomain request合法域名
wsrequestdomain socket合法域名
uploaddomain uploadFile合法域名
downloaddomain downloadFile合法域名
2 小程序业务域名
为授权小程序提供业务域名
web-view的合法域名
第三方平台先登记后,在给旗下小程序授权
旗下小程序可以使用配置域名的子域名作为业务域名
代小程序代码包管理机制
1 提交代码包
详细关于代码包管理参考https://developers.weixin.qq.com/community/develop/article/doc/000622ad764e48a45419e25b151813
①ext.json的配置项更改体现在代码包配置json数据里。ext_json字段对应ext.json里的字段,这里template_id关联第三方平台》小程序模板管理里的模板ID。
② 那么要提交小程序的appid呢?还是通过ext_json字段来配置。ext_jsonjson字符串里的extAppid就是第三方平台账号旗下授权,本次要提交代码的小程序appid,通过上传代码时候的来指定extAppid就可以给一个小程序代提交代码。
2 提交审核
3 收到审核通知审核通过后提交上线
4 查询最近一次提交审核进度
5 回退到上一个版本
第三方代码模板管理
1 创建小程序账号,授权给平台账号,并绑定到第三方平台账号的开发小程序列表
2 用开发小程序appid创建项目的开发代码包模板
3 用开发小程序appid提交代码到草稿箱
4从草稿箱添加到模板库
超赞
C>B,这是永恒的。不是所有账号接口都开放给第三方的。B没有包含的接口 就是没开放的 ,微信支持反馈需求评估安排。有需要反馈接口需求不知道渠道的可联系我
大佬,我想问问如果我想批量去更新授权方的小程序,ext.json这个里面如何去填写呢
你好,想请问一下 extAppid 3rdMiniProgramAppid 和 开发者 appId 三者之间的关系是什么?
我理解的开发者 appId 是开发者自己创建的一个小程序的appId,extAppid 是客户授权后的替换的 appId,在开发阶段开发者的 appId = extAppid,那么3rdMiniProgramAppid又是什么,这一块搞懵了,想请教一下。
大佬,可以问下哪个授权事件接收URL在哪里可以看得到吗,之前注册的时候,填写没保存,现在一直找不到
有这个文档链接吗
大神您好,请问呢授权发起页域名一定要是自己所拥有的有服务器的企业域名吗?请帮忙抽空回答一下。谢谢!
大神,我想问一下那个ext.json文件在开发小程序(模版)中不是必写的吧,在上传代码是ext_json后面直接跟value(extAppid写对)就可以吧
我是第三方平台开发商
有平方APPID,平台方APPID
有开发小程序模板的APPID,开发模板的小程序APPID
现在要给A商户,B商户 ,他们也APPID 。商户APPID
现在要调
https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/code/commit.html
上传小程序代码
总是报
{
"errcode": 47001,
"errmsg": "data format error hint: [NmniwA02043955]"
}
这是为什么?
参数为:
{"access_token":"31_hzCUjtqASctz2icBQuDWycouVMNRr9eHvSOTQtzhcl03E0Yyd-5q6m64iVSJhbnG4Xk88jj7JvKrYU","user_desc":"test","user_version":"0.0.1","ext_json":"{\r\n\"extEnable\": true,\r\n\"extAppid\": \"wx9f1d74a5324b0200\",\r\n\"directCommit\": false,\r\n\"ext\": {\r\n \"name\": \"wechat\",\r\n \"attr\": {\r\n \"host\": \"open.weixin.qq.com\",\r\n \"users\": [\r\n \"tom\",\r\n \"jack\"\r\n ]\r\n }\r\n}\r\n}","template_id":"7"}
content-Type:application/json
URL:https://api.weixin.qq.com/wxa/commit?access_token=31_hzCUjtqASctz2icBQuDWycouVMNRr9eHvSOTQtzhcl03E0Yyd-5q6m64iVSJhbnG4Xk88jj7JvKrYU
ext.json 文件与参数中 "ext_json"一样,求高手指点一下
那配置错了
\""pages/logs/logs\"": {
\""navigationBarTitleText\"": \""logs\""
}
},
\""window\"": {
\""backgroundTextStyle\"": \""light\"",
\""navigationBarBackgroundColor\"": \""#ffffff\"",
\""navigationBarTitleText\"": \""@navigationBarTitleText\"",
\""navigationBarTextStyle\"": \""black\"",
\""enablePullDownRefresh\"": \""true\""
},
\""networkTimeout\"": {
\""request\"": 10000,
\""downloadFile\"": 10000
}
}
"",
""user_version"":"" v1.9.20191221sp1"",
""user_desc"":"" id=28;v1.9.20191221sp1;1重构代码; 2 404修复; 3 错误日志上报; 4 支持错误后自动恢复;""
}";
"template_id":"7"
"template_id":7
从问答过来,最近也在搞这个第三方平台,非常有用.