~ghost08/gopay-go-api

0c7beb7dfcec3c2f0d047ff19e594a2c418e78ef — Vladimír Magyar 1 year, 6 months ago 825c030
feat: add payment status
4 files changed, 233 insertions(+), 15 deletions(-)

M go.mod
M gopay.go
M gopay_test.go
M objects.go
M go.mod => go.mod +1 -1
@@ 1,3 1,3 @@
module git.nws.company/vladimir_magyar/go-gopay
module git.sr.ht/~ghost08/go-gopay

go 1.17

M gopay.go => gopay.go +46 -6
@@ 4,9 4,7 @@ import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/http/httputil"
	"time"
)



@@ 64,14 62,18 @@ func (c *Client) CreatePayment(p *Payment) (*PaymentResp, error) {
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/json")
	c.addAuthorization(req)
	data, _ := httputil.DumpRequest(req, true)
	log.Println(string(data))
	/*
		data, _ := httputil.DumpRequest(req, true)
		log.Println(string(data))
	*/
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	data, _ = httputil.DumpResponse(resp, true)
	log.Println(string(data))
	/*
		data, _ = httputil.DumpResponse(resp, true)
		log.Println(string(data))
	*/
	if resp.StatusCode != http.StatusOK {
		var errorResp ErrorResp
		if err := json.NewDecoder(resp.Body).Decode(&errorResp); err != nil {


@@ 85,3 87,41 @@ func (c *Client) CreatePayment(p *Payment) (*PaymentResp, error) {
	}
	return &paymentResp, nil
}

func (c *Client) PaymentStatus(id int) (*PaymentStatus, error) {
	req, err := http.NewRequest(
		"GET",
		fmt.Sprintf("%s/api/payments/payment/%d", apiURL, id),
		nil,
	)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	c.addAuthorization(req)
	/*
		data, _ := httputil.DumpRequest(req, true)
		log.Println(string(data))
	*/
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	/*
		data, _ = httputil.DumpResponse(resp, true)
		log.Println(string(data))
	*/
	if resp.StatusCode != http.StatusOK {
		var errorResp ErrorResp
		if err := json.NewDecoder(resp.Body).Decode(&errorResp); err != nil {
			return nil, err
		}
		return nil, fmt.Errorf("payment status response status: %s\n%w", resp.Status, errorResp)
	}
	var ps PaymentStatus
	if err := json.NewDecoder(resp.Body).Decode(&ps); err != nil {
		return nil, fmt.Errorf("payment status - decoding response: %w", err)
	}
	return &ps, nil
}

M gopay_test.go => gopay_test.go +18 -6
@@ 5,24 5,29 @@ import (
	"testing"
)

const (
	GO_ID         = 8712700986
	CLIENT_ID     = "1689337452"
	CLIENT_SECRET = "CKr7FyEE"
)

func TestLogin(t *testing.T) {
	client, err := Login("1061399163", "stDTmVXF")
	_, err := Login(CLIENT_ID, CLIENT_SECRET)
	if err != nil {
		t.Fatal(err)
	}
	log.Println(client.token)
}

func TestCreatePayment(t *testing.T) {
	client, err := Login("1061399163", "stDTmVXF")
	client, err := Login(CLIENT_ID, CLIENT_SECRET)
	if err != nil {
		t.Fatal()
	}
	payment := &Payment{
		Payer: Payer{
			AllowedPaymentInstruments: []PaymentInstrument{
				PaymentInstrumentPaymentCard,
				PaymentInstrumentBankAccount,
				PaymentInstrumentPaymentCard,
			},
			DefaultPaymentInstrument: PaymentInstrumentPaymentCard,
			AllowedSwifts: []Swift{


@@ 43,7 48,7 @@ func TestCreatePayment(t *testing.T) {
		},
		Target: Target{
			Type: "ACCOUNT",
			Goid: 8123456789,
			Goid: GO_ID,
		},
		Items: []Item{
			{


@@ 76,5 81,12 @@ func TestCreatePayment(t *testing.T) {
	if err != nil {
		t.Fatal(err)
	}
	log.Println(resp)
	log.Println(resp.GwURL)
	status, err := client.PaymentStatus(resp.ID)
	if err != nil {
		t.Fatal(err)
	}
	if status.State != StateCreated {
		t.Fatal("not paid", status.State)
	}
}

M objects.go => objects.go +168 -2
@@ 42,7 42,7 @@ type Payment struct {
	Preauthorization bool `json:"preauthorization,omitempty"`

	//Contains object describing recurrence, if the payment should be recurrent
	Recurrence Recurrence `json:"recurrence,omitempty"`
	Recurrence *Recurrence `json:"recurrence,omitempty"`
}

type Payer struct {


@@ 364,7 364,7 @@ const (

type PaymentResp struct {
	//Payment ID
	Id int `json:"id,omitempty"`
	ID int `json:"id,omitempty"`

	//Order ID
	OrderNumber string `json:"order_number,omitempty"`


@@ 431,6 431,172 @@ const (
	PreauthorizationStateCanceled   PreauthorizationState = "CANCELED"   //Pre-authorization canceled
)

type PaymentStatus struct {
	id int
	//Order ID
	//Example: OBJ20200825
	OrderNumber string `json:"order_number,omitempty"`
	//Payment status
	//Example: PAID
	State State `json:"state,omitempty"`
	//Payment substate
	//Example: _3001
	SubState Substate
	//Payment amount in cents
	//Example: 139950
	Amount int `json:"amount,omitempty"`
	//Payment currency
	//Example: CZK
	Currency Currency `json:"currency,omitempty"`
	//Payment method used
	//Example: BANK_ACCOUNT
	PaymentInstrument PaymentInstrument `json:"payment_intrument,omitempty"`
	//Information about payer and payment methods
	Payer Payer `json:"payer,omitempty"`
	//Payee information
	Target Target `json:"target,omitempty"`
	//Additional payment parameters
	AdditionalParams []AdditionalParam `json:"additional_params,omitempty"`
	//Payment gateway language
	//Example: CS
	Lang Lang `json:"lang,omitempty"`
	//Recurrence info if the payment is recurrent
	Recurrence *Recurrence `json:"recurrence,omitempty"`
	//Preauthorization info if the payment is preauthorized
	Preauthorization bool `json:"preauthorization,omitempty"`
	EetCode          struct {
		//Fiskální identifikační kód (FIK)
		//Example: 28da0811-e050-46c7-a62c-aa456d1f07ef-ff
		FIK string

		//Bezpečnostní kód poplatníka (BKP)
		//Example: 5d874afc-251f8661-ff0e0b13-c7cd8793-6bf0386a
		BKP string

		//Podpisový kód poplatníka (PKP)
		//Example: Ca8sTbURReQjjgcy/znXBKjPOnZof3AxWK5WySpyMrUXF0o7cz1BP6a.....
		PKP string
	} `json:"eet_code,omitempty"`
	//Payment gateway URL
	//Example: https://gw.sandbox.gopay.com/gw/v3/bCcvmwTKK5hrJx2aGG8ZnFyBJhAvF
	GwURL string `json:"gw_url,omitempty"`
}

type Substate string

func (s Substate) String() string {
	switch s {
	case "_101":
		return "We are waiting for an online payment."
	case "_102":
		return "We are waiting for an offline payment."
	case "_3001":
		return "Bank payment confirmed by advice."
	case "_3002":
		return "Bank payment confirmed by statement."
	case "_3003":
		return "Bank payment was not confirmed."
	case "_5001":
		return "Approved with zero amount"
	case "_5002":
		return "Rejection of the payment in the authorization center of the customer’s bank due to reaching the limits on the payment card."
	case "_5003":
		return "Refusal of payment in the authorization center of the customer’s bank due to problems on the part of the payment card issuer."
	case "_5004":
		return "Rejection of the payment in the authorization center of the customer’s bank due to a problem on the part of the payment card issuer."
	case "_5005":
		return "Rejection of the payment in the authorization center of the customer’s bank due to a blocked payment card."
	case "_5006":
		return "Refusal of payment in the authorization center of the customer’s bank due to lack of funds on the payment card."
	case "_5007":
		return "Rejection of the payment in the authorization center of the customer’s bank due to the expired payment card."
	case "_5008":
		return "Rejection of payment in the authorization center of the customer’s bank due to rejection of the CVV/CVC code."
	case "_5009":
		return "Rejection of payment in the customer’s 3D Secure bank system."
	case "_5015":
		return "Rejection of payment in the customer’s 3D Secure bank system."
	case "_5017":
		return "Rejection of payment in the customer’s 3D Secure bank system."
	case "_5018":
		return "Rejection of payment in the customer’s 3D Secure bank system."
	case "_5019":
		return "Rejection of payment in the customer’s 3D Secure bank system."
	case "_6502":
		return "Rejection of payment in the customer’s 3D Secure bank system."
	case "_6504":
		return "Rejection of payment in the customer’s 3D Secure bank system."
	case "_5010":
		return "Rejection of the payment in the authorization center of the customer’s bank due to problems on the payment card."
	case "_5014":
		return "Rejection of the payment in the authorization center of the customer’s bank due to problems on the payment card."
	case "_5011":
		return "Rejection of the payment in the authorization center of the customer’s bank due to problems on the payment card."
	case "_5036":
		return "Rejection of the payment in the authorization center of the customer’s bank due to problems on the payment card."
	case "_5012":
		return "Rejection of the payment in the authorization center of the customer’s bank due to problems on the payment card."
	case "_5013":
		return "Rejection of the payment in the authorization center of the customer’s bank due to problems on the payment card."
	case "_5016":
		return "Rejection of the payment in the authorization center of the customer’s bank due to problems on the payment card."
	case "_5020":
		return "Unknown configuration"
	case "_5021":
		return "Rejection of the payment in the authorization center of the customer’s bank due to reaching the set limits on the payment card."
	case "_5022":
		return "There was a technical problem associated with the customer’s bank authorization center."
	case "_5023":
		return "Payment was not made."
	case "_5038":
		return "Payment was not made."
	case "_5024":
		return "Payment was not made. Payment details were not entered within the time limit on the payment gateway."
	case "_5025":
		return "Payment was not made. The specific reason for rejection is communicated directly to the customer."
	case "_5026":
		return "Payment was not made. The sum of the credited amounts exceeded the amount paid."
	case "_5027":
		return "Payment was not made. The user is not authorized to perform the operation."
	case "_5028":
		return "Payment was not made. The amount to be paid exceeded the authorized amount."
	case "_5029":
		return "Payment has not been made yet."
	case "_5030":
		return "The payment was not made due to a re-entry."
	case "_5031":
		return "There was a technical problem with the payment on the part of the bank."
	case "_5033":
		return "SMS could not be delivered."
	case "_5035":
		return "The payment card is issued in a region where card payments are not supported."
	case "_5037":
		return "The credit card holder canceled the payment."
	case "_5039":
		return "The payment was declined at the customer’s bank authorization center due to a blocked credit card."
	case "_5040":
		return "Duplicate reversal transactions"
	case "_5041":
		return "Duplicate transactions"
	case "_5042":
		return "Bank payment declined."
	case "_5043":
		return "Payment canceled by user."
	case "_5044":
		return "SMS has been sent. It has not yet been delivered."
	case "_5045":
		return "Payment received. Payment will be credited after processing on Bitcoin."
	case "_5046":
		return "The payment was not paid in full."
	case "_5047":
		return "Payment was made overdue."
	case "_5048":
		return "Customer has not given consent for PSD2 payment."
	default:
		return string(s)
	}
}

type ErrorResp struct {
	DateIssued time.Time
	Errors     []Error