附近小店
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 

349 行
10 KiB

  1. package weapp
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "net/http"
  6. "net/http/httptest"
  7. "strings"
  8. "testing"
  9. )
  10. func TestAddNearbyPoi(t *testing.T) {
  11. localServer := http.NewServeMux()
  12. localServer.HandleFunc("/notify", func(w http.ResponseWriter, r *http.Request) {
  13. aesKey := base64.StdEncoding.EncodeToString([]byte("mock-aes-key"))
  14. srv, err := NewServer("mock-app-id", "mock-access-token", aesKey, "mock-mch-id", "mock-api-key", false)
  15. if err != nil {
  16. t.Fatal(err)
  17. }
  18. srv.OnAddNearbyPoi(func(mix *AddNearbyPoiResult) {
  19. if mix.ToUserName == "" {
  20. t.Error("ToUserName can not be empty")
  21. }
  22. if mix.FromUserName == "" {
  23. t.Error("FromUserName can not be empty")
  24. }
  25. if mix.CreateTime == 0 {
  26. t.Error("CreateTime can not be zero")
  27. }
  28. if mix.MsgType != "event" {
  29. t.Error("Unexpected message type")
  30. }
  31. if mix.Event != "add_nearby_poi_audit_info" {
  32. t.Error("Unexpected message event")
  33. }
  34. if mix.AuditID == 0 {
  35. t.Error("audit_id can not be zero")
  36. }
  37. if mix.Status == 0 {
  38. t.Error("status can not be zero")
  39. }
  40. if mix.Reason == "" {
  41. t.Error("reason can not be empty")
  42. }
  43. if mix.PoiID == 0 {
  44. t.Error("poi_id can not be zero")
  45. }
  46. })
  47. if err := srv.Serve(w, r); err != nil {
  48. t.Fatal(err)
  49. }
  50. })
  51. tls := httptest.NewServer(localServer)
  52. defer tls.Close()
  53. remoteServer := http.NewServeMux()
  54. remoteServer.HandleFunc(apiAddNearbyPoi, func(w http.ResponseWriter, r *http.Request) {
  55. if r.Method != "POST" {
  56. t.Fatalf("Expect 'POST' get '%s'", r.Method)
  57. }
  58. path := r.URL.EscapedPath()
  59. if path != apiAddNearbyPoi {
  60. t.Fatalf("Except to path '%s',get '%s'", apiAddNearbyPoi, path)
  61. }
  62. if err := r.ParseForm(); err != nil {
  63. t.Fatal(err)
  64. }
  65. if r.Form.Get("access_token") == "" {
  66. t.Fatalf("access_token can not be empty")
  67. }
  68. params := struct {
  69. IsCommNearby string `json:"is_comm_nearby"`
  70. PicList string `json:"pic_list"` // 门店图片,最多9张,最少1张,上传门店图片如门店外景、环境设施、商品服务等,图片将展示在微信客户端的门店页。图片链接通过文档https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738729中的《上传图文消息内的图片获取URL》接口获取。必填,文件格式为bmp、png、jpeg、jpg或gif,大小不超过5M pic_list是字符串,内容是一个json!
  71. ServiceInfos string `json:"service_infos"` // 必服务标签列表 选填,需要填写服务标签ID、APPID、对应服务落地页的path路径,详细字段格式见下方示例
  72. StoreName string `json:"store_name"` // 门店名字 必填,门店名称需按照所选地理位置自动拉取腾讯地图门店名称,不可修改,如需修改请重现选择地图地点或重新创建地点
  73. Hour string `json:"hour"` // 营业时间,格式11:11-12:12 必填
  74. Credential string `json:"credential"` // 资质号 必填, 15位营业执照注册号或9位组织机构代码
  75. Address string `json:"address"` // 地址 必填
  76. CompanyName string `json:"company_name"` // 主体名字 必填
  77. QualificationList string `json:"qualification_list"` // 证明材料 必填 如果company_name和该小程序主体不一致,需要填qualification_list,详细规则见附近的小程序使用指南-如何证明门店的经营主体跟公众号或小程序帐号主体相关http://kf.qq.com/faq/170401MbUnim17040122m2qY.html
  78. KFInfo string `json:"kf_info"` // 客服信息 选填,可自定义服务头像与昵称,具体填写字段见下方示例kf_info pic_list是字符串,内容是一个json!
  79. PoiID string `json:"poi_id"` // 如果创建新的门店,poi_id字段为空 如果更新门店,poi_id参数则填对应门店的poi_id 选填
  80. }{}
  81. if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
  82. t.Fatal(err)
  83. }
  84. if params.IsCommNearby != "1" {
  85. t.Error("param pic_list is invalid")
  86. }
  87. if params.PicList == "" {
  88. t.Error("param pic_list can not be empty")
  89. }
  90. if params.ServiceInfos == "" {
  91. t.Error("param service_infos can not be empty")
  92. }
  93. if params.StoreName == "" {
  94. t.Error("param store_name can not be empty")
  95. }
  96. if params.Hour == "" {
  97. t.Error("param hour can not be empty")
  98. }
  99. if params.Credential == "" {
  100. t.Error("param credential can not be empty")
  101. }
  102. if params.Address == "" {
  103. t.Error("param address can not be empty")
  104. }
  105. if params.CompanyName == "" {
  106. t.Error("param company_name can not be empty")
  107. }
  108. if params.QualificationList == "" {
  109. t.Error("param qualification_list can not be empty")
  110. }
  111. if params.KFInfo == "" {
  112. t.Error("param kf_info can not be empty")
  113. }
  114. if params.PoiID == "" {
  115. t.Error("param poi_id can not be empty")
  116. }
  117. w.WriteHeader(http.StatusOK)
  118. raw := `{
  119. "errcode": 0,
  120. "errmsg": "ok",
  121. "data":{
  122. "audit_id": "xxxxx",
  123. "poi_id": "xxxxx",
  124. "related_credential":"xxxxx"
  125. }
  126. }`
  127. if _, err := w.Write([]byte(raw)); err != nil {
  128. t.Fatal(err)
  129. }
  130. raw = `<xml>
  131. <ToUserName><![CDATA[gh_4346ac1514d8]]></ToUserName>
  132. <FromUserName><![CDATA[od1P50M-fNQI5Gcq-trm4a7apsU8]]></FromUserName>
  133. <CreateTime>1488856741</CreateTime>
  134. <MsgType><![CDATA[event]]></MsgType>
  135. <Event><![CDATA[add_nearby_poi_audit_info]]></Event>
  136. <audit_id>11111</audit_id>
  137. <status>3</status>
  138. <reason><![CDATA[xxx]]></reason>
  139. <poi_id>111111</poi_id>
  140. </xml>`
  141. reader := strings.NewReader(raw)
  142. http.Post(tls.URL+"/notify", "text/xml", reader)
  143. })
  144. trs := httptest.NewServer(remoteServer)
  145. defer trs.Close()
  146. poi := NearbyPoi{
  147. PicList: PicList{[]string{"first-mock-picture-url", "second-mock-picture-url", "third-mock-picture-url"}},
  148. ServiceInfos: ServiceInfos{[]ServiceInfo{
  149. {1, 1, "mock-name", "mock-app-id", "mock-path"},
  150. }},
  151. StoreName: "mock-store-name",
  152. Hour: "11:11-12:12",
  153. Credential: "mock-credential",
  154. Address: "mock-address", // 地址 必填
  155. CompanyName: "mock-company-name", // 主体名字 必填
  156. QualificationList: "mock-qualification-list", // 证明材料 必填 如果company_name和该小程序主体不一致,需要填qualification_list,详细规则见附近的小程序使用指南-如何证明门店的经营主体跟公众号或小程序帐号主体相关http://kf.qq.com/faq/170401MbUnim17040122m2qY.html
  157. KFInfo: KFInfo{true, "kf-head-img", "kf-name"}, // 客服信息 选填,可自定义服务头像与昵称,具体填写字段见下方示例kf_info pic_list是字符串,内容是一个json!
  158. PoiID: "mock-poi-id", // 如果创建新的门店,poi_id字段为空 如果更新门店,poi_id参数则填对应门店的poi_id 选填
  159. }
  160. _, err := poi.add(trs.URL+apiAddNearbyPoi, "mock-access-token")
  161. if err != nil {
  162. t.Fatal(err)
  163. }
  164. }
  165. func TestDeleteNearbyPoi(t *testing.T) {
  166. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  167. if r.Method != "POST" {
  168. t.Fatalf("Expect 'POST' get '%s'", r.Method)
  169. }
  170. path := r.URL.EscapedPath()
  171. if path != apiDeleteNearbyPoi {
  172. t.Fatalf("Except to path '%s',get '%s'", apiDeleteNearbyPoi, path)
  173. }
  174. if err := r.ParseForm(); err != nil {
  175. t.Fatal(err)
  176. }
  177. if r.Form.Get("access_token") == "" {
  178. t.Fatalf("access_token can not be empty")
  179. }
  180. params := struct {
  181. PoiID string `json:"poi_id"`
  182. }{}
  183. if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
  184. t.Fatal(err)
  185. }
  186. if params.PoiID == "" {
  187. t.Error("Response column poi_id can not be empty")
  188. }
  189. w.WriteHeader(http.StatusOK)
  190. raw := `{
  191. "errcode": 0,
  192. "errmsg": "ok"
  193. }`
  194. if _, err := w.Write([]byte(raw)); err != nil {
  195. t.Fatal(err)
  196. }
  197. }))
  198. defer ts.Close()
  199. _, err := deleteNearbyPoi(ts.URL+apiDeleteNearbyPoi, "mock-access-token", "mock-poi-id")
  200. if err != nil {
  201. t.Fatal(err)
  202. }
  203. }
  204. func TestGetNearbyPoiList(t *testing.T) {
  205. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  206. if r.Method != "POST" {
  207. t.Fatalf("Expect 'POST' get '%s'", r.Method)
  208. }
  209. path := r.URL.EscapedPath()
  210. if path != apiGetNearbyPoiList {
  211. t.Fatalf("Except to path '%s',get '%s'", apiGetNearbyPoiList, path)
  212. }
  213. if err := r.ParseForm(); err != nil {
  214. t.Fatal(err)
  215. }
  216. if r.Form.Get("access_token") == "" {
  217. t.Fatalf("access_token can not be empty")
  218. }
  219. params := struct {
  220. Page uint `json:"page"`
  221. Rows uint `json:"page_rows"`
  222. }{}
  223. if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
  224. t.Fatal(err)
  225. }
  226. if params.Page == 0 {
  227. t.Error("Response column page can not be empty")
  228. }
  229. if params.Rows == 0 {
  230. t.Error("Response column page_rows can not be empty")
  231. }
  232. w.WriteHeader(http.StatusOK)
  233. raw := `{
  234. "errcode": 0,
  235. "errmsg": "",
  236. "data": {
  237. "left_apply_num": 9,
  238. "max_apply_num": 10,
  239. "data": "{\"poi_list\": [{\"poi_id\": \"123456\",\"qualification_address\": \"广东省广州市海珠区新港中路123号\",\"qualification_num\": \"123456789-1\",\"audit_status\": 3,\"display_status\": 0,\"refuse_reason\": \"\"}]}"
  240. }
  241. }`
  242. if _, err := w.Write([]byte(raw)); err != nil {
  243. t.Fatal(err)
  244. }
  245. }))
  246. defer ts.Close()
  247. _, err := getNearbyPoiList(ts.URL+apiGetNearbyPoiList, "mock-access-token", 1, 10)
  248. if err != nil {
  249. t.Fatal(err)
  250. }
  251. }
  252. func TestSetNearbyPoiShowStatus(t *testing.T) {
  253. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  254. if r.Method != "POST" {
  255. t.Fatalf("Expect 'POST' get '%s'", r.Method)
  256. }
  257. path := r.URL.EscapedPath()
  258. if path != apiSetNearbyPoiShowStatus {
  259. t.Fatalf("Except to path '%s',get '%s'", apiSetNearbyPoiShowStatus, path)
  260. }
  261. if err := r.ParseForm(); err != nil {
  262. t.Fatal(err)
  263. }
  264. if r.Form.Get("access_token") == "" {
  265. t.Fatalf("access_token can not be empty")
  266. }
  267. params := struct {
  268. PoiID string `json:"poi_id"`
  269. Status uint8 `json:"status"`
  270. }{}
  271. if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
  272. t.Fatal(err)
  273. }
  274. if params.PoiID == "" {
  275. t.Error("Response column poi_id can not be empty")
  276. }
  277. if params.Status == 0 {
  278. t.Error("Response column status can not be zero")
  279. }
  280. w.WriteHeader(http.StatusOK)
  281. raw := `{
  282. "errcode": 0,
  283. "errmsg": "ok"
  284. }`
  285. if _, err := w.Write([]byte(raw)); err != nil {
  286. t.Fatal(err)
  287. }
  288. }))
  289. defer ts.Close()
  290. _, err := setNearbyPoiShowStatus(ts.URL+apiSetNearbyPoiShowStatus, "mock-access-token", "mock-poi-id", ShowNearbyPoi)
  291. if err != nil {
  292. t.Fatal(err)
  293. }
  294. }