互动
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.

249 lines
5.9 KiB

5 years ago
  1. package wx
  2. import (
  3. "bytes"
  4. "crypto/tls"
  5. "crypto/x509"
  6. "encoding/xml"
  7. "fmt"
  8. "io/ioutil"
  9. "net/http"
  10. )
  11. type cdata string
  12. func (c cdata) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
  13. return e.EncodeElement(struct {
  14. string `xml:",cdata"`
  15. }{string(c)}, start)
  16. }
  17. var _tlsConfig *tls.Config
  18. //var WxClient = NewClient()
  19. func getTLSConfig() (*tls.Config, error) {
  20. if _tlsConfig != nil {
  21. return _tlsConfig, nil
  22. }
  23. // load cert
  24. cert, err := tls.LoadX509KeyPair(WxCertPath, WxKeyPath)
  25. if err != nil {
  26. return nil, err
  27. }
  28. // load root ca
  29. caData, err := ioutil.ReadFile(WxCaPath)
  30. if err != nil {
  31. return nil, err
  32. }
  33. pool := x509.NewCertPool()
  34. pool.AppendCertsFromPEM(caData)
  35. _tlsConfig = &tls.Config{
  36. Certificates: []tls.Certificate{cert},
  37. RootCAs: pool,
  38. }
  39. return _tlsConfig, nil
  40. }
  41. type Client struct {
  42. AppId string
  43. MchId string
  44. secureClient *http.Client
  45. }
  46. func (w *Client) Post(url string, xmlRes []byte) (*http.Response, error) {
  47. return w.secureClient.Post(url, "application/xml", bytes.NewBuffer(xmlRes))
  48. }
  49. // ======= 支付回调
  50. func (w *Client) Callback() {
  51. }
  52. // ======= 统一下单
  53. func (w *Client) UnifiedOrder(param *UnifiedOrderParam) (*UnifiedOrderResult, error) {
  54. param.Appid = w.AppId
  55. param.MchId = w.MchId
  56. xmlParam, err := xml.MarshalIndent(param, "", "")
  57. if err != nil {
  58. return nil, err
  59. }
  60. resp, err := w.Post(UnifiedOrderURL, xmlParam)
  61. if err != nil {
  62. return nil, err
  63. }
  64. body, err := ioutil.ReadAll(resp.Body)
  65. if err != nil {
  66. return nil, err
  67. }
  68. res := new(UnifiedOrderResult)
  69. err = xml.Unmarshal(body, res)
  70. if err != nil {
  71. return nil, err
  72. }
  73. if res.ReturnCode != CODE_SUCCESS {
  74. return res, fmt.Errorf("network error, retrun_code: %v and return_msg: %v", res.ReturnCode, res.ReturnMsg)
  75. }
  76. if res.ResultCode != CODE_SUCCESS {
  77. return res, fmt.Errorf("trade error, err_code: %v and err_code_des: %v", res.ErrCode, res.ErrCodeDes)
  78. }
  79. return res, nil
  80. }
  81. // ======= 查询订单
  82. func (w *Client) QueryOrder(param *QueryOrderParam) (*QueryOrderResult, error) {
  83. param.Appid = w.AppId
  84. param.MchId = w.MchId
  85. xmlParam, err := xml.MarshalIndent(param, "", "")
  86. if err != nil {
  87. return nil, err
  88. }
  89. resp, err := w.Post(QueryOrderURL, xmlParam)
  90. if err != nil {
  91. return nil, err
  92. }
  93. body, err := ioutil.ReadAll(resp.Body)
  94. if err != nil {
  95. return nil, err
  96. }
  97. res := new(QueryOrderResult)
  98. err = xml.Unmarshal(body, res)
  99. if err != nil {
  100. return nil, err
  101. }
  102. if res.ReturnCode != CODE_SUCCESS {
  103. return res, fmt.Errorf("network error, return_code: %v and return_msg: %v", res.ReturnCode, res.ReturnMsg)
  104. }
  105. if res.ResultCode != CODE_SUCCESS {
  106. return res, fmt.Errorf("trade error, err_code: %v and err_code_des: %v", res.ErrCode, res.ErrCodeDes)
  107. }
  108. return res, nil
  109. }
  110. // ======= 关闭订单
  111. func (w *Client) CloseOrder(param *CloseOrderParam) (*CloseOrderResult, error) {
  112. param.Appid = w.AppId
  113. param.MchId = w.MchId
  114. xmlParam, err := xml.MarshalIndent(param, "", "")
  115. if err != nil {
  116. return nil, err
  117. }
  118. resp, err := w.Post(CloseOrderURL, xmlParam)
  119. if err != nil {
  120. return nil, err
  121. }
  122. body, err := ioutil.ReadAll(resp.Body)
  123. if err != nil {
  124. return nil, err
  125. }
  126. res := new(CloseOrderResult)
  127. err = xml.Unmarshal(body, res)
  128. if err != nil {
  129. return nil, err
  130. }
  131. if res.ReturnCode != CODE_SUCCESS {
  132. return res, fmt.Errorf("network error, return_code: %v and return_msg: %v", res.ReturnCode, res.ReturnMsg)
  133. }
  134. if res.ResultCode != CODE_SUCCESS {
  135. return res, fmt.Errorf("trade error, err_code: %v and err_code_des: %v", res.ErrCode, res.ErrCodeDes)
  136. }
  137. return res, nil
  138. }
  139. // ======= 申请退款
  140. func (w *Client) Refund(param *RefundParam) (*RefundResult, error) {
  141. param.Appid = w.AppId
  142. param.MchId = w.MchId
  143. xmlParam, err := xml.MarshalIndent(param, "", "")
  144. if err != nil {
  145. return nil, err
  146. }
  147. resp, err := w.Post(RefundURL, xmlParam)
  148. if err != nil {
  149. return nil, err
  150. }
  151. body, err := ioutil.ReadAll(resp.Body)
  152. if err != nil {
  153. return nil, err
  154. }
  155. res := new(RefundResult)
  156. err = xml.Unmarshal(body, res)
  157. if err != nil {
  158. return nil, err
  159. }
  160. if res.ReturnCode != CODE_SUCCESS {
  161. return res, fmt.Errorf("network error, return_code: %v and return_msg: %v", res.ReturnCode, res.ReturnMsg)
  162. }
  163. if res.ResultCode != CODE_SUCCESS {
  164. return res, fmt.Errorf("trade error, err_code: %v and err_code_des: %v", res.ErrCode, res.ErrCodeDes)
  165. }
  166. return nil, nil
  167. }
  168. // ======= 查询退款
  169. func (w *Client) RefundQuery(param *RefundQueryParam) (*RefundQueryResult, error) {
  170. param.Appid = w.AppId
  171. param.MchId = w.MchId
  172. xmlParam, err := xml.MarshalIndent(param, "", "")
  173. if err != nil {
  174. return nil, err
  175. }
  176. resp, err := w.Post(RefundQueryURL, xmlParam)
  177. if err != nil {
  178. return nil, err
  179. }
  180. body, err := ioutil.ReadAll(resp.Body)
  181. if err != nil {
  182. return nil, err
  183. }
  184. res := new(RefundQueryResult)
  185. err = xml.Unmarshal(body, res)
  186. if err != nil {
  187. return nil, err
  188. }
  189. if res.ReturnCode != CODE_SUCCESS {
  190. return res, fmt.Errorf("network error, return_code: %v and return_msg: %v", res.ReturnCode, res.ReturnMsg)
  191. }
  192. if res.ResultCode != CODE_SUCCESS {
  193. return res, fmt.Errorf("trade error, err_code: %v and err_code_des: %v", res.ErrCode, res.ErrCodeDes)
  194. }
  195. return res, nil
  196. }
  197. // 支付结果通知
  198. // 支付给用户零钱
  199. // 公众号发送红包
  200. func (w *Client) SendRedPack(param *RedPackParam) (*RedPackResult, error) {
  201. param.Appid = w.AppId
  202. param.MchId = w.MchId
  203. xmlParam, err := xml.MarshalIndent(param, "", "")
  204. if err != nil {
  205. return nil, err
  206. }
  207. resp, err := w.Post(SendRedPackURL, xmlParam)
  208. if err != nil {
  209. return nil, err
  210. }
  211. body, err := ioutil.ReadAll(resp.Body)
  212. if err != nil {
  213. return nil, err
  214. }
  215. res := new(RedPackResult)
  216. err = xml.Unmarshal(body, res)
  217. if err != nil {
  218. return nil, err
  219. }
  220. if res.ReturnCode != CODE_SUCCESS {
  221. return res, fmt.Errorf("network error, return_code: %v and return_msg: %v", res.ReturnCode, res.ReturnMsg)
  222. }
  223. if res.ResultCode != CODE_SUCCESS {
  224. return res, fmt.Errorf("trade error, err_code: %v and err_code_des: %v", res.ErrCode, res.ErrCodeDes)
  225. }
  226. return res, nil
  227. }