mirror of
https://github.com/hanzo-fi/payments.git
synced 2026-10-30 20:31:20 +00:00
119 lines
4.3 KiB
Go
119 lines
4.3 KiB
Go
package column
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/big"
|
|
"time"
|
|
|
|
"github.com/hanzo-fi/go-libs/v5/pkg/types/currency"
|
|
"github.com/hanzo-fi/payments/ce/plugins/column/client"
|
|
"github.com/hanzo-fi/payments/pkg/domain/models"
|
|
)
|
|
|
|
func (p *Plugin) createTransfer(ctx context.Context, pi models.PSPPaymentInitiation) (*models.PSPPayment, error) {
|
|
if err := p.validateTransferRequest(pi); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
curr, _, err := currency.GetCurrencyAndPrecisionFromAsset(supportedCurrenciesWithDecimal, pi.Asset)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get currency and precision from asset: %v: %w", err, models.ErrInvalidRequest)
|
|
}
|
|
|
|
allowOverdraft := models.ExtractNamespacedMetadata(pi.Metadata, client.ColumnAllowOverdraftMetadataKey)
|
|
hold := models.ExtractNamespacedMetadata(pi.Metadata, client.ColumnHoldMetadataKey)
|
|
|
|
resp, err := p.client.InitiateTransfer(
|
|
ctx,
|
|
&client.TransferRequest{
|
|
Amount: pi.Amount.Int64(),
|
|
CurrencyCode: curr,
|
|
SenderBankAccountId: pi.SourceAccount.Reference,
|
|
ReceiverBankAccountId: pi.DestinationAccount.Reference,
|
|
AllowOverdraft: allowOverdraft == "true",
|
|
Hold: hold == "true",
|
|
Reference: pi.Reference,
|
|
Details: client.TransferRequestDetails{
|
|
SenderName: *pi.SourceAccount.Name,
|
|
MerchantName: pi.Metadata[client.ColumnMerchantNameMetadataKey],
|
|
MerchantCategoryCode: pi.Metadata[client.ColumnMerchantCategoryCodeMetadataKey],
|
|
AuthorizationMethod: pi.Metadata[client.ColumnAuthorizationMethodMetadataKey],
|
|
InternalTransferType: pi.Metadata[client.ColumnInternalTransferTypeMetadataKey],
|
|
Website: pi.Metadata[client.ColumnWebsiteMetadataKey],
|
|
Address: client.ColumnAddress{
|
|
Line1: pi.Metadata[client.ColumnAddressLine1MetadataKey],
|
|
Line2: pi.Metadata[client.ColumnAddressLine2MetadataKey],
|
|
City: pi.Metadata[client.ColumnAddressCityMetadataKey],
|
|
CountryCode: pi.Metadata[client.ColumnAddressCountryCodeMetadataKey],
|
|
PostalCode: pi.Metadata[client.ColumnAddressPostalCodeMetadataKey],
|
|
State: pi.Metadata[client.ColumnAddressStateMetadataKey],
|
|
},
|
|
},
|
|
},
|
|
)
|
|
if err != nil {
|
|
return &models.PSPPayment{}, err
|
|
}
|
|
|
|
return p.transferToPayment(resp.ID, resp)
|
|
}
|
|
|
|
func (p *Plugin) transferToPayment(id string, transfer *client.TransferResponse) (*models.PSPPayment, error) {
|
|
raw, err := json.Marshal(transfer)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
status := matchPaymentStatus(transfer.Status)
|
|
createdAt, err := time.Parse(time.RFC3339, transfer.CreatedAt)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to parse posted date %s: %w", transfer.CreatedAt, err)
|
|
}
|
|
|
|
metadata := map[string]string{
|
|
client.ColumnUpdatedAtMetadataKey: transfer.UpdatedAt,
|
|
client.ColumnIdempotencyKeyMetadataKey: transfer.IdempotencyKey,
|
|
client.ColumnSenderBankAccountIDMetadataKey: transfer.SenderBankAccountID,
|
|
client.ColumnReceiverBankAccountIDMetadataKey: transfer.ReceiverBankAccountID,
|
|
client.ColumnDescriptionMetadataKey: transfer.Description,
|
|
client.ColumnAllowOverdraftMetadataKey: fmt.Sprintf("%t", transfer.AllowOverdraft),
|
|
}
|
|
|
|
if len(transfer.Details) > 0 {
|
|
detailsJSON, err := json.Marshal(transfer.Details)
|
|
if err == nil {
|
|
metadata[client.ColumnDetailsMetadataKey] = string(detailsJSON)
|
|
}
|
|
}
|
|
|
|
return &models.PSPPayment{
|
|
Reference: id,
|
|
ParentReference: transfer.ID,
|
|
CreatedAt: createdAt,
|
|
Type: models.PAYMENT_TYPE_TRANSFER,
|
|
Amount: big.NewInt(transfer.Amount),
|
|
Asset: currency.FormatAsset(supportedCurrenciesWithDecimal, transfer.CurrencyCode),
|
|
Scheme: models.PAYMENT_SCHEME_OTHER,
|
|
Status: status,
|
|
SourceAccountReference: &transfer.SenderAccountNumberID,
|
|
DestinationAccountReference: &transfer.ReceiverAccountNumberID,
|
|
Raw: raw,
|
|
Metadata: metadata,
|
|
}, nil
|
|
}
|
|
|
|
func matchPaymentStatus(status string) models.PaymentStatus {
|
|
switch status {
|
|
case "COMPLETED":
|
|
return models.PAYMENT_STATUS_SUCCEEDED
|
|
case "REJECTED", "CANCELED":
|
|
return models.PAYMENT_STATUS_FAILED
|
|
case "HOLD":
|
|
return models.PAYMENT_STATUS_PENDING
|
|
default:
|
|
return models.PAYMENT_STATUS_UNKNOWN
|
|
}
|
|
}
|