附近小店
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

express_provider_test.go 36 KiB

2 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332
  1. package weapp
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "encoding/xml"
  6. "net/http"
  7. "net/http/httptest"
  8. "strings"
  9. "testing"
  10. )
  11. func TestGetContact(t *testing.T) {
  12. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  13. if r.Method != "POST" {
  14. t.Fatalf("Expect 'POST' get '%s'", r.Method)
  15. }
  16. path := r.URL.EscapedPath()
  17. if path != "/cgi-bin/express/delivery/contact/get" {
  18. t.Error("Invalid request path")
  19. }
  20. if err := r.ParseForm(); err != nil {
  21. t.Fatal(err)
  22. }
  23. if r.Form.Get("access_token") == "" {
  24. t.Fatalf("access_token can not be empty")
  25. }
  26. params := struct {
  27. Token string `json:"token"`
  28. WaybillID string `json:"waybill_id"`
  29. }{}
  30. if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
  31. t.Fatal(err)
  32. }
  33. if params.Token == "" {
  34. t.Error("param token can not be empty")
  35. }
  36. if params.WaybillID == "" {
  37. t.Error("param waybill_id can not be empty")
  38. }
  39. w.WriteHeader(http.StatusOK)
  40. w.Header().Set("Content-Type", "application/json")
  41. raw := `{
  42. "waybill_id": "12345678901234567890",
  43. "sender": {
  44. "address": "广东省广州市海珠区XX路XX号XX大厦XX栋XX",
  45. "name": "张三",
  46. "tel": "020-88888888",
  47. "mobile": "18666666666"
  48. },
  49. "receiver": {
  50. "address": "广东省广州市天河区XX路XX号XX大厦XX栋XX",
  51. "name": "王小蒙",
  52. "tel": "029-77777777",
  53. "mobile": "18610000000"
  54. }
  55. }`
  56. if _, err := w.Write([]byte(raw)); err != nil {
  57. t.Fatal(err)
  58. }
  59. }))
  60. defer ts.Close()
  61. _, err := getContact(ts.URL+apiGetContact, "mock-access-token", "mock-token", "mock-wat-bill-id")
  62. if err != nil {
  63. t.Fatal(err)
  64. }
  65. }
  66. func TestOnAddExpressOrder(t *testing.T) {
  67. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  68. aesKey := base64.StdEncoding.EncodeToString([]byte("mock-aes-key"))
  69. srv, err := NewServer("mock-app-id", "mock-access-token", aesKey, "mock-mch-id", "mock-api-key", false)
  70. if err != nil {
  71. t.Fatal(err)
  72. }
  73. srv.OnAddExpressOrder(func(result *AddExpressOrderResult) *AddExpressOrderReturn {
  74. if result.ToUserName == "" {
  75. t.Error("ToUserName can not be empty")
  76. }
  77. if result.FromUserName == "" {
  78. t.Error("FromUserName can not be empty")
  79. }
  80. if result.CreateTime == 0 {
  81. t.Error("CreateTime can not be zero")
  82. }
  83. if result.MsgType != "event" {
  84. t.Error("Unexpected message type")
  85. }
  86. if result.Event != "add_waybill" {
  87. t.Error("Unexpected message event")
  88. }
  89. if result.Token == "" {
  90. t.Error("Result column 'Token' can not be empty")
  91. }
  92. if result.OrderID == "" {
  93. t.Error("Result column 'OrderID' can not be empty")
  94. }
  95. if result.BizID == "" {
  96. t.Error("Result column 'BizID' can not be empty")
  97. }
  98. if result.BizPwd == "" {
  99. t.Error("Result column 'BizPwd' can not be empty")
  100. }
  101. if result.ShopAppID == "" {
  102. t.Error("Result column 'ShopAppID' can not be empty")
  103. }
  104. if result.WayBillID == "" {
  105. t.Error("Result column 'WayBillID' can not be empty")
  106. }
  107. if result.Remark == "" {
  108. t.Error("Result column 'Remark' can not be empty")
  109. }
  110. if result.Sender.Name == "" {
  111. t.Error("Result column 'Sender.Name' can not be empty")
  112. }
  113. if result.Sender.Tel == "" {
  114. t.Error("Result column 'Sender.Tel' can not be empty")
  115. }
  116. if result.Sender.Mobile == "" {
  117. t.Error("Result column 'Sender.Mobile' can not be empty")
  118. }
  119. if result.Sender.Company == "" {
  120. t.Error("Result column 'Sender.Company' can not be empty")
  121. }
  122. if result.Sender.PostCode == "" {
  123. t.Error("Result column 'Sender.PostCode' can not be empty")
  124. }
  125. if result.Sender.Country == "" {
  126. t.Error("Result column 'Sender.Country' can not be empty")
  127. }
  128. if result.Sender.Province == "" {
  129. t.Error("Result column 'Sender.Province' can not be empty")
  130. }
  131. if result.Sender.City == "" {
  132. t.Error("Result column 'Sender.City' can not be empty")
  133. }
  134. if result.Sender.Area == "" {
  135. t.Error("Result column 'Sender.Area' can not be empty")
  136. }
  137. if result.Sender.Address == "" {
  138. t.Error("Result column 'Sender.Address' can not be empty")
  139. }
  140. if result.Receiver.Name == "" {
  141. t.Error("Result column 'Receiver.Name' can not be empty")
  142. }
  143. if result.Receiver.Tel == "" {
  144. t.Error("Result column 'Receiver.Tel' can not be empty")
  145. }
  146. if result.Receiver.Mobile == "" {
  147. t.Error("Result column 'Receiver.Mobile' can not be empty")
  148. }
  149. if result.Receiver.Company == "" {
  150. t.Error("Result column 'Receiver.Company' can not be empty")
  151. }
  152. if result.Receiver.PostCode == "" {
  153. t.Error("Result column 'Receiver.PostCode' can not be empty")
  154. }
  155. if result.Receiver.Country == "" {
  156. t.Error("Result column 'Receiver.Country' can not be empty")
  157. }
  158. if result.Receiver.Province == "" {
  159. t.Error("Result column 'Receiver.Province' can not be empty")
  160. }
  161. if result.Receiver.City == "" {
  162. t.Error("Result column 'Receiver.City' can not be empty")
  163. }
  164. if result.Receiver.Area == "" {
  165. t.Error("Result column 'Receiver.Area' can not be empty")
  166. }
  167. if result.Receiver.Address == "" {
  168. t.Error("Result column 'Receiver.Address' can not be empty")
  169. }
  170. if result.Cargo.Weight == 0 {
  171. t.Error("Result column 'Cargo.Weight' can not be zero")
  172. }
  173. if result.Cargo.SpaceX == 0 {
  174. t.Error("Result column 'Cargo.SpaceX' can not be zero")
  175. }
  176. if result.Cargo.SpaceY == 0 {
  177. t.Error("Result column 'Cargo.SpaceY' can not be zero")
  178. }
  179. if result.Cargo.SpaceZ == 0 {
  180. t.Error("Result column 'Cargo.SpaceZ' can not be zero")
  181. }
  182. if result.Cargo.Count == 0 {
  183. t.Error("Result column 'Cargo.Count' can not be zero")
  184. }
  185. if result.Insured.Used == 0 {
  186. t.Error("Result column 'Insured.Used' can not be zero")
  187. }
  188. if result.Insured.Value == 0 {
  189. t.Error("Result column 'Insured.Value' can not be zero")
  190. }
  191. if result.Service.Type == 0 {
  192. t.Error("Result column 'Service.Type' can not be zero")
  193. }
  194. if result.Service.Name == "" {
  195. t.Error("Result column 'Service.Name' can not be empty")
  196. }
  197. res := AddExpressOrderReturn{
  198. CommonServerReturn: CommonServerReturn{
  199. "oABCD", "gh_abcdefg", 1533042556, "event", "add_waybill", 1, "success",
  200. },
  201. Token: "1234ABC234523451",
  202. OrderID: "012345678901234567890123456789",
  203. BizID: "xyz",
  204. WayBillID: "123456789",
  205. WaybillData: "##ZTO_bagAddr##广州##ZTO_mark##888-666-666##",
  206. }
  207. return &res
  208. })
  209. if err := srv.Serve(w, r); err != nil {
  210. t.Fatal(err)
  211. }
  212. }))
  213. defer ts.Close()
  214. xmlData := `<xml>
  215. <ToUserName><![CDATA[gh_abcdefg]]></ToUserName>
  216. <FromUserName><![CDATA[oABCD]]></FromUserName>
  217. <CreateTime>1533042556</CreateTime>
  218. <MsgType><![CDATA[event]]></MsgType>
  219. <Event><![CDATA[add_waybill]]></Event>
  220. <Token>1234ABC234523451</Token>
  221. <OrderID><![CDATA[012345678901234567890123456789]]></OrderID>
  222. <BizID><![CDATA[xyz]]></BizID>
  223. <BizPwd><![CDATA[xyz123]]></BizPwd>
  224. <ShopAppID><![CDATA[wxABCD]]></ShopAppID>
  225. <WayBillID><![CDATA[123456789]]></WayBillID>
  226. <Remark><![CDATA[易碎物品]]></Remark>
  227. <Sender>
  228. <Name><![CDATA[张三]]></Name>
  229. <Tel><![CDATA[020-88888888]]></Tel>
  230. <Mobile><![CDATA[18666666666]]></Mobile>
  231. <Company><![CDATA[公司名]]></Company>
  232. <PostCode><![CDATA[123456]]></PostCode>
  233. <Country><![CDATA[中国]]></Country>
  234. <Province><![CDATA[广东省]]></Province>
  235. <City><![CDATA[广州市]]></City>
  236. <Area><![CDATA[海珠区]]></Area>
  237. <Address><![CDATA[XX路XX号XX大厦XX栋XX]]></Address>
  238. </Sender>
  239. <Receiver>
  240. <Name><![CDATA[王小蒙]]></Name>
  241. <Tel><![CDATA[029-77777777]]></Tel>
  242. <Mobile><![CDATA[18610000000]]></Mobile>
  243. <Company><![CDATA[公司名]]></Company>
  244. <PostCode><![CDATA[654321]]></PostCode>
  245. <Country><![CDATA[中国]]></Country>
  246. <Province><![CDATA[广东省]]></Province>
  247. <City><![CDATA[广州市]]></City>
  248. <Area><![CDATA[天河区]]></Area>
  249. <Address><![CDATA[XX路XX号XX大厦XX栋XX]]></Address>
  250. </Receiver>
  251. <Cargo>
  252. <Weight>1.2</Weight>
  253. <Space_X>20.5</Space_X>
  254. <Space_Y>15.0</Space_Y>
  255. <Space_Z>10.0</Space_Z>
  256. <Count>2</Count>
  257. <DetailList>
  258. <Name><![CDATA[一千零一夜钻石包]]></Name>
  259. <Count>1</Count>
  260. </DetailList>
  261. <DetailList>
  262. <Name><![CDATA[爱马仕柏金钻石包]]></Name>
  263. <Count>1</Count>
  264. </DetailList>
  265. </Cargo>
  266. <Insured>
  267. <UseInsured>1</UseInsured>
  268. <InsuredValue>10000</InsuredValue>
  269. </Insured>
  270. <Service>
  271. <ServiceType>123</ServiceType>
  272. <ServiceName><![CDATA[标准快递]]></ServiceName>
  273. </Service>
  274. </xml>`
  275. xmlResp, err := http.Post(ts.URL, "text/xml", strings.NewReader(xmlData))
  276. if err != nil {
  277. t.Error(err)
  278. }
  279. defer xmlResp.Body.Close()
  280. res := new(AddExpressOrderReturn)
  281. if err := xml.NewDecoder(xmlResp.Body).Decode(res); err != nil {
  282. t.Error(err)
  283. }
  284. if res.ToUserName == "" {
  285. t.Error("Response column 'ToUserName' can not be empty")
  286. }
  287. if res.FromUserName == "" {
  288. t.Error("Response column 'FromUserName' can not be empty")
  289. }
  290. if res.CreateTime == 0 {
  291. t.Error("Response column 'CreateTime' can not be zero")
  292. }
  293. if res.MsgType == "" {
  294. t.Error("Response column 'MsgType' can not be empty")
  295. }
  296. if res.Event == "" {
  297. t.Error("Response column 'Event' can not be empty")
  298. }
  299. if res.Token == "" {
  300. t.Error("Response column 'Token' can not be empty")
  301. }
  302. if res.OrderID == "" {
  303. t.Error("Response column 'OrderID' can not be empty")
  304. }
  305. if res.BizID == "" {
  306. t.Error("Response column 'BizID' can not be empty")
  307. }
  308. if res.WayBillID == "" {
  309. t.Error("Response column 'WayBillID' can not be empty")
  310. }
  311. if res.ResultMsg == "" {
  312. t.Error("Response column 'ResultMsg' can not be empty")
  313. }
  314. if res.WaybillData == "" {
  315. t.Error("Response column 'WaybillData' can not be empty")
  316. }
  317. jsonData := `{
  318. "ToUserName": "gh_abcdefg",
  319. "FromUserName": "oABCD",
  320. "CreateTime": 1533042556,
  321. "MsgType": "event",
  322. "Event": "add_waybill",
  323. "Token": "1234ABC234523451",
  324. "OrderID": "012345678901234567890123456789",
  325. "BizID": "xyz",
  326. "BizPwd": "xyz123",
  327. "ShopAppID": "wxABCD",
  328. "WayBillID": "123456789",
  329. "Remark": "易碎物品",
  330. "Sender": {
  331. "Name": "张三",
  332. "Tel": "020-88888888",
  333. "Mobile": "18666666666",
  334. "Company": "公司名",
  335. "PostCode": "123456",
  336. "Country": "中国",
  337. "Province": "广东省",
  338. "City": "广州市",
  339. "Area": "海珠区",
  340. "Address": "XX路XX号XX大厦XX栋XX"
  341. },
  342. "Receiver": {
  343. "Name": "王小蒙",
  344. "Tel": "029-77777777",
  345. "Mobile": "18610000000",
  346. "Company": "公司名",
  347. "PostCode": "654321",
  348. "Country": "中国",
  349. "Province": "广东省",
  350. "City": "广州市",
  351. "Area": "天河区",
  352. "Address": "XX路XX号XX大厦XX栋XX"
  353. },
  354. "Cargo": {
  355. "Weight": 1.2,
  356. "Space_X": 20.5,
  357. "Space_Y": 15,
  358. "Space_Z": 10,
  359. "Count": 2,
  360. "DetailList": [
  361. {
  362. "Name": "一千零一夜钻石包",
  363. "Count": 1
  364. },
  365. {
  366. "Name": "爱马仕柏金钻石包",
  367. "Count": 1
  368. }
  369. ]
  370. },
  371. "Insured": {
  372. "UseInsured": 1,
  373. "InsuredValue": 10000
  374. },
  375. "Service": {
  376. "ServiceType": 123,
  377. "ServiceName": "标准快递"
  378. }
  379. }`
  380. jsonResp, err := http.Post(ts.URL, "application/json", strings.NewReader(jsonData))
  381. if err != nil {
  382. t.Error(err)
  383. }
  384. defer jsonResp.Body.Close()
  385. res = new(AddExpressOrderReturn)
  386. if err := json.NewDecoder(jsonResp.Body).Decode(res); err != nil {
  387. t.Error(err)
  388. }
  389. if res.ToUserName == "" {
  390. t.Error("Response column 'ToUserName' can not be empty")
  391. }
  392. if res.FromUserName == "" {
  393. t.Error("Response column 'FromUserName' can not be empty")
  394. }
  395. if res.CreateTime == 0 {
  396. t.Error("Response column 'CreateTime' can not be zero")
  397. }
  398. if res.MsgType == "" {
  399. t.Error("Response column 'MsgType' can not be empty")
  400. }
  401. if res.Event == "" {
  402. t.Error("Response column 'Event' can not be empty")
  403. }
  404. if res.Token == "" {
  405. t.Error("Response column 'Token' can not be empty")
  406. }
  407. if res.OrderID == "" {
  408. t.Error("Response column 'OrderID' can not be empty")
  409. }
  410. if res.BizID == "" {
  411. t.Error("Response column 'BizID' can not be empty")
  412. }
  413. if res.WayBillID == "" {
  414. t.Error("Response column 'WayBillID' can not be empty")
  415. }
  416. if res.ResultMsg == "" {
  417. t.Error("Response column 'ResultMsg' can not be empty")
  418. }
  419. if res.WaybillData == "" {
  420. t.Error("Response column 'WaybillData' can not be empty")
  421. }
  422. }
  423. func TestOnCancelExpressOrder(t *testing.T) {
  424. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  425. aesKey := base64.StdEncoding.EncodeToString([]byte("mock-aes-key"))
  426. srv, err := NewServer("mock-app-id", "mock-access-token", aesKey, "mock-mch-id", "mock-api-key", false)
  427. if err != nil {
  428. t.Fatal(err)
  429. }
  430. srv.OnCancelExpressOrder(func(result *CancelExpressOrderResult) *CancelExpressOrderReturn {
  431. if result.ToUserName == "" {
  432. t.Error("ToUserName can not be empty")
  433. }
  434. if result.FromUserName == "" {
  435. t.Error("FromUserName can not be empty")
  436. }
  437. if result.CreateTime == 0 {
  438. t.Error("CreateTime can not be zero")
  439. }
  440. if result.MsgType != "event" {
  441. t.Error("Unexpected message type")
  442. }
  443. if result.Event != "cancel_waybill" {
  444. t.Error("Unexpected message event")
  445. }
  446. if result.OrderID == "" {
  447. t.Error("Result column 'OrderID' can not be empty")
  448. }
  449. if result.BizID == "" {
  450. t.Error("Result column 'BizID' can not be empty")
  451. }
  452. if result.BizPwd == "" {
  453. t.Error("Result column 'BizPwd' can not be empty")
  454. }
  455. if result.ShopAppID == "" {
  456. t.Error("Result column 'ShopAppID' can not be empty")
  457. }
  458. if result.WayBillID == "" {
  459. t.Error("Result column 'WayBillID' can not be empty")
  460. }
  461. res := CancelExpressOrderReturn{
  462. CommonServerReturn: CommonServerReturn{
  463. "oABCD", "gh_abcdefg", 1533042556, "event", "cancel_waybill", 1, "success",
  464. },
  465. OrderID: "012345678901234567890123456789",
  466. BizID: "xyz",
  467. WayBillID: "123456789",
  468. }
  469. return &res
  470. })
  471. if err := srv.Serve(w, r); err != nil {
  472. t.Fatal(err)
  473. }
  474. }))
  475. defer ts.Close()
  476. xmlData := `<xml>
  477. <ToUserName><![CDATA[gh_abcdefg]]></ToUserName>
  478. <FromUserName><![CDATA[oABCD]]></FromUserName>
  479. <CreateTime>1533042556</CreateTime>
  480. <MsgType><![CDATA[event]]></MsgType>
  481. <Event><![CDATA[cancel_waybill]]></Event>
  482. <BizID><![CDATA[xyz]]></BizID>
  483. <BizPwd><![CDATA[xyz123]]></BizPwd>
  484. <ShopAppID><![CDATA[wxABCD]]></ShopAppID>
  485. <OrderID><![CDATA[012345678901234567890123456789]]></OrderID>
  486. <WayBillID><![CDATA[123456789]]></WayBillID>
  487. </xml>`
  488. xmlResp, err := http.Post(ts.URL, "text/xml", strings.NewReader(xmlData))
  489. if err != nil {
  490. t.Error(err)
  491. }
  492. defer xmlResp.Body.Close()
  493. res := new(CancelExpressOrderReturn)
  494. if err := xml.NewDecoder(xmlResp.Body).Decode(res); err != nil {
  495. t.Error(err)
  496. }
  497. if res.ToUserName == "" {
  498. t.Error("Response column 'ToUserName' can not be empty")
  499. }
  500. if res.FromUserName == "" {
  501. t.Error("Response column 'FromUserName' can not be empty")
  502. }
  503. if res.CreateTime == 0 {
  504. t.Error("Response column 'CreateTime' can not be zero")
  505. }
  506. if res.MsgType == "" {
  507. t.Error("Response column 'MsgType' can not be empty")
  508. }
  509. if res.Event == "" {
  510. t.Error("Response column 'Event' can not be empty")
  511. }
  512. if res.OrderID == "" {
  513. t.Error("Response column 'OrderID' can not be empty")
  514. }
  515. if res.BizID == "" {
  516. t.Error("Response column 'BizID' can not be empty")
  517. }
  518. if res.WayBillID == "" {
  519. t.Error("Response column 'WayBillID' can not be empty")
  520. }
  521. if res.ResultMsg == "" {
  522. t.Error("Response column 'ResultMsg' can not be empty")
  523. }
  524. jsonData := `{
  525. "ToUserName": "gh_abcdefg",
  526. "FromUserName": "oABCD",
  527. "CreateTime": 1533042556,
  528. "MsgType": "event",
  529. "Event": "cancel_waybill",
  530. "BizID": "xyz",
  531. "BizPwd": "xyz123",
  532. "ShopAppID": "wxABCD",
  533. "OrderID": "012345678901234567890123456789",
  534. "WayBillID": "123456789"
  535. }`
  536. jsonResp, err := http.Post(ts.URL, "application/json", strings.NewReader(jsonData))
  537. if err != nil {
  538. t.Error(err)
  539. }
  540. defer jsonResp.Body.Close()
  541. res = new(CancelExpressOrderReturn)
  542. if err := json.NewDecoder(jsonResp.Body).Decode(res); err != nil {
  543. t.Error(err)
  544. }
  545. if res.ToUserName == "" {
  546. t.Error("Response column 'ToUserName' can not be empty")
  547. }
  548. if res.FromUserName == "" {
  549. t.Error("Response column 'FromUserName' can not be empty")
  550. }
  551. if res.CreateTime == 0 {
  552. t.Error("Response column 'CreateTime' can not be zero")
  553. }
  554. if res.MsgType == "" {
  555. t.Error("Response column 'MsgType' can not be empty")
  556. }
  557. if res.Event == "" {
  558. t.Error("Response column 'Event' can not be empty")
  559. }
  560. if res.OrderID == "" {
  561. t.Error("Response column 'OrderID' can not be empty")
  562. }
  563. if res.BizID == "" {
  564. t.Error("Response column 'BizID' can not be empty")
  565. }
  566. if res.WayBillID == "" {
  567. t.Error("Response column 'WayBillID' can not be empty")
  568. }
  569. if res.ResultMsg == "" {
  570. t.Error("Response column 'ResultMsg' can not be empty")
  571. }
  572. }
  573. func TestOnCheckBusiness(t *testing.T) {
  574. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  575. aesKey := base64.StdEncoding.EncodeToString([]byte("mock-aes-key"))
  576. srv, err := NewServer("mock-app-id", "mock-access-token", aesKey, "mock-mch-id", "mock-api-key", false)
  577. if err != nil {
  578. t.Fatal(err)
  579. }
  580. srv.OnCheckExpressBusiness(func(result *CheckExpressBusinessResult) *CheckExpressBusinessReturn {
  581. if result.ToUserName == "" {
  582. t.Error("ToUserName can not be empty")
  583. }
  584. if result.FromUserName == "" {
  585. t.Error("FromUserName can not be empty")
  586. }
  587. if result.CreateTime == 0 {
  588. t.Error("CreateTime can not be zero")
  589. }
  590. if result.MsgType != "event" {
  591. t.Error("Unexpected message type")
  592. }
  593. if result.Event != "check_biz" {
  594. t.Error("Unexpected message event")
  595. }
  596. if result.BizID == "" {
  597. t.Error("Result column 'BizID' can not be empty")
  598. }
  599. if result.BizPwd == "" {
  600. t.Error("Result column 'BizPwd' can not be empty")
  601. }
  602. if result.ShopAppID == "" {
  603. t.Error("Result column 'ShopAppID' can not be empty")
  604. }
  605. if result.ShopName == "" {
  606. t.Error("Result column 'ShopName' can not be empty")
  607. }
  608. if result.ShopTelphone == "" {
  609. t.Error("Result column 'ShopTelphone' can not be empty")
  610. }
  611. if result.SenderAddress == "" {
  612. t.Error("Result column 'SenderAddress' can not be empty")
  613. }
  614. if result.ShopContact == "" {
  615. t.Error("Result column 'ShopContact' can not be empty")
  616. }
  617. if result.ServiceName == "" {
  618. t.Error("Result column 'ServiceName' can not be empty")
  619. }
  620. res := CheckExpressBusinessReturn{
  621. CommonServerReturn: CommonServerReturn{
  622. "oABCD", "gh_abcdefg", 1533042556, "event", "check_biz", 1, "success",
  623. },
  624. BizID: "xyz",
  625. Quota: 3.14159265358,
  626. }
  627. return &res
  628. })
  629. if err := srv.Serve(w, r); err != nil {
  630. t.Fatal(err)
  631. }
  632. }))
  633. defer ts.Close()
  634. xmlData := `<xml>
  635. <ToUserName><![CDATA[gh_abcdefg]]></ToUserName>
  636. <FromUserName><![CDATA[oABCD]]></FromUserName>
  637. <CreateTime>1533042556</CreateTime>
  638. <MsgType><![CDATA[event]]></MsgType>
  639. <Event><![CDATA[check_biz]]></Event>
  640. <BizID><![CDATA[xyz]]></BizID>
  641. <BizPwd><![CDATA[xyz123]]></BizPwd>
  642. <ShopAppID><![CDATA[wxABCD]]></ShopAppID>
  643. <ShopName><![CDATA[商户名称]]></ShopName>
  644. <ShopTelphone><![CDATA[18677778888]]></ShopTelphone>
  645. <ShopContact><![CDATA[村正]]></ShopContact>
  646. <ServiceName><![CDATA[标准快递]]></ServiceName>
  647. <SenderAddress><![CDATA[广东省广州市海珠区新港中路397号]]></SenderAddress>
  648. </xml>`
  649. xmlResp, err := http.Post(ts.URL, "text/xml", strings.NewReader(xmlData))
  650. if err != nil {
  651. t.Error(err)
  652. }
  653. defer xmlResp.Body.Close()
  654. res := new(CheckExpressBusinessReturn)
  655. if err := xml.NewDecoder(xmlResp.Body).Decode(res); err != nil {
  656. t.Error(err)
  657. }
  658. if res.ToUserName == "" {
  659. t.Error("Response column 'ToUserName' can not be empty")
  660. }
  661. if res.FromUserName == "" {
  662. t.Error("Response column 'FromUserName' can not be empty")
  663. }
  664. if res.CreateTime == 0 {
  665. t.Error("Response column 'CreateTime' can not be zero")
  666. }
  667. if res.MsgType == "" {
  668. t.Error("Response column 'MsgType' can not be empty")
  669. }
  670. if res.Event == "" {
  671. t.Error("Response column 'Event' can not be empty")
  672. }
  673. if res.Quota == 0 {
  674. t.Error("Response column 'Quota' can not be zero")
  675. }
  676. if res.BizID == "" {
  677. t.Error("Response column 'BizID' can not be empty")
  678. }
  679. if res.ResultMsg == "" {
  680. t.Error("Response column 'ResultMsg' can not be empty")
  681. }
  682. jsonData := `{
  683. "ToUserName": "gh_abcdefg",
  684. "FromUserName": "oABCD",
  685. "CreateTime": 1533042556,
  686. "MsgType": "event",
  687. "Event": "check_biz",
  688. "BizID": "xyz",
  689. "BizPwd": "xyz123",
  690. "ShopAppID": "wxABCD",
  691. "ShopName": "商户名称",
  692. "ShopTelphone": "18677778888",
  693. "ShopContact": "村正",
  694. "ServiceName": "标准快递",
  695. "SenderAddress": "广东省广州市海珠区新港中路397号"
  696. }`
  697. jsonResp, err := http.Post(ts.URL, "application/json", strings.NewReader(jsonData))
  698. if err != nil {
  699. t.Error(err)
  700. }
  701. defer jsonResp.Body.Close()
  702. res = new(CheckExpressBusinessReturn)
  703. if err := json.NewDecoder(jsonResp.Body).Decode(res); err != nil {
  704. t.Error(err)
  705. }
  706. if res.ToUserName == "" {
  707. t.Error("Response column 'ToUserName' can not be empty")
  708. }
  709. if res.FromUserName == "" {
  710. t.Error("Response column 'FromUserName' can not be empty")
  711. }
  712. if res.CreateTime == 0 {
  713. t.Error("Response column 'CreateTime' can not be zero")
  714. }
  715. if res.MsgType == "" {
  716. t.Error("Response column 'MsgType' can not be empty")
  717. }
  718. if res.Event == "" {
  719. t.Error("Response column 'Event' can not be empty")
  720. }
  721. if res.Quota == 0 {
  722. t.Error("Response column 'Quota' can not be zero")
  723. }
  724. if res.BizID == "" {
  725. t.Error("Response column 'BizID' can not be empty")
  726. }
  727. if res.ResultMsg == "" {
  728. t.Error("Response column 'ResultMsg' can not be empty")
  729. }
  730. }
  731. func TestOnGetExpressQuota(t *testing.T) {
  732. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  733. aesKey := base64.StdEncoding.EncodeToString([]byte("mock-aes-key"))
  734. srv, err := NewServer("mock-app-id", "mock-access-token", aesKey, "mock-mch-id", "mock-api-key", false)
  735. if err != nil {
  736. t.Fatal(err)
  737. }
  738. srv.OnGetExpressQuota(func(result *GetExpressQuotaResult) *GetExpressQuotaReturn {
  739. if result.ToUserName == "" {
  740. t.Error("ToUserName can not be empty")
  741. }
  742. if result.FromUserName == "" {
  743. t.Error("FromUserName can not be empty")
  744. }
  745. if result.CreateTime == 0 {
  746. t.Error("CreateTime can not be zero")
  747. }
  748. if result.MsgType != "event" {
  749. t.Error("Unexpected message type")
  750. }
  751. if result.Event != "get_quota" {
  752. t.Error("Unexpected message event")
  753. }
  754. if result.BizID == "" {
  755. t.Error("Result column 'BizID' can not be empty")
  756. }
  757. if result.BizPwd == "" {
  758. t.Error("Result column 'BizPwd' can not be empty")
  759. }
  760. if result.ShopAppID == "" {
  761. t.Error("Result column 'ShopAppID' can not be empty")
  762. }
  763. res := GetExpressQuotaReturn{
  764. CommonServerReturn: CommonServerReturn{
  765. "oABCD", "gh_abcdefg", 1533042556, "event", "get_quota", 1, "success",
  766. },
  767. BizID: "xyz",
  768. Quota: 3.14159265358,
  769. }
  770. return &res
  771. })
  772. if err := srv.Serve(w, r); err != nil {
  773. t.Fatal(err)
  774. }
  775. }))
  776. defer ts.Close()
  777. xmlData := `<xml>
  778. <ToUserName><![CDATA[gh_abcdefg]]></ToUserName>
  779. <FromUserName><![CDATA[oABCD]]></FromUserName>
  780. <CreateTime>1533042556</CreateTime>
  781. <MsgType><![CDATA[event]]></MsgType>
  782. <Event><![CDATA[get_quota]]></Event>
  783. <BizID><![CDATA[xyz]]></BizID>
  784. <BizPwd><![CDATA[xyz123]]></BizPwd>
  785. <ShopAppID><![CDATA[wxABCD]]></ShopAppID>
  786. </xml>`
  787. xmlResp, err := http.Post(ts.URL, "text/xml", strings.NewReader(xmlData))
  788. if err != nil {
  789. t.Error(err)
  790. }
  791. defer xmlResp.Body.Close()
  792. res := new(GetExpressQuotaReturn)
  793. if err := xml.NewDecoder(xmlResp.Body).Decode(res); err != nil {
  794. t.Error(err)
  795. }
  796. if res.ToUserName == "" {
  797. t.Error("Response column 'ToUserName' can not be empty")
  798. }
  799. if res.FromUserName == "" {
  800. t.Error("Response column 'FromUserName' can not be empty")
  801. }
  802. if res.CreateTime == 0 {
  803. t.Error("Response column 'CreateTime' can not be zero")
  804. }
  805. if res.MsgType == "" {
  806. t.Error("Response column 'MsgType' can not be empty")
  807. }
  808. if res.Event != "get_quota" {
  809. t.Error("Invalid event")
  810. }
  811. if res.Quota == 0 {
  812. t.Error("Response column 'Quota' can not be zero")
  813. }
  814. if res.BizID == "" {
  815. t.Error("Response column 'BizID' can not be empty")
  816. }
  817. if res.ResultMsg == "" {
  818. t.Error("Response column 'ResultMsg' can not be empty")
  819. }
  820. jsonData := `{
  821. "ToUserName": "gh_abcdefg",
  822. "FromUserName": "oABCD",
  823. "CreateTime": 1533042556,
  824. "MsgType": "event",
  825. "Event": "get_quota",
  826. "BizID": "xyz",
  827. "BizPwd": "xyz123",
  828. "ShopAppID": "wxABCD"
  829. }`
  830. jsonResp, err := http.Post(ts.URL, "application/json", strings.NewReader(jsonData))
  831. if err != nil {
  832. t.Error(err)
  833. }
  834. defer jsonResp.Body.Close()
  835. res = new(GetExpressQuotaReturn)
  836. if err := json.NewDecoder(jsonResp.Body).Decode(res); err != nil {
  837. t.Error(err)
  838. }
  839. if res.ToUserName == "" {
  840. t.Error("Response column 'ToUserName' can not be empty")
  841. }
  842. if res.FromUserName == "" {
  843. t.Error("Response column 'FromUserName' can not be empty")
  844. }
  845. if res.CreateTime == 0 {
  846. t.Error("Response column 'CreateTime' can not be zero")
  847. }
  848. if res.MsgType == "" {
  849. t.Error("Response column 'MsgType' can not be empty")
  850. }
  851. if res.Event != "get_quota" {
  852. t.Error("Invalid event")
  853. }
  854. if res.Quota == 0 {
  855. t.Error("Response column 'Quota' can not be zero")
  856. }
  857. if res.BizID == "" {
  858. t.Error("Response column 'BizID' can not be empty")
  859. }
  860. if res.ResultMsg == "" {
  861. t.Error("Response column 'ResultMsg' can not be empty")
  862. }
  863. }
  864. func TestPreviewTemplate(t *testing.T) {
  865. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  866. if r.Method != "POST" {
  867. t.Error("UnExpect request method")
  868. }
  869. if r.URL.EscapedPath() != "/cgi-bin/express/delivery/template/preview" {
  870. t.Error("Unexpected path")
  871. }
  872. if err := r.ParseForm(); err != nil {
  873. t.Fatal(err)
  874. }
  875. if r.Form.Get("access_token") == "" {
  876. t.Fatalf("access_token can not be empty")
  877. }
  878. params := struct {
  879. WaybillTemplate string `json:"waybill_template"`
  880. WaybillData string `json:"waybill_data"`
  881. Custom struct {
  882. OrderID string `json:"order_id"`
  883. OpenID string `json:"openid"`
  884. DeliveryID string `json:"delivery_id"`
  885. BizID string `json:"biz_id"`
  886. CustomRemark string `json:"custom_remark"`
  887. Sender struct {
  888. Name string `json:"name"`
  889. Tel string `json:"tel"`
  890. Mobile string `json:"mobile"`
  891. Company string `json:"company"`
  892. PostCode string `json:"post_code"`
  893. Country string `json:"country"`
  894. Province string `json:"province"`
  895. City string `json:"city"`
  896. Area string `json:"area"`
  897. Address string `json:"address"`
  898. } `json:"sender"`
  899. Receiver struct {
  900. Name string `json:"name"`
  901. Tel string `json:"tel"`
  902. Mobile string `json:"mobile"`
  903. Company string `json:"company"`
  904. PostCode string `json:"post_code"`
  905. Country string `json:"country"`
  906. Province string `json:"province"`
  907. City string `json:"city"`
  908. Area string `json:"area"`
  909. Address string `json:"address"`
  910. } `json:"receiver"`
  911. Cargo struct {
  912. Count uint `json:"count"`
  913. Weight float64 `json:"weight"`
  914. SpaceX float64 `json:"space_x"`
  915. SpaceY float64 `json:"space_y"`
  916. SpaceZ float64 `json:"space_z"`
  917. DetailList []struct {
  918. Name string `json:"name"`
  919. Count uint `json:"count"`
  920. } `json:"detail_list"`
  921. } `json:"cargo"`
  922. Shop struct {
  923. WXAPath string `json:"wxa_path"`
  924. IMGUrl string `json:"img_url"`
  925. GoodsName string `json:"goods_name"`
  926. GoodsCount uint `json:"goods_count"`
  927. } `json:"shop"`
  928. Insured struct {
  929. Used InsureStatus `json:"use_insured"`
  930. Value uint `json:"insured_value"`
  931. } `json:"insured"`
  932. Service struct {
  933. Type uint8 `json:"service_type"`
  934. Name string `json:"service_name"`
  935. } `json:"service"`
  936. } `json:"custom"`
  937. }{}
  938. if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
  939. t.Fatal(err)
  940. }
  941. if params.WaybillTemplate == "" {
  942. t.Error("Response column waybill_template can not be empty")
  943. }
  944. if params.WaybillData == "" {
  945. t.Error("Response column waybill_data can not be empty")
  946. }
  947. if params.Custom.OrderID == "" {
  948. t.Error("param custom.order_id can not be empty")
  949. }
  950. if params.Custom.DeliveryID == "" {
  951. t.Error("param custom.delivery_id can not be empty")
  952. }
  953. if params.Custom.BizID == "" {
  954. t.Error("param custom.biz_id can not be empty")
  955. }
  956. if params.Custom.Sender.Name == "" {
  957. t.Error("param custom.sender.name can not be empty")
  958. }
  959. if params.Custom.Sender.Province == "" {
  960. t.Error("param custom.sender.province can not be empty")
  961. }
  962. if params.Custom.Sender.City == "" {
  963. t.Error("param custom.sender.city can not be empty")
  964. }
  965. if params.Custom.Sender.Area == "" {
  966. t.Error("param custom.sender.area can not be empty")
  967. }
  968. if params.Custom.Sender.Address == "" {
  969. t.Error("param custom.sender.address can not be empty")
  970. }
  971. if params.Custom.Receiver.Name == "" {
  972. t.Error("param custom.receiver.name can not be empty")
  973. }
  974. if params.Custom.Receiver.Province == "" {
  975. t.Error("param custom.receiver.province can not be empty")
  976. }
  977. if params.Custom.Receiver.City == "" {
  978. t.Error("param custom.receiver.city can not be empty")
  979. }
  980. if params.Custom.Receiver.Area == "" {
  981. t.Error("param custom.receiver.area can not be empty")
  982. }
  983. if params.Custom.Receiver.Address == "" {
  984. t.Error("param custom.receiver.address can not be empty")
  985. }
  986. if params.Custom.Cargo.Count == 0 {
  987. t.Error("param custom.cargo.count can not be zero")
  988. }
  989. if params.Custom.Cargo.Weight == 0 {
  990. t.Error("param custom.cargo.weight can not be zero")
  991. }
  992. if params.Custom.Cargo.SpaceX == 0 {
  993. t.Error("param custom.cargo.spaceX can not be zero")
  994. }
  995. if params.Custom.Cargo.SpaceY == 0 {
  996. t.Error("param custom.cargo.spaceY can not be zero")
  997. }
  998. if params.Custom.Cargo.SpaceZ == 0 {
  999. t.Error("param custom.cargo.spaceZ can not be zero")
  1000. }
  1001. if len(params.Custom.Cargo.DetailList) == 0 {
  1002. t.Error("param cargo.custom.detailList can not be empty")
  1003. } else {
  1004. if (params.Custom.Cargo.DetailList[0].Name) == "" {
  1005. t.Error("param custom.cargo.detailList.name can not be empty")
  1006. }
  1007. if (params.Custom.Cargo.DetailList[0].Count) == 0 {
  1008. t.Error("param custom.cargo.detailList.count can not be zero")
  1009. }
  1010. }
  1011. if params.Custom.Shop.WXAPath == "" {
  1012. t.Error("param custom.shop.wxa_path can not be empty")
  1013. }
  1014. if params.Custom.Shop.IMGUrl == "" {
  1015. t.Error("param custom.shop.img_url can not be empty")
  1016. }
  1017. if params.Custom.Shop.GoodsName == "" {
  1018. t.Error("param custom.shop.goods_name can not be empty")
  1019. }
  1020. if params.Custom.Shop.GoodsCount == 0 {
  1021. t.Error("param custom.shop.goods_count can not be zero")
  1022. }
  1023. if params.Custom.Insured.Used == 0 {
  1024. t.Error("param custom.insured.use_insured can not be zero")
  1025. }
  1026. if params.Custom.Service.Name == "" {
  1027. t.Error("param custom.service.service_name can not be empty")
  1028. }
  1029. w.WriteHeader(http.StatusOK)
  1030. raw := `{
  1031. "waybill_id": "1234567890123",
  1032. "rendered_waybill_template": "PGh0bWw+dGVzdDwvaHRtbD4="
  1033. }`
  1034. if _, err := w.Write([]byte(raw)); err != nil {
  1035. t.Fatal(err)
  1036. }
  1037. }))
  1038. defer ts.Close()
  1039. raw := `{
  1040. "waybill_id": "1234567890123",
  1041. "waybill_data": "##ZTO_mark##11-22-33##ZTO_bagAddr##广州##",
  1042. "waybill_template": "PGh0bWw+dGVzdDwvaHRtbD4=",
  1043. "custom": {
  1044. "order_id": "012345678901234567890123456789",
  1045. "openid": "oABC123456",
  1046. "delivery_id": "ZTO",
  1047. "biz_id": "xyz",
  1048. "custom_remark": "易碎物品",
  1049. "sender": {
  1050. "name": "张三",
  1051. "tel": "18666666666",
  1052. "mobile": "020-88888888",
  1053. "company": "公司名",
  1054. "post_code": "123456",
  1055. "country": "中国",
  1056. "province": "广东省",
  1057. "city": "广州市",
  1058. "area": "海珠区",
  1059. "address": "XX路XX号XX大厦XX栋XX"
  1060. },
  1061. "receiver": {
  1062. "name": "王小蒙",
  1063. "tel": "18610000000",
  1064. "mobile": "020-77777777",
  1065. "company": "公司名",
  1066. "post_code": "654321",
  1067. "country": "中国",
  1068. "province": "广东省",
  1069. "city": "广州市",
  1070. "area": "天河区",
  1071. "address": "XX路XX号XX大厦XX栋XX"
  1072. },
  1073. "shop": {
  1074. "wxa_path": "/index/index?from=waybill",
  1075. "img_url": "https://mmbiz.qpic.cn/mmbiz_png/KfrZwACMrmwbPGicysN6kibW0ibXwzmA3mtTwgSsdw4Uicabduu2pfbfwdKicQ8n0v91kRAUX6SDESQypl5tlRwHUPA/640",
  1076. "goods_name": "一千零一夜钻石包&爱马仕柏金钻石包",
  1077. "goods_count": 2
  1078. },
  1079. "cargo": {
  1080. "count": 2,
  1081. "weight": 5.5,
  1082. "space_x": 30.5,
  1083. "space_y": 20,
  1084. "space_z": 20,
  1085. "detail_list": [
  1086. {
  1087. "name": "一千零一夜钻石包",
  1088. "count": 1
  1089. },
  1090. {
  1091. "name": "爱马仕柏金钻石包",
  1092. "count": 1
  1093. }
  1094. ]
  1095. },
  1096. "insured": {
  1097. "use_insured": 1,
  1098. "insured_value": 10000
  1099. },
  1100. "service": {
  1101. "service_type": 0,
  1102. "service_name": "标准快递"
  1103. }
  1104. }
  1105. }`
  1106. previewer := new(ExpressTemplatePreviewer)
  1107. err := json.Unmarshal([]byte(raw), previewer)
  1108. if err != nil {
  1109. t.Fatal(err)
  1110. }
  1111. _, err = previewer.preview(ts.URL+apiPreviewTemplate, "mock-access-token")
  1112. if err != nil {
  1113. t.Fatal(err)
  1114. }
  1115. }
  1116. func TestUpdateBusiness(t *testing.T) {
  1117. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1118. if r.Method != "POST" {
  1119. t.Error("UnExpect request method")
  1120. }
  1121. if r.URL.EscapedPath() != "/cgi-bin/express/delivery/service/business/update" {
  1122. t.Error("Unexpected path")
  1123. }
  1124. if err := r.ParseForm(); err != nil {
  1125. t.Fatal(err)
  1126. }
  1127. if r.Form.Get("access_token") == "" {
  1128. t.Fatalf("access_token can not be empty")
  1129. }
  1130. params := struct {
  1131. ShopAppID string `json:"shop_app_id"` // 商户的小程序AppID,即审核商户事件中的 ShopAppID
  1132. BizID string `json:"biz_id"` // 商户账户
  1133. ResultCode int `json:"result_code"` // 审核结果,0 表示审核通过,其他表示审核失败
  1134. ResultMsg string `json:"result_msg"` // 审核错误原因,仅 result_code 不等于 0 时需要设置
  1135. }{}
  1136. if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
  1137. t.Fatal(err)
  1138. }
  1139. if params.ShopAppID == "" {
  1140. t.Error("Response column shop_app_id can not be empty")
  1141. }
  1142. if params.BizID == "" {
  1143. t.Error("Response column biz_id can not be empty")
  1144. }
  1145. if params.ResultCode == 0 {
  1146. t.Error("Response column result_code can not be zero")
  1147. }
  1148. if params.ResultMsg == "" {
  1149. t.Error("Response column result_msg can not be empty")
  1150. }
  1151. w.WriteHeader(http.StatusOK)
  1152. raw := `{
  1153. "errcode": 0,
  1154. "errmsg": "ok"
  1155. }`
  1156. if _, err := w.Write([]byte(raw)); err != nil {
  1157. t.Fatal(err)
  1158. }
  1159. }))
  1160. defer ts.Close()
  1161. raw := `{
  1162. "shop_app_id": "wxABCD",
  1163. "biz_id": "xyz",
  1164. "result_code": 1,
  1165. "result_msg": "审核通过"
  1166. }`
  1167. updater := new(BusinessUpdater)
  1168. err := json.Unmarshal([]byte(raw), updater)
  1169. if err != nil {
  1170. t.Fatal(err)
  1171. }
  1172. _, err = updater.update(ts.URL+apiUpdateBusiness, "mock-access-token")
  1173. if err != nil {
  1174. t.Fatal(err)
  1175. }
  1176. }
  1177. func TestUpdatePath(t *testing.T) {
  1178. ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1179. if r.Method != "POST" {
  1180. t.Error("UnExpect request method")
  1181. }
  1182. if r.URL.EscapedPath() != "/cgi-bin/express/delivery/path/update" {
  1183. t.Error("Unexpected path")
  1184. }
  1185. if err := r.ParseForm(); err != nil {
  1186. t.Fatal(err)
  1187. }
  1188. if r.Form.Get("access_token") == "" {
  1189. t.Fatalf("access_token can not be empty")
  1190. }
  1191. params := struct {
  1192. Token string `json:"token"` // 商户侧下单事件中推送的 Token 字段
  1193. WaybillID string `json:"waybill_id"` // 运单 ID
  1194. ActionTime uint `json:"action_time"` // 轨迹变化 Unix 时间戳
  1195. ActionType int `json:"action_type"` // 轨迹变化类型
  1196. ActionMsg string `json:"action_msg"` // 轨迹变化具体信息说明,展示在快递轨迹详情页中。若有手机号码,则直接写11位手机号码。使用UTF-8编码。
  1197. }{}
  1198. if err := json.NewDecoder(r.Body).Decode(&params); err != nil {
  1199. t.Fatal(err)
  1200. }
  1201. if params.Token == "" {
  1202. t.Error("Response column token can not be empty")
  1203. }
  1204. if params.WaybillID == "" {
  1205. t.Error("Response column waybill_id can not be empty")
  1206. }
  1207. if params.ActionMsg == "" {
  1208. t.Error("Response column action_msg can not be empty")
  1209. }
  1210. if params.ActionTime == 0 {
  1211. t.Error("Response column action_time can not be zero")
  1212. }
  1213. if params.ActionType == 0 {
  1214. t.Error("Response column action_type can not be zero")
  1215. }
  1216. w.WriteHeader(http.StatusOK)
  1217. raw := `{
  1218. "errcode": 0,
  1219. "errmsg": "ok"
  1220. }`
  1221. if _, err := w.Write([]byte(raw)); err != nil {
  1222. t.Fatal(err)
  1223. }
  1224. }))
  1225. defer ts.Close()
  1226. raw := `{
  1227. "token": "TOKEN",
  1228. "waybill_id": "12345678901234567890",
  1229. "action_time": 1533052800,
  1230. "action_type": 300002,
  1231. "action_msg": "丽影邓丽君【18666666666】正在派件"
  1232. }`
  1233. updater := new(ExpressPathUpdater)
  1234. err := json.Unmarshal([]byte(raw), updater)
  1235. if err != nil {
  1236. t.Fatal(err)
  1237. }
  1238. _, err = updater.update(ts.URL+apiUpdatePath, "mock-access-token")
  1239. if err != nil {
  1240. t.Fatal(err)
  1241. }
  1242. }