├── .gitignore ├── README.md ├── client.go ├── corrlist.go ├── examples ├── x1.go ├── x10.go ├── x11.go ├── x13.go ├── x14.go ├── x15.go ├── x16.go ├── x18.go ├── x2.go ├── x20.go ├── x21.go ├── x22.go ├── x23.go ├── x3.go ├── x4.go ├── x5.go ├── x6.go ├── x7.go ├── x8.go └── x9.go ├── go.mod ├── go.sum ├── helpers.go ├── helpers_test.go ├── interfaces.go ├── interfaces_test.go ├── merchant.go ├── tests ├── .x10_test.go ├── .x11_test.go ├── .x1_test.go ├── .x2_test.go ├── .x3_test.go ├── .x4_test.go ├── .x5_test.go ├── .x6_test.go ├── .x7_test.go ├── .x8_test.go ├── _x9_test.go └── x2_test.go ├── w3s.go ├── wmsigner ├── README.md └── wmsigner.go ├── wmstring.go ├── x1.go ├── x10.go ├── x11.go ├── x13.go ├── x14.go ├── x15.go ├── x16.go ├── x18.go ├── x19.go ├── x2.go ├── x20.go ├── x21.go ├── x22.go ├── x23.go ├── x3.go ├── x4.go ├── x5.go ├── x6.go ├── x7.go ├── x8.go └── x9.go /.gitignore: -------------------------------------------------------------------------------- 1 | /cert 2 | /tests/config* 3 | *.toml 4 | .idea 5 | *conf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | go-webmoney 2 | 3 | # Requirements 4 | 5 | * Go1.7 6 | 7 | ABOUT 8 | ------ 9 | XML interfaces are basically text message interfaces that send data via HTTPS protocol (http over 128-bit SSL) to special certification web servers of the system. Data is sent in the XML format with help of special module for authentication of WebMoney Keeper key files or standard certificates (WM Keeper WebPro certificates). 10 | [Detail](http://wiki.wmtransfer.com/projects/webmoney/wiki/XML-interfaces) 11 | 12 | # Install 13 | ```go 14 | package main 15 | 16 | import "github.com/C0nstantin/go-webmoney" 17 | //... 18 | ``` 19 | 20 | How Use 21 | ------- 22 | 23 | # WinPro Client (Classic) 24 | ```go 25 | var CnfClassic = struct { 26 | Wmid string 27 | Key string 28 | Pass string 29 | }{ 30 | `000000000000`, //service wmid 31 | `---key in base64 string---`, 32 | `password for key`, 33 | } 34 | 35 | wmCl := webmoney.WmClient{ 36 | Wmid: CnfClassic.Wmid, 37 | Key: CnfClassic.Key, 38 | Pass: CnfClassic.Pass, 39 | } 40 | 41 | ``` 42 | # WebPro Client (Light) 43 | ```go 44 | var CnfLight = struct{ 45 | Wmid string 46 | Cert string 47 | Key string 48 | }{ 49 | `000000000000`, //service wmid 50 | "/path/to/cert/file.pem", 51 | `/path/to/key/file.key`, 52 | 53 | } 54 | 55 | wmCl := webmoney.WmClient{ 56 | Wmid: CnfLight.Wmid, 57 | Cert: CnfLight.Cert, 58 | Key: CnfLight.Key, 59 | } 60 | 61 | ``` 62 | #WM Signer 63 | 64 | ```go 65 | func main(){ 66 | str := "source string" 67 | signer := wmsigner.NewSigner("wmid","password","key_string") 68 | sign_str,err := signer.Sign(str) 69 | if(err != nil) { 70 | // do something if error}) 71 | } 72 | 73 | //use sign_str 74 | ``` 75 | 76 | 77 | # Webmoney XML Interfaces 78 | 79 | ##X1 Sending Invoice from merchant to customer 80 | 81 | [Detail Desctiption Interface](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X1) 82 | ```go 83 | invoice := webmoney.Invoice{ 84 | OrderId: "10", 85 | CustomerWmid: "000000000000", //cutomer wmid 86 | StorePurse: "R123456789098", //store purse 87 | Amount: "3.2", 88 | Desc: "description invoice", 89 | Address: "Address for delivery", 90 | Period: "1", 91 | Expiration: "1", 92 | OnlyAuth: "0", 93 | } 94 | result, err := wmCl.SendInvoice(invoice) 95 | /* 96 | result implements type: 97 | type InvoiceResponse struct { 98 | Id string `xml:"id,attr"` 99 | Ts string `xml:"ts,attr"` 100 | OrderId string `xml:"orderid"` 101 | CustomerWmid string `xml:"customerwmid"` 102 | StorePurse string `xml:"storepurse"` 103 | Amount string `xml:"amount"` 104 | Desc string `xml:"desc"` 105 | Address string `xml:"address"` 106 | Period string `xml:"period"` 107 | Expiration string `xml:"expiration"` 108 | State string `xml:"state"` 109 | DateCrt string `xml:"datecrt"` 110 | DateUpd string `xml:"dateupd"` 111 | WmTranId string `xml:"wmtranid"` 112 | } 113 | 114 | */ 115 | 116 | ``` 117 | ## X2 Transferring funds from one purse to another. 118 | This interface is available for registered members only and can be used for making 119 | transfers from purses of any WM Keeper, including Budget Automates. 120 | **The option can be enabled at the Web Merchant Interface service settings page in the "additional parameters" section. 121 | Enabling this option you undertake to use the "trans" nlyauth = 1" parameter. 122 | The Keeper that signs requests should have Personal passport. "** 123 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X2) 124 | ```go 125 | transaction := webmoney.Transaction{ 126 | TranId: "1001", 127 | PurseDest: "R000000000000", 128 | PurseSrc: "R111111111111", 129 | Amount: "3.2", 130 | Period: "1", 131 | Desc: "Теst кирилица", 132 | PCode: "", 133 | WmInvid: "0", 134 | OnlyAuth: "1", 135 | } 136 | 137 | result, err := wmClientClassic.CreateTransaction(transaction) 138 | /* 139 | result implements: 140 | 141 | type Operation struct { 142 | XMLName xml.Name `xml:operation` 143 | Id string `xml:"id,attr"` 144 | Ts string `xml:"ts,attr"` 145 | TranId string `xml:"tranid"` 146 | PurseSrc string `xml:"pursesrc"` 147 | PurseDest string `xml:"pursedest"` 148 | Amount string `xml:"amount"` 149 | Commis string `xml:"comiss"` 150 | Opertype string `xml:"opertype"` 151 | Period string `xml:"period"` 152 | WmInvid string `xml:"wminvid"` 153 | Desc string `xml:"desc"` 154 | DateCrt string `xml:"datecrt"` 155 | DateUpd string `xml:"dateupd"` 156 | CorrWm string `xml:"corrwm"` 157 | Rest string `xml:"rest"` 158 | TimeLock bool `xml:timelock` 159 | } 160 | */ 161 | ``` 162 | ## x3 Receiving the History of Transactions; checking Transaction status 163 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X3) 164 | ```go 165 | opts := webmoney.GetOpers{ 166 | TranId: "10",// optional 167 | Purse: "R11111111111", 168 | DateStart: "20160726 00:00:00", 169 | DateFinish: "20160721 00:00:00", 170 | } 171 | result, err := wmCl.GetOperations(opts) 172 | /* 173 | result implements 174 | type Operations struct { 175 | XMLName xml.Name `xml:"operations"` 176 | OperationList []Operation `xml:"operation"` // x1 collection 177 | } 178 | */ 179 | ``` 180 | ## x4 Receiving the history of issued invoices. Verifying whether invoices were paid 181 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X4) 182 | 183 | ```go 184 | invoices := webmoney.OutInvoices{ 185 | Purse: "R111111111111", 186 | DateStart: "20160622 00:00:00", 187 | DateFinish: "20160927 00:00:00", 188 | } 189 | result, err := wmCl.GetOutInvoices(invoices) 190 | /* 191 | result implements 192 | 193 | type OutInvoicesResp struct { 194 | XMLName xml.Name `xml:"outinvoices"` 195 | InvoiceList []InvoiceResponse `xml:"outinvoice"` //x1 196 | } 197 | */ 198 | ``` 199 | ## x5 Completing a code-protected transaction. Entering a protection code 200 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X5) 201 | ```go 202 | //create transactionf with pcode 203 | 204 | wmCl := webmoney.WmClient{ 205 | Wmid: CnfClassic.Wmid, 206 | Key: CnfClassic.Wmid_key, 207 | Pass: CnfClassic.Wmid_pass, 208 | } 209 | pcode := "testtest" 210 | tt := webmoney.Transaction{ 211 | TranId: "1999", 212 | PurseDest: "R000000000000", 213 | PurseSrc: "R222222222222", 214 | Amount: "3.2", 215 | Period: "1", 216 | Desc: "Desc for test", 217 | WmInvid: "0", 218 | OnlyAuth: "1", 219 | PCode: pcode, 220 | } 221 | 222 | result, err := wmCl.CreateTransaction(tt) 223 | 224 | if err != nil { 225 | log.Fatal(err) 226 | } 227 | //registration second client 228 | wmClight := webmoney.WmClient{ 229 | Wmid: CnfLight.Wmid, 230 | Cert: CnfLight.Cert, 231 | Key: CnfLight.Key, 232 | } 233 | 234 | fp := webmoney.FinishProtect{ 235 | WmTranId: result.Ts, 236 | PCode: pcode, 237 | } 238 | //finishing transaction 239 | resultFinish, err := wmClight.DoFinishProtect(fp) 240 | /* resultFinish implements type Operation */ 241 | ``` 242 | ## x6 Sending message to random WM-identifier via internal mail 243 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X6) 244 | ```go 245 | 246 | wmMsg := webmoney.SendMsg{ 247 | ReceiverWmid: "00000000000", 248 | MsgSubj: "testClassic", 249 | MsgText: "Тест сообщения через Классик кирилица", 250 | } 251 | 252 | result, err := wmCl.SendMessage(wmMsg) 253 | /*result implements 254 | type SendMsgResponse struct { 255 | XMLName xml.Name `xml:"message"` 256 | MessageId int `xml:"id,attr"` 257 | ReceiverWmid string `xml:"receiverwmid"` 258 | MsgSubj string `xml:"msgsubj"` 259 | MsgText string `xml:"msgtext"` 260 | DateCrt string `xml:"datecrt"` 261 | } 262 | 263 | */ 264 | 265 | ``` 266 | 267 | ## x7 Verifying client’s handwritten signature – owner of WM Keeper WinPro 268 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X7) 269 | ```go 270 | signature := webmoney.TestSignRequest{ 271 | Wmid: "128756507061", 272 | Plan: "plantext", 273 | Sign: "signtext", 274 | } 275 | result, err := wmCl.TestSign(signature) 276 | /* 277 | result implements 278 | type TestSignResponse struct { 279 | XMLName xml.Name `xml:"testsign"` 280 | Res string `xml:"res"` 281 | } 282 | */ 283 | ``` 284 | 285 | ## x8 Retrieving information about purse ownership. Searching for system user by his/her identifier or purse 286 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X8) 287 | ```go 288 | 289 | testWm := webmoney.TestWmPurse{ 290 | Wmid: `000000000000`, 291 | } 292 | 293 | testPurse := webmoney.TestWmPurse{ 294 | Purse: `Z0000000000000`, 295 | } 296 | testWmidPurse := webmoney.TestWmPurse{ 297 | Wmid: `0000000000000`, 298 | Purse: `K000000000000`, 299 | } 300 | 301 | result, err := wmCl.FindWmidPurse(testWm) 302 | 303 | //OR 304 | 305 | result, err := wmCl.FindWmidPurse(testPurse) 306 | 307 | //OR 308 | 309 | result, err := wmCl.FindWmidPurse(testWmidPurse) 310 | /*result implements 311 | type TestWmPurseResponse struct { 312 | XMLName xml.Name `xml:"testwmpurse"` 313 | Wmid Wmid `xml:"wmid"` 314 | Purse ReturnedPurse `xml:"purse"` 315 | } 316 | type ReturnedPurse struct { 317 | XMLName xml.Name `xml:"purse"` 318 | Value string `xml:",chardata"` 319 | MerchantActiveMode string `xml:"merchant_active_mode,attr"` 320 | MerchantAllowCashier string `xml:"merchant_allow_cashier,attr"` 321 | } 322 | type Wmid struct { 323 | XMLName xml.Name `xml:"wmid"` 324 | Value string `xml:",chardata"` 325 | Available string `xml:"available,attr"` 326 | Themselfcorrstate string `xml:"themselfcorrstate,attr"` 327 | Newattst string `xml:"newattst,attr"` 328 | } 329 | */ 330 | ``` 331 | ## x9 Retrieving information about purse balance 332 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X9) 333 | ```go 334 | p := webmoney.Purses{ 335 | Wmid: CnfClassic.Wmid, 336 | } 337 | result, err := wmCl.GetPurses4Wmid(p) 338 | /*result implements 339 | type PursesResp struct { 340 | XMLName xml.Name `xml:"purses"` 341 | Cnt string `xml:"cnt,attr"` 342 | PurseList []RPurse `xml:"purses"` 343 | } 344 | 345 | type RPurse struct { 346 | XMLName xml.Name `xml:"purse"` 347 | PurseName string `xml:"pursename"` 348 | Amount string `xml:"amount"` 349 | Desc string `xml:"desc"` 350 | Outsideopen string `xml:"outsideopen"` 351 | LastIntr string `xml:"lastintr"` 352 | LastOuttr string `xml:"lastouttr"` 353 | } 354 | */ 355 | ``` 356 | 357 | ## x10 Retrieving list of invoices for payment 358 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X10) 359 | ```go 360 | i := webmoney.InInvoices { 361 | Wmid: CnfLight.Wmid, 362 | WmInvid: "0", 363 | DateStart: "20140101 00:00:00", 364 | DateFinish: "20160930 00:00:00", 365 | } 366 | result, err := wmCl.GetInInvoices(i) 367 | /*result implements 368 | type InInvoicesResponse struct { 369 | XMLName xml.Name `xml:"ininvoices"` 370 | InvoiceList []InvoiceResponse `xml:ininvoices` 371 | } 372 | 373 | */ 374 | ``` 375 | 376 | ## x11 Retrieving information from client’s passport by WM-identifier 377 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X11) 378 | ```go 379 | result, err := webmoney.GetInfoWmid(`128756507061`) 380 | ``` 381 | 382 | ## x13 Recalling incomplete protected transaction 383 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X13) 384 | ```go 385 | rp := RejectProtect { 386 | WmTranId: "111212", 387 | } 388 | result, err := WmCl.RejectProtect(rp) 389 | /*result implements type Operation*/ 390 | ``` 391 | 392 | ## x14 Fee-free refund 393 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X14) 394 | ```go 395 | tr := webmoney.Trans { 396 | InWmTranId:"234", 397 | Amount: "242", 398 | MoneyBackPhone:"925000000", 399 | } 400 | result,err := wmCl.MoneyBack(tr) 401 | /*result implements type Operation*/ 402 | 403 | ``` 404 | 405 | ## x15 Viewing and changing settings of “by trust” management 406 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X15) 407 | ```go 408 | 409 | //get trastlist 410 | tl := webmoney.Trustlist { 411 | Wmid:"000000000000", 412 | } 413 | result,err := wmCl.GetTrustList(tl) 414 | /* 415 | result implemenst 416 | 417 | type TrustListResponse struct { 418 | XMLName xml.Name `xml:"trustlist"` 419 | Cnt string `xml:"cnt,attr"` 420 | TrustList []Trust `xml:"trastlist"` 421 | } 422 | 423 | type Trust struct { 424 | XMLName xml.Name `xml:"trast"` 425 | Id string `xml:"id,attr"` 426 | Inv string `xml:"inv,attr"` 427 | Trast string `xml:"trans,attr"` 428 | PurseAttr string `xml:"purse,attr"` 429 | TransHist string `xml:"transhist"` 430 | Master string `xml:"master"` 431 | Purse string `xml:"purse"` 432 | DayLimit string `xml:"daylimit"` 433 | DLimit string `xml:"dlimit"` 434 | WLimit string `xml:"wlimit"` 435 | MLimit string `xml:"mlimit"` 436 | DSum string `xml:"dsum"` 437 | WSum string `xml:"wsum"` 438 | MSum string `xml:"msum"` 439 | LastSumDate string `xml:lastsumdate` 440 | } 441 | 442 | */ 443 | 444 | st := webmoney.TrastSave{ 445 | Inv: "", 446 | Trans:"", 447 | PurseAttr:"", 448 | TransHist:"", 449 | MasterWmid:"", 450 | SlaveWmid:"", 451 | Purse:"", 452 | Limit:"", 453 | DayLimit:"", 454 | WeekLimit:"", 455 | MonthLimit:"", 456 | } 457 | result,err := wmCl.SetTrast(st) 458 | /* result implements Trust */ 459 | 460 | ``` 461 | 462 | ## x16 Creating a purse 463 | [Detail Information](http://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X16) 464 | ```go 465 | p := webmoney.Purse{ 466 | Wmid:"111111111110", 467 | PurseType:"Z", 468 | Desc:"test", 469 | } 470 | result,error := wmCl.CreatePurese(p) 471 | /* 472 | result implements 473 | 474 | type PurseResponse struct { 475 | XMLName xml.Name `xml:"purse"` 476 | Id string `xml:"id,attr"` 477 | PurseName string `xml:"pursename"` 478 | Amount string `xml:"amount"` 479 | Desc string `xml:"desc"` 480 | } 481 | 482 | 483 | */ 484 | 485 | ``` 486 | 487 | 488 | ##x17-x23 489 | see examples file 490 | 491 | ## Custom domains 492 | If you need change urls for api requests please use this environment variables 493 | ```go 494 | //for merchant requests 495 | os.Setenv("MERCHANT_DOMAIN", "merchant.web.money") //merchant.web.money is a default value 496 | //if you use classic (winpro) auth 497 | os.Setenv("CLASSIC_DOMAIN", "w3s.webmoney.com") // w10s.web.money is a default value 498 | //if you use light (webpro) auth 499 | os.Setenv("LIGHT_DOMAIN", "w3s.webmoney.com") // w10s.web.money is a default value 500 | // for passport request 501 | os.Setenv("API_PASSPORT_DOMAIN", "apipassort.web.money") 502 | ``` 503 | -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Constantin Karataev. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // Package provides Webmoney xml interfaces 6 | // References 7 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/XML-interfaces 8 | // https://wiki.webmoney.ru/projects/webmoney/wiki/XML-%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81%D1%8B 9 | 10 | package webmoney 11 | 12 | import ( 13 | "crypto/tls" 14 | "crypto/x509" 15 | "io" 16 | "log" 17 | "net/http" 18 | "os" 19 | "strings" 20 | 21 | _ "github.com/paulrosania/go-charset/data" 22 | ) 23 | 24 | type WmClient struct { 25 | Wmid string 26 | Key string 27 | Pass string 28 | Cert string 29 | SecretKey string 30 | } 31 | 32 | // IsClassic function return true if current settings indicate 33 | // that request is signed classic key 34 | func (w *WmClient) IsClassic() bool { 35 | if w.Key != "" && w.Pass != "" { 36 | return true 37 | } else { 38 | return false 39 | } 40 | } 41 | 42 | // IsLight function return true if current settings indicate 43 | // that requests is signed light keeper 44 | func (w *WmClient) IsLight() bool { 45 | if w.Key != "" && w.Cert != "" { 46 | return true 47 | } else { 48 | return false 49 | } 50 | } 51 | 52 | // noInit check settings for connetion and sign not set 53 | // before start use you must set Wmid, Key and Pass for Keeper Classic(WinPro) 54 | // or wmid, key and cert for Keepr Light(WebPro) 55 | func (w *WmClient) noInit() bool { 56 | if w.Wmid == "" || w.Key == "" || w.Pass == "" { 57 | return true 58 | } else { 59 | return false 60 | } 61 | } 62 | 63 | // Function send requst to server and return response how string 64 | func (w *WmClient) sendRequest(url string, body string) (string, error) { 65 | var client *http.Client 66 | client = http.DefaultClient 67 | if os.Getenv("USE_W3S_CERT") != "" { 68 | tr, err := w.getTransport() 69 | if err != nil { 70 | return "", err 71 | } 72 | client.Transport = tr 73 | } 74 | 75 | resp, err := client.Post(url, "text/xml", strings.NewReader(body)) 76 | if err != nil { 77 | return "", err 78 | } 79 | 80 | defer func(Body io.ReadCloser) { 81 | err := Body.Close() 82 | if err != nil { 83 | log.Println(err) 84 | } 85 | }(resp.Body) 86 | result, err := io.ReadAll(resp.Body) 87 | if err != nil { 88 | return "", err 89 | } else { 90 | return string(result), nil 91 | } 92 | } 93 | 94 | func (w *WmClient) getTransport() (*http.Transport, error) { 95 | var tr *http.Transport 96 | // load root ca 97 | r := strings.NewReader(ROOT_CA) 98 | caCert, err := io.ReadAll(r) 99 | if err != nil { 100 | return nil, err 101 | } 102 | caCertPool := x509.NewCertPool() 103 | caCertPool.AppendCertsFromPEM(caCert) 104 | 105 | if w.IsClassic() { 106 | tr = &http.Transport{ 107 | TLSClientConfig: &tls.Config{ 108 | //RootCAs: caCertPool, 109 | Renegotiation: tls.RenegotiateFreelyAsClient, 110 | }, 111 | DisableCompression: true, 112 | } 113 | } else { 114 | 115 | cert, err := tls.LoadX509KeyPair(w.Cert, w.Key) 116 | if err != nil { 117 | return nil, err 118 | } 119 | tlsConfig := &tls.Config{ 120 | Certificates: []tls.Certificate{cert}, 121 | //RootCAs: caCertPool, 122 | Renegotiation: tls.RenegotiateFreelyAsClient, 123 | } 124 | tlsConfig.BuildNameToCertificate() 125 | 126 | tr = &http.Transport{ 127 | TLSClientConfig: tlsConfig, 128 | DisableCompression: true, 129 | } 130 | } 131 | return tr, nil 132 | } 133 | -------------------------------------------------------------------------------- /corrlist.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // desc 8 | // https://w3s.webmoney.ru/asp/XMLGetCorrList.asp 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | "errors" 15 | ) 16 | 17 | type CorrList struct { 18 | XMLName xml.Name `xml:"getcorrlist"` 19 | Wmid string `xml:"wmid"` 20 | } 21 | 22 | type CorrListResponse struct { 23 | XMLName xml.Name `xml:"corrlist"` 24 | Count int `xml:"cnt,attr"` 25 | Corrs []Corr `xml:"corr"` 26 | } 27 | 28 | type Corr struct { 29 | Wmid string `xml:"wmid"` 30 | Nick string `xml:"nick"` 31 | } 32 | 33 | func (c CorrList) GetSignSource(reqn string) (string, error) { 34 | return c.Wmid + reqn, nil 35 | } 36 | 37 | func (w *WmClient) GetCorrList(c CorrList) (CorrListResponse, error) { 38 | result := CorrListResponse{} 39 | if !w.IsClassic() { 40 | return result, errors.New("not support Keeper Web Pro") 41 | } 42 | 43 | X := W3s{ 44 | Interface: XInterface{Name: "GetCorrList", Type: "w3s"}, 45 | Request: c, 46 | Client: w, 47 | } 48 | 49 | err := X.getResult(&result) 50 | return result, err 51 | } 52 | -------------------------------------------------------------------------------- /examples/x1.go: -------------------------------------------------------------------------------- 1 | //Webmoney XML Interfaces 2 | //Interface X1. Sending invoice from merchant to customer. 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/C0nstantin/go-webmoney" 9 | "github.com/pelletier/go-toml" 10 | "io/ioutil" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | date, err := ioutil.ReadFile("examples/conf.toml") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | 20 | config, _ := toml.Load(string(date)) 21 | wmClient := webmoney.WmClient{ 22 | Wmid: config.Get("client1.Wmid").(string), 23 | Key: config.Get("client1.Key").(string), 24 | Pass: config.Get("client1.Pass").(string), 25 | } 26 | invoice := webmoney.Invoice{ 27 | OrderId: "111", 28 | CustomerWmid: "128756507061", 29 | StorePurse: "R697541065597", 30 | Amount: "3.2", //AMOUNT 31 | Desc: "DESCRIPTION", //DESCRIPTION FOR INVOICE 32 | Address: "SHOP_ADDRESS", 33 | Period: "1", 34 | Expiration: "1", 35 | OnlyAuth: "0", 36 | } 37 | 38 | result, err := wmClient.SendInvoice(invoice) 39 | 40 | if err != nil { 41 | log.Fatalln(err) 42 | } 43 | 44 | fmt.Printf("%#v", result) 45 | } 46 | -------------------------------------------------------------------------------- /examples/x10.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | 24 | test := webmoney.InInvoices{ 25 | 26 | Wmid: "128756507061", 27 | WmInvid: "0", 28 | DateStart: "20201012", 29 | DateFinish: "20201013", 30 | } 31 | 32 | result, err := wmClient.GetInInvoices(test) 33 | 34 | if err != nil { 35 | log.Fatalln(err) 36 | } 37 | 38 | fmt.Printf("%#v", result) 39 | } 40 | -------------------------------------------------------------------------------- /examples/x11.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "log" 7 | ) 8 | 9 | func main() { 10 | 11 | result, err := webmoney.GetInfoWmid("128756507061") 12 | 13 | if err != nil { 14 | log.Fatalln(err) 15 | } 16 | 17 | fmt.Printf("%#v", result) 18 | } 19 | -------------------------------------------------------------------------------- /examples/x13.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | 24 | test := webmoney.RejectProtect{ 25 | WmTranId: "1766526830", 26 | } 27 | 28 | result, err := wmClient.RejectProtect(test) 29 | 30 | if err != nil { 31 | log.Fatalln(err) 32 | } 33 | 34 | fmt.Printf("%#v", result) 35 | } 36 | -------------------------------------------------------------------------------- /examples/x14.go: -------------------------------------------------------------------------------- 1 | //Webmoney XML Interfaces 2 | //Interface X1. Sending invoice from merchant to customer. 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/C0nstantin/go-webmoney" 9 | "github.com/pelletier/go-toml" 10 | "io/ioutil" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | date, err := ioutil.ReadFile("examples/conf.toml") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | 20 | config, _ := toml.Load(string(date)) 21 | wmClient := webmoney.WmClient{ 22 | Wmid: config.Get("client1.Wmid").(string), 23 | Key: config.Get("client1.Key").(string), 24 | Pass: config.Get("client1.Pass").(string), 25 | } 26 | got := webmoney.Trans{ 27 | InWmTranId: "1766529636", 28 | Amount: "0.01", 29 | MoneyBackPhone: "", 30 | } 31 | 32 | result, err := wmClient.MoneyBack(got) 33 | 34 | if err != nil { 35 | log.Fatalln(err) 36 | } 37 | 38 | fmt.Printf("%#v", result) 39 | } 40 | -------------------------------------------------------------------------------- /examples/x15.go: -------------------------------------------------------------------------------- 1 | //Webmoney XML Interfaces 2 | //Interface X1. Sending invoice from merchant to customer. 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/C0nstantin/go-webmoney" 9 | "github.com/pelletier/go-toml" 10 | "io/ioutil" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | date, err := ioutil.ReadFile("examples/conf.toml") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | 20 | config, _ := toml.Load(string(date)) 21 | wmClient := webmoney.WmClient{ 22 | Wmid: config.Get("client1.Wmid").(string), 23 | Key: config.Get("client1.Key").(string), 24 | Pass: config.Get("client1.Pass").(string), 25 | } 26 | test := webmoney.TrustList{ 27 | Wmid: wmClient.Wmid, 28 | } 29 | 30 | result, err := wmClient.GetTrustList(test) 31 | 32 | if err != nil { 33 | log.Fatalln(err) 34 | } 35 | 36 | fmt.Printf("%#v", result) 37 | } 38 | -------------------------------------------------------------------------------- /examples/x16.go: -------------------------------------------------------------------------------- 1 | //Webmoney XML Interfaces 2 | //Interface X1. Sending invoice from merchant to customer. 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/C0nstantin/go-webmoney" 9 | "github.com/pelletier/go-toml" 10 | "io/ioutil" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | date, err := ioutil.ReadFile("examples/conf.toml") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | 20 | config, _ := toml.Load(string(date)) 21 | wmClient := webmoney.WmClient{ 22 | Wmid: config.Get("client1.Wmid").(string), 23 | Key: config.Get("client1.Key").(string), 24 | Pass: config.Get("client1.Pass").(string), 25 | } 26 | test := webmoney.Purse{ 27 | Wmid: wmClient.Wmid, 28 | PurseType: "R", 29 | Desc: "test R", 30 | } 31 | 32 | result, err := wmClient.CreatePurse(test) 33 | 34 | if err != nil { 35 | log.Fatalln(err) 36 | } 37 | 38 | fmt.Printf("%#v", result) 39 | } 40 | -------------------------------------------------------------------------------- /examples/x18.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | got := webmoney.X18Request{ 24 | LmiPayeePurse: "Z303339773989", 25 | LmiPaymentNo: "881410869", 26 | LmiPaymentNoType: "2", 27 | } 28 | 29 | result, err := wmClient.TransGet(got) 30 | 31 | if err != nil { 32 | log.Fatalln(err) 33 | } 34 | 35 | fmt.Printf("%#v", result) 36 | } 37 | -------------------------------------------------------------------------------- /examples/x2.go: -------------------------------------------------------------------------------- 1 | //Webmoney XML Interfaces 2 | //Interface X1. Sending invoice from merchant to customer. 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/C0nstantin/go-webmoney" 9 | "github.com/pelletier/go-toml" 10 | "io/ioutil" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | date, err := ioutil.ReadFile("examples/conf.toml") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | 20 | config, _ := toml.Load(string(date)) 21 | wmClient := webmoney.WmClient{ 22 | Wmid: config.Get("client1.Wmid").(string), 23 | Key: config.Get("client1.Key").(string), 24 | Pass: config.Get("client1.Pass").(string), 25 | } 26 | 27 | transaction := webmoney.Transaction{ 28 | PurseSrc: "Z30333977000", 29 | PurseDest: "Z214605808000", 30 | Amount: "0.01", 31 | OnlyAuth: "0", 32 | TranId: "4", 33 | WmInvid: "0", 34 | Period: "2", 35 | PCode: "11111", 36 | Desc: "test", 37 | } 38 | 39 | result, err := wmClient.CreateTransaction(transaction) 40 | 41 | if err != nil { 42 | log.Fatalln(err) 43 | } 44 | 45 | fmt.Println(result.Id) 46 | } 47 | -------------------------------------------------------------------------------- /examples/x20.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | got := webmoney.X20Request{ 24 | LmiPayeePurse: "Z303339773989", 25 | LmiPaymentNo: "121", 26 | LmiPaymentNoType: "", 27 | LmiPaymentAmount: "0.1", 28 | LmiPaymentDesc: "test test test", 29 | LmiPaymentDescBase64: "", 30 | LmiClientnumber: "79261919656", 31 | LmiClientnubmerType: "0", 32 | LmiSmsType: "3", 33 | LmiShopId: "", 34 | LmiHold: "", 35 | Lang: "", 36 | EnulatedFlag: "", 37 | } 38 | 39 | result, err := wmClient.TransRequest(got) 40 | 41 | if err != nil { 42 | log.Fatalln(err) 43 | } 44 | 45 | fmt.Printf("%#v", result) 46 | fmt.Println("Insert code for confirmation") 47 | var code string 48 | fmt.Scan(&code) 49 | got1 := webmoney.X202Request{ 50 | LmiPayeePurse: "Z303339773989", 51 | LmiClientnumberCode: code, 52 | LmiWminvoiceid: result.Wminvoiceid, 53 | } 54 | result1, err := wmClient.TransConfirm(got1) 55 | 56 | if err != nil { 57 | log.Fatalln(err) 58 | } 59 | 60 | fmt.Printf("%#v", result1) 61 | } 62 | -------------------------------------------------------------------------------- /examples/x21.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | got := webmoney.X21Request{ 24 | LmiPayeePurse: "Z303339773989", 25 | LmiDayLimit: "1", 26 | LmiWeekLimit: "1", 27 | LmiMonthLimit: "1", 28 | LmiClientnumber: "128756507061", 29 | LmiClientnubmerType: "1", 30 | LmiSmsType: "1", 31 | Lang: "ru-RU", 32 | } 33 | 34 | result, err := wmClient.TrustRequest(got) 35 | 36 | if err != nil { 37 | log.Fatalln(err) 38 | } 39 | 40 | fmt.Printf("%#v", result) 41 | fmt.Println("Insert code for confirmation") 42 | var code string 43 | fmt.Scan(&code) 44 | got1 := webmoney.X212Request{ 45 | LmiPurseId: result.TrustX21.PurseId, 46 | LmiClientnumberCode: code, 47 | } 48 | 49 | result1, err := wmClient.TrustConfirm(got1) 50 | 51 | if err != nil { 52 | log.Fatalln(err) 53 | } 54 | 55 | fmt.Printf("%#v", result1) 56 | } 57 | -------------------------------------------------------------------------------- /examples/x22.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | got := webmoney.X22Request{ 24 | 25 | Validityperiodinhours: "1", 26 | Paymenttags: webmoney.Paymenttags{ 27 | 28 | LmiPayeePurse: "Z303339773989", 29 | LmiPaymentNo: "122", 30 | LmiPaymentNoType: "", 31 | LmiPaymentAmount: "0.1", 32 | LmiPaymentDesc: "test test test", 33 | LmiPaymentDescBase64: "", 34 | LmiClientnumber: "79261919656", 35 | LmiClientnubmerType: "0", 36 | LmiSmsType: "3", 37 | LmiShopId: "", 38 | LmiHold: "", 39 | Lang: "", 40 | EnulatedFlag: "", 41 | }, 42 | } 43 | 44 | result, err := wmClient.TransSave(got) 45 | 46 | if err != nil { 47 | log.Fatalln(err) 48 | } 49 | 50 | fmt.Printf("%#v", result) 51 | fmt.Println("https://merchant.wmtransfer.com/lmi/payment.asp?gid=" + result.Transtoken) 52 | 53 | } 54 | -------------------------------------------------------------------------------- /examples/x23.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | got := webmoney.InvoiceRefuse{ 24 | Wmid: "128756507061", 25 | Wminvid: "882271555", 26 | } 27 | 28 | result, err := wmClient.RefuseInvoice(got) 29 | 30 | if err != nil { 31 | log.Fatalln(err) 32 | } 33 | 34 | fmt.Printf("%#v", result) 35 | } 36 | -------------------------------------------------------------------------------- /examples/x3.go: -------------------------------------------------------------------------------- 1 | //Webmoney XML Interfaces 2 | //Interface X1. Sending invoice from merchant to customer. 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/C0nstantin/go-webmoney" 9 | "github.com/pelletier/go-toml" 10 | "io/ioutil" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | date, err := ioutil.ReadFile("examples/conf.toml") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | 20 | config, _ := toml.Load(string(date)) 21 | wmClient := webmoney.WmClient{ 22 | Wmid: config.Get("client1.Wmid").(string), 23 | Key: config.Get("client1.Key").(string), 24 | Pass: config.Get("client1.Pass").(string), 25 | } 26 | got := webmoney.GetOpers{ 27 | Purse: "Z303339773000", 28 | WmTranId: "", 29 | TranId: "", 30 | WmInvid: "", 31 | OrderId: "", 32 | DateStart: "20200911", 33 | DateFinish: "20201013", 34 | } //1766082859 35 | 36 | result, err := wmClient.GetOperations(got) 37 | 38 | if err != nil { 39 | log.Fatalln(err) 40 | } 41 | 42 | fmt.Printf("%#v", result) 43 | } 44 | -------------------------------------------------------------------------------- /examples/x4.go: -------------------------------------------------------------------------------- 1 | //Webmoney XML Interfaces 2 | //Interface X1. Sending invoice from merchant to customer. 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/C0nstantin/go-webmoney" 9 | "github.com/pelletier/go-toml" 10 | "io/ioutil" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | date, err := ioutil.ReadFile("examples/conf.toml") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | 20 | config, _ := toml.Load(string(date)) 21 | wmClient := webmoney.WmClient{ 22 | Wmid: config.Get("client1.Wmid").(string), 23 | Key: config.Get("client1.Key").(string), 24 | Pass: config.Get("client1.Pass").(string), 25 | } 26 | 27 | got := webmoney.OutInvoices{ 28 | Purse: "Z303339773000", 29 | //WmTranId: "", 30 | //TranId: "4", 31 | WmInvid: "", 32 | OrderId: "", 33 | DateStart: "20201011", 34 | DateFinish: "20201012", 35 | } //1766082859 36 | 37 | result, err := wmClient.GetOutInvoices(got) 38 | 39 | if err != nil { 40 | log.Fatalln(err) 41 | } 42 | 43 | fmt.Printf("%#v", result) 44 | } 45 | -------------------------------------------------------------------------------- /examples/x5.go: -------------------------------------------------------------------------------- 1 | //Webmoney XML Interfaces 2 | //Interface X1. Sending invoice from merchant to customer. 3 | 4 | package main 5 | 6 | import ( 7 | "fmt" 8 | "github.com/C0nstantin/go-webmoney" 9 | "github.com/pelletier/go-toml" 10 | "io/ioutil" 11 | "log" 12 | ) 13 | 14 | func main() { 15 | date, err := ioutil.ReadFile("examples/conf.toml") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | 20 | config, _ := toml.Load(string(date)) 21 | wmClient := webmoney.WmClient{ 22 | Wmid: config.Get("client1.Wmid").(string), 23 | Key: config.Get("client1.Key").(string), 24 | Pass: config.Get("client1.Pass").(string), 25 | } 26 | 27 | got := webmoney.FinishProtect{ 28 | PCode: "11111", 29 | WmTranId: "1766089800", 30 | } //1766082859 31 | 32 | result, err := wmClient.DoFinishProtect(got) 33 | 34 | if err != nil { 35 | log.Fatalln(err) 36 | } 37 | 38 | fmt.Printf("%#v", result) 39 | } 40 | -------------------------------------------------------------------------------- /examples/x6.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | 24 | msg := webmoney.SendMsg{ 25 | ReceiverWmid: "128756507061", 26 | MsgText: `Тестовое сообщение многострочное 27 | сообщение`, 28 | MsgSubj: "Тестовое сообещие", 29 | OnlyAuth: 0, 30 | } 31 | 32 | result, err := wmClient.SendMessage(msg) 33 | 34 | if err != nil { 35 | log.Fatalln(err) 36 | } 37 | 38 | fmt.Printf("%#v", result) 39 | } 40 | -------------------------------------------------------------------------------- /examples/x7.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | 24 | test := webmoney.TestSignRequest{ 25 | Wmid: "128756507061", 26 | Plan: "-", 27 | Sign: "-", 28 | } 29 | 30 | result, err := wmClient.TestSign(test) 31 | 32 | if err != nil { 33 | log.Fatalln(err) 34 | } 35 | 36 | fmt.Printf("%#v", result) 37 | } 38 | -------------------------------------------------------------------------------- /examples/x8.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | 24 | test := webmoney.TestWmPurse{ 25 | Wmid: "128756507061", 26 | Purse: "Z303339773989", 27 | } 28 | 29 | result, _ := wmClient.FindWmidPurse(test) 30 | 31 | fmt.Printf("%#v", result) 32 | } 33 | -------------------------------------------------------------------------------- /examples/x9.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/C0nstantin/go-webmoney" 6 | "github.com/pelletier/go-toml" 7 | "io/ioutil" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | date, err := ioutil.ReadFile("examples/conf.toml") 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | config, _ := toml.Load(string(date)) 18 | wmClient := webmoney.WmClient{ 19 | Wmid: config.Get("client1.Wmid").(string), 20 | Key: config.Get("client1.Key").(string), 21 | Pass: config.Get("client1.Pass").(string), 22 | } 23 | 24 | test := webmoney.Purses{ 25 | Wmid: config.Get("client1.Wmid").(string), 26 | } 27 | 28 | result, err := wmClient.GetPurses4Wmid(test) 29 | 30 | if err != nil { 31 | log.Fatalln(err) 32 | } 33 | 34 | fmt.Printf("%#v", result) 35 | } 36 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/C0nstantin/go-webmoney 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c 7 | github.com/pelletier/go-toml v1.9.5 8 | golang.org/x/crypto v0.31.0 9 | golang.org/x/text v0.21.0 10 | ) 11 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 2 | github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c h1:P6XGcuPTigoHf4TSu+3D/7QOQ1MbL6alNwrGhcW7sKw= 3 | github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c/go.mod h1:YnNlZP7l4MhyGQ4CBRwv6ohZTPrUJJZtEv4ZgADkbs4= 4 | github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= 5 | github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 6 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 7 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 8 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 9 | golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= 10 | golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= 11 | golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= 12 | golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= 13 | golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= 14 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 15 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 16 | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 17 | golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 18 | golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 19 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 20 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 21 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 22 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 23 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 24 | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= 25 | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= 26 | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= 27 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 28 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 29 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 30 | golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= 31 | golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 32 | golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 33 | golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 34 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 35 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 36 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 37 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 38 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 39 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 40 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 41 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 42 | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 43 | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 44 | golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 45 | golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= 46 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 47 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 48 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 49 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 50 | golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= 51 | golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= 52 | golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= 53 | golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= 54 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 55 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 56 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 57 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 58 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 59 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 60 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 61 | golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 62 | golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= 63 | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= 64 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 65 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 66 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 67 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 68 | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= 69 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 70 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 71 | -------------------------------------------------------------------------------- /helpers.go: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Constantin Karataev. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | // This file contains some helper function to form data for requests 5 | 6 | package webmoney 7 | 8 | import ( 9 | "fmt" 10 | "golang.org/x/text/encoding/charmap" 11 | "os" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | // function return reqn params for webmoney request 17 | // each subsequent more as the previews 18 | func Reqn() string { 19 | nanoseconds := fmt.Sprintf("%03.f", float32(time.Now().Nanosecond()/1000000)) 20 | loc, err := time.LoadLocation("Europe/Moscow") 21 | if err != nil { 22 | panic(err) 23 | } 24 | if os.Getenv("USE_OLD_REQN") != "" { 25 | loc, _ = time.LoadLocation("UTC") 26 | return time.Now().In(loc).Format("060102150405") + nanoseconds[0:2] 27 | } 28 | return time.Now().In(loc).Format("20060102150405") + nanoseconds 29 | } 30 | 31 | // Utf8ToWin encode string from utf8 to cp1251 32 | func Utf8ToWin(s string) (string, error) { 33 | encoder := charmap.Windows1251.NewEncoder() 34 | return encoder.String(s) 35 | } 36 | 37 | func DebugLog(v ...interface{}) { 38 | if strings.ToUpper(os.Getenv("LOG_LEVEL")) == "TRACE" { 39 | fmt.Println(v...) 40 | } 41 | } 42 | 43 | func DebugLogf(format string, v ...interface{}) { 44 | if strings.ToUpper(os.Getenv("LOG_LEVEL")) == "TRACE" { 45 | fmt.Printf(format, v...) 46 | } 47 | } 48 | 49 | // Root ca for webmoney requests 50 | const ROOT_CA = ` 51 | -----BEGIN CERTIFICATE----- 52 | MIIFsTCCA5mgAwIBAgIQA7dHzSZ7uJdBxFycIWn+WjANBgkqhkiG9w0BAQUFADBr 53 | MSswKQYDVQQLEyJXTSBUcmFuc2ZlciBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzMRgw 54 | FgYDVQQKEw9XTSBUcmFuc2ZlciBMdGQxIjAgBgNVBAMTGVdlYk1vbmV5IFRyYW5z 55 | ZmVyIFJvb3QgQ0EwHhcNMTAwMzEwMTczNDU2WhcNMzUwMzEwMTc0NDUxWjBrMSsw 56 | KQYDVQQLEyJXTSBUcmFuc2ZlciBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzMRgwFgYD 57 | VQQKEw9XTSBUcmFuc2ZlciBMdGQxIjAgBgNVBAMTGVdlYk1vbmV5IFRyYW5zZmVy 58 | IFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDFLJXtzEkZ 59 | xLj1HIj9EhGvajFJ7RCHzF+MK2ZrAgxmmOafiFP6QD/aVjIexBqRb8SVy38xH+wt 60 | hqkZgLMOGn8uDNpFieEMoX3ZRfqtCcD76KDySTOX1QUwHAzBfGuhe2ZQULUIjxdP 61 | Ra4NDyvmXh4pE/s1+/7dGbUZs/JpYYaD2xxAt5PDTjylsKOk4FMb5kv6jzORkXku 62 | 5UKFGUXEXbbf1xzgYHMIzoeJGn+iPgVFYAvkkQyvxEaVj0lNE+q/ua761krgCo47 63 | BiH1zMFzkv4uNHEZfe/lyHaozzbsu6yaK3EdrURSLuWrlxKy9yo3xDe9TPkzkhPe 64 | JPbV7YgvUUtWSeAJpksBU8GCALEhSgXOfHckuJFj9QB3YecHBvjdSiAUuntwM/iH 65 | vtSOXEUHxqW75E2Gq/2L4vBcxArXVdbUrVQDF3klzYu17OFgfe1hHHMHzgr4HBML 66 | ZiRCcvNLqghBCVxu1DM15YDfw+wnNV/5dUPx60tiocmCZpJKTwVl8gc85QCPyREu 67 | jey8F0kgdgssQosPWTTWDg7X4Ifw20VkplHZDr29K5HdwLe56TvOI/4H24XJdqpA 68 | xoLBx9PL6ZXxH52wU0bSluL8/joXGzavFrhsXH7jJocH6tsFVzBZrmnVswbUMHDN 69 | L3xSnr5fAAXXZa7UwHd3pq/fsdG7s9PByQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw 70 | DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUsTCnSwOZT4Q2HBN9V/TrafuIG8Mw 71 | EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggIBAAy5jHDFpVWtF209 72 | N30I+LHsiqMaLUmYDeV6sUBJqmWAZav7pWnigiMLuJd9yRa/ow6yKlKPRi3sbKaB 73 | wsAQ+xnz811nLFBBdS4PkwlHu1B7P4B2YbcqmF6k1QieJBZxOn7wledtnoBAkZ4d 74 | 6HEW1OM5cvCoyj8YAdJTZIBzn61aNt/viPvypIUQf6Ps6Q2daNEAj7DoxIY8crnO 75 | aSIGdGmlT/y/edSqWv9Am5e9KXkJhQWMnGXh43wJYyHTetxVWPS43bW7gIUADYyc 76 | KSH3isrBN5xQOFXMfL+lVHHSs7ap23DOo7xIDenm5PWz+QdDDFz3zLVeRovnkIdk 77 | a/Wgk3f6rFfKB0y5POJ+BJvkorIYNZiN3dnmc6cDP840BUMv3BUrOe8iSy5lRr8m 78 | R+daktbZfO8E/rAb3zEdN+KG/CNJfAnQvp6DT4LqY/J9pG+VusH5GpUwuXr7UqLw 79 | End1LRp7qm28Cic7fegUnnUpkuF4ZFq8pWq8w59sOWlRuKBuWX46OghMrjgD0AN1 80 | hlA2/d5ULImX70Q2te3xiS1vrQhu77mkb/jA4/9+YfeT7VMpbnC3OoHiZ2bjudKn 81 | thlOs+AuUvzB4Tqo62VSF5+r0sYI593S+STmaZBAzsoaoEB7qxqKbEKCvXb9BlXk 82 | L76xIOEkbSIdPIkGXM4aMo4mTVz7 83 | -----END CERTIFICATE----- 84 | -----BEGIN CERTIFICATE----- 85 | MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU 86 | MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs 87 | IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 88 | MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux 89 | FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h 90 | bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v 91 | dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt 92 | H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 93 | uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX 94 | mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX 95 | a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN 96 | E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 97 | WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD 98 | VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 99 | Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU 100 | cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx 101 | IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN 102 | AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH 103 | YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 104 | 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC 105 | Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX 106 | c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a 107 | mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= 108 | -----END CERTIFICATE----- 109 | -----BEGIN CERTIFICATE----- 110 | MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG 111 | A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz 112 | cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 113 | MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV 114 | BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt 115 | YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN 116 | ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE 117 | BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is 118 | I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G 119 | CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do 120 | lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc 121 | AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k 122 | -----END CERTIFICATE-----` 123 | -------------------------------------------------------------------------------- /helpers_test.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import ( 4 | "os" 5 | "regexp" 6 | "testing" 7 | "time" 8 | ) 9 | 10 | func TestReqn(t *testing.T) { 11 | reqn := Reqn() 12 | // Check if the length of the output is as expected 13 | expectedLength := 17 // YYYYMMDDHHMMSSmmm 14 | if len(reqn) != expectedLength { 15 | t.Errorf("Expected length of reqn to be %d, got %d", expectedLength, len(reqn)) 16 | } 17 | 18 | // Check if the format of the output matches the expected pattern 19 | // The pattern is YYYYMMDDHHMMSSmmm where Y is year, M is month, D is day, 20 | // H is hour, M is minute, S is second, and m is millisecond 21 | pattern := `^\d{17}$` 22 | matched, err := regexp.MatchString(pattern, reqn) 23 | if err != nil { 24 | t.Fatal("Regex match failed:", err) 25 | } 26 | if !matched { 27 | t.Errorf("Reqn %s does not match the expected pattern %s", reqn, pattern) 28 | } 29 | 30 | // Optionally, you can check if the time is within a reasonable range (e.g., +/- 1 minute from now) 31 | // This is a bit more complex and might not be strictly necessary for all use cases 32 | loc, err := time.LoadLocation("Europe/Moscow") 33 | now := time.Now().In(loc) 34 | reqnTime, err := time.ParseInLocation("20060102150405", reqn[0:14], loc) 35 | if err != nil { 36 | t.Fatal("Failed to parse reqn time:", err) 37 | } 38 | if reqnTime.Before(now.Add(-time.Minute)) || reqnTime.After(now.Add(time.Minute)) { 39 | t.Errorf("Reqn time %s is not within a reasonable range of the current time", reqnTime) 40 | } 41 | } 42 | func TestOldReqn(t *testing.T) { 43 | os.Setenv("USE_OLD_REQN", "true") 44 | reqn := Reqn() 45 | // Check if the length of the output is as expected 46 | if len(reqn) != 14 { 47 | t.Errorf("Expected length of reqn to be 14, got %d", len(reqn)) 48 | } 49 | // Check if the format of the output matches the expected pattern 50 | pattern := `^\d{14}$` 51 | matched, err := regexp.MatchString(pattern, reqn) 52 | if err != nil { 53 | t.Fatal("Regex match failed:", err) 54 | } 55 | if !matched { 56 | t.Errorf("Reqn %s does not match the expected pattern %s", reqn, pattern) 57 | } 58 | loc, _ := time.LoadLocation("UTC") 59 | parse, err := time.ParseInLocation("060102150405", reqn[0:12], loc) 60 | if err != nil { 61 | t.Fatal("Failed to parse reqn time:", err) 62 | } 63 | if parse.Before(time.Now().In(loc).Add(-time.Minute)) || parse.After(time.Now().In(loc).Add(time.Minute)) { 64 | t.Errorf("Reqn time %s is not within a reasonable range of the current time", parse) 65 | } 66 | } 67 | 68 | // TestUtf8ToWin tests the Utf8ToWin function to ensure it correctly encodes UTF-8 strings to Windows-1251. 69 | func TestUtf8ToWin(t *testing.T) { 70 | // Example UTF-8 string and its expected Windows-1251 encoding. 71 | // Note: Ensure the example is correct and can be encoded in Windows-1251. 72 | utf8String := "Привет, мир!" // "Hello, world!" in Russian. 73 | expectedWin1251String := "\xcf\xf0\xe8\xe2\xe5\xf2, \xec\xe8\xf0!" // Expected Windows-1251 encoding. 74 | 75 | // Encode the UTF-8 string to Windows-1251. 76 | win1251String, err := Utf8ToWin(utf8String) 77 | if err != nil { 78 | t.Fatalf("Utf8ToWin returned an error: %v", err) 79 | } 80 | 81 | // Compare the encoded string with the expected result. 82 | if win1251String != expectedWin1251String { 83 | t.Errorf("Utf8ToWin failed to encode UTF-8 to Windows-1251 correctly.\nGot: %s\nWant: %s", win1251String, expectedWin1251String) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /interfaces.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import ( 4 | "encoding/xml" 5 | "fmt" 6 | "os" 7 | ) 8 | 9 | type XInterface struct { 10 | Name string 11 | Type string 12 | } 13 | 14 | func (x *XInterface) GetUrl(isClassic bool) string { 15 | merchantDomain := "merchant.web.money" 16 | classicDomain := "w10s.web.money" 17 | lightDomain := "w10s.web.money" 18 | if v, ok := os.LookupEnv("MERCHANT_DOMAIN"); ok { 19 | merchantDomain = v 20 | } 21 | if v, ok := os.LookupEnv("CLASSIC_DOMAIN"); ok { 22 | classicDomain = v 23 | } 24 | if v, ok := os.LookupEnv("LIGHT_DOMAIN"); ok { 25 | lightDomain = v 26 | } 27 | 28 | if x.Type == "w3s" || x.Type == "passport" { 29 | if isClassic { 30 | return fmt.Sprintf("https://%s/asp/XML%s.asp", classicDomain, x.Name) 31 | } else { 32 | if x.Name == "FindWMPurseNew" { 33 | return fmt.Sprintf("https://%s/asp/XMLFindWMPurseNew.asp", lightDomain) 34 | 35 | } else { 36 | return fmt.Sprintf("https://%s/asp/XML%sCert.asp", lightDomain, x.Name) 37 | } 38 | } 39 | } else if x.Type == "merchant" { 40 | return fmt.Sprintf("https://%s/conf/xml/XML%s.asp", merchantDomain, x.Name) 41 | } 42 | panic("unknown interface type " + x.Type) 43 | } 44 | 45 | type requestW3s struct { 46 | XMLName xml.Name `xml:"w3s.request"` 47 | Reqn string `xml:"reqn"` 48 | Wmid string `xml:"wmid"` 49 | Sign string `xml:"sign"` 50 | Request interface{} `xml:",>"` 51 | } 52 | 53 | // base struct for all response 54 | type responseW3s struct { 55 | XMLName xml.Name `xml:"w3s.response"` 56 | Reqn string `xml:"reqn"` 57 | Retval int64 `xml:"retval"` 58 | Retdesc string `xml:"retdesc"` 59 | Ser string `xml:"ser"` 60 | CWmid string `xml:"cwmid"` 61 | Wmid string `xml:"wmid"` 62 | Step string `xml:"step"` 63 | Response interface{} `xml:",any"` 64 | } 65 | type merchantRequest struct { 66 | XMLName xml.Name `xml:"merchant.request"` 67 | Wmid string `xml:"wmid"` 68 | Sign string `xml:"sign"` 69 | Sha256 string `xml:"sha256"` 70 | Md5 string `xml:"md5"` 71 | SecretKey string `xml:"secret_key"` 72 | } 73 | 74 | func (m *merchantRequest) setWmid(w string) { 75 | m.Wmid = w 76 | } 77 | 78 | func (m *merchantRequest) setSign(w string) { 79 | m.Sign = w 80 | } 81 | 82 | func (m *merchantRequest) setSha256(w string) { 83 | m.Sha256 = w 84 | } 85 | 86 | type merchantResponse struct { 87 | XmlName xml.Name `xml:"merchant.response"` 88 | ErrorLog ErrorLog `xml:"errorlog"` 89 | Retval int64 `xml:"retval"` 90 | Retdesc string `xml:"retdesc"` 91 | //Response interface{} `xml:",any"` 92 | } 93 | 94 | func (m *merchantResponse) GetRetVal() int64 { 95 | return m.Retval 96 | } 97 | func (m *merchantResponse) GetRetDesc() string { 98 | return m.Retdesc 99 | } 100 | 101 | type ErrorLog struct { 102 | XmlName xml.Name `xml:"errorlog"` 103 | LmiPayeePurse string `xml:"lmi_payee_purse,attr"` 104 | LmiPaymentNo string `xml:"lmi_payment_no,attr"` 105 | Datecrt string `xml:"datecrt"` 106 | Dateupd string `xml:"dateupd"` 107 | DateS string `xml:"date_s"` 108 | DatePc string `xml:"date_pc"` 109 | DatePd string `xml:"date_pd"` 110 | PType string `xml:"p_type"` 111 | ErrCode string `xml:"err_code"` 112 | Siteid string `xml:"siteid"` 113 | Att string `xml:"att"` 114 | DateNotify string `xml:"date_notify"` 115 | ShopId string `xml:"shop_id"` 116 | } 117 | -------------------------------------------------------------------------------- /interfaces_test.go: -------------------------------------------------------------------------------- 1 | package webmoney_test 2 | 3 | import ( 4 | wm "github.com/C0nstantin/go-webmoney" // Adjust the import path as necessary 5 | "os" 6 | "testing" 7 | ) 8 | 9 | func TestXInterface_GetUrl(t *testing.T) { 10 | // Setup environment variables for testing 11 | os.Setenv("MERCHANT_DOMAIN", "test.merchant.web.money") 12 | os.Setenv("CLASSIC_DOMAIN", "test.w3s.webmoney.com") 13 | os.Setenv("LIGHT_DOMAIN", "test.light.webmoney.com") 14 | 15 | // Define test cases 16 | tests := []struct { 17 | name string 18 | xInterface wm.XInterface 19 | isClassic bool 20 | want string 21 | }{ 22 | { 23 | name: "Classic w3s", 24 | xInterface: wm.XInterface{Name: "InterfaceName", Type: "w3s"}, 25 | isClassic: true, 26 | want: "https://test.w3s.webmoney.com/asp/XMLInterfaceName.asp", 27 | }, 28 | { 29 | name: "Light FindWMPurseNew", 30 | xInterface: wm.XInterface{Name: "FindWMPurseNew", Type: "w3s"}, 31 | isClassic: false, 32 | want: "https://test.light.webmoney.com/asp/XMLFindWMPurseNew.asp", 33 | }, 34 | { 35 | name: "Light other", 36 | xInterface: wm.XInterface{Name: "OtherInterface", Type: "w3s"}, 37 | isClassic: false, 38 | want: "https://test.light.webmoney.com/asp/XMLOtherInterfaceCert.asp", 39 | }, 40 | { 41 | name: "Merchant type", 42 | xInterface: wm.XInterface{Name: "MerchantInterface", Type: "merchant"}, 43 | isClassic: false, 44 | want: "https://test.merchant.web.money/conf/xml/XMLMerchantInterface.asp", 45 | }, 46 | } 47 | 48 | // Execute test cases 49 | for _, tt := range tests { 50 | t.Run(tt.name, func(t *testing.T) { 51 | if got := tt.xInterface.GetUrl(tt.isClassic); got != tt.want { 52 | t.Errorf("XInterface.GetUrl() = %v, want %v", got, tt.want) 53 | } 54 | }) 55 | } 56 | 57 | // Cleanup environment variables 58 | os.Unsetenv("MERCHANT_DOMAIN") 59 | os.Unsetenv("CLASSIC_DOMAIN") 60 | os.Unsetenv("LIGHT_DOMAIN") 61 | } 62 | -------------------------------------------------------------------------------- /merchant.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import ( 4 | "bytes" 5 | "crypto/sha256" 6 | "encoding/xml" 7 | "errors" 8 | "fmt" 9 | "strconv" 10 | 11 | "github.com/C0nstantin/go-webmoney/wmsigner" 12 | "github.com/paulrosania/go-charset/charset" 13 | _ "github.com/paulrosania/go-charset/data" 14 | ) 15 | 16 | type SignedM interface { 17 | Signed 18 | setWmid(string) 19 | setSign(string) 20 | setSha256(string) 21 | } 22 | type RetReturn interface { 23 | GetRetDesc() string 24 | GetRetVal() int64 25 | } 26 | 27 | type Merchant struct { 28 | Request SignedM //X18Request//merchantRequest 29 | Result RetReturn 30 | ResultStr string 31 | Interface XInterface 32 | Client *WmClient 33 | } 34 | 35 | func (m *Merchant) getResult(result RetReturn) error { 36 | str, err := m.sendRequest() 37 | if err != nil { 38 | return err 39 | } 40 | if err := m.parseResponse(result, str); err != nil { 41 | return err 42 | } 43 | if m.Result.GetRetVal() != 0 { 44 | err := errors.New(strconv.FormatInt(m.Result.GetRetVal(), 10) + " " + m.Result.GetRetDesc()) 45 | return err 46 | 47 | } 48 | return nil 49 | } 50 | 51 | func (m *Merchant) parseResponse(resp RetReturn, responseStr string) error { 52 | v := resp 53 | DebugLog("merchant response: ", responseStr) 54 | r := bytes.NewReader([]byte(responseStr)) 55 | dec := xml.NewDecoder(r) 56 | dec.CharsetReader = charset.NewReader 57 | err := dec.Decode(&v) 58 | m.Result = v 59 | if err != nil { 60 | return err 61 | } 62 | return nil 63 | } 64 | 65 | func (m *Merchant) sendRequest() (string, error) { 66 | 67 | url := m.Interface.GetUrl(m.Client.IsClassic()) 68 | 69 | v := m.Request 70 | v.setWmid(m.Client.Wmid) 71 | 72 | if m.Client.IsClassic() { 73 | 74 | signer := wmsigner.NewSigner(m.Client.Wmid, m.Client.Pass, m.Client.Key) 75 | str, err := m.Request.GetSignSource("") 76 | if err != nil { 77 | return "", err 78 | } 79 | str = m.Client.Wmid + str 80 | sign, err := signer.Sign(str) 81 | if err != nil { 82 | return "", nil 83 | } 84 | v.setSign(sign) 85 | } else { 86 | str, err := m.Request.GetSignSource(m.Client.SecretKey) 87 | if err != nil { 88 | return "", err 89 | } 90 | str = m.Client.Wmid + str 91 | sign := fmt.Sprintf("%x", sha256.Sum256([]byte(str))) 92 | v.setSha256(sign) 93 | } 94 | output, err := xml.MarshalIndent(v, " ", " ") 95 | if err != nil { 96 | return "", err 97 | } 98 | body := " \n" + string(output) 99 | DebugLog(" merchant request: to " + url + "\n" + body) 100 | return m.Client.sendRequest(url, body) 101 | } 102 | -------------------------------------------------------------------------------- /tests/.x10_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | import "webmoney" 5 | 6 | func TestX9(t *testing.T) { 7 | wmCl := webmoney.WmClient{ 8 | Wmid: CnfLight.Wmid, 9 | Cert: CnfLight.Cert, 10 | Key: CnfLight.Key, 11 | } 12 | i := webmoney.InInvoices{ 13 | Wmid: CnfLight.Wmid, 14 | WmInvid: "0", 15 | DateStart: "20140101 00:00:00", 16 | DateFinish: "20160930 00:00:00", 17 | } 18 | result, err := wmCl.GetInInvoices(i) 19 | if err != nil { 20 | t.Fatal(err) 21 | } 22 | t.Log(result) 23 | } 24 | -------------------------------------------------------------------------------- /tests/.x11_test.go: -------------------------------------------------------------------------------- 1 | // 2 | 3 | package tests 4 | 5 | import ( 6 | "fmt" 7 | "testing" 8 | "webmoney" 9 | ) 10 | 11 | func TestPassport(t *testing.T) { 12 | result, err := webmoney.GetInfoWmid(`128756507061`) 13 | if err != nil { 14 | t.Fatal(err) 15 | } else { 16 | t.Log(result.CertInfo) 17 | } 18 | fmt.Println(result.CertInfo) 19 | 20 | } 21 | -------------------------------------------------------------------------------- /tests/.x1_test.go: -------------------------------------------------------------------------------- 1 | //finish 2 | package tests 3 | 4 | import "testing" 5 | import "webmoney" 6 | import "fmt" 7 | import "strconv" 8 | 9 | func TestX1(t *testing.T) { 10 | wmCl := webmoney.WmClient{ 11 | Wmid: CnfClassic.Wmid, 12 | Key: CnfClassic.Wmid_key, 13 | Pass: CnfClassic.Wmid_pass, 14 | } 15 | invoice := webmoney.Invoice{ 16 | OrderId: "10", 17 | CustomerWmid: "128756507061", 18 | StorePurse: "R562831674289", 19 | Amount: "3.2", 20 | Desc: "Тест кирилица", 21 | Address: "Россия, Москва, NJ переулок д 1", 22 | Period: "1", 23 | Expiration: "1", 24 | OnlyAuth: "0", 25 | } 26 | result, err := wmCl.SendInvoice(invoice) 27 | fmt.Println(result) 28 | t.Log(result) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | if id, _ := strconv.ParseInt(result.Id, 10, 64); id <= 0 { 33 | t.Log(result) 34 | t.Fatal(" Light Fail Invoice ID is empty !!! ") 35 | } 36 | wmClight := webmoney.WmClient{ 37 | Wmid: CnfLight.Wmid, 38 | Key: CnfLight.Key, 39 | Cert: CnfLight.Cert, 40 | } 41 | invoicel := webmoney.Invoice{ 42 | OrderId: "10", 43 | CustomerWmid: "128756507061", 44 | StorePurse: "Z214605808008", 45 | Amount: "3.2", 46 | Desc: "Теcт кирилица light", 47 | Address: "Россия, Москва, ТТ переулок д 1", 48 | Period: "1", 49 | Expiration: "1", 50 | OnlyAuth: "0", 51 | } 52 | resultl, err := wmClight.SendInvoice(invoicel) 53 | fmt.Println(resultl) 54 | t.Log(resultl) 55 | fmt.Println(wmClight.ResultStr) 56 | if err != nil { 57 | t.Fatal(err) 58 | } 59 | if id, _ := strconv.ParseInt(resultl.Id, 10, 64); id <= 0 { 60 | t.Log(result) 61 | t.Fatal("Light Fail Invoice ID is empty !!! ") 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tests/.x2_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | 5 | func TestClassicX2(t *testing.T) { 6 | wmClientClassic := webmoney.WmClient{ 7 | Wmid: CnfClassic.Wmid, 8 | Key: CnfClassic.Wmid_key, 9 | Pass: CnfClassic.Wmid_pass, 10 | } 11 | 12 | transaction := webmoney.Transaction{ 13 | TranId: "1001", 14 | PurseDest: "R305844543288", 15 | PurseSrc: "R562831674289", 16 | Amount: "3.2", 17 | Period: "1", 18 | Desc: "Теst кирилица", 19 | PCode: "", 20 | WmInvid: "0", 21 | OnlyAuth: "1", 22 | } 23 | 24 | result, err := wmClientClassic.CreateTransaction(transaction) 25 | 26 | t.Log(result) 27 | if err != nil { 28 | t.Fatal(err) 29 | } 30 | } 31 | 32 | func TestLightX2(t *testing.T) { 33 | wmCl := webmoney.WmClient{ 34 | Wmid: CnfLight.Wmid, 35 | Key: CnfLight.Key, 36 | Cert: CnfLight.Cert, 37 | } 38 | 39 | transaction := webmoney.Transaction{ 40 | TranId: "1002", 41 | PurseDest: "Z311164609945", 42 | PurseSrc: "Z214605808008", 43 | Amount: "1.03", 44 | Period: "1", 45 | Desc: "Текст кирилица", 46 | Pcode: "", 47 | WmInvid: "0", 48 | OnlyAuth: "1", 49 | } 50 | 51 | result, err := wmCl.CreateTransaction(transaction) 52 | 53 | t.Log(result) 54 | if err != nil { 55 | t.Fatal(err) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /tests/.x3_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | import "webmoney" 5 | import "fmt" 6 | 7 | func TestX3(t *testing.T) { 8 | wmCl := webmoney.WmClient{ 9 | Wmid: CnfClassic.Wmid, 10 | Key: CnfClassic.Wmid_key, 11 | Pass: CnfClassic.Wmid_pass, 12 | } 13 | opts := webmoney.GetOpers{ 14 | TranId: "10", 15 | Purse: "R562831674289", 16 | DateStart: "20160726 00:00:00", 17 | DateFinish: "20160721 00:00:00", 18 | } 19 | result, err := wmCl.GetOperations(opts) 20 | fmt.Println(wmCl.ResultStr) 21 | 22 | t.Log(result) 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | 27 | wmClight := webmoney.WmClient{ 28 | Wmid: CnfLight.Wmid, 29 | Cert: CnfLight.Cert, 30 | Key: CnfLight.Key, 31 | } 32 | transaction1 := webmoney.GetOpers{ 33 | Purse: "Z311164609945", 34 | DateStart: "20160726 00:00:00", 35 | DateFinish: "20160922 00:00:00", 36 | } 37 | result1, err := wmClight.GetOperations(transaction1) 38 | fmt.Println(wmClight.ResultStr) 39 | fmt.Println(result1) 40 | if err != nil { 41 | t.Fatal(err) 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /tests/.x4_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | import "webmoney" 5 | import "fmt" 6 | 7 | func TestX4(t *testing.T) { 8 | wmCl := webmoney.WmClient{ 9 | Wmid: CnfClassic.Wmid, 10 | Key: CnfClassic.Wmid_key, 11 | Pass: CnfClassic.Wmid_pass, 12 | } 13 | invoices := webmoney.OutInvoices{ 14 | Purse: "R562831674289", 15 | DateStart: "20160622 00:00:00", 16 | DateFinish: "20160927 00:00:00", 17 | } 18 | result, err := wmCl.GetOutInvoices(invoices) 19 | 20 | t.Log(result) 21 | fmt.Println(result) 22 | fmt.Println(wmCl.ResultStr) 23 | if err != nil { 24 | t.Fatal(err) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /tests/.x5_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | 5 | import "webmoney" 6 | 7 | func TestX5(t *testing.T) { 8 | 9 | //create transactionf with pcode 10 | 11 | wmCl := webmoney.WmClient{ 12 | Wmid: CnfClassic.Wmid, 13 | Key: CnfClassic.Wmid_key, 14 | Pass: CnfClassic.Wmid_pass, 15 | } 16 | pcode := "testtest" 17 | tt := webmoney.Transaction{ 18 | TranId: "1999", 19 | PurseDest: "R988180789538", 20 | PurseSrc: "R562831674289", 21 | Amount: "3.2", 22 | Period: "1", 23 | Desc: "Теst кирилица", 24 | WmInvid: "0", 25 | OnlyAuth: "1", 26 | PCode: pcode, 27 | } 28 | 29 | result, err := wmCl.CreateTransaction(tt) 30 | 31 | if err != nil { 32 | t.Fatal(err) 33 | } 34 | 35 | wmClight := webmoney.WmClient{ 36 | Wmid: CnfLight.Wmid, 37 | Cert: CnfLight.Cert, 38 | Key: CnfLight.Key, 39 | } 40 | 41 | fp := webmoney.FinishProtect{ 42 | WmTranId: result.Ts, 43 | PCode: pcode, 44 | } 45 | 46 | result1, err := wmClight.DoFinishProtect(fp) 47 | if err != nil { 48 | t.Fatal(err) 49 | } 50 | t.Log(result1) 51 | 52 | } 53 | -------------------------------------------------------------------------------- /tests/.x6_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | import "webmoney" 5 | import "fmt" 6 | 7 | func TestX6(t *testing.T) { 8 | 9 | wmCl := webmoney.WmClient{ 10 | Wmid: CnfClassic.Wmid, 11 | Key: CnfClassic.Wmid_key, 12 | Pass: CnfClassic.Wmid_pass, 13 | } 14 | 15 | wmMsg := webmoney.SendMsg{ 16 | ReceiverWmid: "128756507061", 17 | MsgSubj: "testClassic", 18 | MsgText: "Тест сообщения через Классик кирилица", 19 | } 20 | 21 | result, err := wmCl.SendMessage(wmMsg) 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | 26 | fmt.Println(result) 27 | 28 | if result.MessageId <= 0 { 29 | t.Log(result) 30 | t.Fatal("Classic fatal test Message ID is empty !!! ") 31 | } 32 | 33 | wmClight := webmoney.WmClient{ 34 | Wmid: CnfLight.Wmid, 35 | Cert: CnfLight.Cert, 36 | Key: CnfLight.Key, 37 | } 38 | 39 | wmMsg1 := webmoney.SendMsg{ 40 | ReceiverWmid: "128756507061", 41 | MsgSubj: "testLight", 42 | MsgText: "Тест сообщения через Light кирилица", 43 | } 44 | 45 | result1, err := wmClight.SendMessage(wmMsg1) 46 | 47 | fmt.Println(wmClight.ResultStr) 48 | 49 | if err != nil { 50 | t.Fatal(err) 51 | } 52 | 53 | if result1.MessageId <= 0 { 54 | t.Log(result) 55 | t.Fatal("Light fatal Message ID is empty !!! ") 56 | } 57 | 58 | fmt.Println(result) 59 | } 60 | -------------------------------------------------------------------------------- /tests/.x7_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | import "webmoney" 5 | import "webmoney/wmsigner" 6 | 7 | func TestX7(t *testing.T) { 8 | wmCl := webmoney.WmClient{ 9 | Wmid: CnfClassic.Wmid, 10 | Key: CnfClassic.Wmid_key, 11 | Pass: CnfClassic.Wmid_pass, 12 | } 13 | signer := wmsigner.NewSigner(CnfClassic.Wmid, CnfClassic.Wmid_pass, CnfClassic.Wmid_key) 14 | teststring, err := signer.Sign("R562831674289") 15 | if err != nil { 16 | t.Fatal(err) 17 | } 18 | signature := webmoney.TestSignRequest{ 19 | Wmid: "128756507061", 20 | Plan: "R562831674289", 21 | Sign: teststring, 22 | } 23 | result, err := wmCl.TestSign(signature) 24 | if err != nil { 25 | t.Fatal(err) 26 | } else { 27 | t.Log(result) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/.x8_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | import "webmoney" 5 | 6 | import "fmt" 7 | 8 | func TestX8(t *testing.T) { 9 | wmCl := webmoney.WmClient{ 10 | Wmid: CnfClassic.Wmid, 11 | Key: CnfClassic.Wmid_key, 12 | Pass: CnfClassic.Wmid_pass, 13 | } 14 | testWm := webmoney.TestWmPurse{ 15 | Wmid: `128756507061`, 16 | } 17 | 18 | testPurse := webmoney.TestWmPurse{ 19 | Purse: `Z214605808008`, 20 | } 21 | testWmidPurse := webmoney.TestWmPurse{ 22 | Wmid: `128756507061`, 23 | Purse: `K133612664763`, 24 | } 25 | 26 | result, err := wmCl.FindWmidPurse(testWm) 27 | fmt.Println(result) 28 | t.Log(result) 29 | if err != nil { 30 | t.Fatal(err) 31 | } 32 | 33 | resultPurse, err1 := wmCl.FindWmidPurse(testPurse) 34 | fmt.Println(resultPurse) 35 | if err1 != nil { 36 | t.Fatal(err1) 37 | } 38 | if resultPurse.Purse.Value == "" { 39 | t.Fatal("Purse not valid") 40 | } else { 41 | fmt.Println(resultPurse.Purse.Value) 42 | } 43 | resultWmPurse, err2 := wmCl.FindWmidPurse(testWmidPurse) 44 | fmt.Println(resultWmPurse) 45 | if err2 != nil { 46 | t.Fatal(err2) 47 | } 48 | if resultWmPurse.Wmid.Value != `128756507061` || resultWmPurse.Purse.Value != `K133612664763` { 49 | t.Fatal("test with wmid and purse not valid") 50 | } else { 51 | fmt.Println(resultWmPurse.Wmid.Value) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/_x9_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | import "webmoney" 5 | 6 | func TestX9(t *testing.T) { 7 | wmCl := webmoney.WmClient{ 8 | Wmid: CnfClassic.Wmid, 9 | Key: CnfClassic.Wmid_key, 10 | Pass: CnfClassic.Wmid_pass, 11 | } 12 | p := webmoney.Purses{ 13 | Wmid: CnfClassic.Wmid, 14 | } 15 | result, err := wmCl.GetPurses4Wmid(p) 16 | if err != nil { 17 | t.Fatal(err) 18 | } 19 | t.Log(result) 20 | } 21 | -------------------------------------------------------------------------------- /tests/x2_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import "testing" 4 | import "webmoney" 5 | 6 | func TestClassicX2(t *testing.T) { 7 | wmClientClassic := webmoney.WmClient{ 8 | Wmid: CnfClassic.Wmid, 9 | Key: CnfClassic.Wmid_key, 10 | Pass: CnfClassic.Wmid_pass, 11 | } 12 | 13 | transaction := webmoney.Transaction{ 14 | TranId: "1001", 15 | PurseDest: "R305844543288", 16 | PurseSrc: "R562831674289", 17 | Amount: "3.2", 18 | Period: "1", 19 | Desc: "Теst кирилица", 20 | PCode: "", 21 | WmInvid: "0", 22 | OnlyAuth: "1", 23 | } 24 | 25 | result, err := wmClientClassic.CreateTransaction(transaction) 26 | 27 | t.Log(result) 28 | if err != nil { 29 | t.Fatal(err) 30 | } 31 | } 32 | 33 | func TestLightX2(t *testing.T) { 34 | wmCl := webmoney.WmClient{ 35 | Wmid: CnfLight.Wmid, 36 | Key: CnfLight.Key, 37 | Cert: CnfLight.Cert, 38 | } 39 | 40 | transaction := webmoney.Transaction{ 41 | TranId: "1002", 42 | PurseDest: "Z311164609945", 43 | PurseSrc: "Z214605808008", 44 | Amount: "1.03", 45 | Period: "1", 46 | Desc: "Текст кирилица", 47 | Pcode: "", 48 | WmInvid: "0", 49 | OnlyAuth: "1", 50 | } 51 | 52 | result, err := wmCl.CreateTransaction(transaction) 53 | 54 | t.Log(result) 55 | if err != nil { 56 | t.Fatal(err) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /w3s.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import ( 4 | "bytes" 5 | "encoding/xml" 6 | "errors" 7 | "fmt" 8 | "github.com/paulrosania/go-charset/charset" 9 | "strconv" 10 | 11 | "github.com/C0nstantin/go-webmoney/wmsigner" 12 | _ "github.com/paulrosania/go-charset/data" 13 | ) 14 | 15 | type Signed interface { 16 | GetSignSource(string) (string, error) 17 | } 18 | 19 | type W3s struct { 20 | Request Signed 21 | Result responseW3s 22 | ResultStr string 23 | Interface XInterface 24 | Client *WmClient 25 | } 26 | 27 | func (w3s *W3s) getResult(result interface{}) error { 28 | str, err := w3s.sendRequest() 29 | DebugLog(str) 30 | if err != nil { 31 | return fmt.Errorf("error after send request %w ", err) 32 | } 33 | if err := w3s.parseResponse(result, str); err != nil { 34 | return err 35 | } 36 | if w3s.Result.Retval != 0 { 37 | err := errors.New(strconv.FormatInt(w3s.Result.Retval, 10) + " " + w3s.Result.Retdesc) 38 | return err 39 | } 40 | return nil 41 | } 42 | func (w3s *W3s) GetResult(result interface{}) error { 43 | return w3s.getResult(result) 44 | } 45 | 46 | func (w3s *W3s) parseResponse(resp interface{}, responseStr string) error { 47 | v := responseW3s{ 48 | Response: resp, 49 | } 50 | 51 | r := bytes.NewReader([]byte(responseStr)) 52 | dec := xml.NewDecoder(r) 53 | dec.CharsetReader = charset.NewReader 54 | err := dec.Decode(&v) 55 | //err := xml.Unmarshal([]byte(responseStr), &v) 56 | if err != nil { 57 | return fmt.Errorf("error decode xml %w", err) 58 | } 59 | w3s.Result = v 60 | return nil 61 | } 62 | 63 | func (w3s *W3s) sendRequest() (string, error) { 64 | reqn := Reqn() 65 | v := &requestW3s{ 66 | Wmid: w3s.Client.Wmid, 67 | Reqn: reqn, 68 | } 69 | 70 | if w3s.Client.IsClassic() { 71 | s := wmsigner.NewSigner(w3s.Client.Wmid, w3s.Client.Pass, w3s.Client.Key) 72 | str, err := w3s.Request.GetSignSource(reqn) 73 | if err != nil { 74 | return "", fmt.Errorf("error get sign %w", err) 75 | } 76 | if w3s.Interface.Name == "ClassicAuth" || w3s.Interface.Name == "TrustSave2" { 77 | str = w3s.Client.Wmid + str 78 | } 79 | 80 | if result, err := s.Sign(str); err != nil { 81 | return "", err 82 | } else { 83 | v.Sign = result 84 | } 85 | 86 | } else { 87 | v.Sign = "" 88 | } 89 | url := w3s.Interface.GetUrl(w3s.Client.IsClassic()) 90 | v.Request = w3s.Request 91 | output, err := xml.MarshalIndent(v, " ", " ") 92 | if err != nil { 93 | return "", fmt.Errorf("error marshal body for request %w", err) 94 | } 95 | body := " \n" + string(output) 96 | DebugLog("w3s request: to " + url) 97 | DebugLog("return body: ", body) 98 | return w3s.Client.sendRequest(url, body) 99 | } 100 | -------------------------------------------------------------------------------- /wmsigner/README.md: -------------------------------------------------------------------------------- 1 | https://github.com/C0nstantin/go-webmoney#wm-signer 2 | -------------------------------------------------------------------------------- /wmsigner/wmsigner.go: -------------------------------------------------------------------------------- 1 | package wmsigner 2 | 3 | /* example for use 4 | 5 | s := signer.Newsigner(wmid,pass,key) 6 | 7 | signature := s.Sign(String) 8 | 9 | */ 10 | 11 | import ( 12 | "bytes" 13 | "crypto/rand" 14 | "encoding/base64" 15 | "encoding/binary" 16 | "errors" 17 | "fmt" 18 | "golang.org/x/crypto/md4" 19 | "math/big" 20 | "regexp" 21 | ) 22 | 23 | // NewSigner return wmsigner object with wmid, pass and key 24 | func NewSigner(wmid string, pass string, key string) *Wmsigner { 25 | return &Wmsigner{wmid, pass, key, nil} 26 | } 27 | 28 | /* 29 | function hashing butes slice to md4 30 | */ 31 | func md4Hash(buff []byte) []byte { 32 | hash := md4.New() 33 | hash.Write(buff) 34 | return hash.Sum(nil) 35 | } 36 | 37 | /* 38 | xor two byte slice 39 | */ 40 | func xorWm(buff []byte, hash []byte) []byte { 41 | b := bytes.NewBuffer([]byte{}) 42 | for i := 0; i < len(buff); i++ { 43 | b.WriteByte(buff[i] ^ hash[i%len(hash)]) 44 | } 45 | return b.Bytes() 46 | } 47 | 48 | /* 49 | reverse byte in bytes slice 50 | */ 51 | 52 | func reversebyte(s []byte) []byte { 53 | for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { 54 | s[i], s[j] = s[j], s[i] 55 | } 56 | return s 57 | } 58 | 59 | /*create bignum object from bytes.Buffer*/ 60 | func readBn(b *bytes.Buffer) *big.Int { 61 | var count uint16 62 | _ = binary.Read(b, binary.LittleEndian, &count) 63 | 64 | data := reversebyte(b.Next(int(count))) 65 | i := new(big.Int) 66 | i.SetBytes(data) 67 | return i 68 | } 69 | 70 | type Wmsigner struct { 71 | wmid string 72 | pass string 73 | key string 74 | err error 75 | } 76 | 77 | func (w *Wmsigner) Sign(data string) (string, error) { 78 | 79 | //check wmid 80 | if matched, _ := regexp.MatchString("[0-9]{12}", w.wmid); !matched { 81 | return "", errors.New("Wmid is incorrected") 82 | } 83 | 84 | //check key 85 | decode_key, err := base64.StdEncoding.DecodeString(w.key) 86 | if err != nil { 87 | 88 | return "", err 89 | } 90 | if len(decode_key) != 164 { 91 | return "", errors.New("Illegal size for keydata") 92 | } 93 | 94 | //checkpassword 95 | if len(w.pass) == 0 { 96 | return "", errors.New("Password can not to be empty!") 97 | } 98 | powers, modules := w.initkey() 99 | hash := md4Hash([]byte(data)) 100 | buf := bytes.NewBuffer(hash) 101 | var ini uint32 102 | //add rendom 40 bytes 103 | for i := 1; i <= 10; i++ { 104 | binary.Read(rand.Reader, binary.LittleEndian, &ini) 105 | ini = 0 106 | binary.Write(buf, binary.LittleEndian, ini) 107 | } 108 | hash = buf.Bytes() 109 | lenn := make([]byte, 2) 110 | binary.LittleEndian.PutUint16(lenn, uint16(len(hash))) 111 | b := bytes.NewBuffer(lenn) 112 | b.Write(hash) 113 | 114 | for b.Len() < len(modules.Bytes()) { 115 | b.WriteByte(byte(0)) 116 | } 117 | 118 | data_res := b.Bytes() 119 | data_res = reversebyte(data_res) 120 | i := new(big.Int) 121 | i.SetBytes(data_res) 122 | signature := i.Exp(i, powers, modules) 123 | 124 | sig := bytes.NewBuffer([]byte{}) 125 | for i := len(signature.Bytes()); i <= len(modules.Bytes()); i++ { 126 | sig.Write([]byte{0}) 127 | } 128 | sig.Write(signature.Bytes()) 129 | sigbyte := reversebyte(sig.Bytes()) 130 | sig = bytes.NewBuffer(sigbyte) 131 | var s = make([]uint16, len(sig.Bytes())/2) 132 | err = binary.Read(sig, binary.LittleEndian, s) 133 | if err != nil { 134 | return "", err 135 | } 136 | result := "" 137 | for _, val := range s { 138 | result += fmt.Sprintf("%04x", val) 139 | } 140 | 141 | return result, nil 142 | 143 | } 144 | 145 | func (w *Wmsigner) initkey() (*big.Int, *big.Int) { 146 | data, _ := base64.StdEncoding.DecodeString(w.key) 147 | 148 | r := bytes.NewBuffer(data) 149 | header := r.Next(30) 150 | body := r.Bytes() 151 | body = w.encryptKey(body) 152 | r = bytes.NewBuffer([]byte{}) 153 | 154 | r.Write(header) 155 | r.Write(body) 156 | 157 | reserved1 := r.Next(2) 158 | r.Next(2) 159 | crc := r.Next(16) 160 | length := r.Next(4) 161 | 162 | body = r.Bytes() 163 | r = bytes.NewBuffer([]byte{}) 164 | reserved1 = append(reserved1, byte(0), byte(0)) 165 | r.Write(reserved1) 166 | r.Write(bytes.Repeat([]byte{0}, 16)) 167 | r.Write(length) 168 | r.Write(body) 169 | 170 | calculated_crc := md4Hash(r.Bytes()) 171 | if !bytes.Equal(crc, calculated_crc) { 172 | if w.err == nil { 173 | w.pass = w.pass[0 : len(w.pass)/2] 174 | w.err = errors.New("invalid crc") 175 | return w.initkey() 176 | } else { 177 | return nil, nil 178 | 179 | } 180 | } 181 | r = bytes.NewBuffer(body) 182 | r.Next(4) 183 | powers := readBn(r) 184 | modules := readBn(r) 185 | return powers, modules 186 | 187 | } 188 | 189 | func (w *Wmsigner) encryptKey(buff []byte) []byte { 190 | hashResult := md4Hash([]byte(w.wmid + w.pass)) 191 | return xorWm(buff, hashResult) 192 | } 193 | 194 | func add_tobegin(b []byte, bb []byte) { 195 | buf := bytes.NewBuffer(bb) 196 | buf.Write(b) 197 | b = buf.Bytes() 198 | } 199 | -------------------------------------------------------------------------------- /wmstring.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import "fmt" 4 | import "strings" 5 | import "strconv" 6 | 7 | type WmString string 8 | 9 | func (w WmString) IsCompatibleWithWmXml() bool { 10 | for _, ch := range w { 11 | if ch >= '\u0400' && ch <= '\u052F' || ch >= '\u0000' && ch <= '\u007F' || ch == '\u2116' || ch == '\u2212' || ch == '\u00AB' || ch == '\u00BB' || ch == '\u2010' || ch == '\u2013' || ch == '\u2014' { 12 | continue 13 | } 14 | return false 15 | } 16 | return true 17 | } 18 | 19 | func (w WmString) IsWmEncoded() bool { 20 | s := strings.ToLower(string(w)) 21 | 22 | if !strings.HasPrefix(s, w.Prefix()) { 23 | return false 24 | } 25 | 26 | for i := len(w.Prefix()); i < len(s); i++ { 27 | ch := rune(w[i]) 28 | switch ch { 29 | case '0': 30 | case '1': 31 | case '2': 32 | case '3': 33 | case '4': 34 | case '5': 35 | case '6': 36 | case '7': 37 | case '8': 38 | case '9': 39 | case 'a': 40 | case 'b': 41 | case 'c': 42 | case 'd': 43 | case 'e': 44 | case 'f': 45 | case ';': 46 | break 47 | default: 48 | return false 49 | } 50 | 51 | } 52 | 53 | return true 54 | } 55 | 56 | func (w WmString) Prefix() string { 57 | return "u:" 58 | } 59 | 60 | func (w WmString) ToWmString() string { 61 | s := strings.ToLower(string(w)) 62 | if w.IsCompatibleWithWmXml() { 63 | s = strings.ReplaceAll(s, string("\u2212"), "-") 64 | s = strings.ReplaceAll(s, "—", "-") 65 | return s 66 | } 67 | DebugLog("String in WmString.ToWmString", s) 68 | retval := w.Prefix() 69 | for _, c := range s { 70 | retval += fmt.Sprintf("%x;", c) 71 | } 72 | return retval 73 | } 74 | 75 | func (w WmString) FromWmString() string { 76 | 77 | if !w.IsWmEncoded() { 78 | s := strings.ToLower(string(w)) 79 | return s 80 | } 81 | 82 | elements := strings.Split(string(w), ":") 83 | el := strings.Split(elements[1], ";") 84 | retval := "" 85 | 86 | for _, i := range el { 87 | if len(i) == 0 { 88 | continue 89 | } 90 | if s, err := strconv.ParseInt(i, 16, 64); err == nil { 91 | retval += string(fmt.Sprintf("%c", s)) 92 | } 93 | } 94 | 95 | return retval 96 | 97 | } 98 | -------------------------------------------------------------------------------- /x1.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // Sending invoice from merchant to customer. 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X1 9 | 10 | //use in client 11 | /*w = new WmClient {Wmid: "", Cert:"", Key:""} 12 | 13 | s,_ := w.SendInvoice(new Invoice{ 14 | OrderId: "", 15 | CustomerWmid:"", 16 | .... 17 | }) 18 | s.Ts*/ 19 | 20 | package webmoney 21 | 22 | import ( 23 | "encoding/xml" 24 | ) 25 | 26 | type Invoice struct { 27 | XMLName xml.Name `xml:"invoice"` 28 | OrderId string `xml:"orderid"` 29 | CustomerWmid string `xml:"customerwmid"` 30 | StorePurse string `xml:"storepurse"` 31 | Amount string `xml:"amount"` 32 | Desc string `xml:"desc"` 33 | Address string `xml:"address"` 34 | Period string `xml:"period"` 35 | Expiration string `xml:"expiration"` 36 | OnlyAuth string `xml:"onlyauth"` 37 | Lmi_shop_id string `xml:"lmi_shop_id"` 38 | } 39 | 40 | func (i Invoice) GetSignSource(reqn string) (string, error) { 41 | desc, err := Utf8ToWin(i.Desc) 42 | if err != nil { 43 | return "", err 44 | } 45 | address, err := Utf8ToWin(i.Address) 46 | if err != nil { 47 | return "", err 48 | } 49 | return string(i.OrderId) + 50 | i.CustomerWmid + 51 | i.StorePurse + 52 | i.Amount + 53 | desc + 54 | address + 55 | i.Period + 56 | i.Expiration + 57 | reqn, nil 58 | } 59 | 60 | type InvoiceResponse struct { 61 | Id string `xml:"id,attr"` 62 | Ts string `xml:"ts,attr"` 63 | OrderId string `xml:"orderid"` 64 | CustomerWmid string `xml:"customerwmid"` 65 | StorePurse string `xml:"storepurse"` 66 | Amount string `xml:"amount"` 67 | Desc string `xml:"desc"` 68 | Address string `xml:"address"` 69 | Period string `xml:"period"` 70 | Expiration string `xml:"expiration"` 71 | State string `xml:"state"` 72 | DateCrt string `xml:"datecrt"` 73 | DateUpd string `xml:"dateupd"` 74 | WmTranId string `xml:"wmtranid"` 75 | } 76 | 77 | func (w *WmClient) SendInvoice(i Invoice) (InvoiceResponse, error) { 78 | X := W3s{ 79 | Request: i, 80 | Interface: XInterface{Name: "Invoice", Type: "w3s"}, 81 | Client: w, 82 | } 83 | result := InvoiceResponse{} 84 | err := X.getResult(&result) 85 | return result, err 86 | } 87 | -------------------------------------------------------------------------------- /x10.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // desc 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X10 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | ) 15 | 16 | type InInvoices struct { 17 | XMLName xml.Name `xml:"getininvoices"` 18 | Wmid string `xml:"wmid"` 19 | WmInvid string `xml:"wminvid"` 20 | DateStart string `xml:"datestart"` 21 | DateFinish string `xml:"datefinish"` 22 | } 23 | 24 | func (i InInvoices) GetSignSource(reqn string) (string, error) { 25 | return i.Wmid + i.WmInvid + i.DateStart + i.DateFinish + reqn, nil 26 | } 27 | 28 | type InInvoicesResponse struct { 29 | XMLName xml.Name `xml:"ininvoices"` 30 | InvoiceList []InvoiceResponse `xml:"ininvoices"` 31 | } 32 | 33 | func (w *WmClient) GetInInvoices(i InInvoices) (InInvoicesResponse, error) { 34 | X := W3s{ 35 | Interface: XInterface{Name: "InInvoices", Type: "w3s"}, 36 | Request: i, 37 | Client: w, 38 | } 39 | 40 | result := InInvoicesResponse{} 41 | err := X.getResult(&result) 42 | return result, err 43 | } 44 | -------------------------------------------------------------------------------- /x11.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import ( 4 | "bytes" 5 | "encoding/xml" 6 | "errors" 7 | "fmt" 8 | "github.com/paulrosania/go-charset/charset" 9 | _ "github.com/paulrosania/go-charset/data" 10 | "io" 11 | "net/http" 12 | "os" 13 | "strings" 14 | ) 15 | 16 | var ( 17 | ErrAttestatRecalled = errors.New("attestat recalled") 18 | ErrAttestatNotFound = errors.New("attestat not found") 19 | ) 20 | 21 | type RequestX11 struct { 22 | XMLName xml.Name `xml:"request"` 23 | Wmid string `xml:"wmid"` 24 | PassportWmid string `xml:"passportwmid"` 25 | Sign string `xml:"sign"` 26 | Dict string `xml:"params>dict"` 27 | Info string `xml:"params>info"` 28 | Mode string `xml:"params>mode"` 29 | } 30 | 31 | type ResponseX11 struct { 32 | XMLName xml.Name `xml:"response"` 33 | Retval int `xml:"retval,attr"` 34 | CertInfo CertInfo `xml:"certinfo"` 35 | } 36 | 37 | type CertInfo struct { 38 | XMLName xml.Name `xml:"certinfo"` 39 | Attestat Attestat `xml:"attestat>row"` 40 | Wmid string `xml:"wmid,attr"` 41 | Wmids []WmidP `xml:"wmids>row"` 42 | UserInfo UserInfo `xml:"userinfo>value>row"` 43 | } 44 | 45 | type WmidP struct { 46 | XMLName xml.Name `xml:"row"` 47 | Wmid string `xml:"wmid,attr"` 48 | Info string `xml:"info,attr"` 49 | Nickname string `xml:"nickname,attr"` 50 | Datereg string `xml:"datereg,attr"` 51 | Ctype string `xml:"ctype,attr"` 52 | Companyname string `xml:"companyname,attr"` 53 | Companyid string `xml:"companyid,attr"` 54 | } 55 | 56 | type UserInfo struct { 57 | XMLName xml.Name `xml:"row"` 58 | Nickname string `xml:"nickname,attr"` 59 | Country string `xml:"country,attr"` 60 | City string `xml:"city,attr"` 61 | Zipcode string `xml:"zipcode,attr"` 62 | Adres string `xml:"adres,attr"` 63 | Fname string `xml:"fname,attr"` 64 | Iname string `xml:"iname,attr"` 65 | Oname string `xml:"oname,attr"` 66 | Pnomer string `xml:"pnomer,attr"` 67 | Pdate string `xml:"pdate,attr"` 68 | Pdateend string `xml:"pdateend,attr"` 69 | Pcountry string `xml:"pcountry,attr"` 70 | Pbywhom string `xml:"pbywhom,attr"` 71 | Inn string `xml:"inn,attr"` 72 | Bplace string `xml:"bplace,attr"` 73 | Bday string `xml:"bday,attr"` 74 | Bmonth string `xml:"bmonth,attr"` 75 | Byear string `xml:"byear,attr"` 76 | Icq string `xml:"icq,attr"` 77 | Email string `xml:"email,attr"` 78 | Web string `xml:"web,attr"` 79 | Phone string `xml:"phone,attr"` 80 | CapOwner string `xml:"cap_owner,attr"` 81 | Pasdoc string `xml:"pasdoc,attr"` 82 | Regdoc string `xml:"regdoc,attr"` 83 | Inndoc string `xml:"inndoc,attr"` 84 | Photoid string `xml:"phoneid,attr"` 85 | Jabberid string `xml:"jabberid,attr"` 86 | Sex string `xml:"sex,attr"` 87 | Infoopen string `xml:"infoopen,attr"` 88 | } 89 | 90 | type Attestat struct { 91 | TID string `xml:"tid,attr"` 92 | Recalled string `xml:"recalled,attr"` 93 | Datecrt string `xml:"datecrt,attr"` 94 | Dateupd string `xml:"dateupd,attr"` 95 | Regnikname string `xml:"regnickname,attr"` 96 | Regwmid string `xml:"regwmid,attr"` 97 | Status string `xml:"status,attr"` 98 | Notary string `xml:"notary,attr"` 99 | } 100 | 101 | func IssetWmid(wmid string) (bool, error) { 102 | if result, err := GetInfoWmid(wmid); result.CertInfo.Wmid == "" || err != nil { 103 | return false, err 104 | } 105 | return true, nil 106 | } 107 | 108 | func GetInfoWmid(wmid string) (ResponseX11, error) { 109 | v := RequestX11{PassportWmid: wmid} 110 | v1 := ResponseX11{} 111 | out, err := xml.MarshalIndent(v, " ", " ") 112 | if err != nil { 113 | return v1, err 114 | } 115 | apiPassportDomain := "apipassport.web.money" 116 | if v, ok := os.LookupEnv("API_PASSPORT_DOMAIN"); ok { 117 | apiPassportDomain = v 118 | } 119 | resp, err := http.Post(fmt.Sprintf("https://%s/asp/XMLGetWMPassport.asp", apiPassportDomain), "text/xml", strings.NewReader(string(out))) 120 | if err != nil { 121 | return v1, err 122 | } 123 | body, err := io.ReadAll(resp.Body) 124 | defer resp.Body.Close() 125 | if err != nil { 126 | return v1, err 127 | } 128 | r := bytes.NewReader(body) 129 | dec := xml.NewDecoder(r) 130 | dec.CharsetReader = charset.NewReader 131 | err = dec.Decode(&v1) 132 | if err != nil { 133 | return ResponseX11{}, err 134 | } 135 | 136 | if v1.CertInfo.Attestat.Recalled == "1" { 137 | 138 | return v1, ErrAttestatRecalled 139 | } 140 | 141 | if v1.CertInfo.Attestat.TID != "" { 142 | return v1, nil 143 | } else { 144 | return v1, ErrAttestatNotFound 145 | } 146 | 147 | } 148 | 149 | func WMPassportByWmid(wmid string) (*ResponseX11, error) { 150 | v := RequestX11{PassportWmid: wmid} 151 | 152 | out, err := xml.MarshalIndent(v, " ", " ") 153 | if err != nil { 154 | return nil, err 155 | } 156 | apiPassportDomain := "apipassport.web.money" 157 | if v, ok := os.LookupEnv("API_PASSPORT_DOMAIN"); ok { 158 | apiPassportDomain = v 159 | } 160 | resp, err := http.Post(fmt.Sprintf("https://%s/asp/XMLGetWMPassport.asp", apiPassportDomain), "text/xml", strings.NewReader(string(out))) 161 | if err != nil { 162 | return nil, err 163 | } 164 | body, err := io.ReadAll(resp.Body) 165 | defer resp.Body.Close() 166 | if err != nil { 167 | return nil, err 168 | } 169 | r := bytes.NewReader(body) 170 | dec := xml.NewDecoder(r) 171 | dec.CharsetReader = charset.NewReader 172 | v1 := &ResponseX11{} 173 | err = dec.Decode(v1) 174 | if err != nil { 175 | return nil, err 176 | } 177 | return v1, nil 178 | 179 | } 180 | 181 | func (w *WmClient) GetInfoWmid(wmid string) (ResponseX11, error) { 182 | return GetInfoWmid(wmid) 183 | } 184 | 185 | func (w *WmClient) IssetWmid(wmid string) (bool, error) { 186 | return IssetWmid(wmid) 187 | } 188 | -------------------------------------------------------------------------------- /x13.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // desc 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X13 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | ) 15 | 16 | type RejectProtect struct { 17 | XMLName xml.Name `xml:"rejectprotect"` 18 | WmTranId string `xml:"wmtranid"` 19 | } 20 | 21 | func (i RejectProtect) GetSignSource(reqn string) (string, error) { 22 | return i.WmTranId + reqn, nil 23 | } 24 | 25 | func (w *WmClient) RejectProtect(i RejectProtect) (Operation, error) { 26 | 27 | X := W3s{ 28 | Interface: XInterface{Name: "RejectProtect", Type: "w3s"}, 29 | Request: i, 30 | Client: w, 31 | } 32 | 33 | result := Operation{} 34 | err := X.getResult(&result) 35 | return result, err 36 | } 37 | -------------------------------------------------------------------------------- /x14.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // Sending invoice from merchant to customer. 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X14 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | ) 15 | 16 | type Trans struct { 17 | XMLName xml.Name `xml:"trans"` 18 | InWmTranId string `xml:"inwmtranid"` 19 | Amount string `xml:"amount"` 20 | MoneyBackPhone string `xml:"moneybackphone"` 21 | } 22 | 23 | func (t Trans) GetSignSource(reqn string) (string, error) { 24 | return reqn + t.InWmTranId + t.Amount, nil 25 | } 26 | 27 | func (w *WmClient) MoneyBack(t Trans) (Operation, error) { 28 | 29 | X := W3s{ 30 | Interface: XInterface{Name: "TransMoneyback", Type: "w3s"}, 31 | Request: t, 32 | Client: w, 33 | } 34 | 35 | result := Operation{} 36 | 37 | err := X.getResult(&result) 38 | return result, err 39 | } 40 | -------------------------------------------------------------------------------- /x15.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // desc 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X15 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | ) 15 | 16 | type TrustList struct { 17 | XMLName xml.Name `xml:"gettrustlist"` 18 | Wmid string `xml:"wmid"` 19 | } 20 | 21 | func (t TrustList) GetSignSource(reqn string) (string, error) { 22 | return t.Wmid + reqn, nil 23 | } 24 | 25 | type TrustListResponse struct { 26 | XMLName xml.Name `xml:"trustlist"` 27 | Cnt string `xml:"cnt,attr"` 28 | TrustList []Trust `xml:"trastlist"` 29 | } 30 | 31 | type Trust struct { 32 | XMLName xml.Name `xml:"trast"` 33 | Id string `xml:"id,attr"` 34 | Inv string `xml:"inv,attr"` 35 | Trast string `xml:"trans,attr"` 36 | PurseAttr string `xml:"purse,attr"` 37 | TransHist string `xml:"transhist"` 38 | Master string `xml:"master"` 39 | Purse string `xml:"purse"` 40 | DayLimit string `xml:"daylimit"` 41 | DLimit string `xml:"dlimit"` 42 | WLimit string `xml:"wlimit"` 43 | MLimit string `xml:"mlimit"` 44 | DSum string `xml:"dsum"` 45 | WSum string `xml:"wsum"` 46 | MSum string `xml:"msum"` 47 | LastSumDate string `xml:"lastsumdate"` 48 | } 49 | 50 | type TrustSave struct { 51 | XMLName xml.Name `xml:"trust"` 52 | Inv string `xml:"inv,attr"` 53 | Trans string `xml:"trans,attr"` 54 | PurseAttr string `xml:"purse,attr"` 55 | TransHist string `xml:"transhist"` 56 | MasterWmid string `xml:"masterwmid"` 57 | SlaveWmid string `xml:"slavewmid"` 58 | Purse string `xml:"purse"` 59 | Limit string `xml:"limit"` 60 | DayLimit string `xml:"daylimit"` 61 | WeekLimit string `xml:"weeklimit"` 62 | MonthLimit string `xml:"monthlimit"` 63 | } 64 | 65 | func (t TrustSave) GetSignSource(reqn string) (string, error) { 66 | return t.Purse + t.MasterWmid + reqn, nil 67 | } 68 | 69 | //func GetTrastList 70 | func (w *WmClient) GetTrustList(t TrustList) (TrustListResponse, error) { 71 | var InterfaceName string 72 | 73 | if w.Wmid != t.Wmid { 74 | InterfaceName = "TrustList2" 75 | } else { 76 | InterfaceName = "TrustList" 77 | } 78 | X := W3s{ 79 | Interface: XInterface{Name: InterfaceName, Type: "w3s"}, 80 | Request: t, 81 | Client: w, 82 | } 83 | result := TrustListResponse{} 84 | err := X.getResult(&result) 85 | return result, err 86 | } 87 | 88 | func (w *WmClient) SetTrust(t TrustSave) (Trust, error) { 89 | X := W3s{ 90 | Interface: XInterface{Name: "TrustSave2", Type: "w3s"}, 91 | Request: t, 92 | Client: w, 93 | } 94 | 95 | result := Trust{} 96 | err := X.getResult(&result) 97 | return result, err 98 | } 99 | -------------------------------------------------------------------------------- /x16.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // desc 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X16 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | ) 15 | 16 | type Purse struct { 17 | XMLName xml.Name `xml:"createpurse"` 18 | Wmid string `xml:"wmid"` 19 | PurseType string `xml:"pursetype"` 20 | Desc string `xml:"desc"` 21 | } 22 | 23 | func (p Purse) GetSignSource(reqn string) (string, error) { 24 | return p.Wmid + p.PurseType + reqn, nil 25 | } 26 | 27 | type PurseResponse struct { 28 | XMLName xml.Name `xml:"purse"` 29 | Id string `xml:"id,attr"` 30 | PurseName string `xml:"pursename"` 31 | Amount string `xml:"amount"` 32 | Desc string `xml:"desc"` 33 | } 34 | 35 | func (w *WmClient) CreatePurse(p Purse) (PurseResponse, error) { 36 | X := W3s{ 37 | Interface: XInterface{Name: "CreatePurse", Type: "w3s"}, 38 | Client: w, 39 | Request: p, 40 | } 41 | 42 | result := PurseResponse{} 43 | err := X.getResult(&result) 44 | return result, err 45 | } 46 | -------------------------------------------------------------------------------- /x18.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import "encoding/xml" 4 | 5 | type X18Request struct { 6 | merchantRequest 7 | LmiPayeePurse string `xml:"lmi_payee_purse"` 8 | LmiPaymentNo string `xml:"lmi_payment_no"` 9 | LmiPaymentNoType string `xml:"lmi_payment_no_type"` 10 | } 11 | 12 | func (x X18Request) GetSignSource(s string) (string, error) { 13 | return x.LmiPayeePurse + x.LmiPaymentNo + s, nil 14 | } 15 | 16 | type MerchantOperation struct { 17 | XmlName xml.Name `xml:"operation"` 18 | Wmtransid string `xml:"wmtransid,attr"` 19 | Wminvoiceid string `xml:"wminvoiceid,attr"` 20 | Realsmstype string `xml:"realsmstype"` 21 | Amount string `xml:"amount"` 22 | Operdate string `xml:"operdate"` 23 | Purpose string `xml:"purpose"` 24 | Purposefrom string `xml:"pursefrom"` 25 | Wmidfrom string `xml:"wmidfrom"` 26 | HoldPeriod string `xml:"hold_period"` 27 | HoldState string `xml:"hold_state"` 28 | Capitallerflag string `xml:"capitallerflag"` 29 | Enumflag string `xml:"enumflag"` 30 | IPAddress string `xml:"IPAddress"` 31 | TelepayPhone string `xml:"telepat_phone"` 32 | TelepayPaytype string `xml:"telepat_paytype"` 33 | PaymerNumber string `xml:"paymer_number"` 34 | PaymerEmail string `xml:"paymer_email"` 35 | PaymerType string `xml:"paymer_type"` 36 | CashierNumber string `xml:"cashier_number"` 37 | CashierDate string `xml:"cashier_date"` 38 | CashierAmount string `xml:"cashier_amount"` 39 | SdpType string `xml:"sdp_type"` 40 | } 41 | 42 | func (w *WmClient) TransGet(m X18Request) (MerchantOperation, error) { 43 | 44 | X := Merchant{ 45 | Request: &m, 46 | Interface: XInterface{Name: "TransGet", Type: "merchant"}, 47 | Client: w, 48 | } 49 | result := struct { 50 | merchantResponse 51 | Operation MerchantOperation 52 | }{} 53 | err := X.getResult(&result) 54 | 55 | return result.Operation, err 56 | } 57 | -------------------------------------------------------------------------------- /x19.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | -------------------------------------------------------------------------------- /x2.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | 7 | // Create Transaction 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X2 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | ) 15 | 16 | type Transaction struct { 17 | XMLName xml.Name `xml:"trans"` 18 | TranId string `xml:"tranid"` 19 | PurseSrc string `xml:"pursesrc"` 20 | PurseDest string `xml:"pursedest"` 21 | Amount string `xml:"amount"` 22 | Period string `xml:"period"` 23 | Desc string `xml:"desc"` 24 | PCode string `xml:"pcode"` 25 | WmInvid string `xml:"wminvid"` 26 | OnlyAuth string `xml:"onlyauth"` 27 | } 28 | 29 | func (t Transaction) GetSignSource(reqn string) (string, error) { 30 | var desc string 31 | if t.Period == "" { 32 | t.Period = "0" 33 | } 34 | desc, err := Utf8ToWin(t.Desc) 35 | if desc != "" && err != nil { 36 | return "", err 37 | } 38 | 39 | return reqn + 40 | t.TranId + 41 | t.PurseSrc + 42 | t.PurseDest + 43 | t.Amount + 44 | string(t.Period) + 45 | t.PCode + 46 | desc + 47 | t.WmInvid, nil 48 | } 49 | 50 | type Operation struct { 51 | XMLName xml.Name `xml:"operation"` 52 | Id string `xml:"id,attr"` 53 | Ts string `xml:"ts,attr"` 54 | TranId string `xml:"tranid"` 55 | PurseSrc string `xml:"pursesrc"` 56 | PurseDest string `xml:"pursedest"` 57 | Amount string `xml:"amount"` 58 | Commis string `xml:"comiss"` 59 | Opertype string `xml:"opertype"` 60 | Period string `xml:"period"` 61 | WmInvid string `xml:"wminvid"` 62 | Desc string `xml:"desc"` 63 | DateCrt string `xml:"datecrt"` 64 | DateUpd string `xml:"dateupd"` 65 | CorrWm string `xml:"corrwm"` 66 | Rest string `xml:"rest"` 67 | TimeLock bool `xml:"timelock"` 68 | } 69 | 70 | func (w *WmClient) CreateTransaction(t Transaction) (Operation, error) { 71 | 72 | X := W3s{ 73 | Request: t, 74 | Interface: XInterface{Name: "Trans", Type: "w3s"}, 75 | Client: w, 76 | } 77 | 78 | result := Operation{} 79 | err := X.getResult(&result) 80 | 81 | return result, err 82 | 83 | } 84 | -------------------------------------------------------------------------------- /x20.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | type X20Request struct { 4 | merchantRequest 5 | LmiPayeePurse string `xml:"lmi_payee_purse"` 6 | LmiPaymentNo string `xml:"lmi_payment_no"` 7 | LmiPaymentNoType string `xml:"lmi_payment_no_type"` 8 | LmiPaymentAmount string `xml:"lmi_payment_amount"` 9 | LmiPaymentDesc string `xml:"lmi_payment_desc"` 10 | LmiPaymentDescBase64 string `xml:"lmi_payment_desc_base64"` 11 | LmiClientnumber string `xml:"lmi_clientnumber"` 12 | LmiClientnubmerType string `xml:"lmi_clientnumber_type"` 13 | LmiSmsType string `xml:"lmi_sms_type"` 14 | LmiShopId string `xml:"lmi_shop_id"` 15 | LmiHold string `xml:"LMI_HOLD"` 16 | Lang string `xml:"lang"` 17 | EnulatedFlag string `xml:"emulated_flag"` 18 | } 19 | 20 | func (x X20Request) GetSignSource(s string) (string, error) { 21 | return x.LmiPayeePurse + x.LmiPaymentNo + x.LmiClientnumber + x.LmiClientnubmerType, nil 22 | } 23 | 24 | type X202Request struct { 25 | merchantRequest 26 | LmiPayeePurse string `xml:"lmi_payee_purse"` 27 | LmiClientnumberCode string `xml:"lmi_clientnumber_code"` 28 | LmiWminvoiceid string `xml:"lmi_wminvoiceid"` 29 | } 30 | 31 | func (x X202Request) GetSignSource(s string) (string, error) { 32 | return x.LmiPayeePurse + x.LmiWminvoiceid + x.LmiClientnumberCode, nil 33 | } 34 | 35 | func (w *WmClient) TransRequest(x X20Request) (MerchantOperation, error) { 36 | X := Merchant{ 37 | Request: &x, 38 | Interface: XInterface{Name: "TransRequest", Type: "merchant"}, 39 | Client: w, 40 | } 41 | result := struct { 42 | merchantResponse 43 | Operation MerchantOperation 44 | }{} 45 | err := X.getResult(&result) 46 | 47 | return result.Operation, err 48 | } 49 | 50 | func (w *WmClient) TransConfirm(x X202Request) (MerchantOperation, error) { 51 | 52 | X := Merchant{ 53 | Request: &x, 54 | Interface: XInterface{Name: "TransConfirm", Type: "merchant"}, 55 | Client: w, 56 | } 57 | 58 | result := struct { 59 | merchantResponse 60 | Operation MerchantOperation 61 | }{} 62 | err := X.getResult(&result) 63 | 64 | return result.Operation, err 65 | } 66 | -------------------------------------------------------------------------------- /x21.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import "encoding/xml" 4 | 5 | type X21Request struct { 6 | merchantRequest 7 | LmiPayeePurse string `xml:"lmi_payee_purse"` 8 | LmiDayLimit string `xml:"lmi_day_limit"` 9 | LmiWeekLimit string `xml:"lmi_week_limit"` 10 | LmiMonthLimit string `xml:"lmi_month_limit"` 11 | LmiClientnumber string `xml:"lmi_clientnumber"` 12 | LmiClientnubmerType string `xml:"lmi_clientnumber_type"` 13 | LmiSmsType string `xml:"lmi_sms_type"` 14 | Lang string `xml:"lang"` 15 | } 16 | 17 | func (x X21Request) GetSignSource(s string) (string, error) { 18 | return x.LmiPayeePurse + x.LmiClientnumber + x.LmiClientnubmerType + x.LmiSmsType, nil 19 | 20 | } 21 | 22 | type X21Response struct { 23 | merchantResponse 24 | Slavepurse string `xml:"slavepurse"` 25 | Slavewmid string `xml:"slavewmid"` 26 | Smssecureid string `xml:"smssecureid"` 27 | TrustX21 TrustX21 `xml:"trust"` 28 | } 29 | type TrustX21 struct { 30 | XMLName xml.Name `xml:"trust"` 31 | PurseId string `xml:"purseid,attr"` 32 | RealsmsType string `xml:"realsmstype"` 33 | } 34 | 35 | type X212Request struct { 36 | merchantRequest 37 | LmiPurseId string `xml:"lmi_purseid"` 38 | LmiClientnumberCode string `xml:"lmi_clientnumber_code"` 39 | } 40 | type TrustX212 struct { 41 | XMLName xml.Name `xml:"trust"` 42 | Id string `xml:"id,attr"` 43 | Slavepurse string `xml:"slavepurse"` 44 | Slavewmid string `xml:"slavewmid"` 45 | Masterwmid string `xml:"masterwmid"` 46 | } 47 | type X212Response struct { 48 | merchantResponse 49 | TrustX212 TrustX212 `xml:"trust"` 50 | Smssentstate string `xml:"smssentstate"` 51 | } 52 | 53 | func (x X212Request) GetSignSource(s string) (string, error) { 54 | return x.LmiPurseId + x.LmiClientnumberCode, nil 55 | } 56 | 57 | func (w *WmClient) TrustRequest(x X21Request) (X21Response, error) { 58 | 59 | X := Merchant{ 60 | Request: &x, 61 | Interface: XInterface{Name: "TrustRequest", Type: "merchant"}, 62 | Client: w, 63 | } 64 | 65 | result := X21Response{} 66 | err := X.getResult(&result) 67 | 68 | return result, err 69 | } 70 | func (w *WmClient) TrustConfirm(x X212Request) (X212Response, error) { 71 | 72 | X := Merchant{ 73 | Request: &x, 74 | Interface: XInterface{Name: "TrustConfirm", Type: "merchant"}, 75 | Client: w, 76 | } 77 | 78 | result := X212Response{} 79 | err := X.getResult(&result) 80 | 81 | return result, err 82 | } 83 | -------------------------------------------------------------------------------- /x22.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import "encoding/xml" 4 | 5 | type Paymenttags struct { 6 | LmiPayeePurse string `xml:"lmi_payee_purse"` 7 | LmiPaymentNo string `xml:"lmi_payment_no"` 8 | LmiPaymentNoType string `xml:"lmi_payment_no_type"` 9 | LmiPaymentAmount string `xml:"lmi_payment_amount"` 10 | LmiPaymentDesc string `xml:"lmi_payment_desc"` 11 | LmiPaymentDescBase64 string `xml:"lmi_payment_desc_base64"` 12 | LmiClientnumber string `xml:"lmi_clientnumber"` 13 | LmiClientnubmerType string `xml:"lmi_clientnumber_type"` 14 | LmiSmsType string `xml:"lmi_sms_type"` 15 | LmiShopId string `xml:"lmi_shop_id"` 16 | LmiHold string `xml:"LMI_HOLD"` 17 | Lang string `xml:"lang"` 18 | EnulatedFlag string `xml:"emulated_flag"` 19 | } 20 | 21 | type X22Request struct { 22 | XMLName xml.Name `xml:"merchant.request"` 23 | Wmid string `xml:"signtags>wmid"` 24 | Sign string `xml:"signtags>sign"` 25 | Sha256 string `xml:"signtags>sha256"` 26 | Md5 string `xml:"signtags>md5"` 27 | SecretKey string `xml:"signtags>secret_key"` 28 | Lang string `xml:"signtags>lang"` 29 | Validityperiodinhours string `xml:"signtags>validityperiodinhours"` 30 | Paymenttags Paymenttags `xml:"paymenttags"` 31 | } 32 | 33 | func (x *X22Request) setWmid(s string) { 34 | x.Wmid = s 35 | 36 | } 37 | 38 | func (x *X22Request) setSign(s string) { 39 | x.Sign = s 40 | 41 | } 42 | 43 | func (x *X22Request) setSha256(s string) { 44 | x.Sha256 = s 45 | 46 | } 47 | 48 | func (x *X22Request) GetSignSource(s string) (string, error) { 49 | return x.Paymenttags.LmiPayeePurse + x.Paymenttags.LmiPaymentNo + x.Validityperiodinhours, nil 50 | } 51 | 52 | type X22Response struct { 53 | merchantResponse 54 | Transtoken string `xml:"transtoken"` 55 | Validityperiodinhours string `xml:"validityperiodinhours"` 56 | } 57 | 58 | func (w *WmClient) TransSave(x X22Request) (X22Response, error) { 59 | X := Merchant{ 60 | Request: &x, 61 | Interface: XInterface{Name: "TransSave", Type: "merchant"}, 62 | Client: w, 63 | } 64 | result := X22Response{} 65 | err := X.getResult(&result) 66 | return result, err 67 | } 68 | -------------------------------------------------------------------------------- /x23.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | type InvoiceRefuse struct { 8 | XMLName xml.Name `xml:"invoicerefuse"` 9 | Wmid string `xml:"wmid"` 10 | Wminvid string `xml:"wminvid"` 11 | } 12 | 13 | func (i InvoiceRefuse) GetSignSource(reqn string) (string, error) { 14 | return i.Wmid + i.Wminvid + reqn, nil 15 | } 16 | 17 | type InvoiceRefuseResponse struct { 18 | Id string `xml:"id,attr"` 19 | Ts string `xml:"ts,attr"` 20 | State string `xml:"state"` 21 | DateUpd string `xml:"dateupd"` 22 | } 23 | 24 | func (w *WmClient) RefuseInvoice(i InvoiceRefuse) (InvoiceRefuseResponse, error) { 25 | X := W3s{ 26 | Client: w, 27 | Interface: XInterface{Name: "InvoiceRefusal", Type: "w3s"}, 28 | Request: i, 29 | } 30 | result := InvoiceRefuseResponse{} 31 | err := X.getResult(&result) 32 | return result, err 33 | } 34 | -------------------------------------------------------------------------------- /x3.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | 7 | // Receiving Transaction History. Checking Transaction Status. 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X3 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | ) 15 | 16 | type GetOpers struct { 17 | XMLName xml.Name `xml:"getoperations"` 18 | Purse string `xml:"purse"` 19 | WmTranId string `xml:"wmtranid"` 20 | TranId string `xml:"tranid"` 21 | WmInvid string `xml:"wminvid"` 22 | OrderId string `xml:"orderid"` 23 | DateStart string `xml:"datestart"` 24 | DateFinish string `xml:"datefinish"` 25 | } 26 | 27 | func (o GetOpers) GetSignSource(reqn string) (string, error) { 28 | return o.Purse + reqn, nil 29 | } 30 | 31 | type Operations struct { 32 | XMLName xml.Name `xml:"operations"` 33 | OperationList []Operation `xml:"operation"` 34 | } 35 | 36 | func (w *WmClient) GetOperations(o GetOpers) (Operations, error) { 37 | 38 | X := W3s{ 39 | Interface: XInterface{Name: "Operations", Type: "w3s"}, 40 | Request: o, 41 | Client: w, 42 | } 43 | 44 | result := Operations{} 45 | 46 | err := X.getResult(&result) 47 | return result, err 48 | } 49 | -------------------------------------------------------------------------------- /x4.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // Receiving the history of issued invoices. Verifying whether invoices were paid. 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X4 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | ) 15 | 16 | type OutInvoices struct { 17 | XMLName xml.Name `xml:"getoutinvoices"` 18 | Purse string `xml:"purse"` 19 | WmInvid string `xml:"wminvid"` 20 | OrderId string `xml:"orderid"` 21 | DateStart string `xml:"datestart"` 22 | DateFinish string `xml:"datefinish"` 23 | } 24 | 25 | func (i OutInvoices) GetSignSource(reqn string) (string, error) { 26 | return i.Purse + reqn, nil 27 | } 28 | 29 | type OutInvoicesResp struct { 30 | XMLName xml.Name `xml:"outinvoices"` 31 | InvoiceList []InvoiceResponse `xml:"outinvoice"` 32 | } 33 | 34 | func (w *WmClient) GetOutInvoices(i OutInvoices) (OutInvoicesResp, error) { 35 | 36 | X := W3s{ 37 | Request: i, 38 | Interface: XInterface{Name: "OutInvoices", Type: "w3s"}, 39 | Client: w, 40 | } 41 | 42 | result := OutInvoicesResp{} 43 | err := X.getResult(&result) 44 | return result, err 45 | } 46 | -------------------------------------------------------------------------------- /x5.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import ( 4 | "encoding/xml" 5 | ) 6 | 7 | type FinishProtect struct { 8 | XMLName xml.Name `xml:"finishprotect"` 9 | WmTranId string `xml:"wmtranid"` 10 | PCode string `xml:"pcode"` 11 | } 12 | 13 | func (f FinishProtect) GetSignSource(reqn string) (string, error) { 14 | return f.WmTranId + f.PCode + reqn, nil 15 | } 16 | 17 | func (w *WmClient) DoFinishProtect(f FinishProtect) (Operation, error) { 18 | 19 | X := W3s{ 20 | Request: f, 21 | Interface: XInterface{Name: "FinishProtect", Type: "w3s"}, 22 | Client: w, 23 | } 24 | 25 | result := Operation{} 26 | err := X.getResult(&result) 27 | return result, err 28 | } 29 | -------------------------------------------------------------------------------- /x6.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | import ( 4 | "encoding/xml" 5 | "strings" 6 | ) 7 | 8 | type SendMsg struct { 9 | XMLName xml.Name `xml:"message"` 10 | ReceiverWmid string `xml:"receiverwmid"` 11 | MsgSubj string `xml:"msgsubj"` 12 | MsgText string `xml:"msgtext"` 13 | OnlyAuth int `xml:"onlyauth"` 14 | } 15 | 16 | func (s SendMsg) GetSignSource(reqn string) (string, error) { 17 | subject, err := Utf8ToWin(strings.Trim(s.MsgSubj, " ")) 18 | if err != nil { 19 | return "", err 20 | } 21 | 22 | text, err := Utf8ToWin(strings.Trim(s.MsgText, " ")) 23 | if err != nil { 24 | return "", err 25 | } 26 | 27 | return s.ReceiverWmid + reqn + text + subject, nil 28 | 29 | } 30 | 31 | type SendMsgResponse struct { 32 | XMLName xml.Name `xml:"message"` 33 | MessageId int `xml:"id,attr"` 34 | ReceiverWmid string `xml:"receiverwmid"` 35 | MsgSubj string `xml:"msgsubj"` 36 | MsgText string `xml:"msgtext"` 37 | DateCrt string `xml:"datecrt"` 38 | } 39 | 40 | func (w *WmClient) SendMessage(s SendMsg) (SendMsgResponse, error) { 41 | 42 | X := W3s{ 43 | Request: s, 44 | Interface: XInterface{Name: "SendMsg", Type: "w3s"}, 45 | Client: w, 46 | } 47 | 48 | result := SendMsgResponse{} 49 | err := X.getResult(&result) 50 | return result, err 51 | } 52 | -------------------------------------------------------------------------------- /x7.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // Interface X7. Verifying client's handwritten signature - owner 8 | // of WM Keeper WinPro (Classic). 9 | // This interface is designed for verifying authenticity 10 | // of the handwritten signature in messages, generated by WM Keeper WinPro (Classic) keys. All parameters are passed in Win-1251 encoding. 11 | 12 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X7 13 | 14 | package webmoney 15 | 16 | import ( 17 | "encoding/xml" 18 | ) 19 | 20 | type TestSignRequest struct { 21 | XMLName xml.Name `xml:"testsign"` 22 | Wmid string `xml:"wmid"` 23 | Plan PlanString `xml:"plan"` 24 | Sign string `xml:"sign"` 25 | } 26 | type PlanString struct { 27 | Text string `xml:",cdata"` 28 | } 29 | 30 | func (t TestSignRequest) GetSignSource(reqn string) (string, error) { 31 | 32 | return t.Wmid + t.Plan.Text + t.Sign, nil 33 | } 34 | 35 | type TestSignResponse struct { 36 | XMLName xml.Name `xml:"testsign"` 37 | Res string `xml:"res"` 38 | } 39 | 40 | func (w *WmClient) TestSign(t TestSignRequest) (TestSignResponse, error) { 41 | X := W3s{ 42 | Interface: XInterface{Name: "ClassicAuth", Type: "w3s"}, 43 | Request: t, 44 | Client: w, 45 | } 46 | result := TestSignResponse{} 47 | err := X.getResult(&result) 48 | return result, err 49 | } 50 | -------------------------------------------------------------------------------- /x8.go: -------------------------------------------------------------------------------- 1 | package webmoney 2 | 3 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 4 | // 5 | // Use of this source code is governed by a BSD-style 6 | // license that can be found in the LICENSE file or at 7 | // https://developers.google.com/open-source/licenses/bsd. 8 | // 9 | // desc 10 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X8 11 | 12 | /* 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | */ 21 | /* 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | */ 32 | import ( 33 | "encoding/xml" 34 | ) 35 | 36 | // request 37 | type TestWmPurse struct { 38 | XMLName xml.Name `xml:"testwmpurse"` 39 | Wmid string `xml:"wmid"` 40 | Purse string `xml:"purse"` 41 | } 42 | 43 | func (t TestWmPurse) GetSignSource(reqn string) (string, error) { 44 | return t.Wmid + t.Purse, nil 45 | 46 | } 47 | 48 | type TestWmPurseResponse struct { 49 | XMLName xml.Name `xml:"testwmpurse"` 50 | Wmid Wmid `xml:"wmid"` 51 | Purse ReturnedPurse `xml:"purse"` 52 | } 53 | type ReturnedPurse struct { 54 | XMLName xml.Name `xml:"purse"` 55 | Value string `xml:",chardata"` 56 | MerchantActiveMode string `xml:"merchant_active_mode,attr"` 57 | MerchantAllowCashier string `xml:"merchant_allow_cashier,attr"` 58 | BlockedinByPT string `xml:"blockedinByPT,attr"` 59 | ByPTLimit string `xml:"ByPTLimit,attr"` 60 | Deleted_flag string `xml:"deleted_flag,attr"` 61 | } 62 | type Wmid struct { 63 | XMLName xml.Name `xml:"wmid"` 64 | Value string `xml:",chardata"` 65 | Available string `xml:"available,attr"` 66 | Themselfcorrstate string `xml:"themselfcorrstate,attr"` 67 | Newattst string `xml:"newattst,attr"` 68 | Pasdoc string `xml:"pasdoc,attr"` 69 | Blockedin string `xml:"blockedin"` 70 | Blockedout string `xml:"blockedout"` 71 | } 72 | 73 | func (w *WmClient) FindWmidPurse(t TestWmPurse) (TestWmPurseResponse, error) { 74 | X := W3s{ 75 | Interface: XInterface{Name: "FindWMPurseNew", Type: "w3s"}, 76 | Request: t, 77 | Client: w, 78 | } 79 | result := TestWmPurseResponse{} 80 | X.getResult(&result) 81 | return result, nil 82 | } 83 | -------------------------------------------------------------------------------- /x9.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016 The Constantin Karataev. All rights reserved. 2 | // 3 | // Use of this source code is governed by a BSD-style 4 | // license that can be found in the LICENSE file or at 5 | // https://developers.google.com/open-source/licenses/bsd. 6 | // 7 | // desc 8 | // https://wiki.wmtransfer.com/projects/webmoney/wiki/Interface_X9 9 | 10 | package webmoney 11 | 12 | import ( 13 | "encoding/xml" 14 | ) 15 | 16 | type Purses struct { 17 | XMLName xml.Name `xml:"getpurses"` 18 | Wmid string `xml:"wmid"` 19 | } 20 | 21 | func (p Purses) GetSignSource(reqn string) (string, error) { 22 | 23 | return p.Wmid + reqn, nil 24 | } 25 | 26 | type PursesResp struct { 27 | XMLName xml.Name `xml:"purses"` 28 | Cnt string `xml:"cnt,attr"` 29 | PurseList []RPurse `xml:"purse"` 30 | } 31 | 32 | type RPurse struct { 33 | XMLName xml.Name `xml:"purse"` 34 | Id string `xml:"id,attr"` 35 | PurseName string `xml:"pursename"` 36 | Amount string `xml:"amount"` 37 | Desc string `xml:"desc"` 38 | Outsideopen string `xml:"outsideopen"` 39 | Outsideopenstate string `xml:"outsideopenstate"` 40 | Byptlimit string `xml:"byptlimit"` 41 | LastIntr string `xml:"lastintr"` 42 | LastOuttr string `xml:"lastouttr"` 43 | } 44 | 45 | func (w *WmClient) GetPurses4Wmid(p Purses) (PursesResp, error) { 46 | 47 | X := W3s{ 48 | Interface: XInterface{Name: "Purses", Type: "w3s"}, 49 | Request: p, 50 | Client: w, 51 | } 52 | 53 | result := PursesResp{} 54 | 55 | err := X.getResult(&result) 56 | 57 | return result, err 58 | } 59 | --------------------------------------------------------------------------------