summaryrefslogtreecommitdiff
path: root/c2ec/transfer.go
blob: 915db6773ac30c9a98f2adaf6831aadac019dc76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package main

import (
	"context"
	"encoding/base64"
	"errors"
	"fmt"
	"strconv"
	"time"
)

const REFUND_CHANNEL_BUFFER_SIZE = 10
const PS_REFUND_CHANNEL = "transfer"

const TRANSFER_STATUS_SUCCESS = 0
const TRANSFER_STATUS_RETRY = 1
const TRANSFER_STATUS_FAILED = -1

// Sets up and runs an attestor in the background. This must be called at startup.
func RunRefunder(
	ctx context.Context,
	errs chan error,
) {

	go RunListener(
		ctx,
		PS_REFUND_CHANNEL,
		transferCallback,
		make(chan *Notification, REFUND_CHANNEL_BUFFER_SIZE),
		errs,
	)
}

func transferCallback(notification *Notification, errs chan error) {

	LogInfo("refunder", fmt.Sprintf("retrieved information on channel=%s with payload=%s", notification.Channel, notification.Payload))

	transferRequestUidBase64 := notification.Payload
	if transferRequestUidBase64 == "" {
		errs <- errors.New("the transfer to refund is not specified")
		return
	}

	transferRequestUid, err := base64.StdEncoding.DecodeString(transferRequestUidBase64)
	if err != nil {
		errs <- errors.New("malformed transfer request uid: " + err.Error())
		return
	}

	// Load Transfer from DB
	transfer, err := DB.GetTransferById(transferRequestUid)
	if err != nil {
		LogError("refunder", err)
		transferFailed(transfer, errs)
		errs <- err
	}

	// Load Provider from DB (by payto uri)
	paytoTargetType, tid, err := ParsePaytoWalleeTransaction(transfer.CreditAccount)
	if err != nil {
		errs <- errors.New("malformed transfer request uid: " + err.Error())
		transferFailed(transfer, errs)
		return
	}

	provider, err := DB.GetTerminalProviderByPaytoTargetType(paytoTargetType)
	if err != nil {
		LogError("refunder", err)
		transferFailed(transfer, errs)
		errs <- err
	}

	client := PROVIDER_CLIENTS[provider.Name]
	if client == nil {
		errs <- errors.New("no provider client registered for provider " + provider.Name)
	}

	err = client.Refund(strconv.Itoa(tid))
	if err != nil {
		LogError("refunder", err)
		transferFailed(transfer, errs)
		return
	}

	err = DB.UpdateTransfer(
		transfer.RequestUid,
		time.Now().Unix(),
		TRANSFER_STATUS_SUCCESS, // success
		transfer.Retries,
	)
	if err != nil {
		errs <- err
	}
}

func transferFailed(
	transfer *Transfer,
	errs chan error,
) {

	if transfer.Retries > 2 {
		err := DB.UpdateTransfer(
			transfer.RequestUid,
			time.Now().Unix(),
			TRANSFER_STATUS_FAILED, // transfer ultimatively failed.
			transfer.Retries,
		)
		if err != nil {
			errs <- err
		}
	} else {
		err := DB.UpdateTransfer(
			transfer.RequestUid,
			time.Now().Unix(),
			TRANSFER_STATUS_RETRY, // retry transfer.
			transfer.Retries+1,
		)
		if err != nil {
			errs <- err
		}
	}
}