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
}
}
}
|