Skip to content

Commit

Permalink
bnpl payment integration
Browse files Browse the repository at this point in the history
  • Loading branch information
deryacakmak committed Nov 6, 2023
1 parent 4362e26 commit 761e3b5
Show file tree
Hide file tree
Showing 3 changed files with 267 additions and 1 deletion.
128 changes: 128 additions & 0 deletions adapter/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type PosOperationType string
type FileStatus string
type AccountOwner string
type PayoutAccountType string
type BnplCartItemType string

const (
ApiKeyHeaderName = "x-api-key"
Expand Down Expand Up @@ -77,6 +78,8 @@ const (
ApmType_AFTERPAY ApmType = "AFTERPAY"
ApmType_KASPI ApmType = "KASPI"
ApmType_TOMPAY ApmType = "TOMPAY"
ApmType_MASLAK ApmType = "MASLAK"
ApmType_ALFABANK ApmType = "ALFABANK"
ApmType_STRIPE ApmType = "STRIPE"
ApmType_FUND_TRANSFER ApmType = "FUND_TRANSFER"
ApmType_CASH_ON_DELIVERY ApmType = "CASH_ON_DELIVERY"
Expand Down Expand Up @@ -441,6 +444,34 @@ const (
PayoutAccountType_WISE PayoutAccountType = "WISE"
)

// BnplCartItemType type declaration
const (
BnplCartItemType_MOBILE_PHONE_OVER_5000_TRY BnplCartItemType = "MOBILE_PHONE_OVER_5000_TRY"
BnplCartItemType_MOBILE_PHONE_BELOW_5000_TRY BnplCartItemType = "MOBILE_PHONE_BELOW_5000_TRY"
BnplCartItemType_TABLET BnplCartItemType = "TABLET"
BnplCartItemType_COMPUTER BnplCartItemType = "COMPUTER"
BnplCartItemType_CONSTRUCTION_MARKET BnplCartItemType = "CONSTRUCTION_MARKET"
BnplCartItemType_GOLD BnplCartItemType = "GOLD"
BnplCartItemType_DIGITAL_PRODUCTS BnplCartItemType = "DIGITAL_PRODUCTS"
BnplCartItemType_SUPERMARKET BnplCartItemType = "SUPERMARKET"
BnplCartItemType_WHITE_GOODS BnplCartItemType = "WHITE_GOODS"
BnplCartItemType_WEARABLE_TECHNOLOGY BnplCartItemType = "WEARABLE_TECHNOLOGY"
BnplCartItemType_SMALL_HOME_APPLIANCES BnplCartItemType = "SMALL_HOME_APPLIANCES"
BnplCartItemType_TV BnplCartItemType = "TV"
BnplCartItemType_GAMES_CONSOLES BnplCartItemType = "GAMES_CONSOLES"
BnplCartItemType_AIR_CONDITIONER_AND_HEATER BnplCartItemType = "AIR_CONDITIONER_AND_HEATER"
BnplCartItemType_ELECTRONICS BnplCartItemType = "ELECTRONICS"
BnplCartItemType_ACCESSORIES BnplCartItemType = "ACCESSORIES"
BnplCartItemType_MOM_AND_BABY_AND_KIDS BnplCartItemType = "MOM_AND_BABY_AND_KIDS"
BnplCartItemType_SHOES BnplCartItemType = "SHOES"
BnplCartItemType_CLOTHING BnplCartItemType = "CLOTHING"
BnplCartItemType_COSMETICS_AND_PERSONAL_CARE BnplCartItemType = "COSMETICS_AND_PERSONAL_CARE"
BnplCartItemType_FURNITURE BnplCartItemType = "FURNITURE"
BnplCartItemType_HOME_LIVING BnplCartItemType = "HOME_LIVING"
BnplCartItemType_AUTOMOBILE_MOTORCYCLE BnplCartItemType = "AUTOMOBILE_MOTORCYCLE"
BnplCartItemType_OTHER BnplCartItemType = "OTHER"
)

// requests
type CreatePaymentRequest struct {
Price float64 `json:"price,omitempty"`
Expand Down Expand Up @@ -755,6 +786,47 @@ type MasterpassPaymentThreeDSCompleteRequest struct {
PaymentId int64 `json:"paymentId,omitempty"`
}

type BnplPaymentInitRequest struct {
ApmType ApmType `json:"apmType"`
MerchantApmId int64 `json:"merchantApmId,omitempty"`
Price float64 `json:"price"`
PaidPrice float64 `json:"paidPrice"`
CommissionRate float64 `json:"commissionRate,omitempty"`
Currency Currency `json:"currency"`
PaymentType PaymentType `json:"paymentType"`
PaymentGroup PaymentGroup `json:"paymentGroup"`
PaymentSource PaymentSource `json:"paymentSource,omitempty"`
PaymentChannel string `json:"paymentChannel,omitempty"`
ConversationId string `json:"conversationId,omitempty"`
ExternalId string `json:"externalId,omitempty"`
CallbackUrl string `json:"callbackUrl"`
BuyerMemberId int64 `json:"buyerMemberId,omitempty"`
ApmOrderId string `json:"apmOrderId,omitempty"`
ClientIp string `json:"clientIp,omitempty"`
ApmUserIdentity string `json:"apmUserIdentity,omitempty"`
AdditionalParams map[string]interface{} `json:"additionalParams"`
Items []PaymentItem `json:"items"`
BankCode string `json:"bankCode"`
CartItems []BnplPaymentCartItem `json:"cartItems"`
}

type BnplPaymentCartItem struct {
Id string `json:"id"`
Name string `json:"name"`
BrandName string `json:"brandName"`
Type BnplCartItemType `json:"type"`
UnitPrice float64 `json:"unitPrice"`
Quantity int64 `json:"quantity"`
}

type BnplPaymentOfferRequest struct {
ApmType ApmType `json:"apmType,omitempty"`
MerchantApmId int64 `json:"merchantApmId,omitempty"`
Price float64 `json:"price,omitempty"`
Currency Currency `json:"currency,omitempty"`
Items []BnplPaymentCartItem `json:"items"`
}

// responses
type PaymentResponse struct {
Id *int64 `json:"id"`
Expand Down Expand Up @@ -1468,6 +1540,38 @@ type ReportingPaymentTransactionResponse struct {
PayoutStatus *PayoutStatus `json:"payoutStatus"`
}

type BnplPaymentInitResponse struct {
PaymentId int64 `json:"paymentId"`
RedirectUrl string `json:"redirectUrl"`
PaymentStatus PaymentStatus `json:"paymentStatus"`
AdditionalAction ApmAdditionalAction `json:"additionalAction"`
PaymentError PaymentError `json:"paymentError"`
}

type BnplPaymentOfferResponse struct {
OfferId string `json:"offerId"`
Price *float64 `json:"price"`
BnplBankOffers *[]BnplBankOffer `json:"nnplBankOffers"`
}

type BnplBankOffer struct {
BankCode string `json:"bankCode"`
BankName string `json:"bankName"`
BankIconUrl string `json:"bankIconUrl"`
BankTableBannerMessage string `json:"bankTableBannerMessage"`
BankSmallBannerMessage string `json:"bankSmallBannerMessage"`
IsSupportNonCustomer bool `json:"isSupportNonCustomer"`
BnplBankOfferTerm *[]BnplBankOfferTerm `json:"bankOfferTerms"`
}

type BnplBankOfferTerm struct {
Term int64 `json:"term"`
Amount *float64 `json:"amount"`
TotalAmount *float64 `json:"totalAmount"`
InterestRate *float64 `json:"interestRate"`
AnnualInterestRate *float64 `json:"annualInterestRate"`
}

type Payout struct {
PaidPrice *float64 `json:"paidPrice"`
Parity *float64 `json:"parity"`
Expand All @@ -1476,6 +1580,30 @@ type Payout struct {
SubMerchantMemberPayoutAmount *float64 `json:"subMerchantMemberPayoutAmount"`
}

type ApmPaymentResponse struct {
Id *int64 `json:"id"`
CreatedDate *TimeResponse `json:"createdDate"`
Price *float64 `json:"price"`
PaidPrice *float64 `json:"paidPrice"`
WalletPrice *float64 `json:"walletPrice"`
Currency *Currency `json:"currency"`
BuyerMemberId *int64 `json:"buyerMemberId"`
ConversationId *string `json:"conversationId"`
ExternalId *string `json:"externalId"`
PaymentType *PaymentType `json:"paymentType"`
PaymentProvider *PaymentProvider `json:"paymentProvider"`
PaymentSource *PaymentSource `json:"paymentSource"`
PaymentGroup *PaymentGroup `json:"paymentGroup"`
PaymentStatus *PaymentStatus `json:"paymentStatus"`
PaymentChannel *string `json:"paymentChannel"`
OrderId *string `json:"orderId"`
PaymentError *PaymentError `json:"paymentError"`
ApmType ApmType `json:"apmType,apmType"`

Check failure on line 1601 in adapter/model.go

View workflow job for this annotation

GitHub Actions / build

SA5008: unknown JSON option "apmType" (staticcheck)

Check failure on line 1601 in adapter/model.go

View workflow job for this annotation

GitHub Actions / build

SA5008: unknown JSON option "apmType" (staticcheck)
TransactionId string `json:"transactionId"`
RedirectUrl *Currency `json:"redirectUrl"`
PaymentTransactions *[]PaymentTransactionResponse `json:"paymentTransactions"`
}

type PayoutStatus struct {
MerchantStatus *TransactionPayoutStatus `json:"merchantStatus"`
MerchantStatusDate *TimeResponse `json:"merchantStatusDate"`
Expand Down
45 changes: 45 additions & 0 deletions adapter/payment.go
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,51 @@ func (api *Payment) DisapprovePaymentTransactions(ctx context.Context, request P
return response.Data, nil
}

func (api *Payment) InitBnplPayment(ctx context.Context, request BnplPaymentInitRequest) (*BnplPaymentInitResponse, error) {
newRequest, err := api.Client.NewRequest(ctx, http.MethodPost, "/payment/v1/bnpl-payments/init", request)
if err != nil {
return nil, err
}
response := &Response[BnplPaymentInitResponse]{}
err = api.Client.Do(ctx, newRequest, response)
if err != nil {
return nil, err
}

return response.Data, nil
}

func (api *Payment) OfferBnplPayment(ctx context.Context, request BnplPaymentOfferRequest) (*DataResponse[BnplPaymentOfferResponse], error) {
newRequest, err := api.Client.NewRequest(ctx, http.MethodPost, "/payment/v1/bnpl-payments/offers", request)
if err != nil {
return nil, err
}

response := &Response[DataResponse[BnplPaymentOfferResponse]]{}
err = api.Client.Do(ctx, newRequest, response)
if err != nil {
return nil, err
}

return response.Data, nil
}

func (api *Payment) ApproveBnplPayment(ctx context.Context, paymentId int64) (*ApmPaymentResponse, error) {

newRequest, err := api.Client.NewRequest(ctx, http.MethodPost, fmt.Sprintf("/payment/v1/bnpl-payments/%d/approve", paymentId), nil)
if err != nil {
return nil, err
}

response := &Response[ApmPaymentResponse]{}
err = api.Client.Do(ctx, newRequest, response)
if err != nil {
return nil, err
}

return response.Data, nil
}

func (c *Payment) Is3DSecureCallbackVerified(threeDSecureCallbackKey string, params map[string]string) bool {
hash := params["hash"]
hashString := strings.Join([]string{threeDSecureCallbackKey,
Expand Down
95 changes: 94 additions & 1 deletion tests/payment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"testing"
)

var paymentClient, _ = craftgate.New("api-key", "secret-key", "https://sandbox-api.craftgate.io")
var paymentClient, _ = craftgate.New("sandbox-BMSPbGKBaMOcmOiVpyjDZOIfSzLAuXsb", "sandbox-LpvzxnyrFkOCRRiUpQHUUZUpeQuXNntd", "https://sandbox-api.craftgate.io")

func TestPayment_CreatePayment(t *testing.T) {
request := adapter.CreatePaymentRequest{
Expand Down Expand Up @@ -770,3 +770,96 @@ func TestPayment_NotVerify3DSCallback(t *testing.T) {

require.False(t, is3DSecureCallbackVerified)
}

func TestPayment_InitBnplPayment(t *testing.T) {
request := adapter.BnplPaymentInitRequest{
ApmType: craftgate.ApmType_MASLAK,
Price: 10000,
PaidPrice: 10000,
PaymentType: craftgate.PaymentType_APM,
Currency: craftgate.Currency_TRY,
ApmOrderId: "order_id",
PaymentGroup: craftgate.PaymentGroup_PRODUCT,
ConversationId: "29393-mXld92ko3",
ExternalId: "external_id-345",
CallbackUrl: "callback",
BankCode: "103",
Items: []craftgate.PaymentItem{
{
Name: "Item 1",
Price: 3000,
ExternalId: "38983903",
},
{
Name: "Item 2",
Price: 7000,
ExternalId: "92983294",
},
},
CartItems: []craftgate.BnplPaymentCartItem{
{
Id: "200",
Name: "Test Elektronik 2",
BrandName: "iphone",
Type: craftgate.BnplCartItemType_OTHER,
UnitPrice: 4000,
Quantity: 2,
},
{
Id: "100",
Name: "Test Elektronik 1",
BrandName: "Samsung",
Type: craftgate.BnplCartItemType_MOBILE_PHONE_OVER_5000_TRY,
UnitPrice: 3000,
Quantity: 1,
},
},
}
res, err := paymentClient.Payment.InitBnplPayment(context.Background(), request)
_, _ = spew.Printf("%#v\n", res)

if err != nil {
t.Errorf("Error %s", err)
}
}

func TestPayment_OfferBnplPayment(t *testing.T) {
request := adapter.BnplPaymentOfferRequest{
ApmType: craftgate.ApmType_MASLAK,
Price: 10000,
Currency: craftgate.Currency_TRY,
Items: []craftgate.BnplPaymentCartItem{
{
Id: "200",
Name: "Test Elektronik 2",
BrandName: "iphone",
Type: craftgate.BnplCartItemType_MOBILE_PHONE_BELOW_5000_TRY,
UnitPrice: 3000,
Quantity: 2,
},
{
Id: "100",
Name: "Test Elektronik 1",
BrandName: "Samsung",
Type: craftgate.BnplCartItemType_OTHER,
UnitPrice: 4000,
Quantity: 1,
},
},
}
res, err := paymentClient.Payment.OfferBnplPayment(context.Background(), request)
_, _ = spew.Printf("%#v\n", res)

if err != nil {
t.Errorf("Error %s", err)
}
}

func TestPayment_ApproveBnplPayment(t *testing.T) {
res, err := paymentClient.Payment.ApproveBnplPayment(context.Background(), 407016)
_, _ = spew.Printf("%#v\n", res)

if err != nil {
t.Errorf("Error %s", err)
}
}

0 comments on commit 761e3b5

Please sign in to comment.