Repository: VictorAvelar/mollie-api-go
Pull request #33 (2019-10-13 19:29:13)

Profiles service implementation
## Types of changes

What types of changes does your code introduce? Put an `x` in all the boxes that apply:
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)

## Checklist:

Go over all the following points, and put an `x` in all the boxes that apply.

Please, please, please, don't send your pull request until all of the boxes are ticked. Once your pull request is created, it will trigger a build on our continuous integration server to make sure your [tests and code style pass](https://help.github.com/articles/about-required-status-checks/).

- [x] I have read the **[CONTRIBUTING](CONTRIBUTING.md)** document.
- [x] My pull request addresses exactly one patch/feature.
- [x] I have created a branch for this patch/feature.
- [x] Each individual commit in the pull request is meaningful.
- [x] I have added tests to cover my changes.
- [x] If my change requires a change to the documentation, I have updated it accordingly.

If you're unsure about any of these, don't hesitate to ask. We're here to help!



Patch:
diff --git a/mollie/common_types.go b/mollie/common_types.go
index 8b44dd1..a30092e 100644
--- a/mollie/common_types.go
+++ b/mollie/common_types.go
@@ -97,3 +97,30 @@ type PaginationLinks struct {
 	Next     *URL `json:"next,omitempty"`
 	Docs     *URL `json:"documentation,omitempty"`
 }
+
+// CategoryCode specifies an industry or category
+type CategoryCode uint
+
+// Available category codes
+const (
+	BookMagazinesAndNewspapers      CategoryCode = 5192
+	GeneralMerchandise              CategoryCode = 5399
+	FoodAndDrinks                   CategoryCode = 5499
+	AutomotiveProducts              CategoryCode = 5533
+	ChildrenProducts                CategoryCode = 5641
+	ClothingAndShoes                CategoryCode = 5651
+	ElectronicsComputersAndSoftware CategoryCode = 5732
+	HostingOrVpnServices            CategoryCode = 5734
+	Entertainment                   CategoryCode = 5735
+	CreditsOrVouchersOrGiftCards    CategoryCode = 5815
+	Alcohol                         CategoryCode = 5921
+	JewelryAndAccessories           CategoryCode = 5944
+	HealthAndBeautyProducts         CategoryCode = 5977
+	FinancialServices               CategoryCode = 6012
+	Consultancy                     CategoryCode = 7299
+	TravelRentalAndTransportation   CategoryCode = 7999
+	AdvisingOrCoachingOrTraining    CategoryCode = 8299
+	CharityAndDonations             CategoryCode = 8398
+	PoliticalParties                CategoryCode = 8699
+	Others                          CategoryCode = 0
+)
diff --git a/mollie/mollie.go b/mollie/mollie.go
index 20ddc31..7d18815 100644
--- a/mollie/mollie.go
+++ b/mollie/mollie.go
@@ -41,6 +41,7 @@ type Client struct {
 	Methods       *MethodsService
 	Invoices      *InvoicesService
 	Organizations *OrganizationsService
+	Profiles    *ProfilesService
 }
 
 type service struct {
@@ -154,6 +155,7 @@ func NewClient(baseClient *http.Client, c *Config) (mollie *Client, err error) {
 	mollie.Methods = (*MethodsService)(&mollie.common)
 	mollie.Invoices = (*InvoicesService)(&mollie.common)
 	mollie.Organizations = (*OrganizationsService)(&mollie.common)
+	mollie.Profiles = (*ProfilesService)(&mollie.common)
 
 	// Parse authorization from environment
 	if tkn, ok := os.LookupEnv(APITokenEnv); ok {
diff --git a/mollie/profiles.go b/mollie/profiles.go
new file mode 100644
index 0000000..06af748
--- /dev/null
+++ b/mollie/profiles.go
@@ -0,0 +1,199 @@
+package mollie
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"time"
+
+	"github.com/google/go-querystring/query"
+)
+
+// ProfileStatus determines whether the profile is able to receive live payments
+type ProfileStatus string
+
+// Possible profile statuses
+const (
+	StatusUnverified ProfileStatus = "unverified"
+	StatusVerified   ProfileStatus = "verified"
+	StatusBlocked    ProfileStatus = "blocked"
+)
+
+// Profile will usually reflect the trademark or brand name
+// of the profile’s website or application.
+type Profile struct {
+	ID           string       `json:"id,omitempty"`
+	CategoryCode CategoryCode `json:"categoryCode,omitempty"`
+	CreatedAt    *time.Time   `json:"createdAt,omitempty"`
+	Email        string       `json:"email,omitempty"`
+	Mode         Mode         `json:"mode,omitempty"`
+	Name         string       `json:"name,omitempty"`
+	Phone        PhoneNumber  `json:"phone,omitempty"`
+	Resource     string       `json:"resource,omitempty"`
+	Review       struct {
+		Status string `json:"status,omitempty"`
+	} `json:"review,omitempty"`
+	Status  ProfileStatus `json:"status,omitempty"`
+	Website string        `json:"website,omitempty"`
+	Links   ProfileLinks  `json:"_links,omitempty"`
+}
+
+// ProfileLinks contains URL's to relevant information related to
+// a profile.
+type ProfileLinks struct {
+	Self               URL `json:"self,omitempty"`
+	Chargebacks        URL `json:"chargebacks,omitempty"`
+	Methods            URL `json:"methods,omitempty"`
+	Refunds            URL `json:"refunds,omitempty"`
+	CheckoutPreviewURL URL `json:"checkoutPreviewUrl,omitempty"`
+	Documentation      URL `json:"documentation,omitempty"`
+}
+
+// ProfileListOptions are optional query string parameters for the list profiles request
+type ProfileListOptions struct {
+	From  string `url:"from,omitempty"`
+	Limit uint   `url:"limit,omitempty"`
+}
+
+// ProfileList contains a list of profiles for your account.
+type ProfileList struct {
+	Count    int             `json:"count,omitempty"`
+	Embedded profiles        `json:"_embedded,omitempty"`
+	Links    PaginationLinks `json:"_links,omitempty"`
+}
+
+type profiles struct {
+	Profiles []Profile `json:"profiles,omitempty"`
+}
+
+// ProfilesService operates over profile resource
+type ProfilesService service
+
+// List returns all the profiles for the authenticated account
+func (ps *ProfilesService) List(options *ProfileListOptions) (pl *ProfileList, err error) {
+	u := "v2/profiles"
+	if options != nil {
+		v, _ := query.Values(options)
+		u = fmt.Sprintf("%s?%s", u, v.Encode())
+	}
+	req, err := ps.client.NewAPIRequest(http.MethodGet, u, nil)
+	if err != nil {
+		return
+	}
+	res, err := ps.client.Do(req)
+	if err != nil {
+		return
+	}
+	if err = json.Unmarshal(res.content, &pl); err != nil {
+		return
+	}
+	return
+}
+
+// Get retrieves the a profile by ID.
+func (ps *ProfilesService) Get(id string) (p *Profile, err error) {
+	return ps.get(id)
+}
+
+// Current returns the profile belonging to the API key.
+// This method only works when using API keys.
+func (ps *ProfilesService) Current() (p *Profile, err error) {
+	return ps.get("me")
+}
+
+func (ps *ProfilesService) get(id string) (p *Profile, err error) {
+	u := fmt.Sprintf("v2/profiles/%s", id)
+	req, err := ps.client.NewAPIRequest(http.MethodGet, u, nil)
+	if err != nil {
+		return
+	}
+	res, err := ps.client.Do(req)
+	if err != nil {
+		return
+	}
+	if err = json.Unmarshal(res.content, &p); err != nil {
+		return
+	}
+	return
+}
+
+// Create stores a new profile in your Mollie account.
+func (ps *ProfilesService) Create(np *Profile) (p *Profile, err error) {
+	req, err := ps.client.NewAPIRequest(http.MethodPost, "v2/profiles", np)
+	if err != nil {
+		return
+	}
+	res, err := ps.client.Do(req)
+	if err != nil {
+		return
+	}
+	if err = json.Unmarshal(res.content, &p); err != nil {
+		return
+	}
+	return
+}
+
+// Update allows you to perform mutations on a profile
+func (ps *ProfilesService) Update(id string, up *Profile) (p *Profile, err error) {
+	u := fmt.Sprintf("v2/profiles/%s", id)
+	req, err := ps.client.NewAPIRequest(http.MethodPatch, u, up)
+	if err != nil {
+		return
+	}
+	res, err := ps.client.Do(req)
+	if err != nil {
+		return
+	}
+	if err = json.Unmarshal(res.content, &p); err != nil {
+		return
+	}
+	return
+}
+
+// Delete  enables profile deletions, rendering the profile unavailable
+// for further API calls and transactions.
+func (ps *ProfilesService) Delete(id string) (err error) {
+	u := fmt.Sprintf("v2/profiles/%s", id)
+	req, err := ps.client.NewAPIRequest(http.MethodDelete, u, nil)
+	if err != nil {
+		return
+	}
+	_, err = ps.client.Do(req)
+	if err != nil {
+		return
+	}
+	return
+}
+
+// EnablePaymentMethod enables a payment method on a specific or authenticated profile.
+// If you're using API tokens for authentication, pass "me" as id.
+func (ps *ProfilesService) EnablePaymentMethod(id string, pm PaymentMethod) (pmi *PaymentMethodInfo, err error) {
+	u := fmt.Sprintf("v2/profiles/%s/methods/%s", id, pm)
+	req, err := ps.client.NewAPIRequest(http.MethodPost, u, nil)
+	if err != nil {
+		return
+	}
+	res, err := ps.client.Do(req)
+	if err != nil {
+		return
+	}
+	if err = json.Unmarshal(res.content, &pmi); err != nil {
+		return
+	}
+	return
+}
+
+// DisablePaymentMethod disables a payment method on a specific or authenticated profile.
+// If you're using API tokens for authentication, pass "me" as id.
+func (ps *ProfilesService) DisablePaymentMethod(id string, pm PaymentMethod) (err error) {
+	u := fmt.Sprintf("v2/profiles/%s/methods/%s", id, pm)
+	req, err := ps.client.NewAPIRequest(http.MethodDelete, u, nil)
+	if err != nil {
+		return
+	}
+	_, err = ps.client.Do(req)
+	if err != nil {
+		return
+	}
+	return
+}


Test patch:
diff --git a/mollie/profiles_test.go b/mollie/profiles_test.go
new file mode 100644
index 0000000..135dc72
--- /dev/null
+++ b/mollie/profiles_test.go
@@ -0,0 +1,320 @@
+package mollie
+
+import (
+	"net/http"
+	"net/url"
+	"strings"
+	"testing"
+
+	"github.com/VictorAvelar/mollie-api-go/testdata"
+)
+
+func TestProfilesService_Get(t *testing.T) {
+	setup()
+	defer teardown()
+	id := "pfl_v9hTwCvYqw"
+
+	_ = tClient.WithAuthenticationValue("test_token")
+
+	tMux.HandleFunc("/v2/profiles/"+id, func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "GET")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusOK)
+		_, _ = w.Write([]byte(testdata.GetProfileResponse))
+	})
+
+	p, err := tClient.Profiles.Get(id)
+	if err != nil {
+		t.Error(err)
+	}
+
+	if p.ID != id {
+		t.Errorf("unexpected response, want: %v got: %v", p.ID, id)
+	}
+}
+
+func TestProfilesService_Current(t *testing.T) {
+	setup()
+	defer teardown()
+	id := "pfl_v9hTwCvYqw"
+
+	_ = tClient.WithAuthenticationValue("test_token")
+
+	tMux.HandleFunc("/v2/profiles/me", func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "GET")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusOK)
+		_, _ = w.Write([]byte(testdata.GetProfileResponse))
+	})
+
+	p, err := tClient.Profiles.Current()
+	if err != nil {
+		t.Error(err)
+	}
+
+	if p.ID != id {
+		t.Errorf("unexpected response, want: %v got: %v", p.ID, id)
+	}
+}
+
+func TestProfilesService_List(t *testing.T) {
+	setup()
+	defer teardown()
+
+	_ = tClient.WithAuthenticationValue("test_token")
+
+	tMux.HandleFunc("/v2/profiles", func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "GET")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusOK)
+		_, _ = w.Write([]byte(testdata.GetProfilesListResponse))
+	})
+
+	opt := &ProfileListOptions{
+		Limit: 10,
+	}
+
+	pl, err := tClient.Profiles.List(opt)
+	if err != nil {
+		t.Error(err)
+	}
+
+	if len(pl.Embedded.Profiles) < 1 {
+		t.Errorf("returned empty list")
+	}
+}
+
+func TestProfilesService_Create(t *testing.T) {
+	setup()
+	defer teardown()
+	id := "pfl_v9hTwCvYqw"
+
+	_ = tClient.WithAuthenticationValue("test_token")
+
+	tMux.HandleFunc("/v2/profiles", func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "POST")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusCreated)
+		_, _ = w.Write([]byte(testdata.CreateProfileResponse))
+	})
+	np := &Profile{
+		ID:           "pfl_v9hTwCvYqw",
+		CategoryCode: GeneralMerchandise,
+		Email:        "info@mywebsite.com",
+		Mode:         LiveMode,
+		Name:         "My website name",
+	}
+
+	p, err := tClient.Profiles.Create(np)
+	if err != nil {
+		t.Error(err)
+	}
+
+	if p.ID != np.ID {
+		t.Errorf("unexpected response, want: %v got: %v", p.ID, id)
+	}
+}
+
+func TestProfilesService_Update(t *testing.T) {
+	setup()
+	defer teardown()
+	id := "pfl_v9hTwCvYqw"
+
+	_ = tClient.WithAuthenticationValue("test_token")
+
+	tMux.HandleFunc("/v2/profiles/"+id, func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "PATCH")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusOK)
+		_, _ = w.Write([]byte(testdata.GetProfileResponse))
+	})
+
+	np := &Profile{
+		ID:           "pfl_v9hTwCvYqw",
+		CategoryCode: GeneralMerchandise,
+		Email:        "info@mywebsite.com",
+		Mode:         LiveMode,
+		Name:         "My website name",
+		Phone:        "",
+	}
+
+	p, err := tClient.Profiles.Update(id, np)
+	if err != nil {
+		t.Error(err)
+	}
+
+	if p.ID != id {
+		t.Errorf("unexpected response, want: %v got: %v", p.ID, id)
+	}
+}
+
+func TestProfilesService_Delete(t *testing.T) {
+	setup()
+	defer teardown()
+	id := "pfl_v9hTwCvYqw"
+
+	_ = tClient.WithAuthenticationValue("test_token")
+
+	tMux.HandleFunc("/v2/profiles/"+id, func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "DELETE")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	err := tClient.Profiles.Delete(id)
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func TestProfilesService_EnablePaymentMethod(t *testing.T) {
+	setup()
+	defer teardown()
+	id := "pfl_v9hTwCvYqw"
+
+	_ = tClient.WithAuthenticationValue("test_token")
+
+	tMux.HandleFunc("/v2/profiles/"+id+"/methods/bancontact", func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "POST")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusOK)
+		_, _ = w.Write([]byte(testdata.EnablePaymentMethodResponse))
+	})
+
+	res, err := tClient.Profiles.EnablePaymentMethod(id, Bancontact)
+	if err != nil {
+		t.Error(err)
+	}
+
+	if res.ID != string(Bancontact) {
+		t.Errorf("unexpected response, want: %v got: %v", Bancontact, res.ID)
+	}
+}
+
+func TestProfilesService_DisablePaymentMethod(t *testing.T) {
+	setup()
+	defer teardown()
+	id := "pfl_v9hTwCvYqw"
+
+	_ = tClient.WithAuthenticationValue("test_token")
+
+	tMux.HandleFunc("/v2/profiles/"+id+"/methods/bancontact", func(w http.ResponseWriter, r *http.Request) {
+		testHeader(t, r, AuthHeader, "Bearer test_token")
+		testMethod(t, r, "DELETE")
+		if _, ok := r.Header[AuthHeader]; !ok {
+			w.WriteHeader(http.StatusUnauthorized)
+		}
+
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	err := tClient.Profiles.DisablePaymentMethod(id, Bancontact)
+	if err != nil {
+		t.Error(err)
+	}
+}
+
+func TestProfilesService_HttpRequestErrors(t *testing.T) {
+	setup()
+	defer teardown()
+	tMux.HandleFunc("/v2/profiles/", errorHandler)
+
+	p := Profile{}
+
+	_, cerr := tClient.Profiles.Create(&p)
+	_, rerr := tClient.Profiles.List(nil)
+	_, uerr := tClient.Profiles.Update("1212", &p)
+	derr := tClient.Profiles.Delete("1212")
+	_, gerr := tClient.Profiles.Get("1212")
+	_, ccerr := tClient.Profiles.Current()
+	dderr := tClient.Profiles.DisablePaymentMethod("1212", PayPal)
+	_, eperr := tClient.Profiles.EnablePaymentMethod("1212", PayPal)
+
+	tests := []error{cerr, rerr, uerr, derr, gerr, ccerr, eperr, dderr}
+
+	for _, tt := range tests {
+		if tt == nil {
+			t.Fail()
+		}
+	}
+}
+
+func TestProfilesService_EncodingResponseErrors(t *testing.T) {
+	setup()
+	defer teardown()
+	tMux.HandleFunc("/v2/profiles/", encodingHandler)
+
+	p := Profile{}
+
+	_, cerr := tClient.Profiles.Create(&p)
+	_, rerr := tClient.Profiles.List(nil)
+	_, uerr := tClient.Profiles.Update("1212", &p)
+	_, gerr := tClient.Profiles.Get("1212")
+	_, ccerr := tClient.Profiles.Current()
+	_, eperr := tClient.Profiles.EnablePaymentMethod("1212", PayPal)
+
+	tests := []error{cerr, rerr, uerr, gerr, ccerr, eperr}
+
+	for _, tt := range tests {
+		if tt == nil {
+			t.Error(tt)
+		} else if !strings.Contains(tt.Error(), "invalid character") {
+			t.Errorf("unexpected error %v", tt)
+		}
+	}
+}
+
+func TestProfilesService_NewAPIRequestBaseError(t *testing.T) {
+	setup()
+	defer teardown()
+	u, _ := url.Parse(tServer.URL)
+	tClient.BaseURL = u
+	tMux.HandleFunc("/v2/profiles/", errorHandler)
+
+	p := Profile{}
+
+	_, cerr := tClient.Profiles.Create(&p)
+	_, rerr := tClient.Profiles.List(nil)
+	_, uerr := tClient.Profiles.Update("1212", &p)
+	_, gerr := tClient.Profiles.Get("1212")
+	_, ccerr := tClient.Profiles.Current()
+	ddcerr := tClient.Profiles.Delete("1212")
+	_, eperr := tClient.Profiles.EnablePaymentMethod("1212", PayPal)
+	deperr := tClient.Profiles.DisablePaymentMethod("1212", PayPal)
+
+	tests := []error{cerr, rerr, uerr, gerr, ccerr, eperr, deperr, ddcerr}
+
+	for _, tt := range tests {
+		if tt != errBadBaseURL {
+			t.Error(tt)
+		}
+	}
+}
diff --git a/testdata/profiles.go b/testdata/profiles.go
new file mode 100644
index 0000000..a7c2a41
--- /dev/null
+++ b/testdata/profiles.go
@@ -0,0 +1,231 @@
+package testdata
+
+// GetProfileResponse example
+const GetProfileResponse = `{
+    "resource": "profile",
+    "id": "pfl_v9hTwCvYqw",
+    "mode": "live",
+    "name": "My website name",
+    "website": "https://www.mywebsite.com",
+    "email": "info@mywebsite.com",
+    "phone": "+31208202070",
+    "categoryCode": 5399,
+    "status": "verified",
+    "review": {
+        "status": "pending"
+    },
+    "createdAt": "2018-03-20T09:28:37+00:00",
+    "_links": {
+        "self": {
+            "href": "https://api.mollie.com/v2/profiles/pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "chargebacks": {
+            "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "methods": {
+            "href": "https://api.mollie.com/v2/methods?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "payments": {
+            "href": "https://api.mollie.com/v2/payments?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "refunds": {
+            "href": "https://api.mollie.com/v2/refunds?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "checkoutPreviewUrl": {
+            "href": "https://www.mollie.com/payscreen/preview/pfl_v9hTwCvYqw",
+            "type": "text/html"
+        },
+        "documentation": {
+            "href": "https://docs.mollie.com/reference/v2/profiles-api/create-profile",
+            "type": "text/html"
+        }
+    }
+}`
+
+// GetProfilesListResponse example
+const GetProfilesListResponse = `{
+    "_embedded": {
+        "profiles": [
+            {
+                "resource": "profiles",
+                "id": "pfl_v9hTwCvYqw",
+                "mode": "live",
+                "name": "My website name",
+                "website": "https://www.mywebsite.com",
+                "email": "info@mywebsite.com",
+                "phone": "+31208202070",
+                "categoryCode": 5399,
+                "status": "verified",
+                "review": {
+                    "status": "pending"
+                },
+                "createdAt": "2018-03-20T09:28:37+00:00",
+                "_links": {
+                    "self": {
+                        "href": "https://api.mollie.com/v2/profiles/pfl_v9hTwCvYqw",
+                        "type": "application/hal+json"
+                    },
+                    "chargebacks": {
+                        "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_v9hTwCvYqw",
+                        "type": "application/hal+json"
+                    },
+                    "methods": {
+                        "href": "https://api.mollie.com/v2/methods?profileId=pfl_v9hTwCvYqw",
+                        "type": "application/hal+json"
+                    },
+                    "payments": {
+                        "href": "https://api.mollie.com/v2/payments?profileId=pfl_v9hTwCvYqw",
+                        "type": "application/hal+json"
+                    },
+                    "refunds": {
+                        "href": "https://api.mollie.com/v2/refunds?profileId=pfl_v9hTwCvYqw",
+                        "type": "application/hal+json"
+                    },
+                    "checkoutPreviewUrl": {
+                        "href": "https://www.mollie.com/payscreen/preview/pfl_v9hTwCvYqw",
+                        "type": "text/html"
+                    },
+                    "documentation": {
+                        "href": "https://docs.mollie.com/reference/v2/profiles-api/create-profile",
+                        "type": "text/html"
+                    }
+                }
+            }
+        ]
+    },
+    "count": 5,
+    "_links": {
+        "documentation": {
+            "href": "https://docs.mollie.com/reference/v2/profiles-api/list-profiles",
+            "type": "text/html"
+        },
+        "self": {
+            "href": "https://api.mollie.com/v2/profiles?limit=5",
+            "type": "application/hal+json"
+        },
+        "previous": null,
+        "next": {
+            "href": "https://api.mollie.com/v2/profiles?from=pfl_3RkSN1zuPE&limit=5",
+            "type": "application/hal+json"
+        }
+    }
+}`
+
+// CreateProfileResponse example
+const CreateProfileResponse = `
+{
+    "resource": "profile",
+    "id": "pfl_v9hTwCvYqw",
+    "mode": "live",
+    "name": "My website name",
+    "website": "https://www.mywebsite.com",
+    "email": "info@mywebsite.com",
+    "phone": "+31208202070",
+    "categoryCode": 5399,
+    "status": "unverified",
+    "createdAt": "2018-03-20T09:28:37+00:00",
+    "_links": {
+        "self": {
+            "href": "https://api.mollie.com/v2/profiles/pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "chargebacks": {
+            "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "methods": {
+            "href": "https://api.mollie.com/v2/methods?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "payments": {
+            "href": "https://api.mollie.com/v2/payments?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "refunds": {
+            "href": "https://api.mollie.com/v2/refunds?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "checkoutPreviewUrl": {
+            "href": "https://www.mollie.com/payscreen/preview/pfl_v9hTwCvYqw",
+            "type": "text/html"
+        },
+        "documentation": {
+            "href": "https://docs.mollie.com/reference/v2/profiles-api/create-profile",
+            "type": "text/html"
+        }
+    }
+}`
+
+const UpdateProfileResponse = `{
+    "resource": "profile",
+    "id": "pfl_v9hTwCvYqw",
+    "mode": "live",
+    "name": "My website name - Update 1",
+    "website": "https://www.mywebsite2.com",
+    "email": "info@mywebsite2.com",
+    "phone": "+31208202070",
+    "categoryCode": 5399,
+    "status": "verified",
+    "review": {
+        "status": "pending"
+    },
+    "createdAt": "2018-03-20T09:28:37+00:00",
+    "_links": {
+        "self": {
+            "href": "https://api.mollie.com/v2/profiles/pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "chargebacks": {
+            "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "methods": {
+            "href": "https://api.mollie.com/v2/methods?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "payments": {
+            "href": "https://api.mollie.com/v2/payments?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "refunds": {
+            "href": "https://api.mollie.com/v2/refunds?profileId=pfl_v9hTwCvYqw",
+            "type": "application/hal+json"
+        },
+        "checkoutPreviewUrl": {
+            "href": "https://www.mollie.com/payscreen/preview/pfl_v9hTwCvYqw",
+            "type": "text/html"
+        },
+        "documentation": {
+            "href": "https://docs.mollie.com/reference/v2/profiles-api/create-profile",
+            "type": "text/html"
+        }
+    }
+}`
+
+// EnablePaymentMethodResponse example
+const EnablePaymentMethodResponse = `{
+    "resource": "method",
+    "id": "bancontact",
+    "description": "Bancontact",
+    "image": {
+        "size1x": "https://www.mollie.com/external/icons/payment-methods/bancontact.png",
+        "size2x": "https://www.mollie.com/external/icons/payment-methods/bancontact%402x.png",
+        "svg": "https://www.mollie.com/external/icons/payment-methods/bancontact.svg"
+    },
+    "_links": {
+        "self": {
+            "href": "https://api.mollie.com/v2/methods/bancontact",
+            "type": "application/hal+json"
+        },
+        "documentation": {
+            "href": "https://docs.mollie.com/reference/v2/profiles-api/activate-method",
+            "type": "text/html"
+        }
+    }
+}
+`