diff --git a/dns.go b/dns.go
index 726bf30..c5f19f0 100644
--- a/dns.go
+++ b/dns.go
@@ -7,9 +7,10 @@ import (
)
const (
- domainsDNSGetHosts = "namecheap.domains.dns.getHosts"
- domainsDNSSetHosts = "namecheap.domains.dns.setHosts"
- domainsDNSSetCustom = "namecheap.domains.dns.setCustom"
+ domainsDNSGetHosts = "namecheap.domains.dns.getHosts"
+ domainsDNSSetHosts = "namecheap.domains.dns.setHosts"
+ domainsDNSSetCustom = "namecheap.domains.dns.setCustom"
+ domainsDNSSetDefault = "namecheap.domains.dns.setDefault"
)
type DomainDNSGetHostsResult struct {
@@ -99,3 +100,24 @@ func (client *Client) DomainDNSSetCustom(sld, tld, nameservers string) (*DomainD
}
return resp.DomainDNSSetCustom, nil
}
+
+type DomainDNSSetDefaultResult struct {
+ Domain string `xml:"Domain,attr"`
+ Update bool `xml:"Updated,attr"`
+}
+
+func (client *Client) DomainDNSSetDefault(sld, tld string) (*DomainDNSSetDefaultResult, error) {
+ requestInfo := &ApiRequest{
+ command: domainsDNSSetDefault,
+ method: "POST",
+ params: url.Values{},
+ }
+ requestInfo.params.Set("SLD", sld)
+ requestInfo.params.Set("TLD", tld)
+
+ resp, err := client.do(requestInfo)
+ if err != nil {
+ return nil, err
+ }
+ return resp.DomainDNSSetDefault, nil
+}
diff --git a/dns_test.go b/dns_test.go
index 8944239..c41455e 100644
--- a/dns_test.go
+++ b/dns_test.go
@@ -169,3 +169,45 @@ func TestDomainsDNSSetCustom(t *testing.T) {
t.Errorf("DomainsDNSSetCustom returned %+v, want %+v", result, want)
}
}
+
+func TestDomainsDNSSetDefault(t *testing.T) {
+ setup()
+ defer teardown()
+
+ respXML := `
+
+
+
+ namecheap.domains.dns.setDefault
+
+
+
+ SERVER-NAME
+ +5
+ 32.76
+`
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ correctParams := fillDefaultParams(url.Values{})
+ correctParams.Set("Command", "namecheap.domains.dns.setDefault")
+ correctParams.Set("SLD", "domain")
+ correctParams.Set("TLD", "com")
+ testBody(t, r, correctParams)
+ testMethod(t, r, "POST")
+ fmt.Fprint(w, respXML)
+ })
+
+ result, err := client.DomainDNSSetDefault("domain", "com")
+ if err != nil {
+ t.Errorf("DomainDNSSetDefault returned error: %v", err)
+ }
+
+ want := &DomainDNSSetDefaultResult{
+ Domain: "domain.com",
+ Update: true,
+ }
+
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("DomainsDNSSetDefault returned %+v, want %+v", result, want)
+ }
+}
diff --git a/domain.go b/domain.go
index aefb601..cb1bb69 100644
--- a/domain.go
+++ b/domain.go
@@ -8,12 +8,14 @@ import (
)
const (
- domainsGetList = "namecheap.domains.getList"
- domainsGetInfo = "namecheap.domains.getInfo"
- domainsCheck = "namecheap.domains.check"
- domainsCreate = "namecheap.domains.create"
- domainsTLDList = "namecheap.domains.getTldList"
- domainsRenew = "namecheap.domains.renew"
+ domainsGetList = "namecheap.domains.getList"
+ domainsGetInfo = "namecheap.domains.getInfo"
+ domainsCheck = "namecheap.domains.check"
+ domainsCreate = "namecheap.domains.create"
+ domainsTLDList = "namecheap.domains.getTldList"
+ domainsRenew = "namecheap.domains.renew"
+ domainsReactivate = "namecheap.domains.reactivate"
+ domainsSetContacts = "namecheap.domains.setContacts"
)
// DomainGetListResult represents the data returned by 'domains.getList'
@@ -50,9 +52,10 @@ type DNSDetails struct {
}
type Whoisguard struct {
- Enabled bool `xml:"Enabled,attr"`
- ID int64 `xml:"ID"`
- ExpiredDate string `xml:"ExpiredDate"`
+ EnabledString string `xml:"Enabled,attr"`
+ Enabled bool
+ ID int64 `xml:"ID"`
+ ExpiredDate string `xml:"ExpiredDate"`
}
type DomainCheckResult struct {
@@ -91,6 +94,19 @@ type DomainRenewResult struct {
ExpireDate string `xml:"DomainDetails>ExpiredDate"`
}
+type DomainReactivateResult struct {
+ Name string `xml:"Domain,attr"`
+ Reactivated bool `xml:"IsSuccess,attr"`
+ ChargedAmount float64 `xml:"ChargedAmount,attr"`
+ OrderID int `xml:"OrderID,attr"`
+ TransactionID int `xml:"TransactionID,attr"`
+}
+
+type DomainSetContactsResult struct {
+ Name string `xml:"Domain,attr"`
+ ContactsChanged bool `xml:"IsSuccess,attr"`
+}
+
type DomainCreateOption struct {
AddFreeWhoisguard bool
WGEnabled bool
@@ -126,6 +142,11 @@ func (client *Client) DomainGetInfo(domainName string) (*DomainInfo, error) {
return nil, err
}
+ switch strings.ToLower(resp.DomainInfo.Whoisguard.EnabledString) {
+ case "1", "true":
+ resp.DomainInfo.Whoisguard.Enabled = true
+ }
+
return resp.DomainInfo, nil
}
@@ -212,3 +233,40 @@ func (client *Client) DomainRenew(domainName string, years int) (*DomainRenewRes
return resp.DomainRenew, nil
}
+
+func (client *Client) DomainReactivate(domainName string, years int) (*DomainReactivateResult, error) {
+ requestInfo := &ApiRequest{
+ command: domainsReactivate,
+ method: "POST",
+ params: url.Values{},
+ }
+ requestInfo.params.Set("DomainName", domainName)
+ requestInfo.params.Set("Years", strconv.Itoa(years))
+
+ resp, err := client.do(requestInfo)
+ if err != nil {
+ return nil, err
+ }
+
+ return resp.DomainReactivate, nil
+}
+
+func (client *Client) DomainSetContacts(domainName string, registrant *Registrant) (*DomainSetContactsResult, error) {
+ requestInfo := &ApiRequest{
+ command: domainsSetContacts,
+ method: "POST",
+ params: url.Values{},
+ }
+ requestInfo.params.Set("DomainName", domainName)
+
+ if err := registrant.addValues(requestInfo.params); err != nil {
+ return nil, err
+ }
+
+ resp, err := client.do(requestInfo)
+ if err != nil {
+ return nil, err
+ }
+
+ return resp.DomainSetContacts, nil
+}
diff --git a/domain_test.go b/domain_test.go
index 9224b88..a649730 100644
--- a/domain_test.go
+++ b/domain_test.go
@@ -139,9 +139,94 @@ func TestDomainGetInfo(t *testing.T) {
},
},
Whoisguard: Whoisguard{
- Enabled: true,
- ID: 53536,
- ExpiredDate: "11/04/2015",
+ Enabled: true,
+ EnabledString: "True",
+ ID: 53536,
+ ExpiredDate: "11/04/2015",
+ },
+ }
+
+ if !reflect.DeepEqual(domain, want) {
+ t.Errorf("DomainGetInfo returned %+v, want %+v", domain, want)
+ }
+}
+
+func TestDomainGetInfoNotAlloted(t *testing.T) {
+ setup()
+ defer teardown()
+
+ respXML := `
+
+
+
+ namecheap.domains.getinfo
+
+
+
+ 07/25/2019
+ 07/25/2020
+ 0
+
+
+
+ 0
+
+
+ false
+ -1
+ 0001-01-01T00:00:00
+ 0001-01-01T00:00:00
+ false
+
+
+ dns1.registrar-servers.com
+ dns2.registrar-servers.com
+
+
+
+
+ PHX01APIEXT01
+ --4:00
+ 0.018
+`
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ correctParams := fillDefaultParams(url.Values{})
+ correctParams.Set("Command", "namecheap.domains.getInfo")
+ correctParams.Set("DomainName", "example.com")
+ testBody(t, r, correctParams)
+ testMethod(t, r, "POST")
+ fmt.Fprint(w, respXML)
+ })
+
+ domain, err := client.DomainGetInfo("example.com")
+
+ if err != nil {
+ t.Errorf("DomainGetInfo returned error: %v", err)
+ }
+
+ // DomainInfo we expect, given the respXML above
+ want := &DomainInfo{
+ ID: 37103805,
+ Name: "example.com",
+ Owner: "anUser",
+ Created: "07/25/2019",
+ Expires: "07/25/2020",
+ IsExpired: false,
+ IsLocked: false,
+ AutoRenew: false,
+ DNSDetails: DNSDetails{
+ ProviderType: "FREE",
+ IsUsingOurDNS: true,
+ Nameservers: []string{
+ "dns1.registrar-servers.com",
+ "dns2.registrar-servers.com",
+ },
+ },
+ Whoisguard: Whoisguard{
+ Enabled: false,
+ EnabledString: "NotAlloted",
+ ID: 0,
},
}
@@ -321,3 +406,104 @@ func TestDomainsRenew(t *testing.T) {
t.Errorf("DomainRenew returned %+v, want %+v", result, want)
}
}
+
+func TestDomainsReactivate(t *testing.T) {
+ setup()
+ defer teardown()
+
+ respXML := `
+
+
+
+ namecheap.domains.reactivate
+
+
+
+ SERVER-NAME
+ +5:00
+ 12.915
+`
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ correctParams := fillDefaultParams(url.Values{})
+ correctParams.Set("Command", "namecheap.domains.reactivate")
+ correctParams.Set("DomainName", "domain1.com")
+ correctParams.Set("Years", "1")
+ testBody(t, r, correctParams)
+ testMethod(t, r, "POST")
+ fmt.Fprint(w, respXML)
+ })
+
+ result, err := client.DomainReactivate("domain1.com", 1)
+ if err != nil {
+ t.Errorf("DomainReactivate returned error: %v", err)
+ }
+
+ // DomainReactivateResult we expect, given the respXML above
+ want := &DomainReactivateResult{
+ Name: "domain1.com",
+ Reactivated: true,
+ ChargedAmount: 650,
+ TransactionID: 25080,
+ OrderID: 23569,
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("DomainsReactivate returned %+v, want %+v", result, want)
+ }
+}
+
+func TestDomainsSetContacts(t *testing.T) {
+ setup()
+ defer teardown()
+
+ respXML := `
+
+
+ namecheap.domains.setContacts
+
+
+
+ SERVER-NAME
+ +5
+ 0.078
+`
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ correctParams := fillDefaultParams(url.Values{})
+ fillInfo := func(prefix string) {
+ correctParams.Set(prefix+"FirstName", "John")
+ correctParams.Set(prefix+"LastName", "Smith")
+ correctParams.Set(prefix+"Address1", "8939 S.cross Blvd")
+ correctParams.Set(prefix+"StateProvince", "CA")
+ correctParams.Set(prefix+"PostalCode", "90045")
+ correctParams.Set(prefix+"Country", "US")
+ correctParams.Set(prefix+"Phone", "+1.6613102107")
+ correctParams.Set(prefix+"EmailAddress", "john@gmail.com")
+ correctParams.Set(prefix+"City", "CA")
+ }
+ correctParams.Set("Command", "namecheap.domains.setContacts")
+ correctParams.Set("DomainName", "domain1.com")
+ fillInfo("AuxBilling")
+ fillInfo("Tech")
+ fillInfo("Admin")
+ fillInfo("Registrant")
+ testBody(t, r, correctParams)
+ testMethod(t, r, "POST")
+ fmt.Fprint(w, respXML)
+ })
+
+ registrant := NewRegistrant("John", "Smith", "8939 S.cross Blvd", "", "CA", "CA", "90045", "US", "+1.6613102107", "john@gmail.com")
+ result, err := client.DomainSetContacts("domain1.com", registrant)
+ if err != nil {
+ t.Errorf("DomainSetContacts returned error: %v", err)
+ }
+
+ // DomainSetContactsResult we expect, given the respXML above
+ want := &DomainSetContactsResult{
+ Name: "domain1.com",
+ ContactsChanged: true,
+ }
+ if !reflect.DeepEqual(result, want) {
+ t.Errorf("DomainSetContacts returned %+v, want %+v", result, want)
+ }
+}
diff --git a/namecheap.go b/namecheap.go
index 1a3961c..3083e6c 100644
--- a/namecheap.go
+++ b/namecheap.go
@@ -12,9 +12,11 @@ import (
"net/url"
"strconv"
"strings"
+ "time"
)
const defaultBaseURL = "https://api.namecheap.com/xml.response"
+const defaultTimeout = 0
// Client represents a client used to make calls to the Namecheap API.
type Client struct {
@@ -23,6 +25,10 @@ type Client struct {
UserName string
HttpClient *http.Client
+ // Timeout specifies a time limit for requests made by this
+ // Client. Default value is zero, which means no timeout.
+ Timeout time.Duration
+
// Base URL for API requests.
// Defaults to the public Namecheap API,
// but can be set to a different endpoint (e.g. the sandbox).
@@ -39,27 +45,31 @@ type ApiRequest struct {
}
type ApiResponse struct {
- Status string `xml:"Status,attr"`
- Command string `xml:"RequestedCommand"`
- TLDList []TLDListResult `xml:"CommandResponse>Tlds>Tld"`
- Domains []DomainGetListResult `xml:"CommandResponse>DomainGetListResult>Domain"`
- DomainInfo *DomainInfo `xml:"CommandResponse>DomainGetInfoResult"`
- DomainDNSHosts *DomainDNSGetHostsResult `xml:"CommandResponse>DomainDNSGetHostsResult"`
- DomainDNSSetHosts *DomainDNSSetHostsResult `xml:"CommandResponse>DomainDNSSetHostsResult"`
- DomainCreate *DomainCreateResult `xml:"CommandResponse>DomainCreateResult"`
- DomainRenew *DomainRenewResult `xml:"CommandResponse>DomainRenewResult"`
- DomainsCheck []DomainCheckResult `xml:"CommandResponse>DomainCheckResult"`
- DomainNSInfo *DomainNSInfoResult `xml:"CommandResponse>DomainNSInfoResult"`
- DomainDNSSetCustom *DomainDNSSetCustomResult `xml:"CommandResponse>DomainDNSSetCustomResult"`
- SslActivate *SslActivateResult `xml:"CommandResponse>SSLActivateResult"`
- SslCreate *SslCreateResult `xml:"CommandResponse>SSLCreateResult"`
- SslCertificates []SslGetListResult `xml:"CommandResponse>SSLListResult>SSL"`
- UsersGetPricing []UsersGetPricingResult `xml:"CommandResponse>UserGetPricingResult>ProductType"`
- WhoisguardList []WhoisguardGetListResult `xml:"CommandResponse>WhoisguardGetListResult>Whoisguard"`
- WhoisguardEnable whoisguardEnableResult `xml:"CommandResponse>WhoisguardEnableResult"`
- WhoisguardDisable whoisguardDisableResult `xml:"CommandResponse>WhoisguardDisableResult"`
- WhoisguardRenew *WhoisguardRenewResult `xml:"CommandResponse>WhoisguardRenewResult"`
- Errors ApiErrors `xml:"Errors>Error"`
+ Status string `xml:"Status,attr"`
+ Command string `xml:"RequestedCommand"`
+ TLDList []TLDListResult `xml:"CommandResponse>Tlds>Tld"`
+ Domains []DomainGetListResult `xml:"CommandResponse>DomainGetListResult>Domain"`
+ DomainInfo *DomainInfo `xml:"CommandResponse>DomainGetInfoResult"`
+ DomainDNSHosts *DomainDNSGetHostsResult `xml:"CommandResponse>DomainDNSGetHostsResult"`
+ DomainDNSSetHosts *DomainDNSSetHostsResult `xml:"CommandResponse>DomainDNSSetHostsResult"`
+ DomainCreate *DomainCreateResult `xml:"CommandResponse>DomainCreateResult"`
+ DomainRenew *DomainRenewResult `xml:"CommandResponse>DomainRenewResult"`
+ DomainReactivate *DomainReactivateResult `xml:"CommandResponse>DomainReactivateResult"`
+ DomainSetContacts *DomainSetContactsResult `xml:"CommandResponse>DomainSetContactResult"`
+ DomainsCheck []DomainCheckResult `xml:"CommandResponse>DomainCheckResult"`
+ DomainNSInfo *DomainNSInfoResult `xml:"CommandResponse>DomainNSInfoResult"`
+ DomainDNSSetCustom *DomainDNSSetCustomResult `xml:"CommandResponse>DomainDNSSetCustomResult"`
+ DomainDNSSetDefault *DomainDNSSetDefaultResult `xml:"CommandResponse>DomainDNSSetDefaultResult"`
+ SslActivate *SslActivateResult `xml:"CommandResponse>SSLActivateResult"`
+ SslCreate *SslCreateResult `xml:"CommandResponse>SSLCreateResult"`
+ SslCertificates []SslGetListResult `xml:"CommandResponse>SSLListResult>SSL"`
+ UsersGetPricing []UsersGetPricingResult `xml:"CommandResponse>UserGetPricingResult>ProductType"`
+ UsersGetBalances *UsersGetBalancesResult `xml:"CommandResponse>UserGetBalancesResult"`
+ WhoisguardList []WhoisguardGetListResult `xml:"CommandResponse>WhoisguardGetListResult>Whoisguard"`
+ WhoisguardEnable whoisguardEnableResult `xml:"CommandResponse>WhoisguardEnableResult"`
+ WhoisguardDisable whoisguardDisableResult `xml:"CommandResponse>WhoisguardDisableResult"`
+ WhoisguardRenew *WhoisguardRenewResult `xml:"CommandResponse>WhoisguardRenewResult"`
+ Errors ApiErrors `xml:"Errors>Error"`
}
// ApiError is the format of the error returned in the api responses.
@@ -90,6 +100,7 @@ func NewClient(apiUser, apiToken, userName string) *Client {
UserName: userName,
HttpClient: http.DefaultClient,
BaseURL: defaultBaseURL,
+ Timeout: defaultTimeout,
}
}
@@ -100,7 +111,7 @@ func (client *Client) NewRegistrant(
city, state, postalCode, country,
phone, email string,
) {
- client.Registrant = newRegistrant(
+ client.Registrant = NewRegistrant(
firstName, lastName,
addr1, addr2,
city, state, postalCode, country,
@@ -161,6 +172,8 @@ func (client *Client) sendRequest(request *ApiRequest) ([]byte, int, error) {
return nil, 0, err
}
+ client.HttpClient.Timeout = client.Timeout
+
resp, err := client.HttpClient.Do(req)
if err != nil {
return nil, 0, err
diff --git a/registrant.go b/registrant.go
index 5b8b303..885114e 100644
--- a/registrant.go
+++ b/registrant.go
@@ -34,9 +34,9 @@ type Registrant struct {
AuxBillingPhone, AuxBillingEmailAddress string
}
-// newRegistrant return a new registrant where all the required fields are the same.
+// NewRegistrant return a new registrant where all the required fields are the same.
// Feel free to change them as needed
-func newRegistrant(
+func NewRegistrant(
firstName, lastName,
addr1, addr2,
city, state, postalCode, country,
diff --git a/registrant_test.go b/registrant_test.go
index 6e34a82..ca231b4 100644
--- a/registrant_test.go
+++ b/registrant_test.go
@@ -6,7 +6,7 @@ import (
)
func TestAddValues(t *testing.T) {
- reg := newRegistrant(
+ reg := NewRegistrant(
"r", "m",
"10 Park Ave.",
"Apt. 3F",
diff --git a/users.go b/users.go
index 7d8e0f0..a7db45f 100644
--- a/users.go
+++ b/users.go
@@ -5,7 +5,8 @@ import (
)
const (
- usersGetPricing = "namecheap.users.getPricing"
+ usersGetPricing = "namecheap.users.getPricing"
+ usersGetBalances = "namecheap.users.getBalances"
)
type UsersGetPricingResult struct {
@@ -27,6 +28,15 @@ type UsersGetPricingResult struct {
} `xml:"ProductCategory"`
}
+type UsersGetBalancesResult struct {
+ Currency string `xml:"Currency,attr"`
+ AvailableBalance float64 `xml:"AvailableBalance,attr"`
+ AccountBalance float64 `xml:"AccountBalance,attr"`
+ EarnedAmount float64 `xml:"EarnedAmount,attr"`
+ WithdrawableAmount float64 `xml:"WithdrawableAmount,attr"`
+ FundsRequiredForAutoRenew float64 `xml:"FundsRequiredForAutoRenew,attr"`
+}
+
func (client *Client) UsersGetPricing(productType string) ([]UsersGetPricingResult, error) {
requestInfo := &ApiRequest{
command: usersGetPricing,
@@ -42,3 +52,18 @@ func (client *Client) UsersGetPricing(productType string) ([]UsersGetPricingResu
return resp.UsersGetPricing, nil
}
+
+func (client *Client) UsersGetBalances() (*UsersGetBalancesResult, error) {
+ requestInfo := &ApiRequest{
+ command: usersGetBalances,
+ method: "POST",
+ params: url.Values{},
+ }
+
+ resp, err := client.do(requestInfo)
+ if err != nil {
+ return nil, err
+ }
+
+ return resp.UsersGetBalances, nil
+}
diff --git a/users_test.go b/users_test.go
new file mode 100644
index 0000000..f1fc9d4
--- /dev/null
+++ b/users_test.go
@@ -0,0 +1,53 @@
+package namecheap
+
+import (
+ "fmt"
+ "net/http"
+ "net/url"
+ "reflect"
+ "testing"
+)
+
+func TestUsersGetBalances(t *testing.T) {
+ setup()
+ defer teardown()
+ respXML := `
+
+
+ namecheap.users.getBalances
+
+
+
+ SERVER-NAME
+ +5
+ 0.024
+`
+
+ mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ correctParams := fillDefaultParams(url.Values{})
+ correctParams.Set("Command", "namecheap.users.getBalances")
+ testBody(t, r, correctParams)
+ testMethod(t, r, "POST")
+ fmt.Fprint(w, respXML)
+ })
+
+ balances, err := client.UsersGetBalances()
+
+ if err != nil {
+ t.Errorf("UsersGetBalances returned error: %v", err)
+ }
+
+ // Balances response we want, given the above respXML
+ want := &UsersGetBalancesResult{
+ Currency: "USD",
+ AvailableBalance: 4932.96,
+ AccountBalance: 4932.96,
+ EarnedAmount: 381.70,
+ WithdrawableAmount: 1243.36,
+ FundsRequiredForAutoRenew: 0.00,
+ }
+
+ if !reflect.DeepEqual(balances, want) {
+ t.Errorf("UsersGetBalances returned %+v, want %+v", balances, want)
+ }
+}