使用golang快速开发微信公众平台(九):下载对账单
2017-07-11 15:52
866 查看
首先,对账单是csv格式的;其次,对账单不是非常标准非常标准的csv格式——你直接解析会挂掉。
所以我采用的方式为:把对账单分为2部分,先写第1部分,再把第2部分拼进去。
唉卧槽他大爷的微信。
所以我采用的方式为:把对账单分为2部分,先写第1部分,再把第2部分拼进去。
唉卧槽他大爷的微信。
package controllers import ( "github.com/astaxie/beego" "monkeyServer/shopUtils/RandomStrUtil" "encoding/xml" "strings" "net/http" "bytes" "io/ioutil" "fmt" "os" "encoding/csv" "io" "log" ) type AdminWXBillsController struct { beego.Controller } func (c *AdminWXBillsController) Post() { c.EnableRender = false //查询哪一天的对账单 date := c.GetString("wxDate", "") if len(date) != 8 || date == "" { c.Ctx.WriteString("日期参数长度错误") } //https://api.mch.weixin.qq.com/pay/downloadbill //商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。 //注意: //1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致; //2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取; //3、对账单中涉及金额的字段单位为“元”。 //4、对账单接口只能下载三个月以内的账单。 //首先定义一个UnifyOrderReq用于填入我们要传入的参数。 type WXBillReq struct { Appid string `xml:"appid"` //公众账号ID Mch_id string `xml:"mch_id"` //商户号 Nonce_str string `xml:"nonce_str"` //随机字符串 Sign string `xml:"sign"` //签名 BillDate string `xml:"bill_date"` //下载对账单的日期,格式:20140603 BillType string `xml:"bill_type"` //ALL,返回当日所有订单信息,默认值 SUCCESS,返回当日成功支付的订单 REFUND,返回当日退款订单 RECHARGE_REFUND,返回当日充值退款订单(相比其他对账单多一栏“返还手续费”) } type WXBillResp struct { Return_code string `xml:"return_code"` Return_msg string `xml:"return_msg"` } var yourReq WXBillReq yourReq.Appid = beego.AppConfig.String("APPID") yourReq.Mch_id = beego.AppConfig.String("Mchid") yourReq.Nonce_str = RandomStrUtil.GetRandomString(32) yourReq.BillDate = date yourReq.BillType = "ALL" var m map[string]interface{} m = make(map[string]interface{}, 0) m["appid"] = yourReq.Appid m["mch_id"] = yourReq.Mch_id m["nonce_str"] = yourReq.Nonce_str m["bill_date"] = yourReq.BillDate m["bill_type"] = yourReq.BillType yourReq.Sign = wxpayCalcSign(m, WX_PAY_API_KEY) //这个key 微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全 bytes_req, err := xml.Marshal(yourReq) if err != nil { beego.Error("wxpay转换为xml错误:", err) return } str_req := strings.Replace(string(bytes_req), "UnifyOrderReq", "xml", -1) //beego.Error("请求UnifiedOrder 拼接 xml 完成--------", str_req) bytes_req = []byte(str_req) //发送unified order请求. req, err := http.NewRequest("POST", "https://api.mch.weixin.qq.com/pay/downloadbill", bytes.NewReader(bytes_req)) if err != nil { beego.Error("New Http Request发生错误,原因:", err) return } req.Header.Set("Accept", "application/xml") //这里的http header的设置是必须设置的. req.Header.Set("Content-Type", "application/xml;charset=utf-8") client := http.Client{} resp, _err := client.Do(req) if _err != nil { beego.Error("请求微信对账单接口发送错误, 原因:", _err) return } beego.Error("请求微信对账单接口已经执行完成") respBytes, err := ioutil.ReadAll(resp.Body) if err != nil { beego.Error("解析返回body错误", err) return } defer resp.Body.Close() xmlResp := WXBillResp{} _err = xml.Unmarshal(respBytes, &xmlResp) if xmlResp.Return_code == "FAIL" { fmt.Printf("请求微信对账单失败 %+v\n:", xmlResp) } else { newPath := createWxBillCSVFile(date) in := string(respBytes) in = strings.Replace(in, "`", "", -1) spliteAfter := strings.Split(in, "总交易单数") r := csv.NewReader(strings.NewReader(spliteAfter[0])) resultStr := make([][]string, 0) for { record, err := r.Read() if err == io.EOF { break } if err != nil { log.Fatal(err) } resultStr = append(resultStr, record) } //写入文件 f, err := os.Create(newPath)//创建文件 if err != nil { beego.Error("创建csv文件错误", err) } defer f.Close() w := csv.NewWriter(f)//创建一个新的写入文件流 err = w.WriteAll(resultStr)//写入数据 w.Flush() //再读取文件 把因为分割缺少的文字补进来 r2 := csv.NewReader(strings.NewReader(strings.Replace(spliteAfter[1], ",总交易额", "总交易单数,总交易额", -1))) resultStr2 := make([][]string, 0) for { record2, err := r2.Read() if err == io.EOF { break } if err != nil { log.Fatal(err) } resultStr2 = append(resultStr2, record2) } //写入剩下2行 w2 := csv.NewWriter(f) //创建一个新的写入文件流 w2.WriteAll(resultStr2) //写入数据 w2.Flush() c.Ctx.WriteString(string(respBytes)) } } func createWxBillCSVFile(date string) string { dirPath := "static/wxcsv/" if !IsFileExist(dirPath) { err := os.MkdirAll(dirPath, 0) beego.Error("创建csv文件夹存在错误 ", err) } newPath := dirPath + date + ".csv" if IsFileExist(newPath) { err := os.Remove(newPath) if err != nil { beego.Error("删除旧的csv文件错误", err) } } return newPath }
相关文章推荐
- 使用golang快速开发微信公众平台(五):公众号支付
- 使用golang快速开发微信公众平台(一):开启服务器配置
- 使用golang快速开发微信公众平台(三):定制菜单
- 使用golang快速开发微信公众平台(六):给用户发红包(用户提现至微信钱包)
- 使用golang快速开发微信公众平台(二):获取accessToken
- 使用golang快速开发微信公众平台(四):网页授权
- 使用golang快速开发微信公众平台(七):通过客服向用户发消息
- 使用golang快速开发微信公众平台(六):给用户发红包(用户提现至微信钱包)
- 使用golang快速开发微信公众平台(八):获取用户二维码
- android mvp快速开发框架介绍(dileber使用之图片下载工具)
- SNF开发平台WinForm之六-上传下载组件使用-SNF快速开发平台3.3-Spring.Net.Framework
- 使用Golang开发微信公众平台----接收消息
- PHP导出EXCEL快速开发指南--PHPEXCEL的使用详解,解决PHP下载文件名中文乱码
- 使用Golang开发微信公众平台----自定义菜单(删除、新
- 使用Golang开发微信公众平台----接入验证
- Ruby on rails开发从头来(windows)(一)-使用InstantRails快速搭建Ruby On Rails开发环境
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)
- 使用 Ruby on Rails 快速开发 Web 应用程序
- 使用企业库DAAB开发企业级应用的示例[下载]
- Asp.net 2.0 自定义控件开发专题[详细探讨页面状态(视图状态和控件状态)机制及其使用场景](示例代码下载)