//下载汇率文件接口 func (ot *OverseaTrade) MustGetExchangeRateList() (output []ExchangeRate) { query := map[string]string{ "service": "forex_rate_file", "partner": ot.PartnerId, } ot.md5Sign(query) content := kmgHttp.MustUrlGetContent(kmgHttp.MustSetParameterMapToUrl("https://mapi.alipay.com/gateway.do", query)) lineList := strings.Split(string(content), "\n") output = make([]ExchangeRate, 0, len(lineList)) for _, line := range lineList { line := strings.TrimSpace(line) if line == "" { continue } part := strings.Split(line, "|") if len(part) < 4 { panic(fmt.Errorf("[MustGetExchangeRateList] format error")) } t, err := time.Parse("20060102150405", part[0]+part[1]) //考虑别处基本不会使用,就直接写在这个地方了. if err != nil { panic(err) } rate, err := kmgStrconv.ParseFloat64(part[3]) if err != nil { panic(err) } output = append(output, ExchangeRate{ Time: t, Currency: part[2], Rate: rate, }) } return output }
func MustGetExchangeRate(from string, to string) float64 { if !kmgStrings.IsAllAphphabet(from) { panic(fmt.Errorf("[MustGetExchangeRate] fromName [%s] should like USD", from)) } if !kmgStrings.IsAllAphphabet(to) { panic(fmt.Errorf("[MustGetExchangeRate] toName [%s] should like USD", to)) } if from == to { panic(fmt.Errorf("[MustGetExchangeRate] fromName [%s] =toName [%s] ")) } out := kmgHttp.MustUrlGetContent(kmgHttp.MustSetParameterMapToUrl("https://query.yahooapis.com/v1/public/yql", map[string]string{ "q": fmt.Sprintf(`select * from yahoo.finance.xchange where pair="%s%s"`, from, to), "format": "json", "env": "store://datatables.org/alltableswithkeys", "callback": "", })) //out should look like {"query":{"count":1,"created":"2015-06-01T02:37:44Z","lang":"en","results":{"rate":{"id":"JPYCNY","Name":"JPY/CNY","Rate":"0.0501","Date":"6/1/2015","Time":"3:37am","Ask":"0.0501","Bid":"0.0501"}}}} resp := yqlRateResponse{} kmgJson.MustUnmarshal(out, &resp) if resp.Query.Results.Rate.Rate == "N/A" { panic(fmt.Errorf("[MustGetExchangeRate] Currency [%s][%s] not exist", from, to)) //有一种货币不存在. } rate, err := kmgStrconv.ParseFloat64(resp.Query.Results.Rate.Rate) if err != nil { panic(err) } return rate }
// 通知验证接口 // 和支付宝手机接口一模一样. func (ot *OverseaTrade) VerifyNotify(NotifyId string) (err error) { u := kmgHttp.MustSetParameterMapToUrl("https://mapi.alipay.com/gateway.do", map[string]string{ "service": "notify_verify", "partner": ot.PartnerId, "notify_id": NotifyId, }) content, err := kmgHttp.UrlGetContent(u) if err != nil { return err } if !bytes.Equal(content, []byte(`true`)) { return fmt.Errorf("notify_id verify fail") } return nil }
//用户发起支付,请传入Request,然后redirect到这个函数返回的url里面去. func (ot *OverseaTrade) Pay(req *OverseaTradePayRequest) (url string) { query := map[string]string{ "_input_charset": "utf-8", "service": "create_forex_trade", "partner": ot.PartnerId, "notify_url": ot.SelfSchemeAndHost + "/?n=github.com.bronze1man.kmg.third.kmgAlipay.OverseaTrade.NotifyAction", "return_url": ot.SelfSchemeAndHost + "/?n=github.com.bronze1man.kmg.third.kmgAlipay.OverseaTrade.ReturnPage", "subject": req.Subject, "body": req.Body, "out_trade_no": req.OutTradeNo, "currency": req.Currency, "supplier": req.Supplier, "timeout_rule": req.TimeoutRule, "specified_pay_channel": req.SpecifiedPayChannel, "seller_id": req.SellerId, "seller_name": req.SellerName, "seller_industry": req.SellerIndustry, } if req.NotifyUrl != "" { query["notify_url"] = req.NotifyUrl } if req.ReturnUrl != "" { query["return_url"] = req.ReturnUrl } if req.TotalFee != 0 { if req.Currency == "JPY" { //日元精度是整数,传入小数点会报错,这个文档上没有写,但是经过实验发现是这个样子的. query["total_fee"] = kmgStrconv.FormatFloatPrec0(req.TotalFee) } else { query["total_fee"] = kmgStrconv.FormatFloatPrec2(req.TotalFee) } } if req.RmbFee != 0 { query["rmb_fee"] = kmgStrconv.FormatFloatPrec2(req.RmbFee) } ot.md5Sign(query) kmgLog.Log("Alipay", "Oversea Pay", query) //已经手动验证url里面的参数顺序无关紧要. return kmgHttp.MustSetParameterMapToUrl("https://mapi.alipay.com/gateway.do", query) }
// 单条交易查询接口 func (ot *OverseaTrade) SingleTransactionQuery(outTradeId string) (tran *OverseaTradeTransaction, err error) { query := map[string]string{ "service": "single_trade_query", "partner": ot.PartnerId, "_input_charset": "utf-8", "out_trade_no": outTradeId, } ot.md5Sign(query) content := kmgHttp.MustUrlGetContent(kmgHttp.MustSetParameterMapToUrl("https://mapi.alipay.com/gateway.do", query)) response := overseaTradeTransactionQueryResponse{} err = xml.Unmarshal(content, &response) if err != nil { return nil, err } if response.IsSuccess != "T" { return nil, fmt.Errorf("[支付宝单条交易查询接口错误] [%s]", response.Error) } return &OverseaTradeTransaction{ TradeNo: response.TradeNo, OutTradeNo: response.OutTradeNo, Subject: response.Subject, TradeStatus: response.TradeStatus, }, nil }