| import ( | import ( | ||||
| "encoding/json" | "encoding/json" | ||||
| "fmt" | |||||
| "io/ioutil" | "io/ioutil" | ||||
| "log" | "log" | ||||
| ) | ) | ||||
| log.Fatal("cannot print back to json") | log.Fatal("cannot print back to json") | ||||
| return err | return err | ||||
| } | } | ||||
| fmt.Println(string(j)) | |||||
| log.Println(string(j)) | |||||
| return err | return err | ||||
| } | } |
| dbUser := c.DB.User | dbUser := c.DB.User | ||||
| dbPass := c.DB.Pass | dbPass := c.DB.Pass | ||||
| dbName := c.DB.Schema | dbName := c.DB.Schema | ||||
| h, err := sql.Open(dbDriver, dbUser+":"+dbPass+"@/"+dbName) | |||||
| h, err := sql.Open(dbDriver, dbUser+":"+dbPass+"@/"+dbName+"?parseTime=true") | |||||
| if err != nil { | if err != nil { | ||||
| m.h = nil | m.h = nil | ||||
| panic(err.Error()) | panic(err.Error()) |
| import ( | import ( | ||||
| "errors" | "errors" | ||||
| "github.com/go-sql-driver/mysql" | |||||
| "time" | |||||
| ) | ) | ||||
| type LeanworkRequest struct { | type LeanworkRequest struct { | ||||
| CustomerId string | CustomerId string | ||||
| Sign string | Sign string | ||||
| Valid bool | Valid bool | ||||
| Ts mysql.NullTime | |||||
| Ts time.Time | |||||
| Ip4 uint32 | Ip4 uint32 | ||||
| Ip4Location string | Ip4Location string | ||||
| } | } |
| package main | package main | ||||
| import ( | import ( | ||||
| "database/sql" | |||||
| "errors" | |||||
| "fmt" | "fmt" | ||||
| "log" | "log" | ||||
| "math" | |||||
| "net/http" | "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) { | |||||
| func rpnNotify(w http.ResponseWriter, r *http.Request) { | |||||
| if r.Method != "POST" { | |||||
| errPage(w, http.StatusMethodNotAllowed, "invalid request") | |||||
| return | |||||
| } | |||||
| ri, err := GetRpnInFromHTTPRequest(r) //ParseForm called | |||||
| if err != nil { | |||||
| errPage(w, http.StatusBadRequest, "invalid parameters") | |||||
| return | |||||
| } | |||||
| if _, ok := form[key]; ok { | |||||
| r = form[key][0] | |||||
| err = nil | |||||
| } else { | |||||
| r = "" | |||||
| err = errors.New("Key [" + key + "] not found in HTTP request") | |||||
| ro, _ := getRpnOutByOrderId(ri.Order_id) | |||||
| ri.Leanwork = ro.Leanwork | |||||
| ri1, err := ri.add2db() //TODO:check error add | |||||
| if err != nil { | |||||
| log.Printf("failed to add rpnIn %+v , error is %s", ri, err.Error()) | |||||
| } | } | ||||
| return r, err | |||||
| } | |||||
| func rpnNotify(w http.ResponseWriter, r *http.Request) { | |||||
| fmt.Fprint(w, "ok notify") | |||||
| fmt.Fprintf(w, "[SUCCESS]") | |||||
| return | |||||
| } | } | ||||
| //receive RPN user name and card number | //receive RPN user name and card number | ||||
| //build rpn redirect page and send it | //build rpn redirect page and send it | ||||
| ro.sendRedirect(w, row) | 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 | |||||
| } |
| import ( | import ( | ||||
| "database/sql" | "database/sql" | ||||
| "errors" | |||||
| "log" | "log" | ||||
| "net/http" | |||||
| "strconv" | "strconv" | ||||
| "github.com/go-sql-driver/mysql" | |||||
| "time" | |||||
| ) | ) | ||||
| type RpnIn struct { | type RpnIn struct { | ||||
| Pay_amount string | Pay_amount string | ||||
| Pay_result string | Pay_result string | ||||
| Signature string | Signature string | ||||
| Ts mysql.NullTime | |||||
| Ts time.Time | |||||
| Ip4 uint32 | |||||
| } | } | ||||
| //get given RpnIn record based on ID | //get given RpnIn record based on ID | ||||
| &ret.Id, &ret.Leanwork, &ret.Order_id, | &ret.Id, &ret.Leanwork, &ret.Order_id, | ||||
| &ret.Order_time, &ret.Order_amount, &ret.Deal_id, | &ret.Order_time, &ret.Order_amount, &ret.Deal_id, | ||||
| &ret.Deal_time, &ret.Pay_amount, &ret.Pay_result, | &ret.Deal_time, &ret.Pay_amount, &ret.Pay_result, | ||||
| &ret.Signature, &ret.Ts) | |||||
| &ret.Signature, &ret.Ts, &ret.Ip4) | |||||
| if err != nil { | if err != nil { | ||||
| if err == sql.ErrNoRows { | if err == sql.ErrNoRows { | ||||
| log.Println("trying to retrieve rpnIn(" + strconv.FormatInt(id, 10) + ") but not found") | log.Println("trying to retrieve rpnIn(" + strconv.FormatInt(id, 10) + ") but not found") | ||||
| } | } | ||||
| //add to database | //add to database | ||||
| func (m *RpnIn) add() (ret RpnIn, err error) { | |||||
| func (m *RpnIn) add2db() (ret RpnIn, err error) { | |||||
| if err = db.conn(Config); err != nil { | if err = db.conn(Config); err != nil { | ||||
| return | return | ||||
| } | } | ||||
| defer db.close() | defer db.close() | ||||
| q := `"INSERT INTO rpnIn( | |||||
| q := `INSERT INTO rpnIn( | |||||
| leanwork, order_id, order_time, order_amount, deal_id, | leanwork, order_id, order_time, order_amount, deal_id, | ||||
| deal_time, pay_amount, pay_result, signature) | deal_time, pay_amount, pay_result, signature) | ||||
| VALUES(?,?,?,?,?,?,?,?,?) | VALUES(?,?,?,?,?,?,?,?,?) | ||||
| ` | ` | ||||
| insForm, err := db.h.Prepare(q) | insForm, err := db.h.Prepare(q) | ||||
| if err != nil { | if err != nil { | ||||
| log.Printf("Failed to prepare SQL statment for insert") | |||||
| log.Printf("Failed to prepare SQL statment for insert " + err.Error()) | |||||
| return | return | ||||
| } | } | ||||
| res, err := insForm.Exec( | res, err := insForm.Exec( | ||||
| m.Leanwork, m.Order_id, m.Order_time, m.Order_amount, m.Deal_id, | m.Leanwork, m.Order_id, m.Order_time, m.Order_amount, m.Deal_id, | ||||
| m.Deal_time, m.Pay_amount, m.Pay_result, m.Signature) | m.Deal_time, m.Pay_amount, m.Pay_result, m.Signature) | ||||
| if err != nil { | if err != nil { | ||||
| log.Printf("Error inserting rpnIn with orderNo =%s \n", m.Order_id) | |||||
| log.Printf("Error inserting rpnIn with orderNo =%s, %s \n", m.Order_id, err.Error()) | |||||
| return | return | ||||
| } | } | ||||
| id, err := res.LastInsertId() | id, err := res.LastInsertId() | ||||
| return | return | ||||
| } | } | ||||
| return getRpnInById(id) | |||||
| ret, err = getRpnInById(id) | |||||
| if err == nil { | |||||
| *m = ret | |||||
| } | |||||
| return | |||||
| } | } | ||||
| func (m *RpnIn) signature() string { | func (m *RpnIn) signature() string { | ||||
| s += "|deal_time=" + m.Deal_time | s += "|deal_time=" + m.Deal_time | ||||
| s += "|pay_amount=" + m.Pay_amount | s += "|pay_amount=" + m.Pay_amount | ||||
| s += "|pay_result=" + m.Pay_result | s += "|pay_result=" + m.Pay_result | ||||
| s += "|key=" + m.md5key() | |||||
| return md5str(s) | |||||
| } | |||||
| func (m *RpnIn) md5key() string { | |||||
| if m.Order_id == "" { | |||||
| return "" | |||||
| } | |||||
| ro, err := getRpnOutByOrderId(m.Order_id) | |||||
| if err != nil { | |||||
| log.Println("Cannot get RpnOut by order_id=" + m.Order_id) | |||||
| return "" | |||||
| } | |||||
| return ro.getMD5Key() | |||||
| } | |||||
| return s | |||||
| func GetRpnInFromHTTPRequest(r *http.Request) (ret RpnIn, err error) { | |||||
| r.ParseForm() | |||||
| ret.Order_id = r.FormValue("order_id") | |||||
| ret.Order_time = r.FormValue("order_time") | |||||
| ret.Order_amount = r.FormValue("order_amount") | |||||
| ret.Deal_id = r.FormValue("deal_id") | |||||
| ret.Deal_time = r.FormValue("deal_time") | |||||
| ret.Pay_amount = r.FormValue("pay_amount") | |||||
| ret.Pay_result = r.FormValue("pay_result") | |||||
| ret.Signature = r.FormValue("signature") | |||||
| ret.Ip4 = getClientIPLong(r) | |||||
| ret.Ts = time.Now() | |||||
| if ret.Order_id == "" { | |||||
| err = errors.New("Invalid OrderId for RpnIn") | |||||
| return | |||||
| } | |||||
| ro, err := getRpnOutByOrderId(ret.Order_id) | |||||
| if err != nil || ro.Order_id != ret.Order_id { | |||||
| log.Println("Cannot get RpnOut by order_id=" + ret.Order_id) | |||||
| return | |||||
| } | |||||
| if ret.Signature != ret.signature() { | |||||
| log.Println("Invalid RpnIn Signature") | |||||
| err = errors.New("Invalid signauture for RpnIn") | |||||
| return | |||||
| } | |||||
| return | |||||
| } | } |
| package main | |||||
| import ( | |||||
| "io/ioutil" | |||||
| "net/http" | |||||
| "net/url" | |||||
| "testing" | |||||
| "time" | |||||
| ) | |||||
| func TestRpnInCall(t *testing.T) { | |||||
| form := url.Values{} | |||||
| ri := RpnIn{} | |||||
| ri.Order_id = "200310160057TW002184000000000001" | |||||
| ri.Order_time = time.Now().Format("20060102150405") | |||||
| ri.Order_amount = "120000" | |||||
| ri.Deal_id = "deal_id_demo_01" | |||||
| ri.Deal_time = time.Now().Format("20060102150405") | |||||
| ri.Pay_amount = "120000" | |||||
| ri.Pay_result = "3" //3 success, 1 processing | |||||
| ri.Signature = ri.signature() | |||||
| form.Set("order_id", ri.Order_id) | |||||
| form.Set("order_time", ri.Order_time) | |||||
| form.Set("order_amount", ri.Order_amount) | |||||
| form.Set("deal_id", ri.Deal_id) | |||||
| form.Set("deal_time", ri.Deal_time) | |||||
| form.Set("pay_amount", ri.Pay_amount) | |||||
| form.Set("pay_result", ri.Pay_result) | |||||
| form.Set("signature", ri.Signature) | |||||
| resp, err := http.PostForm(Config.Rpn.UrlCallBack, form) | |||||
| if err != nil { | |||||
| t.Error("response should have no error") | |||||
| } | |||||
| defer resp.Body.Close() | |||||
| if resp.StatusCode != http.StatusOK { | |||||
| t.Error("response should be OK 200") | |||||
| } | |||||
| bodyBytes, err := ioutil.ReadAll(resp.Body) | |||||
| if err != nil { | |||||
| t.Error("response Body cannot be read") | |||||
| } | |||||
| bodyString := string(bodyBytes) | |||||
| if bodyString != "[SUCCESS]" { | |||||
| t.Error("we expect [SUCCESS] but we received:" + bodyString) | |||||
| } | |||||
| } |
| package main | |||||
| import ( | |||||
| "database/sql" | |||||
| "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 | |||||
| } | |||||
| 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") | |||||
| } | |||||
| //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 (m *RpnOut) sendRedirect(w http.ResponseWriter, row LeanworkRequest) { | |||||
| //execute redirect | |||||
| m.Url = Config.Rpn.Url | |||||
| tmpl.ExecuteTemplate(w, "rpnCallOutRedirect", *m) | |||||
| } | |||||
| func (m *RpnOut) getMD5Key() string { | |||||
| if m.Mid == Config.Rpn.MIDP2P { | |||||
| return Config.Rpn.MD5P2P | |||||
| } else if m.Mid == Config.Rpn.MD5FAT { | |||||
| return Config.Rpn.MD5FAT | |||||
| } else { | |||||
| return "" | |||||
| } | |||||
| } | |||||
| 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 | |||||
| } |