commit 23c15bc81deb564b0d2011a0590a3440ebf02461
parent f840c891ca0235637225bf5349348fe768aa048a
Author: Joel-Haeberli <haebu@rubigen.ch>
Date: Mon, 3 Jun 2024 11:32:00 +0200
fix: refund
Diffstat:
7 files changed, 106 insertions(+), 17 deletions(-)
diff --git a/c2ec/amount.go b/c2ec/amount.go
@@ -197,12 +197,16 @@ func ParseAmount(s string, fractionDigits int) (*Amount, error) {
if len(valueAndFraction[1]) > fractionDigits {
return nil, fmt.Errorf("invalid amount: %s expected at max %d fractional digits", s, fractionDigits)
}
+ k := 0
+ if len(valueAndFraction[1]) < fractionDigits {
+ k = fractionDigits - len(valueAndFraction[1])
+ }
fractionInt, err := strconv.Atoi(valueAndFraction[1])
if err != nil {
LogError("amount", err)
return nil, fmt.Errorf("invalid fraction in amount %s", s)
}
- fraction = fractionInt
+ fraction = fractionInt * int(math.Pow10(k))
}
a := NewAmount(currency, uint64(value), uint64(fraction))
@@ -216,12 +220,15 @@ func (a *Amount) IsZero() bool {
// Returns the string representation of the amount: <currency>:<value>[.<fraction>]
// Omits trailing zeroes.
-func (a *Amount) String() string {
- v := strconv.FormatUint(a.Value, 10)
- if a.Fraction != 0 {
- f := strconv.FormatUint(a.Fraction, 10)
- f = strings.TrimRight(f, "0")
- v = fmt.Sprintf("%s.%s", v, f)
- }
- return fmt.Sprintf("%s:%s", a.Currency, v)
+func (a *Amount) String(fractionalDigits int) string {
+
+ return FormatAmount(a, fractionalDigits)
+
+ // v := strconv.FormatUint(a.Value, 10)
+ // if a.Fraction != 0 {
+ // f := strconv.FormatUint(a.Fraction, 10)
+ // f = strings.TrimRight(f, "0")
+ // v = fmt.Sprintf("%s.%s", v, f)
+ // }
+ // return fmt.Sprintf("%s:%s", a.Currency, v)
}
diff --git a/c2ec/amount_test.go b/c2ec/amount_test.go
@@ -44,7 +44,7 @@ func TestAmountAdd(t *testing.T) {
if err != nil {
t.Errorf("Failed adding amount")
}
- if c.String() != d.String() {
+ if c.String(8) != d.String(8) {
t.Errorf("Failed to add to correct amount")
}
}
@@ -54,7 +54,7 @@ func TestAmountSub(t *testing.T) {
if err != nil {
t.Errorf("Failed substracting amount")
}
- if a.String() != d.String() {
+ if a.String(8) != d.String(8) {
t.Errorf("Failed to substract to correct amount")
}
}
@@ -72,6 +72,68 @@ func TestAmountLarge(t *testing.T) {
}
}
+func TestAmountSub2(t *testing.T) {
+
+ amnts := []string{
+ "CHF:30",
+ "EUR:20.34",
+ "CHF:23.99",
+ "CHF:50.35",
+ "USD:109992332",
+ "CHF:0.0",
+ "EUR:00.0",
+ "USD:0.00",
+ "CHF:00.00",
+ }
+
+ for _, a := range amnts {
+ am, err := ParseAmount(a, 2)
+ if err != nil {
+ fmt.Println("parsing failed!", a, err)
+ t.FailNow()
+ }
+ fmt.Println("subtracting", am.String(2))
+ a2, err := am.Sub(*am)
+ if err != nil {
+ fmt.Println("subtracting failed!", a, err)
+ t.FailNow()
+ }
+ fmt.Println("subtraction result", a2.String(2))
+ if !a2.IsZero() {
+ fmt.Println("subtracting failure... expected zero amount but was", a2.String(2))
+ }
+ }
+}
+
+func TestAmountSub3(t *testing.T) {
+
+ amnts := []string{
+ "CHF:30.0004",
+ "CHF:30.004",
+ "CHF:30.04",
+ "CHF:30.4",
+ "CHF:30",
+ }
+
+ for _, a := range amnts {
+ am, err := ParseAmount(a, 4)
+ if err != nil {
+ fmt.Println("parsing failed!", a, err)
+ t.FailNow()
+ }
+ fmt.Println("subtracting", am.String(4))
+ a2, err := am.Sub(*am)
+ if err != nil {
+ fmt.Println("subtracting failed!", a, err)
+ t.FailNow()
+ }
+ fmt.Println("subtraction result", a2.String(4))
+ if !a2.IsZero() && a2.String(4) != am.Currency+":0" {
+ fmt.Println("subtracting failure... expected zero amount but was", a2.String(4))
+ }
+ }
+}
+
func TestParseValid(t *testing.T) {
amnts := []string{
diff --git a/c2ec/api-wire-gateway.go b/c2ec/api-wire-gateway.go
@@ -500,6 +500,6 @@ func historyOutgoing(res http.ResponseWriter, req *http.Request) {
func adminAddIncoming(res http.ResponseWriter, req *http.Request) {
// not implemented, because not used
- setLastResponseCodeForLogger(HTTP_BAD_REQUEST)
- res.WriteHeader(HTTP_BAD_REQUEST)
+ setLastResponseCodeForLogger(HTTP_NOT_IMPLEMENTED)
+ res.WriteHeader(HTTP_NOT_IMPLEMENTED)
}
diff --git a/c2ec/http-util.go b/c2ec/http-util.go
@@ -20,6 +20,7 @@ const HTTP_NOT_FOUND = 404
const HTTP_METHOD_NOT_ALLOWED = 405
const HTTP_CONFLICT = 409
const HTTP_INTERNAL_SERVER_ERROR = 500
+const HTTP_NOT_IMPLEMENTED = 501
const CONTENT_TYPE_HEADER = "Content-Type"
diff --git a/c2ec/wallee-client.go b/c2ec/wallee-client.go
@@ -192,8 +192,27 @@ func (w *WalleeClient) Refund(transactionId string) error {
return err
}
+ amountWithFeesStr := fmt.Sprintf("%s:%s", CONFIG.Server.Currency, decodedWalleeTransaction.CompletedAmount)
+ amountWithFees, err := ParseAmount(amountWithFeesStr, CONFIG.Server.CurrencyFractionDigits)
+ if err != nil {
+ LogError("wallee-client", err)
+ return err
+ }
+
+ fees, err := ParseAmount(CONFIG.Server.WithdrawalFees, CONFIG.Server.CurrencyFractionDigits)
+ if err != nil {
+ LogError("wallee-client", err)
+ return err
+ }
+
+ refundAmount, err := amountWithFees.Sub(*fees)
+ if err != nil {
+ LogError("wallee-client", err)
+ return err
+ }
+
refund := &WalleeRefund{
- Amount: decodedWalleeTransaction.CompletedAmount,
+ Amount: refundAmount.String(CONFIG.Server.CurrencyFractionDigits),
ExternalID: encodeCrock(withdrawal.Wopid),
MerchantReference: decodedWalleeTransaction.MerchantReference,
Transaction: WalleeRefundTransaction{
diff --git a/c2ec/wallee-client_test.go b/c2ec/wallee-client_test.go
@@ -19,7 +19,7 @@ const INT_TEST_SPACE_ID = 0
const INT_TEST_USER_ID = 0
const INT_TEST_ACCESS_TOKEN = ""
-const INT_TEST_REFUND_AMOUNT = 0
+const INT_TEST_REFUND_AMOUNT = "0"
const INT_TEST_REFUND_EXT_ID = "" // can be anything -> idempotency
const INT_TEST_REFUND_MERCHANT_REFERENCE = ""
const INT_TEST_REFUND_TRANSACTION_ID = 0
diff --git a/c2ec/wallee-models.go b/c2ec/wallee-models.go
@@ -76,7 +76,7 @@ type WalleeTransactionCompletion struct {
}
*/
type WalleeRefund struct {
- Amount float64 `json:"amount"`
+ Amount string `json:"amount"`
ExternalID string `json:"externalId"` // idempotence support
MerchantReference string `json:"merchantReference"`
Transaction WalleeRefundTransaction `json:"transaction"`
@@ -189,7 +189,7 @@ type WalleeTransaction struct {
AutoConfirmationEnabled bool `json:"autoConfirmationEnabled"`
BillingAddress interface{} `json:"billingAddress"`
ChargeRetryEnabled bool `json:"chargeRetryEnabled"`
- CompletedAmount float64 `json:"completedAmount"`
+ CompletedAmount string `json:"completedAmount"`
CompletedOn interface{} `json:"completedOn"`
CompletionBehavior string `json:"completionBehavior"`
CompletionTimeoutOn interface{} `json:"completionTimeoutOn"`