PoiApi.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. #region Apache License Version 2.0
  2. /*----------------------------------------------------------------
  3. Copyright 2019 Jeffrey Su & Suzhou Senparc Network Technology Co.,Ltd.
  4. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5. except in compliance with the License. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software distributed under the
  8. License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  9. either express or implied. See the License for the specific language governing permissions
  10. and limitations under the License.
  11. Detail: https://github.com/JeffreySu/WeiXinMPSDK/blob/master/license.md
  12. ----------------------------------------------------------------*/
  13. #endregion Apache License Version 2.0
  14. /*----------------------------------------------------------------
  15. Copyright (C) 2019 Senparc
  16. 文件名:StoreApi.cs
  17. 文件功能描述:门店管理接口
  18. 创建标识:Senparc - 20150513
  19. 修改标识:Senparc - 201501018
  20. 修改描述:修改UploadImage()方法bug
  21. 修改标识:Senparc - 20160719
  22. 修改描述:增加其接口的异步方法
  23. 修改标识:Senparc - 20160812
  24. 修改描述:修改获取门店类目接口地址
  25. 修改标识:Senparc - 20170707
  26. 修改描述:v14.5.1 完善异步方法async/await
  27. ----------------------------------------------------------------*/
  28. /*
  29. 开发文档下载地址:https://mp.weixin.qq.com/zh_CN/htmledition/comm_htmledition/res/store_manage/store_manage_file.zip
  30. */
  31. using System.Collections.Generic;
  32. using System.Threading.Tasks;
  33. using Senparc.CO2NET.Extensions;
  34. using Senparc.NeuChar;
  35. using Senparc.Weixin.CommonAPIs;
  36. using Senparc.Weixin.Entities;
  37. using Senparc.CO2NET.HttpUtility;
  38. using Senparc.Weixin.MP.AdvancedAPIs.Poi;
  39. using Senparc.Weixin.MP.CommonAPIs;
  40. namespace Senparc.Weixin.MP.AdvancedAPIs
  41. {
  42. #region 商户在使用门店管理接口时需注意以下几个问题:
  43. /*
  44. * 门店信息全部需要经过审核方能生效,门店创建完成后,只会返回创建成功提示,并不能
  45. 获得poi_id,只有经过审核后才能获取poi_id,收到微信推送的审核结果通知,并使用在微
  46. 信各个业务场景中;
  47. * 为保证在审核通过后,获取到的poi_id 能与商户自身数据做对应,将会允许商户在创建时
  48. 提交自己内部或自定义的sid(字符串格式,微信不会对唯一性进行校验,请商户自己保证),
  49. 用于后续获取poi_id 后对数据进行对应;
  50. * 门店的可用状态available_state,将标记门店相应审核状态,只有审核通过状态,才能进行
  51. 更新,更新字段仅限扩展字段(表1 中前11 个字段);
  52. * 扩展字段属于公共编辑信息,提交更新后将由微信进行审核采纳,但扩展字段更新并不影
  53. 响门店的可用状态(即available_state 仍为审核通过),但update_status 状态变为1,更新中
  54. 状态,此时不可再次对门店进行更新,直到微信审核采纳后;
  55. * 在update_status 为1,更新中状态下的门店,此时调用getpoi 接口,获取到的扩展字段为更
  56. 新的最新字段,但并不是最终结果,仍需等待微信编辑对扩展字段的建议进行采纳后,最
  57. 终决定是否生效(有可能更新字段不被采纳);
  58. */
  59. #endregion
  60. /// <summary>
  61. /// 门店管理接口
  62. /// </summary>
  63. public static class PoiApi
  64. {
  65. #region 同步方法
  66. /// <summary>
  67. /// 上传图片
  68. /// </summary>
  69. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  70. /// <param name="file">文件路径</param>
  71. /// <param name="timeOut"></param>
  72. /// <returns></returns>
  73. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.UploadImage", true)]
  74. public static UploadImageResultJson UploadImage(string accessTokenOrAppId, string file, int timeOut = Config.TIME_OUT)
  75. {
  76. return ApiHandlerWapper.TryCommonApi(accessToken =>
  77. {
  78. var url = string.Format(Config.ApiMpHost + "/cgi-bin/media/uploadimg?access_token={0}", accessToken.AsUrlData());
  79. var fileDictionary = new Dictionary<string, string>();
  80. fileDictionary["media"] = file;
  81. return Post.PostFileGetJson<UploadImageResultJson>(url, null, fileDictionary, null, timeOut: timeOut);
  82. }, accessTokenOrAppId);
  83. }
  84. /// <summary>
  85. /// 创建门店
  86. /// </summary>
  87. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  88. /// <param name="createStoreData"></param>
  89. /// <param name="timeOut"></param>
  90. /// <returns></returns>
  91. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.AddPoi", true)]
  92. public static WxJsonResult AddPoi(string accessTokenOrAppId, CreateStoreData createStoreData,
  93. int timeOut = Config.TIME_OUT)
  94. {
  95. return ApiHandlerWapper.TryCommonApi(accessToken =>
  96. {
  97. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/addpoi?access_token={0}", accessToken.AsUrlData());
  98. return CommonJsonSend.Send<WxJsonResult>(null, url, createStoreData, CommonJsonSendType.POST, timeOut);
  99. }, accessTokenOrAppId);
  100. }
  101. /// <summary>
  102. /// 查询门店信息
  103. /// </summary>
  104. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  105. /// <param name="poiId"></param>
  106. /// <param name="timeOut"></param>
  107. /// <returns></returns>
  108. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.GetPoi", true)]
  109. public static GetStoreResultJson GetPoi(string accessTokenOrAppId, string poiId, int timeOut = Config.TIME_OUT)
  110. {
  111. return ApiHandlerWapper.TryCommonApi(accessToken =>
  112. {
  113. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/getpoi?access_token={0}", accessToken.AsUrlData());
  114. var data = new
  115. {
  116. poi_id = poiId
  117. };
  118. return CommonJsonSend.Send<GetStoreResultJson>(null, url, data, CommonJsonSendType.POST, timeOut);
  119. }, accessTokenOrAppId);
  120. }
  121. /// <summary>
  122. /// 查询门店列表
  123. /// </summary>
  124. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  125. /// <param name="begin">开始位置,0 即为从第一条开始查询</param>
  126. /// <param name="limit">返回数据条数,最大允许50,默认为20</param>
  127. /// <param name="timeOut"></param>
  128. /// <returns></returns>
  129. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.GetPoiList", true)]
  130. public static GetStoreListResultJson GetPoiList(string accessTokenOrAppId, int begin, int limit = 20, int timeOut = Config.TIME_OUT)
  131. {
  132. return ApiHandlerWapper.TryCommonApi(accessToken =>
  133. {
  134. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/getpoilist?access_token={0}", accessToken.AsUrlData());
  135. var data = new
  136. {
  137. begin = begin,
  138. limit = limit
  139. };
  140. return CommonJsonSend.Send<GetStoreListResultJson>(null, url, data, CommonJsonSendType.POST, timeOut);
  141. }, accessTokenOrAppId);
  142. }
  143. /// <summary>
  144. /// 删除门店
  145. /// </summary>
  146. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  147. /// <param name="poiId"></param>
  148. /// <param name="timeOut"></param>
  149. /// <returns></returns>
  150. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.DeletePoi", true)]
  151. public static WxJsonResult DeletePoi(string accessTokenOrAppId, string poiId, int timeOut = Config.TIME_OUT)
  152. {
  153. return ApiHandlerWapper.TryCommonApi(accessToken =>
  154. {
  155. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/delpoi?access_token={0}", accessToken.AsUrlData());
  156. var data = new
  157. {
  158. poi_id = poiId
  159. };
  160. return CommonJsonSend.Send<WxJsonResult>(null, url, data, CommonJsonSendType.POST, timeOut);
  161. }, accessTokenOrAppId);
  162. }
  163. /// <summary>
  164. /// 修改门店服务信息
  165. /// </summary>
  166. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  167. /// <param name="updateStoreData">修改门店服务信息需要Post的数据</param>
  168. /// 商户可以通过该接口,修改门店的服务信息,包括:图片列表、营业时间、推荐、特色服务、简介、人均价格、电话7 个字段。目前基础字段包括(名称、坐标、地址等不可修改)
  169. /// 若有填写内容则为覆盖更新,若无内容则视为不修改,维持原有内容。
  170. /// photo_list 字段为全列表覆盖,若需要增加图片,需将之前图片同样放入list 中,在其后增加新增图片。如:已有A、B、C 三张图片,又要增加D、E 两张图,则需要调用该接口,photo_list 传入A、B、C、D、E 五张图片的链接。
  171. /// <param name="timeOut"></param>
  172. /// <returns></returns>
  173. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.UpdatePoi", true)]
  174. public static WxJsonResult UpdatePoi(string accessTokenOrAppId, UpdateStoreData updateStoreData, int timeOut = Config.TIME_OUT)
  175. {
  176. return ApiHandlerWapper.TryCommonApi(accessToken =>
  177. {
  178. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/updatepoi?access_token={0}", accessToken.AsUrlData());
  179. return CommonJsonSend.Send<WxJsonResult>(null, url, updateStoreData, CommonJsonSendType.POST, timeOut);
  180. }, accessTokenOrAppId);
  181. }
  182. /// <summary>
  183. /// 获取门店类目表
  184. /// </summary>
  185. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  186. /// <returns></returns>
  187. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.GetCategory", true)]
  188. public static GetCategoryResult GetCategory(string accessTokenOrAppId)
  189. {
  190. return ApiHandlerWapper.TryCommonApi(accessToken =>
  191. {
  192. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/getwxcategory?access_token={0}", accessToken.AsUrlData());
  193. return CommonJsonSend.Send<GetCategoryResult>(null, url, null, CommonJsonSendType.GET);
  194. }, accessTokenOrAppId);
  195. }
  196. #endregion
  197. #if !NET35 && !NET40
  198. #region 异步方法
  199. /// <summary>
  200. /// 【异步方法】上传图片
  201. /// </summary>
  202. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  203. /// <param name="file">文件路径</param>
  204. /// <param name="timeOut"></param>
  205. /// <returns></returns>
  206. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.UploadImageAsync", true)]
  207. public static async Task<UploadImageResultJson> UploadImageAsync(string accessTokenOrAppId, string file, int timeOut = Config.TIME_OUT)
  208. {
  209. return await ApiHandlerWapper.TryCommonApiAsync(async accessToken =>
  210. {
  211. var url = string.Format(Config.ApiMpHost + "/cgi-bin/media/uploadimg?access_token={0}", accessToken.AsUrlData());
  212. var fileDictionary = new Dictionary<string, string>();
  213. fileDictionary["media"] = file;
  214. return await Post.PostFileGetJsonAsync<UploadImageResultJson>(url, null, fileDictionary, null, timeOut: timeOut);
  215. }, accessTokenOrAppId);
  216. }
  217. /// <summary>
  218. /// 【异步方法】创建门店
  219. /// </summary>
  220. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  221. /// <param name="createStoreData"></param>
  222. /// <param name="timeOut"></param>
  223. /// <returns></returns>
  224. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.AddPoiAsync", true)]
  225. public static async Task<WxJsonResult> AddPoiAsync(string accessTokenOrAppId, CreateStoreData createStoreData,
  226. int timeOut = Config.TIME_OUT)
  227. {
  228. return await ApiHandlerWapper.TryCommonApiAsync(async accessToken =>
  229. {
  230. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/addpoi?access_token={0}", accessToken.AsUrlData());
  231. return await Senparc.Weixin.CommonAPIs.CommonJsonSend.SendAsync<WxJsonResult>(null, url, createStoreData, CommonJsonSendType.POST, timeOut);
  232. }, accessTokenOrAppId);
  233. }
  234. /// <summary>
  235. /// 【异步方法】查询门店信息
  236. /// </summary>
  237. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  238. /// <param name="poiId"></param>
  239. /// <param name="timeOut"></param>
  240. /// <returns></returns>
  241. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.GetPoiAsync", true)]
  242. public static async Task<GetStoreResultJson> GetPoiAsync(string accessTokenOrAppId, string poiId, int timeOut = Config.TIME_OUT)
  243. {
  244. return await ApiHandlerWapper.TryCommonApiAsync(async accessToken =>
  245. {
  246. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/getpoi?access_token={0}", accessToken.AsUrlData());
  247. var data = new
  248. {
  249. poi_id = poiId
  250. };
  251. return await Senparc.Weixin.CommonAPIs.CommonJsonSend.SendAsync<GetStoreResultJson>(null, url, data, CommonJsonSendType.POST, timeOut);
  252. }, accessTokenOrAppId);
  253. }
  254. /// <summary>
  255. /// 【异步方法】查询门店列表
  256. /// </summary>
  257. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  258. /// <param name="begin">开始位置,0 即为从第一条开始查询</param>
  259. /// <param name="limit">返回数据条数,最大允许50,默认为20</param>
  260. /// <param name="timeOut"></param>
  261. /// <returns></returns>
  262. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.GetPoiListAsync", true)]
  263. public static async Task<GetStoreListResultJson> GetPoiListAsync(string accessTokenOrAppId, int begin, int limit = 20, int timeOut = Config.TIME_OUT)
  264. {
  265. return await ApiHandlerWapper.TryCommonApiAsync(async accessToken =>
  266. {
  267. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/getpoilist?access_token={0}", accessToken.AsUrlData());
  268. var data = new
  269. {
  270. begin = begin,
  271. limit = limit
  272. };
  273. return await Senparc.Weixin.CommonAPIs.CommonJsonSend.SendAsync<GetStoreListResultJson>(null, url, data, CommonJsonSendType.POST, timeOut);
  274. }, accessTokenOrAppId);
  275. }
  276. /// <summary>
  277. /// 【异步方法】删除门店
  278. /// </summary>
  279. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  280. /// <param name="poiId"></param>
  281. /// <param name="timeOut"></param>
  282. /// <returns></returns>
  283. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.DeletePoiAsync", true)]
  284. public static async Task<WxJsonResult> DeletePoiAsync(string accessTokenOrAppId, string poiId, int timeOut = Config.TIME_OUT)
  285. {
  286. return await ApiHandlerWapper.TryCommonApiAsync(async accessToken =>
  287. {
  288. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/delpoi?access_token={0}", accessToken.AsUrlData());
  289. var data = new
  290. {
  291. poi_id = poiId
  292. };
  293. return await Senparc.Weixin.CommonAPIs.CommonJsonSend.SendAsync<WxJsonResult>(null, url, data, CommonJsonSendType.POST, timeOut);
  294. }, accessTokenOrAppId);
  295. }
  296. /// <summary>
  297. /// 【异步方法】修改门店服务信息
  298. /// </summary>
  299. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  300. /// <param name="updateStoreData">修改门店服务信息需要Post的数据</param>
  301. /// 商户可以通过该接口,修改门店的服务信息,包括:图片列表、营业时间、推荐、特色服务、简介、人均价格、电话7 个字段。目前基础字段包括(名称、坐标、地址等不可修改)
  302. /// 若有填写内容则为覆盖更新,若无内容则视为不修改,维持原有内容。
  303. /// photo_list 字段为全列表覆盖,若需要增加图片,需将之前图片同样放入list 中,在其后增加新增图片。如:已有A、B、C 三张图片,又要增加D、E 两张图,则需要调用该接口,photo_list 传入A、B、C、D、E 五张图片的链接。
  304. /// <param name="timeOut"></param>
  305. /// <returns></returns>
  306. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.UpdatePoiAsync", true)]
  307. public static async Task<WxJsonResult> UpdatePoiAsync(string accessTokenOrAppId, UpdateStoreData updateStoreData, int timeOut = Config.TIME_OUT)
  308. {
  309. return await ApiHandlerWapper.TryCommonApiAsync(async accessToken =>
  310. {
  311. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/updatepoi?access_token={0}", accessToken.AsUrlData());
  312. return await Senparc.Weixin.CommonAPIs.CommonJsonSend.SendAsync<WxJsonResult>(null, url, updateStoreData, CommonJsonSendType.POST, timeOut);
  313. }, accessTokenOrAppId);
  314. }
  315. /// <summary>
  316. /// 【异步方法】获取门店类目表
  317. /// </summary>
  318. /// <param name="accessTokenOrAppId">AccessToken或AppId(推荐使用AppId,需要先注册)</param>
  319. /// <returns></returns>
  320. [ApiBind(NeuChar.PlatformType.WeChat_OfficialAccount, "PoiApi.GetCategoryAsync", true)]
  321. public static async Task<GetCategoryResult> GetCategoryAsync(string accessTokenOrAppId)
  322. {
  323. return await ApiHandlerWapper.TryCommonApiAsync(async accessToken =>
  324. {
  325. var url = string.Format(Config.ApiMpHost + "/cgi-bin/poi/getwxcategory?access_token={0}", accessToken.AsUrlData());
  326. return await Senparc.Weixin.CommonAPIs.CommonJsonSend.SendAsync<GetCategoryResult>(null, url, null, CommonJsonSendType.GET);
  327. }, accessTokenOrAppId);
  328. }
  329. #endregion
  330. #endif
  331. }
  332. }