mirror of
https://github.com/hanzo-fi/payments.git
synced 2026-10-30 20:31:20 +00:00
325 lines
12 KiB
Go
325 lines
12 KiB
Go
package stripe
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/hanzo-fi/go-libs/v5/pkg/observe/log"
|
|
"github.com/hanzo-fi/payments/ce/plugins/stripe/client"
|
|
"github.com/hanzo-fi/payments/pkg/domain/models"
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
stripesdk "github.com/stripe/stripe-go/v80"
|
|
gomock "go.uber.org/mock/gomock"
|
|
)
|
|
|
|
var _ = Describe("Stripe Plugin Payments", func() {
|
|
var (
|
|
logger = logging.NewDefaultLogger(GinkgoWriter, true, false, false)
|
|
plg *Plugin
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
plg = &Plugin{logger: logger}
|
|
})
|
|
|
|
Context("fetch next Payments", func() {
|
|
var (
|
|
ctrl *gomock.Controller
|
|
m *client.MockClient
|
|
|
|
samplePayments []*stripesdk.BalanceTransaction
|
|
accRef string
|
|
pageSize int
|
|
)
|
|
|
|
BeforeEach(func() {
|
|
ctrl = gomock.NewController(GinkgoT())
|
|
m = client.NewMockClient(ctrl)
|
|
plg.client = m
|
|
|
|
pageSize = 15
|
|
accRef = "baseAcc"
|
|
samplePayments = []*stripesdk.BalanceTransaction{
|
|
{
|
|
ID: "charge",
|
|
Type: stripesdk.BalanceTransactionTypeCharge,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyBIF,
|
|
PaymentMethodDetails: &stripesdk.ChargePaymentMethodDetails{Card: &stripesdk.ChargePaymentMethodDetailsCard{Brand: stripesdk.PaymentMethodCardBrandVisa}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "refund",
|
|
Type: stripesdk.BalanceTransactionTypeRefund,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Refund: &stripesdk.Refund{
|
|
Currency: stripesdk.CurrencyEUR,
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyGBP,
|
|
BalanceTransaction: &stripesdk.BalanceTransaction{ID: "refund_original"},
|
|
PaymentMethodDetails: &stripesdk.ChargePaymentMethodDetails{Card: &stripesdk.ChargePaymentMethodDetailsCard{Brand: stripesdk.PaymentMethodCardBrandJCB}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "refund_failure",
|
|
Type: stripesdk.BalanceTransactionTypeRefundFailure,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Refund: &stripesdk.Refund{
|
|
Currency: stripesdk.CurrencyGEL,
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyGIP,
|
|
BalanceTransaction: &stripesdk.BalanceTransaction{ID: "refund_failure_original"},
|
|
PaymentMethodDetails: &stripesdk.ChargePaymentMethodDetails{Card: &stripesdk.ChargePaymentMethodDetailsCard{Brand: stripesdk.PaymentMethodCardBrandAmex}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "payment",
|
|
Type: stripesdk.BalanceTransactionTypePayment,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyHKD,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "payment_refund",
|
|
Type: stripesdk.BalanceTransactionTypePaymentRefund,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Refund: &stripesdk.Refund{
|
|
Currency: stripesdk.CurrencyEUR,
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyGBP,
|
|
BalanceTransaction: &stripesdk.BalanceTransaction{ID: "payment_refund_original"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "payment_refund_failure",
|
|
Type: stripesdk.BalanceTransactionTypePaymentFailureRefund,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Refund: &stripesdk.Refund{
|
|
Currency: stripesdk.CurrencyGEL,
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyGIP,
|
|
BalanceTransaction: &stripesdk.BalanceTransaction{ID: "payment_refund_failure_original"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "payout",
|
|
Type: stripesdk.BalanceTransactionTypePayout,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Payout: &stripesdk.Payout{
|
|
Currency: stripesdk.CurrencyLKR,
|
|
Status: stripesdk.PayoutStatusPaid,
|
|
Destination: &stripesdk.PayoutDestination{Card: &stripesdk.Card{Brand: stripesdk.CardBrandJCB}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "payout_failure",
|
|
Type: stripesdk.BalanceTransactionTypePayoutFailure,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Payout: &stripesdk.Payout{
|
|
Currency: stripesdk.CurrencyMYR,
|
|
BalanceTransaction: &stripesdk.BalanceTransaction{ID: "payout_failure_original"},
|
|
Destination: &stripesdk.PayoutDestination{Card: &stripesdk.Card{Brand: stripesdk.CardBrandUnionPay}},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "transfer",
|
|
Type: stripesdk.BalanceTransactionTypeTransfer,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Transfer: &stripesdk.Transfer{
|
|
Currency: stripesdk.CurrencyCLP,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "transfer_refund",
|
|
Type: stripesdk.BalanceTransactionTypeTransferRefund,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Transfer: &stripesdk.Transfer{
|
|
Currency: stripesdk.CurrencyCOP,
|
|
BalanceTransaction: &stripesdk.BalanceTransaction{ID: "transfer_refund_original"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "transfer_failed",
|
|
Type: stripesdk.BalanceTransactionTypeTransferFailure,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Transfer: &stripesdk.Transfer{
|
|
Currency: stripesdk.CurrencyCAD,
|
|
BalanceTransaction: &stripesdk.BalanceTransaction{ID: "transfer_failed_original"},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "adjustment_with_dispute",
|
|
Type: stripesdk.BalanceTransactionTypeAdjustment,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Dispute: &stripesdk.Dispute{
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyDZD,
|
|
BalanceTransaction: &stripesdk.BalanceTransaction{ID: "adjustment_with_dispute_original"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "payment_refund_failure_without_source",
|
|
Type: stripesdk.BalanceTransactionTypePaymentFailureRefund,
|
|
Source: &stripesdk.BalanceTransactionSource{},
|
|
Currency: stripesdk.CurrencyUSD,
|
|
},
|
|
{
|
|
ID: "adjustment_without_dispute",
|
|
Type: stripesdk.BalanceTransactionTypeAdjustment,
|
|
Currency: stripesdk.CurrencyUSD,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Refund: &stripesdk.Refund{
|
|
FailureReason: stripesdk.RefundFailureReasonExpiredOrCanceledCard,
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyDZD,
|
|
BalanceTransaction: &stripesdk.BalanceTransaction{ID: "adjustment_refund_original"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
ID: "skipped", // unsupported types are skipped
|
|
Type: stripesdk.BalanceTransactionTypeStripeFee,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyJPY,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
})
|
|
|
|
AfterEach(func() {
|
|
ctrl.Finish()
|
|
})
|
|
|
|
It("skips payments with unsupported currencies", func(ctx SpecContext) {
|
|
req := models.FetchNextPaymentsRequest{
|
|
FromPayload: json.RawMessage(fmt.Sprintf(`{"reference": "%s"}`, accRef)),
|
|
State: json.RawMessage(`{}`),
|
|
PageSize: pageSize,
|
|
}
|
|
p := []*stripesdk.BalanceTransaction{
|
|
{
|
|
ID: "someid",
|
|
Type: stripesdk.BalanceTransactionTypeCharge,
|
|
Source: &stripesdk.BalanceTransactionSource{
|
|
Charge: &stripesdk.Charge{
|
|
Currency: stripesdk.CurrencyEEK,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
m.EXPECT().GetPayments(gomock.Any(), accRef, gomock.Any(), int64(pageSize)).Return(
|
|
p,
|
|
client.Timeline{},
|
|
true,
|
|
nil,
|
|
)
|
|
res, err := plg.FetchNextPayments(ctx, req)
|
|
Expect(err).To(BeNil())
|
|
Expect(res.Payments).To(BeEmpty())
|
|
Expect(res.HasMore).To(BeTrue())
|
|
})
|
|
|
|
It("fetches payments", func(ctx SpecContext) {
|
|
req := models.FetchNextPaymentsRequest{
|
|
FromPayload: json.RawMessage(fmt.Sprintf(`{"reference": "%s"}`, accRef)),
|
|
State: json.RawMessage(`{}`),
|
|
PageSize: pageSize,
|
|
}
|
|
m.EXPECT().GetPayments(gomock.Any(), accRef, gomock.Any(), int64(pageSize)).Return(
|
|
samplePayments,
|
|
client.Timeline{LatestID: samplePayments[len(samplePayments)-1].ID},
|
|
true,
|
|
nil,
|
|
)
|
|
res, err := plg.FetchNextPayments(ctx, req)
|
|
Expect(err).To(BeNil())
|
|
Expect(res.Payments).To(HaveLen(len(samplePayments) - 2))
|
|
Expect(res.HasMore).To(BeTrue())
|
|
|
|
// Charges
|
|
Expect(res.Payments[0].Reference).To(Equal(samplePayments[0].ID))
|
|
Expect(res.Payments[0].Type).To(Equal(models.PAYMENT_TYPE_PAYIN))
|
|
Expect(res.Payments[0].Status).To(Equal(models.PAYMENT_STATUS_SUCCEEDED))
|
|
Expect(res.Payments[1].Reference).To(Equal(samplePayments[1].ID))
|
|
Expect(res.Payments[1].ParentReference).To(Equal(samplePayments[1].Source.Refund.Charge.BalanceTransaction.ID))
|
|
Expect(res.Payments[1].Type).To(Equal(models.PAYMENT_TYPE_PAYIN))
|
|
Expect(res.Payments[1].Status).To(Equal(models.PAYMENT_STATUS_REFUNDED))
|
|
Expect(res.Payments[2].Reference).To(Equal(samplePayments[2].ID))
|
|
Expect(res.Payments[2].ParentReference).To(Equal(samplePayments[2].Source.Refund.Charge.BalanceTransaction.ID))
|
|
Expect(res.Payments[2].Type).To(Equal(models.PAYMENT_TYPE_PAYIN))
|
|
Expect(res.Payments[2].Status).To(Equal(models.PAYMENT_STATUS_REFUNDED_FAILURE))
|
|
// Payments
|
|
Expect(res.Payments[3].Reference).To(Equal(samplePayments[3].ID))
|
|
Expect(res.Payments[3].Type).To(Equal(models.PAYMENT_TYPE_PAYIN))
|
|
Expect(res.Payments[3].Status).To(Equal(models.PAYMENT_STATUS_SUCCEEDED))
|
|
Expect(res.Payments[4].Reference).To(Equal(samplePayments[4].ID))
|
|
Expect(res.Payments[4].ParentReference).To(Equal(samplePayments[4].Source.Refund.Charge.BalanceTransaction.ID))
|
|
Expect(res.Payments[4].Type).To(Equal(models.PAYMENT_TYPE_PAYIN))
|
|
Expect(res.Payments[4].Status).To(Equal(models.PAYMENT_STATUS_REFUNDED))
|
|
Expect(res.Payments[5].Reference).To(Equal(samplePayments[5].ID))
|
|
Expect(res.Payments[5].ParentReference).To(Equal(samplePayments[5].Source.Refund.Charge.BalanceTransaction.ID))
|
|
Expect(res.Payments[5].Type).To(Equal(models.PAYMENT_TYPE_PAYIN))
|
|
Expect(res.Payments[5].Status).To(Equal(models.PAYMENT_STATUS_REFUNDED_FAILURE))
|
|
// Payouts
|
|
Expect(res.Payments[6].Reference).To(Equal(samplePayments[6].ID))
|
|
Expect(res.Payments[6].Type).To(Equal(models.PAYMENT_TYPE_PAYOUT))
|
|
Expect(res.Payments[6].Status).To(Equal(models.PAYMENT_STATUS_SUCCEEDED))
|
|
Expect(res.Payments[7].Reference).To(Equal(samplePayments[7].ID))
|
|
Expect(res.Payments[7].ParentReference).To(Equal(samplePayments[7].Source.Payout.BalanceTransaction.ID))
|
|
Expect(res.Payments[7].Type).To(Equal(models.PAYMENT_TYPE_PAYOUT))
|
|
Expect(res.Payments[7].Status).To(Equal(models.PAYMENT_STATUS_FAILED))
|
|
// Transfers
|
|
Expect(res.Payments[8].Reference).To(Equal(samplePayments[8].ID))
|
|
Expect(res.Payments[8].Type).To(Equal(models.PAYMENT_TYPE_TRANSFER))
|
|
Expect(res.Payments[8].Status).To(Equal(models.PAYMENT_STATUS_SUCCEEDED))
|
|
Expect(res.Payments[9].Reference).To(Equal(samplePayments[9].ID))
|
|
Expect(res.Payments[9].ParentReference).To(Equal(samplePayments[9].Source.Transfer.BalanceTransaction.ID))
|
|
Expect(res.Payments[9].Type).To(Equal(models.PAYMENT_TYPE_TRANSFER))
|
|
Expect(res.Payments[9].Status).To(Equal(models.PAYMENT_STATUS_REFUNDED))
|
|
Expect(res.Payments[10].Reference).To(Equal(samplePayments[10].ID))
|
|
Expect(res.Payments[10].ParentReference).To(Equal(samplePayments[10].Source.Transfer.BalanceTransaction.ID))
|
|
Expect(res.Payments[10].Type).To(Equal(models.PAYMENT_TYPE_TRANSFER))
|
|
Expect(res.Payments[10].Status).To(Equal(models.PAYMENT_STATUS_FAILED))
|
|
// Adjustments
|
|
Expect(res.Payments[11].Reference).To(Equal(samplePayments[11].ID))
|
|
Expect(res.Payments[11].ParentReference).To(Equal(samplePayments[11].Source.Dispute.Charge.BalanceTransaction.ID))
|
|
Expect(res.Payments[11].Type).To(Equal(models.PAYMENT_TYPE_PAYIN))
|
|
Expect(res.Payments[11].Status).To(Equal(models.PAYMENT_STATUS_DISPUTE))
|
|
// Payment failure refund
|
|
Expect(res.Payments[12].Reference).To(Equal(samplePayments[12].ID))
|
|
Expect(res.Payments[12].ParentReference).To(Equal(""))
|
|
Expect(res.Payments[12].Type).To(Equal(models.PAYMENT_TYPE_PAYIN))
|
|
Expect(res.Payments[12].Status).To(Equal(models.PAYMENT_STATUS_REFUNDED_FAILURE))
|
|
|
|
var state paymentsState
|
|
|
|
err = json.Unmarshal(res.NewState, &state)
|
|
Expect(err).To(BeNil())
|
|
Expect(state.Timeline.LatestID).To(Equal(samplePayments[len(samplePayments)-1].ID))
|
|
})
|
|
})
|
|
})
|