customers

package
v1.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 21, 2025 License: MIT Imports: 9 Imported by: 0

README

Customers API

Comprehensive customer management including creation, updates, authorization management, and risk controls.

Available Operations

  • Create - Create a new customer
  • List - List customers with filtering and pagination
  • Fetch - Get customer by ID or code
  • Update - Update customer information
  • Validate - Validate customer identity
  • Whitelist/Blacklist - Set customer risk status
  • Deactivate Authorization - Disable saved payment methods
  • Risk Action - Set customer risk actions

Quick Examples

Create a Customer
import "github.com/huysamen/paystack-go/api/customers"

request := customers.NewCreateRequestBuilder().
    Email("customer@example.com").
    FirstName("John").
    LastName("Doe").
    Phone("+2348012345678").
    Build()

result, err := client.Customers.Create(ctx, *request)
if err != nil {
    return fmt.Errorf("failed to create customer: %w", err)
}

if err := result.Err(); err != nil {
    return fmt.Errorf("customer creation failed: %w", err)
}

customer := result.Data
fmt.Printf("Created customer: %s (ID: %d)\n", 
    customer.Email.String(), 
    customer.ID.Uint64())
List Customers
query := customers.NewListRequestBuilder().
    PerPage(50).
    Page(1).
    Build()

result, err := client.Customers.List(ctx, *query)
if err != nil {
    return err
}

if err := result.Err(); err != nil {
    return err
}

for _, customer := range result.Data {
    fmt.Printf("Customer: %s %s <%s>\n",
        customer.FirstName.String(),
        customer.LastName.String(),
        customer.Email.String())
}
Fetch Customer
// By ID
result, err := client.Customers.Fetch(ctx, 12345)

// By email or customer code
result, err := client.Customers.FetchByCode(ctx, "CUS_abc123xyz")
Update Customer
request := customers.NewUpdateRequestBuilder(12345).
    FirstName("Jane").
    LastName("Smith").
    Phone("+2348087654321").
    Build()

result, err := client.Customers.Update(ctx, *request)
if err != nil {
    return err
}

if err := result.Err(); err != nil {
    return err
}

fmt.Printf("Updated customer: %s\n", result.Data.Email.String())

Advanced Operations

Customer Validation

Validate customer identity with BVN, account number, etc.:

request := customers.NewValidateRequestBuilder().
    CustomerCode("CUS_abc123xyz").
    FirstName("John").
    LastName("Doe").
    Type("bvn").
    Value("12345678901").  // BVN
    Country("NG").
    Build()

result, err := client.Customers.Validate(ctx, *request)
if err != nil {
    return err
}

if err := result.Err(); err != nil {
    return fmt.Errorf("validation failed: %w", err)
}

fmt.Printf("Validation status: %s\n", result.Data.Status.String())
Risk Management
Whitelist a Customer
request := customers.NewWhitelistRequestBuilder().
    CustomerCode("CUS_abc123xyz").
    Build()

result, err := client.Customers.Whitelist(ctx, *request)
Blacklist a Customer
request := customers.NewBlacklistRequestBuilder().
    CustomerCode("CUS_abc123xyz").
    RiskAction("deny").  // deny, allow
    Build()

result, err := client.Customers.Blacklist(ctx, *request)
Set Risk Action
request := customers.NewRiskActionRequestBuilder().
    Customer(12345).
    Action(customers.RiskActionDeny).  // or RiskActionAllow
    Build()

result, err := client.Customers.RiskAction(ctx, *request)
Authorization Management
Deactivate Authorization

Remove a saved payment method:

request := customers.NewDeactivateAuthorizationRequestBuilder().
    AuthorizationCode("AUTH_abc123xyz").
    Build()

result, err := client.Customers.DeactivateAuthorization(ctx, *request)
if err != nil {
    return err
}

if err := result.Err(); err != nil {
    return err
}

fmt.Printf("Authorization deactivated: %s\n", 
    result.Data.Status.String())

Request Builder Options

Create Customer Builder
request := customers.NewCreateRequestBuilder().
    // Required
    Email("customer@example.com").
    
    // Optional personal info
    FirstName("John").
    LastName("Doe").
    Phone("+2348012345678").
    
    // Optional metadata
    Metadata(map[string]any{
        "customer_id": "internal_123",
        "source": "website",
    }).
    
    Build()
List Customers Builder
query := customers.NewListRequestBuilder().
    // Pagination
    PerPage(100).  // Max 100
    Page(1).
    
    // Optional filters
    // Note: Specific filters depend on API capabilities
    
    Build()
Update Customer Builder
request := customers.NewUpdateRequestBuilder(customerID).
    // Update any field
    FirstName("UpdatedFirstName").
    LastName("UpdatedLastName").
    Phone("+2348087654321").
    
    // Update metadata
    Metadata(map[string]any{
        "updated_at": time.Now().Format(time.RFC3339),
        "source": "mobile_app",
    }).
    
    Build()
Validation Builder
request := customers.NewValidateRequestBuilder().
    CustomerCode("CUS_abc123xyz").
    
    // Identity verification
    FirstName("John").
    LastName("Doe").
    Type("bvn").           // bvn, bank_account, etc.
    Value("12345678901").  // BVN, account number, etc.
    Country("NG").
    
    // Additional fields for bank account validation
    BankCode("011").       // For bank account validation
    AccountNumber("0123456789").
    
    Build()

Response Data Types

Customer Object
type Customer struct {
    ID           data.Uint       `json:"id"`
    FirstName    data.NullString `json:"first_name"`
    LastName     data.NullString `json:"last_name"`
    Email        data.String     `json:"email"`
    CustomerCode data.String     `json:"customer_code"`
    Phone        data.NullString `json:"phone"`
    Metadata     Metadata        `json:"metadata"`
    RiskAction   data.String     `json:"risk_action"`
    
    // Timestamps
    CreatedAt    data.Time       `json:"createdAt"`
    UpdatedAt    data.Time       `json:"updatedAt"`
    
    // Integration info
    Integration  data.Int        `json:"integration"`
    Domain       data.String     `json:"domain"`
    
    // Identification (if validated)
    Identified              data.Bool       `json:"identified"`
    Identifications         []Identification `json:"identifications"`
    
    // Additional fields may be present
}
Authorization Object
type Authorization struct {
    AuthorizationCode data.String     `json:"authorization_code"`
    Bin              data.String     `json:"bin"`
    Last4            data.String     `json:"last4"`
    ExpMonth         data.String     `json:"exp_month"`
    ExpYear          data.String     `json:"exp_year"`
    Channel          enums.Channel   `json:"channel"`
    CardType         data.String     `json:"card_type"`
    Bank             data.String     `json:"bank"`
    CountryCode      data.String     `json:"country_code"`
    Brand            data.String     `json:"brand"`
    Reusable         data.Bool       `json:"reusable"`
    Signature        data.String     `json:"signature"`
    AccountName      data.NullString `json:"account_name"`
}

Error Handling

Common Error Scenarios
result, err := client.Customers.Create(ctx, request)

// Network errors
if err != nil {
    return fmt.Errorf("network error: %w", err)
}

// API errors
if err := result.Err(); err != nil {
    switch {
    case strings.Contains(err.Error(), "email"):
        return fmt.Errorf("invalid email address: %w", err)
    case strings.Contains(err.Error(), "duplicate"):
        return fmt.Errorf("customer already exists: %w", err)
    case strings.Contains(err.Error(), "phone"):
        return fmt.Errorf("invalid phone number: %w", err)
    default:
        return fmt.Errorf("customer creation failed: %w", err)
    }
}
Validation Errors
result, err := client.Customers.Validate(ctx, request)
if err != nil {
    return err
}

if err := result.Err(); err != nil {
    switch {
    case strings.Contains(err.Error(), "bvn"):
        return fmt.Errorf("BVN validation failed: %w", err)
    case strings.Contains(err.Error(), "mismatch"):
        return fmt.Errorf("customer details don't match records: %w", err)
    default:
        return fmt.Errorf("validation failed: %w", err)
    }
}

// Check validation status
if result.Data.Status.String() != "success" {
    return fmt.Errorf("validation unsuccessful: %s", result.Data.Status.String())
}

Best Practices

1. Email Validation

Always validate email addresses before creating customers:

import "net/mail"

func isValidEmail(email string) bool {
    _, err := mail.ParseAddress(email)
    return err == nil
}

if !isValidEmail(email) {
    return fmt.Errorf("invalid email format: %s", email)
}
2. Phone Number Format

Use international format for phone numbers:

// Good: International format
phone := "+2348012345678"

// Avoid: Local format
// phone := "08012345678"
3. Metadata Usage

Use metadata for internal tracking:

metadata := map[string]any{
    "internal_customer_id": userID,
    "source": "mobile_app",
    "signup_date": time.Now().Format(time.RFC3339),
    "plan": "premium",
}

request := customers.NewCreateRequestBuilder().
    Email(email).
    Metadata(metadata).
    Build()
4. Customer Lookup

Implement efficient customer lookup:

type CustomerService struct {
    client *paystack.Client
    cache  map[string]*types.Customer // Simple cache
}

func (s *CustomerService) GetOrCreateCustomer(ctx context.Context, email string) (*types.Customer, error) {
    // Check cache first
    if customer, exists := s.cache[email]; exists {
        return customer, nil
    }
    
    // Try to find existing customer
    // Note: You may need to implement search by email
    // or maintain your own customer mapping
    
    // Create new customer if not found
    request := customers.NewCreateRequestBuilder().
        Email(email).
        Build()
        
    result, err := s.client.Customers.Create(ctx, *request)
    if err != nil {
        return nil, err
    }
    
    if err := result.Err(); err != nil {
        // If customer already exists, you might want to handle this
        if strings.Contains(err.Error(), "duplicate") {
            // Handle duplicate customer scenario
        }
        return nil, err
    }
    
    // Cache the result
    s.cache[email] = &result.Data
    return &result.Data, nil
}
5. Risk Management

Implement automated risk management:

func (s *CustomerService) EvaluateCustomerRisk(ctx context.Context, customerID uint64, transaction *types.Transaction) error {
    // Example risk evaluation logic
    if transaction.Amount.Int64() > 1000000 { // Large transaction
        request := customers.NewRiskActionRequestBuilder().
            Customer(customerID).
            Action(customers.RiskActionDeny).
            Build()
            
        result, err := s.client.Customers.RiskAction(ctx, *request)
        if err != nil {
            return err
        }
        
        if err := result.Err(); err != nil {
            return err
        }
    }
    
    return nil
}

Testing

See api/customers/*_test.go for comprehensive examples using real JSON fixtures from resources/examples/responses/customers/.

Tests cover:

  • Customer creation and updates
  • List operations with pagination
  • Validation workflows
  • Risk management operations
  • Error handling scenarios

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewInitializeDirectDebitRequestBuilder

func NewInitializeDirectDebitRequestBuilder(accountNumber, bankCode, street, city, state string) *initializeDirectDebitRequestBuilder

Types

type Account

type Account struct {
	Number   string `json:"number"`
	BankCode string `json:"bank_code"`
}

type Address

type Address struct {
	Street string `json:"street"`
	City   string `json:"city"`
	State  string `json:"state"`
}

type Client

type Client api.API

func (*Client) Create

func (c *Client) Create(ctx context.Context, builder CreateRequestBuilder) (*CreateResponse, error)

func (*Client) DirectDebitActivationCharge

func (c *Client) DirectDebitActivationCharge(ctx context.Context, customerID string, builder DirectDebitActivationChargeRequestBuilder) (*DirectDebitActivationChargeResponse, error)

func (*Client) Fetch

func (c *Client) Fetch(ctx context.Context, emailOrCode string) (*FetchCustomerResponse, error)

func (*Client) FetchMandateAuthorizations

func (c *Client) FetchMandateAuthorizations(ctx context.Context, customerID string) (*FetchMandateAuthorizationsResponse, error)

func (*Client) InitializeDirectDebit

func (c *Client) InitializeDirectDebit(ctx context.Context, customerID string, builder initializeDirectDebitRequestBuilder) (*InitializeDirectDebitResponse, error)

func (*Client) List

func (c *Client) List(ctx context.Context, builder ListRequestBuilder) (*ListResponse, error)

func (*Client) SetRiskAction

func (c *Client) SetRiskAction(ctx context.Context, builder RiskActionRequestBuilder) (*RiskActionResponse, error)

func (*Client) Update

func (c *Client) Update(ctx context.Context, customerCode string, builder UpdateRequestBuilder) (*UpdateResponse, error)

func (*Client) Validate

func (c *Client) Validate(ctx context.Context, customerCode string, builder ValidateRequestBuilder) (*CustomerValidateResponse, error)

func (*Client) VerifyAuthorization

func (c *Client) VerifyAuthorization(ctx context.Context, reference string) (*VerifyAuthorizationResponse, error)

type CreateRequestBuilder

type CreateRequestBuilder struct {
	// contains filtered or unexported fields
}

func NewCreateRequestBuilder

func NewCreateRequestBuilder(email string) *CreateRequestBuilder

func (*CreateRequestBuilder) Build

func (b *CreateRequestBuilder) Build() *createRequest

func (*CreateRequestBuilder) FirstName

func (b *CreateRequestBuilder) FirstName(firstName string) *CreateRequestBuilder

func (*CreateRequestBuilder) LastName

func (b *CreateRequestBuilder) LastName(lastName string) *CreateRequestBuilder

func (*CreateRequestBuilder) Metadata

func (b *CreateRequestBuilder) Metadata(metadata map[string]any) *CreateRequestBuilder

func (*CreateRequestBuilder) Phone

type CreateResponse

type CreateResponse = types.Response[CreateResponseData]

type CreateResponseData

type CreateResponseData = types.Customer

type CustomerReference

type CustomerReference struct {
	Code  string `json:"code"`
	Email string `json:"email"`
}

type CustomerValidateResponse

type CustomerValidateResponse = types.Response[ValidateResponseData]

type CustomerWithRelations

type CustomerWithRelations struct {
	types.Customer
	Subscriptions  []types.Subscription  `json:"subscriptions"`
	Authorizations []types.Authorization `json:"authorizations"`
	Transactions   []types.Transaction   `json:"transactions"`
}

type DeactivateAuthorizationRequestBuilder

type DeactivateAuthorizationRequestBuilder struct {
	// contains filtered or unexported fields
}

func NewDeactivateAuthorizationRequestBuilder

func NewDeactivateAuthorizationRequestBuilder(authorizationCode string) *DeactivateAuthorizationRequestBuilder

func (*DeactivateAuthorizationRequestBuilder) Build

func (b *DeactivateAuthorizationRequestBuilder) Build() *deactivateAuthorizationRequest

type DeactivateAuthorizationResponseData

type DeactivateAuthorizationResponseData = any

type DirectDebitActivationChargeRequestBuilder

type DirectDebitActivationChargeRequestBuilder struct {
	// contains filtered or unexported fields
}

func NewDirectDebitActivationChargeRequestBuilder

func NewDirectDebitActivationChargeRequestBuilder(authorizationID int) *DirectDebitActivationChargeRequestBuilder

func (*DirectDebitActivationChargeRequestBuilder) Build

func (b *DirectDebitActivationChargeRequestBuilder) Build() *directDebitActivationChargeRequest

type DirectDebitActivationChargeResponseData

type DirectDebitActivationChargeResponseData = any

type FetchCustomerResponse

type FetchCustomerResponse = types.Response[FetchCustomerResponseData]

type FetchCustomerResponseData

type FetchCustomerResponseData = CustomerWithRelations

type FetchMandateAuthorizationsResponseData

type FetchMandateAuthorizationsResponseData = []types.MandateAuthorization

type InitializeAuthorizationRequestBuilder

type InitializeAuthorizationRequestBuilder struct {
	// contains filtered or unexported fields
}

func NewInitializeAuthorizationRequestBuilder

func NewInitializeAuthorizationRequestBuilder(email, channel string) *InitializeAuthorizationRequestBuilder

func (*InitializeAuthorizationRequestBuilder) Account

func (*InitializeAuthorizationRequestBuilder) Address

func (*InitializeAuthorizationRequestBuilder) Build

func (b *InitializeAuthorizationRequestBuilder) Build() *initializeAuthorizationRequest

func (*InitializeAuthorizationRequestBuilder) CallbackURL

type InitializeAuthorizationResponseData

type InitializeAuthorizationResponseData struct {
	RedirectURL data.String `json:"redirect_url"`
	AccessCode  data.String `json:"access_code"`
	Reference   data.String `json:"reference"`
}

type InitializeDirectDebitRequest

type InitializeDirectDebitRequest struct {
	Account Account `json:"account"`
	Address Address `json:"address"`
}

type InitializeDirectDebitResponseData

type InitializeDirectDebitResponseData struct {
	RedirectURL data.String `json:"redirect_url"`
	AccessCode  data.String `json:"access_code"`
	Reference   data.String `json:"reference"`
}

type ListRequestBuilder

type ListRequestBuilder struct {
	// contains filtered or unexported fields
}

func NewListRequestBuilder

func NewListRequestBuilder() *ListRequestBuilder

func (*ListRequestBuilder) Build

func (b *ListRequestBuilder) Build() *listRequest

func (*ListRequestBuilder) DateRange

func (b *ListRequestBuilder) DateRange(from, to time.Time) *ListRequestBuilder

func (*ListRequestBuilder) From

func (*ListRequestBuilder) Page

func (b *ListRequestBuilder) Page(page int) *ListRequestBuilder

func (*ListRequestBuilder) PerPage

func (b *ListRequestBuilder) PerPage(perPage int) *ListRequestBuilder

func (*ListRequestBuilder) To

type ListResponse

type ListResponse = types.Response[ListResponseData]

type ListResponseData

type ListResponseData = []types.Customer

type RiskAction

type RiskAction string
const (
	RiskActionDefault RiskAction = "default"
	RiskActionAllow   RiskAction = "allow"
	RiskActionDeny    RiskAction = "deny"
)

type RiskActionRequestBuilder

type RiskActionRequestBuilder struct {
	// contains filtered or unexported fields
}

func NewRiskActionRequestBuilder

func NewRiskActionRequestBuilder(customer string) *RiskActionRequestBuilder

func (*RiskActionRequestBuilder) Build

func (b *RiskActionRequestBuilder) Build() *riskActionRequest

func (*RiskActionRequestBuilder) RiskAction

type RiskActionResponse

type RiskActionResponse = types.Response[RiskActionResponseData]

type RiskActionResponseData

type RiskActionResponseData = types.Customer

type UpdateRequestBuilder

type UpdateRequestBuilder struct {
	// contains filtered or unexported fields
}

func NewUpdateRequestBuilder

func NewUpdateRequestBuilder() *UpdateRequestBuilder

func (*UpdateRequestBuilder) Build

func (b *UpdateRequestBuilder) Build() *updateRequest

func (*UpdateRequestBuilder) FirstName

func (b *UpdateRequestBuilder) FirstName(firstName string) *UpdateRequestBuilder

func (*UpdateRequestBuilder) LastName

func (b *UpdateRequestBuilder) LastName(lastName string) *UpdateRequestBuilder

func (*UpdateRequestBuilder) Metadata

func (b *UpdateRequestBuilder) Metadata(metadata map[string]any) *UpdateRequestBuilder

func (*UpdateRequestBuilder) Phone

type UpdateResponse

type UpdateResponse = types.Response[UpdateResponseData]

type UpdateResponseData

type UpdateResponseData = types.Customer

type ValidateRequestBuilder

type ValidateRequestBuilder struct {
	// contains filtered or unexported fields
}

func NewValidateRequestBuilder

func NewValidateRequestBuilder(firstName, lastName, type_, value, country, bvn string) *ValidateRequestBuilder

func (*ValidateRequestBuilder) AccountNumber

func (b *ValidateRequestBuilder) AccountNumber(accountNumber string) *ValidateRequestBuilder

func (*ValidateRequestBuilder) BankCode

func (b *ValidateRequestBuilder) BankCode(bankCode string) *ValidateRequestBuilder

func (*ValidateRequestBuilder) Build

func (b *ValidateRequestBuilder) Build() *validateRequest

func (*ValidateRequestBuilder) MiddleName

func (b *ValidateRequestBuilder) MiddleName(middleName string) *ValidateRequestBuilder

type ValidateResponseData

type ValidateResponseData = any

type VerifyAuthorizationResponse

type VerifyAuthorizationResponse = types.Response[verifyAuthorizationResponseData]

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL