| {"files":{"dashboard.html":{"frameworks":["form","pg.insight.events","pg.css.grid","pg.image.overlay","pg.code-validator","pg.project.items","pg.asset.manager","bs4","pg.html","pg.components"],"last_page_width":1024},"index.html":{"frameworks":["PG","pg.insight.events","pg.asset.manager","pg.project.items","pg.css.grid","pg.code-validator","pg.image.overlay","bs4","pg.html","pg.components"],"last_page_width":1024},"rpnAskNameAndCard.html":{"frameworks":["PG","pg.insight.events","pg.asset.manager","pg.css.grid","pg.project.items","pg.image.overlay","pg.code-validator","bs4","pg.html","pg.components"],"last_page_width":1024},"error.html":{"frameworks":["PG","pg.insight.events","pg.css.grid","pg.image.overlay","pg.code-validator","pg.project.items","pg.asset.manager","bs4","pg.html","pg.components"],"last_page_width":1024},"StartPay.html":{"frameworks":["PG","pg.insight.events","pg.asset.manager","pg.project.items","pg.code-validator","pg.css.grid","pg.image.overlay","bs4","pg.html","pg.components"],"last_page_width":1024}},"breakpoints":["576px","768px","992px","1200px"],"frameworks":["PG","pg.insight.events","pg.css.grid","pg.image.overlay","pg.code-validator","pg.project.items","pg.asset.manager","bs4","pg.html","pg.components"],"template_framework_id":"bootstrap"} | |||||
| {"files":{"dashboard.html":{"frameworks":["form","pg.insight.events","pg.css.grid","pg.image.overlay","pg.code-validator","pg.project.items","pg.asset.manager","bs4","pg.html","pg.components"],"last_page_width":1024},"index.html":{"frameworks":["PG","pg.insight.events","pg.asset.manager","pg.project.items","pg.css.grid","pg.code-validator","pg.image.overlay","bs4","pg.html","pg.components"],"last_page_width":1024},"rpnAskNameAndCard.html":{"frameworks":["PG","pg.insight.events","pg.asset.manager","pg.css.grid","pg.project.items","pg.image.overlay","pg.code-validator","bs4","pg.html","pg.components"],"last_page_width":1024},"error.html":{"frameworks":["PG","pg.insight.events","pg.css.grid","pg.image.overlay","pg.code-validator","pg.project.items","pg.asset.manager","bs4","pg.html","pg.components"],"last_page_width":1024},"StartPay.html":{"frameworks":["PG","pg.insight.events","pg.asset.manager","pg.project.items","pg.code-validator","pg.css.grid","pg.image.overlay","bs4","pg.html","pg.components"],"last_page_width":1024}},"breakpoints":["576px","768px","992px","1200px"],"frameworks":["PG","pg.insight.events","pg.asset.manager","pg.css.grid","pg.project.items","pg.image.overlay","pg.code-validator","bs4","pg.html","pg.components"],"template_framework_id":"bootstrap"} |
| <p class="card-text">转帐之前,请预留您的卡号和姓名,转帐单将会核对没一笔交易,卡号</p> | <p class="card-text">转帐之前,请预留您的卡号和姓名,转帐单将会核对没一笔交易,卡号</p> | ||||
| <div class="alert alert-primary" role="alert">出账的卡号和姓名必须和网银转帐的信息一致,否则将会极大的延迟转帐时间和过程</div> | <div class="alert alert-primary" role="alert">出账的卡号和姓名必须和网银转帐的信息一致,否则将会极大的延迟转帐时间和过程</div> | ||||
| <form method="POST" action="/rpnNameAndCard"> | <form method="POST" action="/rpnNameAndCard"> | ||||
| <input type="hidden" name="id" value="{{.Id}}"/> | |||||
| <input type="hidden" name="sign" value="{{.Sign}}"/> | |||||
| <input type="hidden" name="rpnType" value="{{.RpnType}}"/> | |||||
| <input type="hidden" name="id" value="{{.Id}}"> | |||||
| <input type="hidden" name="sign" value="{{.Sign}}"> | |||||
| <input type="hidden" name="rpnType" value="{{.RpnType}}"> | |||||
| <div class="form-group"> | <div class="form-group"> | ||||
| <label for="formGroupExampleInput">您即将使用的银行卡号</label> | |||||
| <label for="formGroupExampleInput">转出账户卡号</label> | |||||
| <input type="text" class="form-control" id="formGroupExampleInput" name="card" placeholder="6212262002002377849"> | <input type="text" class="form-control" id="formGroupExampleInput" name="card" placeholder="6212262002002377849"> | ||||
| </div> | </div> | ||||
| <div class="form-group"> | |||||
| <label for="formGroupExampleInput2">上述银行卡,持卡人姓名</label> | |||||
| <div class="form-group">转出账户姓名 | |||||
| <br> | |||||
| <input type="text" class="form-control" id="formGroupExampleInput2" name="name" placeholder="王建林"> | <input type="text" class="form-control" id="formGroupExampleInput2" name="name" placeholder="王建林"> | ||||
| </div> | </div> | ||||
| <input type="submit" class="btn btn-primary btn-lg btn-block" style="margin-top: 50px;" value="下一步"/> | |||||
| <input type="submit" class="btn btn-primary btn-lg btn-block" style="margin-top: 50px;" value="下一步"> | |||||
| </form> | </form> | ||||
| </div> | </div> | ||||
| </div> | </div> |
| type AppConfig struct { | type AppConfig struct { | ||||
| Rpn struct { | Rpn struct { | ||||
| Url string `json:Url` | |||||
| UrlTest string `json:UrlTest` | |||||
| MD5P2P string `json:MD5P2P` | |||||
| MD5FAT string `json:MD5FAT` | |||||
| MIDP2P string `json:MIDP2P` | |||||
| MIDFAT string `json:MIDFAT` | |||||
| Url string `json:Url` | |||||
| UrlTest string `json:UrlTest` | |||||
| MD5P2P string `json:MD5P2P` | |||||
| MD5FAT string `json:MD5FAT` | |||||
| MIDP2P string `json:MIDP2P` | |||||
| MIDFAT string `json:MIDFAT` | |||||
| UrlCallBack string `json:UrlCallBack` | |||||
| } `json:Rpn` | } `json:Rpn` | ||||
| LeanWork struct { | LeanWork struct { | ||||
| MD5Key string `json:MD5Key` | MD5Key string `json:MD5Key` |
| "MIDP2P": "EU85201311P2P", | "MIDP2P": "EU85201311P2P", | ||||
| "MD5P2P": "p1j4A3mEMj+ft0xkSfVULQ", | "MD5P2P": "p1j4A3mEMj+ft0xkSfVULQ", | ||||
| "MIDFAT": "EU85201311FAT", | "MIDFAT": "EU85201311FAT", | ||||
| "MD5FAT": "24QSfwYtH+tbefkMFPhuew" | |||||
| "MD5FAT": "24QSfwYtH+tbefkMFPhuew", | |||||
| "UrlCallBack": "http://rpn.supertraderfx.ayvwd8em49pvoa3g.com/rpn_notify" | |||||
| }, | }, | ||||
| "LeanWork": { | "LeanWork": { | ||||
| "MD5Key": "492815086935204", | "MD5Key": "492815086935204", |
| "MIDP2P": "EU85201311P2P", | "MIDP2P": "EU85201311P2P", | ||||
| "MD5P2P": "p1j4A3mEMj+ft0xkSfVULQ", | "MD5P2P": "p1j4A3mEMj+ft0xkSfVULQ", | ||||
| "MIDFAT": "EU85201311FAT", | "MIDFAT": "EU85201311FAT", | ||||
| "MD5FAT": "24QSfwYtH+tbefkMFPhuew" | |||||
| "MD5FAT": "24QSfwYtH+tbefkMFPhuew", | |||||
| "UrlCallBack": "http://debug.biukop.com:8080/rpn_notify" | |||||
| }, | }, | ||||
| "LeanWork": { | "LeanWork": { | ||||
| "MD5Key": "492815086935204", | "MD5Key": "492815086935204", |
| var db TransactionDB | var db TransactionDB | ||||
| func (m *TransactionDB) conn(c AppConfig) error { | func (m *TransactionDB) conn(c AppConfig) error { | ||||
| if m.h != nil { | |||||
| return nil //already connected, prevent multiple connection | |||||
| } | |||||
| dbDriver := c.DB.Driver | dbDriver := c.DB.Driver | ||||
| 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) | ||||
| if err != nil { | if err != nil { | ||||
| m.h = nil | |||||
| panic(err.Error()) | panic(err.Error()) | ||||
| } | } | ||||
| m.h = h | m.h = h | ||||
| } | } | ||||
| func (m *TransactionDB) close() { | func (m *TransactionDB) close() { | ||||
| defer m.h.Close() | |||||
| if m.h != nil { | |||||
| m.h.Close() | |||||
| } | |||||
| m.h = nil //clear it, very important to prevent multiple opening | |||||
| } | } | ||||
| func (m *TransactionDB) addRequest(r *http.Request) (row LeanworkRequest, err error) { | func (m *TransactionDB) addRequest(r *http.Request) (row LeanworkRequest, err error) { | ||||
| return row, err | return row, err | ||||
| } | } | ||||
| func (m *TransactionDB) addRpnOut(r RpnReq) error { | |||||
| return nil | |||||
| func (m *TransactionDB) addRpnOut(r RpnReq) (row RpnReq, err error) { | |||||
| if err = m.conn(Config); err != nil { | |||||
| return row, err | |||||
| } | |||||
| defer m.close() | |||||
| sql := `INSERT INTO rpnOut | |||||
| (order_id, version, sign_type, mid, notify_url, order_amount, order_time, | |||||
| user_id, user_name, user_cardno, signature, leanwork, ip4 ) | |||||
| VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)` | |||||
| insForm, err := m.h.Prepare(sql) | |||||
| if err != nil { | |||||
| log.Println("cannot insert RpnOut record, sql prepare failed " + err.Error()) | |||||
| return | |||||
| } | |||||
| order_id := r.Order_id | |||||
| version := r.Version | |||||
| sign_type := r.Sign_type | |||||
| mid := r.Mid | |||||
| notify_url := r.Notify_url | |||||
| order_amount := r.Order_amount | |||||
| order_time := r.Order_time | |||||
| user_id := r.User_id | |||||
| user_name := r.User_name | |||||
| user_cardno := r.User_cardno | |||||
| signature := r.Signature | |||||
| leanwork := r.Leanwork | |||||
| ip4 := r.Ip4 | |||||
| res, err := insForm.Exec(order_id, version, sign_type, mid, notify_url, order_amount, order_time, | |||||
| user_id, user_name, user_cardno, signature, leanwork, ip4) | |||||
| if err != nil { | |||||
| log.Println("Failed to execute sql statment for insert RpnOut order_id=" + r.Order_id + " " + err.Error()) | |||||
| return | |||||
| } | |||||
| id, err := res.LastInsertId() | |||||
| if err != nil { | |||||
| log.Println("Cannot get last insert ID with new RpnOut record") | |||||
| return | |||||
| } | |||||
| row = r | |||||
| row.Id = id | |||||
| return row, err | |||||
| } | } | ||||
| func (m *TransactionDB) updateRpnOutNameAndCard(orderid string, signature string, name string, card string) (row RpnReq, err error) { | func (m *TransactionDB) updateRpnOutNameAndCard(orderid string, signature string, name string, card string) (row RpnReq, err error) { |
| func main() { | func main() { | ||||
| //readConfig() | //readConfig() | ||||
| readConfigForTest() | readConfigForTest() | ||||
| db.h = nil //make sure it's in proper state. | |||||
| http.HandleFunc("/choosePayment", choosePayment) | http.HandleFunc("/choosePayment", choosePayment) | ||||
| http.HandleFunc("/rpnNameAndCard", rpnNameAndCard) | http.HandleFunc("/rpnNameAndCard", rpnNameAndCard) |
| "net/url" | "net/url" | ||||
| "strconv" | "strconv" | ||||
| "time" | "time" | ||||
| "github.com/go-sql-driver/mysql" | |||||
| ) | ) | ||||
| // var url = "https://deposit.paylomo.net/pay.php?r=payEasy" //production | |||||
| // var url = "https://deposit-mac.chinapaytech.com/pay.php?r=payEasy" //test | |||||
| // var md5p2p = "370296119874502" | |||||
| // var md5fat = "207841502473198" | |||||
| type RpnReq struct { | type RpnReq struct { | ||||
| Order_id string | |||||
| Version string | Version string | ||||
| Sign_type string | Sign_type string | ||||
| Mid string | Mid string | ||||
| Notify_url string | Notify_url string | ||||
| Order_id string | |||||
| Order_amount string | Order_amount string | ||||
| Order_time string //YYYYMMDDHHMMSS | Order_time string //YYYYMMDDHHMMSS | ||||
| User_id string | User_id string | ||||
| User_name string | User_name string | ||||
| User_cardno string | User_cardno string | ||||
| Signature string | Signature string | ||||
| Url string //where to post entire data structure | |||||
| //template | |||||
| Url string //where to post entire data structure | |||||
| //database specific | |||||
| Id int64 | |||||
| Leanwork int64 | |||||
| Callback int64 | |||||
| Ip4 uint32 | |||||
| Ip4location string | |||||
| Ts mysql.NullTime | |||||
| } | } | ||||
| // //build request from leanwork request forms | // //build request from leanwork request forms | ||||
| // } | // } | ||||
| func (m *RpnReq) buildReqByLeanworkRequestP2P(row LeanworkRequest, user_name string, user_cardno string) RpnReq { | func (m *RpnReq) buildReqByLeanworkRequestP2P(row LeanworkRequest, user_name string, user_cardno string) RpnReq { | ||||
| r := RpnReq{} | |||||
| r.Version = "1.1" | |||||
| r.Sign_type = "MD5" | |||||
| r.Mid = Config.Rpn.MIDP2P | |||||
| r.Notify_url = "http://rpn.supertraderfx.ayvwd8em49pvoa3g.com/rpn_notify" | |||||
| r.Order_id = row.OrderNo | |||||
| r.Order_amount = m.translateAmountFromLeanwork(row.OrderAmount) | |||||
| r.Order_time = m.now() | |||||
| r.User_id = row.CustomerId | |||||
| r.User_name = user_name | |||||
| r.User_cardno = user_cardno | |||||
| r.Signature = md5RpnFormP2P(r) | |||||
| *m = r | |||||
| return r | |||||
| 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 *RpnReq) buildReqByLeanworkRequestFAT(row LeanworkRequest, user_name string, user_cardno string) RpnReq { | func (m *RpnReq) buildReqByLeanworkRequestFAT(row LeanworkRequest, user_name string, user_cardno string) RpnReq { | ||||
| r := RpnReq{} | |||||
| r.Version = "1.1" | |||||
| r.Sign_type = "MD5" | |||||
| r.Mid = Config.Rpn.MIDFAT | |||||
| r.Notify_url = "http://rpn.supertraderfx.ayvwd8em49pvoa3g.com/rpn_notify" | |||||
| r.Order_id = row.OrderNo | |||||
| r.Order_amount = m.translateAmountFromLeanwork(row.OrderAmount) | |||||
| r.Order_time = m.now() | |||||
| r.User_id = row.CustomerId | |||||
| r.User_name = user_name | |||||
| r.User_cardno = user_cardno | |||||
| r.Signature = md5RpnFormFAT(r) | |||||
| *m = r | |||||
| return r | |||||
| 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 | //from 0.1 to 10 cents | ||||
| return r, err | return r, err | ||||
| } | } | ||||
| func rpnNotify(w http.ResponseWriter, r *http.Request) { | func rpnNotify(w http.ResponseWriter, r *http.Request) { | ||||
| fmt.Fprint(w, "ok notify") | |||||
| } | } | ||||
| //receive RPN user name and card number | //receive RPN user name and card number | ||||
| } | } | ||||
| ro := RpnReq{} | ro := RpnReq{} | ||||
| ro.Ip4 = getClientIPLong(r) | |||||
| ro.Leanwork = row.Id | |||||
| if rpn_type == "rpnp2p" { | if rpn_type == "rpnp2p" { | ||||
| ro.buildReqByLeanworkRequestP2P(row, user_name, user_card) | ro.buildReqByLeanworkRequestP2P(row, user_name, user_card) | ||||
| } else { | } else { | ||||
| ro.buildReqByLeanworkRequestFAT(row, user_name, user_card) | ro.buildReqByLeanworkRequestFAT(row, user_name, user_card) | ||||
| } | } | ||||
| //create db record | |||||
| db.addRpnOut(ro) | |||||
| //build rpn redirect page and send it | //build rpn redirect page and send it | ||||
| ro.sendRedirect(w, row) | ro.sendRedirect(w, row) | ||||
| } | } | ||||
| func (m *RpnReq) sendRedirect(w http.ResponseWriter, row LeanworkRequest) { | func (m *RpnReq) sendRedirect(w http.ResponseWriter, row LeanworkRequest) { | ||||
| //create db record | |||||
| //execute redirect | |||||
| m.Url = Config.Rpn.Url | m.Url = Config.Rpn.Url | ||||
| tmpl.ExecuteTemplate(w, "rpnCallOutRedirect", *m) | tmpl.ExecuteTemplate(w, "rpnCallOutRedirect", *m) | ||||
| } | } |