package main import ( "database/sql" "errors" "fmt" "log" "math" "net/http" "net/url" "strconv" "time" "github.com/go-sql-driver/mysql" ) type RpnOut struct { Version string Sign_type string Mid string Notify_url string Order_amount string Order_time string //YYYYMMDDHHMMSS Order_id string User_id string User_name string User_cardno string Signature string //template Url string //where to post entire data structure //database specific Id int64 Leanwork int64 Ip4 uint32 Ip4location sql.NullString Ts mysql.NullTime } // //build request from leanwork request forms // func (m *RpnOut) buildReqByForm(form url.Values) RpnOut { // r := RpnOut{} // r.version = "1.1" // r.sign_type = "MD5" // r.mid = "EU85201311P2P" // r.notify_url = "http://rpn.supertraderfx.ayvwd8em49pvoa3g.com/rpn_notify" // r.order_id = form["orderNo"][0] // r.order_amount = form["orderAmount"][0] //cents // r.order_time = m.now() // r.user_id = form["customerId"][0] // r.user_name = "SuperForex" // r.user_cardno = "6212262002002377849" // r.signature = md5RpnFormP2P(r) // *m = r // return r // } func (m *RpnOut) buildReqByLeanworkRequestP2P(row LeanworkRequest, user_name string, user_cardno string) RpnOut { m.Version = "1.1" m.Sign_type = "MD5" m.Mid = Config.Rpn.MIDP2P m.Notify_url = Config.Rpn.UrlCallBack m.Order_id = row.OrderNo m.Order_amount = m.translateAmountFromLeanwork(row.OrderAmount) m.Order_time = m.now() m.User_id = row.CustomerId m.User_name = user_name m.User_cardno = user_cardno m.Signature = md5RpnFormP2P(*m) m.Leanwork = row.Id return *m } func (m *RpnOut) buildReqByLeanworkRequestFAT(row LeanworkRequest, user_name string, user_cardno string) RpnOut { m.Version = "1.1" m.Sign_type = "MD5" m.Mid = Config.Rpn.MIDFAT m.Notify_url = Config.Rpn.UrlCallBack m.Order_id = row.OrderNo m.Order_amount = m.translateAmountFromLeanwork(row.OrderAmount) m.Order_time = m.now() m.User_id = row.CustomerId m.User_name = user_name m.User_cardno = user_cardno m.Signature = md5RpnFormFAT(*m) m.Leanwork = row.Id return *m } //from 0.1 to 10 cents func (m *RpnOut) translateAmountFromLeanwork(from string) string { f, _ := strconv.ParseFloat(from, 32) f = f * 100 //convert to cents t := int(math.Ceil(f)) s := strconv.Itoa(t) return s } func (m *RpnOut) now() string { t := time.Now() return t.Format("20060102150405") } //send request to RPN to initiate transaction func (m *RpnOut) SendReq(form url.Values) (*http.Response, error) { return nil, nil // r := m.buildReqByForm(form) // hc := http.Client{Timeout: 15 * time.Second} // myForm := url.Values{} // myForm.Set("version", r.version) // myForm.Set("sign_type", r.sign_type) // myForm.Set("mid", r.mid) // myForm.Set("notify_url", r.notify_url) // myForm.Set("order_id", r.order_id) // myForm.Set("order_amount", r.order_amount) // myForm.Set("order_time", r.order_time) // myForm.Set("user_id", r.user_id) // myForm.Set("user_name", r.user_name) // myForm.Set("user_cardno", r.user_cardno) // myForm.Set("signature", r.signature) // //req, err := http.NewRequest("POST", "https://lawipac.com/dumprequest.php", strings.NewReader(myForm.Encode())) // req, err := http.NewRequest("POST", Config.Rpn.UrlTest, strings.NewReader(m.encode())) // if err != nil { // panic("wrong") // } // req.Header.Add("Content-Type", "application/x-www-form-urlencoded") // req.Header.Add("content-Length", strconv.Itoa(len(form.Encode()))) // return hc.Do(req) //Config.Rpn.UrlTest // return http.PostForm(Config.Rpn.UrlTest, myForm) //return http.PostForm("https://lawipac.com/dumprequest.php", myForm) } //encode without disturbing it's original order func (m *RpnOut) encode() string { s := "version=" + m.Version s += "&sign_type=" + m.Sign_type s += "&mid=" + m.Mid s += "¬ify_url=" + url.QueryEscape(m.Notify_url) s += "&order_id=" + m.Order_id s += "&order_amount=" + m.Order_amount s += "&order_time=" + m.Order_time s += "&user_id=" + m.User_id s += "&user_name=" + url.QueryEscape(m.User_name) s += "&user_cardno=" + m.User_cardno s += "&signature=" + m.Signature return s } func retrieveFormValue(form url.Values, key string) (r string, err error) { if _, ok := form[key]; ok { r = form[key][0] err = nil } else { r = "" err = errors.New("Key [" + key + "] not found in HTTP request") } return r, err } func rpnNotify(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, "ok notify") } //receive RPN user name and card number func rpnNameAndCard(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { errPage(w, http.StatusMethodNotAllowed, "invalid request") return } r.ParseForm() id := r.FormValue("id") sign := r.FormValue("sign") user_name := r.FormValue("name") user_card := r.FormValue("card") rpn_type := r.FormValue("rpnType") if !(id != "" && sign != "" && user_name != "" && user_card != "") { errPage(w, http.StatusBadRequest, "missing parameters") return } row, err := getRequestRowByIdAndSign(id, sign) if err != nil { w.WriteHeader(http.StatusBadRequest) fmt.Fprintf(w, "bad parameters") return } ro := RpnOut{} ro.Ip4 = getClientIPLong(r) ro.Leanwork = row.Id if rpn_type == "rpnp2p" { ro.buildReqByLeanworkRequestP2P(row, user_name, user_card) } else { ro.buildReqByLeanworkRequestFAT(row, user_name, user_card) } //create db record db.addRpnOut(ro) //build rpn redirect page and send it ro.sendRedirect(w, row) } func (m *RpnOut) sendRedirect(w http.ResponseWriter, row LeanworkRequest) { //execute redirect m.Url = Config.Rpn.Url tmpl.ExecuteTemplate(w, "rpnCallOutRedirect", *m) } func getRpnOutByOrderId(order_id string) (ret RpnOut, err error) { if err = db.conn(Config); err != nil { return } defer db.close() q := "SELECT * FROM rpnOut WHERE order_id = ? ORDER BY id DESC LIMIT 1" err = db.h.QueryRow(q, order_id).Scan( &ret.Id, &ret.Leanwork, &ret.Version, &ret.Sign_type, &ret.Mid, &ret.Notify_url, &ret.Order_amount, &ret.Order_time, &ret.Order_id, &ret.User_id, &ret.User_name, &ret.User_cardno, &ret.Signature, &ret.Ip4, &ret.Ip4location, &ret.Ts) if err != nil { if err == sql.ErrNoRows { log.Println("trying to retrieve rpnOut(order_id=" + order_id + ") but not found") } else { log.Println("Error retrieving rpnOut(order_id=" + order_id + ") encountered : " + err.Error()) } } return }