diff --git a/default.go b/default.go index dd23b2a..1824408 100644 --- a/default.go +++ b/default.go @@ -49,6 +49,15 @@ type PayoutRequest struct { Correspondent string } +type DepositRequest struct { + DepositId string + Amount Amount + Description string + PhoneNumber PhoneNumber + Correspondent string + PreAuthCode string +} + // PhoneNumber holds country code and number, eg countryCode:234, number: 7017238745 type PhoneNumber struct { CountryCode string `json:"countryCode"` @@ -83,6 +92,11 @@ type CreatePayoutRequest struct { StatementDescription string `json:"statementDescription"` } +type Payer struct { + Type string `json:"type"` + Address Address `json:"address"` +} + type CreatePayoutResponse struct { PayoutID string `json:"payoutId"` Status string `json:"status"` @@ -131,7 +145,8 @@ func (t Payout) IsNotFound() bool { } type ResendCallbackRequest struct { - PayoutId string `json:"payoutId"` + PayoutId string `json:"payoutId,omitempty"` + DepositId string `json:"depositId,omitempty"` } type PayoutStatusResponse struct { @@ -140,6 +155,30 @@ type PayoutStatusResponse struct { Annotation APIAnnotation } +type CreateDepositRequest struct { + DepositId string `json:"depositId"` + Amount string `json:"amount"` + Currency string `json:"currency"` + Country string `json:"country"` + Correspondent string `json:"correspondent"` + Payer Payer `json:"payer"` + CustomerTimestamp string `json:"customerTimestamp"` + StatementDescription string `json:"statementDescription"` + PreAuthorizationCode string `json:"preAuthorisationCode"` +} + +type CreateDepositResponse struct { + DepositId string `json:"depositId"` + Status string `json:"status"` + Created string `json:"created"` + Annotation APIAnnotation +} + +type CreateBulkDepositResponse struct { + Result []CreateDepositResponse + Annotation APIAnnotation +} + // TimeProviderFunc represents a provider of time type TimeProviderFunc func() time.Time @@ -249,6 +288,70 @@ func (s *Service) newCreateBulkPayoutRequest(timeProvider TimeProviderFunc, req return requests, nil } +func (s *Service) newDepositRequest(timeProvider TimeProviderFunc, depositId string, amt Amount, countryCode, code, description string, + pn PhoneNumber, authCode string) CreateDepositRequest { + layout := "2006-01-02T15:04:05Z" + if len(description) > 22 { + description = description[:22] + } + + return CreateDepositRequest{ + DepositId: depositId, + Amount: amt.Value, + Currency: amt.Currency, + Country: countryCode, + Correspondent: code, + CustomerTimestamp: timeProvider().Format(layout), + StatementDescription: description, + PreAuthorizationCode: authCode, + Payer: Payer{Type: recipientType, Address: Address{Value: fmt.Sprintf("%s%s", pn.CountryCode, pn.Number)}}, + } +} + +func (s *Service) newCreateBulkDepositRequest(timeProvider TimeProviderFunc, req []DepositRequest) ([]CreateDepositRequest, error) { + requests := []CreateDepositRequest{} + for _, payload := range req { + + query := gountries.New() + se, err := query.FindCountryByCallingCode(payload.PhoneNumber.CountryCode) + if err != nil { + return []CreateDepositRequest{}, err + } + + countryCode := se.Alpha3 + + requests = append(requests, s.newDepositRequest(timeProvider, payload.DepositId, payload.Amount, + countryCode, payload.Correspondent, payload.Description, payload.PhoneNumber, payload.PreAuthCode)) + } + + return requests, nil +} + +type Deposit struct { + DepositId string `json:"depositId"` + Status string `json:"status"` + RequestedAmount string `json:"requestedAmount"` + DepositedAmount string `json:"depositedAmount"` + Currency string `json:"currency"` + Country string `json:"country"` + Payer Payer `json:"recipient"` + Correspondent string `json:"correspondent"` + StatementDescription string `json:"statementDescription"` + CustomerTimestamp string `json:"customerTimestamp"` + Created string `json:"created"` + RespondedByPayer string `json:"respondedByPayer"` + CorrespondentIds map[string]interface{} `json:"correspondentIds"` + SuspiciousActivity map[string]interface{} `json:"suspiciousActivityReport"` + FailureReason FailureReason `json:"failureReason"` + Annotation APIAnnotation +} + +type DepositStatusResponse struct { + DepositId string `json:"depositId"` + Status string `json:"status"` + Annotation APIAnnotation +} + func GetAllCorrespondents() ([]MomoMapping, error) { var path string diff --git a/deposit.go b/deposit.go new file mode 100644 index 0000000..2c3d80c --- /dev/null +++ b/deposit.go @@ -0,0 +1,90 @@ +package pawapay + +import ( + "fmt" + "net/http" + + "github.com/pariz/gountries" +) + +// InitiateDeposit provides the functionality of initiating a deposit for the sender to confirm +// See docs https://docs.pawapay.co.uk/#operation/createDesposit for more details +func (s *Service) InitiateDeposit(timeProvider TimeProviderFunc, depositReq DepositRequest) (CreateDepositResponse, error) { + + query := gountries.New() + se, err := query.FindCountryByCallingCode(depositReq.PhoneNumber.CountryCode) + if err != nil { + return CreateDepositResponse{}, err + } + countryCode := se.Alpha3 + + resource := "deposits" + payload := s.newDepositRequest(timeProvider, depositReq.DepositId, depositReq.Amount, countryCode, + depositReq.Correspondent, depositReq.Description, depositReq.PhoneNumber, depositReq.PreAuthCode) + + var response CreateDepositResponse + annotation, err := s.makeRequest(http.MethodPost, resource, payload, &response) + if err != nil { + return CreateDepositResponse{}, err + } + response.Annotation = annotation + + return response, nil +} + +// CreateBulkDeposit provides the functionality of creating a bulk deposit +// See docs https://docs.pawapay.co.uk/#operation/createDeposits for more details +func (s *Service) CreateBulkDeposit(timeProvider TimeProviderFunc, data []DepositRequest) (CreateBulkDepositResponse, error) { + + resource := "deposits/bulk" + payload, err := s.newCreateBulkDepositRequest(timeProvider, data) + if err != nil { + return CreateBulkDepositResponse{}, err + } + + var response []CreateDepositResponse + annotation, err := s.makeRequest(http.MethodPost, resource, payload, &response) + if err != nil { + return CreateBulkDepositResponse{}, err + } + + return CreateBulkDepositResponse{Result: response, Annotation: annotation}, nil +} + +// GetDeposit provides the functionality of retrieving a deposit +// See docs https://docs.pawapay.co.uk/#operation/getDeposit for more details +func (s *Service) GetDeposit(depositId string) (Deposit, error) { + + resource := fmt.Sprintf("payouts/%s", depositId) + var ( + response []Deposit + result Deposit + ) + + annotation, err := s.makeRequest(http.MethodGet, resource, nil, &response) + if err != nil { + return Deposit{}, err + } + if len(response) > 0 { + result = response[0] + } + result.Annotation = annotation + return result, nil +} + +// ResendCallback provides the functionality of resending a callback (webhook) for a deposit +// See docs https://docs.pawapay.co.uk/#operation/depositsResendCallback for more details +func (s *Service) ResendDepositCallback(depositId string) (DepositStatusResponse, error) { + + resource := "deposits/resend-callback" + payload := ResendCallbackRequest{DepositId: depositId} + + var response DepositStatusResponse + annotation, err := s.makeRequest(http.MethodPost, resource, payload, &response) + if err != nil { + return DepositStatusResponse{}, err + } + response.Annotation = annotation + + return response, nil +}