<commit_before>// Copyright 2015 Dalenys. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package be2bill

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// These strings represent the alias modes supported by the payment and
// authorization methods of the Direct Link API.
const (
	aliasModeOneClick     = "oneclick"
	aliasModeSubscription = "subscription"
)

// these strings represent the search modes supported by the getTransactions
// operation.
const (
	searchByOrderID       = "ORDERID"
	searchByTransactionID = "TRANSACTIONID"
)

// A Result represents the return value from a call to an operation of the
// DirectLink API.
// It is a map of key/values where keys are strings and values are generic.
//
// See the Notification Parameters at https://developer.be2bill.com/annexes/parameters
// for the supported keys.
type Result map[string]interface{}

// StringValue returns the value for the given property of a Result object.
// The value must be of string type, otherwise an empty string is returned instead.
func (r Result) StringValue(name string) string {
	val, ok := r[name]
	if !ok {
		return ""
	}
	return val.(string)
}

// OperationType returns the name of the operation that returned this object.
func (r Result) OperationType() string {
	return r.StringValue(ResultParamOperationType)
}

// ExecCode returns the execution code that represents the success status
// of the operation.
//
// See https://developer.be2bill.com/annexes/execcodes for a list of supported
// execution codes.
func (r Result) ExecCode() string {
	return r.StringValue(ResultParamExecCode)
}

// Message returns the textual message associated with the result's execution
// code.
func (r Result) Message() string {
	return r.StringValue(ResultParamMessage)
}

// TransactionID returns the identifier of the transaction associated with
// the current operation.
func (r Result) TransactionID() string {
	return r.StringValue(ResultParamTransactionID)
}

// Success returns true if the operation succeeded, false otherwise.
func (r Result) Success() bool {
	return r.ExecCode() == ExecCodeSuccess
}

const (
	directLinkPath     = "/front/service/rest/process"
	exportPath         = "/front/service/rest/export"
	reconciliationPath = "/front/service/rest/reconciliation"

	defaultRequestTimeout = 30 * time.Second
)

var (
	// ErrTimeout is returned by DirectClient operations if the request
	// encounters a timeout and cannot finish.
	ErrTimeout = errors.New("timeout")
	// ErrURLMissing is returned by DirectClient operations if the current
	// environment has no URL specified.
	ErrURLMissing = errors.New("no URL provided")
	// ErrServerError is returned by DirectClient operations if the request
	// encounters a server-side error.
	ErrServerError = errors.New("server error")
)

// A DirectLinkClient represent an access to the Direct Link Be2bill API
// that allows a merchant to perform direct calls to the Be2bill servers
// without the need for a graphical interface such as a web page.
// It supports a variety of operations used to perform payments, captures,
// or getting informations about past transactions.
type DirectLinkClient struct {
	credentials *Credentials
	urls        []string
	hasher      Hasher
	// RequestTimeout is the duration after which requests time out
	// and return an ErrTimeout error.
	// The default timeout is 30 seconds.
	RequestTimeout time.Duration
}

// NewDirectLinkClient returns a new DirectLinkClient using the given
// credentials.
func NewDirectLinkClient(credentials *Credentials) *DirectLinkClient {
	return &DirectLinkClient{
		credentials,
		credentials.environment,
		&defaultHasher{},
		defaultRequestTimeout,
	}
}

func (p *DirectLinkClient) getURLs(path string) []string {
	urls := make([]string, len(p.urls))
	for i, url := range p.urls {
		urls[i] = url + path
	}
	return urls
}

func (p *DirectLinkClient) getDirectLinkURLs() []string {
	return p.getURLs(directLinkPath)
}

func (p *DirectLinkClient) doPostRequest(url string, params Options) ([]byte, error) {
	requestParams := Options{
		"method": params[ParamOperationType],
		"params": params,
	}

	responseChan := make(chan []byte, 1)
	errChan := make(chan error, 1)

	go func() {
		resp, err := http.PostForm(url, requestParams.urlValues())
		if err != nil {
			errChan <- err
			return
		}

		if resp.StatusCode != 200 {
			errChan <- ErrServerError
			return
		}

		defer func() { _ = resp.Body.Close() }()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {<commit_msg>Use timeout parameter in http.Client<commit_after>// Copyright 2015 Dalenys. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package be2bill

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

// These strings represent the alias modes supported by the payment and
// authorization methods of the Direct Link API.
const (
	aliasModeOneClick     = "oneclick"
	aliasModeSubscription = "subscription"
)

// these strings represent the search modes supported by the getTransactions
// operation.
const (
	searchByOrderID       = "ORDERID"
	searchByTransactionID = "TRANSACTIONID"
)

// A Result represents the return value from a call to an operation of the
// DirectLink API.
// It is a map of key/values where keys are strings and values are generic.
//
// See the Notification Parameters at https://developer.be2bill.com/annexes/parameters
// for the supported keys.
type Result map[string]interface{}

// StringValue returns the value for the given property of a Result object.
// The value must be of string type, otherwise an empty string is returned instead.
func (r Result) StringValue(name string) string {
	val, ok := r[name]
	if !ok {
		return ""
	}
	return val.(string)
}

// OperationType returns the name of the operation that returned this object.
func (r Result) OperationType() string {
	return r.StringValue(ResultParamOperationType)
}

// ExecCode returns the execution code that represents the success status
// of the operation.
//
// See https://developer.be2bill.com/annexes/execcodes for a list of supported
// execution codes.
func (r Result) ExecCode() string {
	return r.StringValue(ResultParamExecCode)
}

// Message returns the textual message associated with the result's execution
// code.
func (r Result) Message() string {
	return r.StringValue(ResultParamMessage)
}

// TransactionID returns the identifier of the transaction associated with
// the current operation.
func (r Result) TransactionID() string {
	return r.StringValue(ResultParamTransactionID)
}

// Success returns true if the operation succeeded, false otherwise.
func (r Result) Success() bool {
	return r.ExecCode() == ExecCodeSuccess
}

const (
	directLinkPath     = "/front/service/rest/process"
	exportPath         = "/front/service/rest/export"
	reconciliationPath = "/front/service/rest/reconciliation"

	defaultRequestTimeout = 30 * time.Second
)

var (
	// ErrTimeout is returned by DirectClient operations if the request
	// encounters a timeout and cannot finish.
	ErrTimeout = errors.New("timeout")
	// ErrURLMissing is returned by DirectClient operations if the current
	// environment has no URL specified.
	ErrURLMissing = errors.New("no URL provided")
	// ErrServerError is returned by DirectClient operations if the request
	// encounters a server-side error.
	ErrServerError = errors.New("server error")
)

// A DirectLinkClient represent an access to the Direct Link Be2bill API
// that allows a merchant to perform direct calls to the Be2bill servers
// without the need for a graphical interface such as a web page.
// It supports a variety of operations used to perform payments, captures,
// or getting informations about past transactions.
type DirectLinkClient struct {
	credentials *Credentials
	urls        []string
	hasher      Hasher
	// RequestTimeout is the duration after which requests time out
	// and return an ErrTimeout error.
	// The default timeout is 30 seconds.
	RequestTimeout time.Duration
}

// NewDirectLinkClient returns a new DirectLinkClient using the given
// credentials.
func NewDirectLinkClient(credentials *Credentials) *DirectLinkClient {
	return &DirectLinkClient{
		credentials,
		credentials.environment,
		&defaultHasher{},
		defaultRequestTimeout,
	}
}

func (p *DirectLinkClient) getURLs(path string) []string {
	urls := make([]string, len(p.urls))
	for i, url := range p.urls {
		urls[i] = url + path
	}
	return urls
}

func (p *DirectLinkClient) getDirectLinkURLs() []string {
	return p.getURLs(directLinkPath)
}

func (p *DirectLinkClient) doPostRequest(url string, params Options) ([]byte, error) {
	requestParams := Options{
		"method": params[ParamOperationType],
		"params": params,
	}

	responseChan := make(chan []byte, 1)
	errChan := make(chan error, 1)

	go func() {
		client := &http.Client{
			Timeout: p.RequestTimeout,
		}

		resp, err := client.PostForm(url, requestParams.urlValues())
		if err != nil {
			errChan <- err
			return
		}

		if resp.StatusCode != 200 {
			errChan <- ErrServerError
			return
		}

		defer func() { _ = resp.Body.Close() }()

		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
{'fraction_non_alphanumeric': 0.09416559416559417, 'fraction_numerical': 0.003861003861003861, 'mean_word_length': 3.944326617179215, 'pattern_counts': {'":': 4, '<': 7, '<?xml version=': 0, '>': 3, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2916005', 'n_tokens_mistral': 2761, 'n_tokens_neox': 2639, 'n_words': 1008}