package perfectmoney
import (
"crypto/md5"
"encoding/hex"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"time"
)
type PerfectMoney struct {
account string
passwd string
}
func NewPerfectMoney(account, passwd string) *PerfectMoney {
return &PerfectMoney{
account: account,
passwd: passwd,
}
}
func (pm *PerfectMoney) fetch(endpoint string, params url.Values) (string, error) {
finalURL := fmt.Sprintf("acct/%s.asp", endpoint)
if params == nil {
params = url.Values{}
}
params.Add("AccountID", pm.account)
params.Add("PassPhrase", pm.passwd)
resp, err := http.PostForm(finalURL, params)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}
func parseResponse(body string) (map[string]string, error) {
result := make(map[string]string)
errorRe := regexp.MustCompile("")
valueRe := regexp.MustCompile("")
if errorMatch := errorRe.FindStringSubmatch(body); errorMatch != nil {
return nil, fmt.Errorf(errorMatch[1])
}
matches := valueRe.FindAllStringSubmatch(body, -1)
for _, match := range matches {
result[match[1]] = match[2]
}
return result, nil
}
func (pm *PerfectMoney) Balance() (map[string]string, error) {
body, err := pm.fetch("balance", nil)
if err != nil {
return nil, err
}
return parseResponse(body)
}
func (pm *PerfectMoney) History(start, end time.Time) ([]string, error) {
params := url.Values{}
params.Add("startday", strconv.Itoa(start.Day()))
params.Add("startmonth", strconv.Itoa(int(start.Month())))
params.Add("startyear", strconv.Itoa(start.Year()))
params.Add("endday", strconv.Itoa(end.Day()))
params.Add("endmonth", strconv.Itoa(int(end.Month())))
params.Add("endyear", strconv.Itoa(end.Year()))
body, err := pm.fetch("historycsv", params)
if err != nil {
return nil, err
}
lines := strings.Split(body, "\n")
return lines[1:], nil // Skipping the CSV header
}
func (pm *PerfectMoney) Transfer(payer, payee string, amount float64, memo, paymentID string) (map[string]string, error) {
params := url.Values{}
params.Add("Payer_Account", payer)
params.Add("Payee_Account", payee)
params.Add("Amount", fmt.Sprintf("%.2f", amount))
params.Add("Memo", memo)
params.Add("PAYMENT_ID", paymentID)
body, err := pm.fetch("confirm", params)
if err != nil {
return nil, err
}
return parseResponse(body)
}
func (pm *PerfectMoney) EVCreate(payer string, amount float64) (map[string]string, error) {
params := url.Values{}
params.Add("Payer_Account", payer)
params.Add("Amount", fmt.Sprintf("%.2f", amount))
body, err := pm.fetch("ev_create", params)
if err != nil {
return nil, err
}
return parseResponse(body)
}
func (pm *PerfectMoney) EVCsv() ([]string, error) {
body, err := pm.fetch("evcsv", nil)
if err != nil {
return nil, err
}
lines := strings.Split(body, "\n")
return lines[1:], nil // Skipping the CSV header
}
func (pm *PerfectMoney) Check(payee, payer string, amount float64, units, batchNumber, secret, timestamp, paymentID, v2Hash string) bool {
data := fmt.Sprintf("%s:%s:%.2f:%s:%s:%s:%s:%s",
paymentID, payee, amount, units, batchNumber, payer, secret, timestamp)
hash := md5.Sum([]byte(data))
calculatedHash := strings.ToUpper(hex.EncodeToString(hash[:]))
return calculatedHash == v2Hash
}