Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions craftgate/adapter/payment_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from craftgate.request.init_apm_deposit_payment_request import InitApmDepositPaymentRequest
from craftgate.request.init_apm_payment_request import InitApmPaymentRequest
from craftgate.request.init_bnpl_payment_request import InitBnplPaymentRequest
from craftgate.request.init_checkout_card_verify_request import InitCheckoutCardVerifyRequest
from craftgate.request.init_checkout_payment_request import InitCheckoutPaymentRequest
from craftgate.request.init_garanti_pay_payment_request import InitGarantiPayPaymentRequest
from craftgate.request.init_pos_apm_payment_request import InitPosApmPaymentRequest
Expand All @@ -31,6 +32,7 @@
from craftgate.request.store_card_request import StoreCardRequest
from craftgate.request.update_card_request import UpdateCardRequest
from craftgate.request.update_payment_transaction_request import UpdatePaymentTransactionRequest
from craftgate.request.verify_card_request import VerifyCardRequest
from craftgate.request_options import RequestOptions
from craftgate.response.apm_deposit_payment_response import ApmDepositPaymentResponse
from craftgate.response.apm_payment_complete_response import ApmPaymentCompleteResponse
Expand All @@ -40,6 +42,7 @@
from craftgate.response.deposit_payment_response import DepositPaymentResponse
from craftgate.response.fund_transfer_deposit_payment_response import FundTransferDepositPaymentResponse
from craftgate.response.init_bnpl_payment_response import InitBnplPaymentResponse
from craftgate.response.init_checkout_card_verify_response import InitCheckoutCardVerifyResponse
from craftgate.response.init_checkout_payment_response import InitCheckoutPaymentResponse
from craftgate.response.init_garanti_pay_payment_response import InitGarantiPayPaymentResponse
from craftgate.response.init_pos_apm_payment_response import InitPosApmPaymentResponse
Expand All @@ -55,6 +58,7 @@
from craftgate.response.retrieve_loyalties_response import RetrieveLoyaltiesResponse
from craftgate.response.stored_card_list_response import StoredCardListResponse
from craftgate.response.stored_card_response import StoredCardResponse
from craftgate.response.verify_card_response import VerifyCardResponse
from craftgate.utils.hash_generator import HashGenerator
from craftgate.utils.request_query_params_builder import RequestQueryParamsBuilder

Expand Down Expand Up @@ -130,6 +134,17 @@ def init_checkout_payment(self, request: InitCheckoutPaymentRequest) -> InitChec
response_type=InitCheckoutPaymentResponse
)

def init_checkout_card_verify(self, request: InitCheckoutCardVerifyRequest) -> InitCheckoutCardVerifyResponse:
path = "/payment/v1/checkout-card-verify/init"
headers = self._create_headers(request, path)
return self._http_client.request(
method="POST",
url=self.request_options.base_url + path,
headers=headers,
body=request,
response_type=InitCheckoutCardVerifyResponse
)

def retrieve_checkout_payment(self, token: str) -> PaymentResponse:
path = "/payment/v1/checkout-payments/{}".format(token)
headers = self._create_headers(None, path)
Expand Down Expand Up @@ -413,6 +428,17 @@ def delete_stored_card(self, request: DeleteStoredCardRequest) -> None:
response_type=None
)

def verify_card(self, request: VerifyCardRequest) -> VerifyCardResponse:
path = "/payment/v1/cards/verify"
headers = self._create_headers(request, path)
return self._http_client.request(
method="POST",
url=self.request_options.base_url + path,
headers=headers,
body=request,
response_type=VerifyCardResponse
)

def approve_payment_transactions(self,
request: ApprovePaymentTransactionsRequest) -> PaymentTransactionApprovalListResponse:
path = "/payment/v1/payment-transactions/approve"
Expand Down
2 changes: 2 additions & 0 deletions craftgate/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from .card_expiry_status import CardExpiryStatus
from .card_provider import CardProvider
from .card_type import CardType
from .card_verification_auth_type import CardVerificationAuthType
from .card_verify_status import CardVerifyStatus
from .currency import Currency
from .file_status import FileStatus
from .fraud_action import FraudAction
Expand Down
7 changes: 7 additions & 0 deletions craftgate/model/card_verification_auth_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from enum import Enum


class CardVerificationAuthType(str, Enum):
NON_THREE_DS = "NON_THREE_DS"
THREE_DS = "THREE_DS"
NONE = "NONE"
7 changes: 7 additions & 0 deletions craftgate/model/card_verify_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from enum import Enum


class CardVerifyStatus(str, Enum):
SUCCESS = "SUCCESS"
FAILURE = "FAILURE"
THREE_DS_PENDING = "THREE_DS_PENDING"
2 changes: 2 additions & 0 deletions craftgate/request/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from .init_apm_payment_request import InitApmPaymentRequest
from .init_bkm_express_request import InitBkmExpressRequest
from .init_bnpl_payment_request import InitBnplPaymentRequest
from .init_checkout_card_verify_request import InitCheckoutCardVerifyRequest
from .init_checkout_payment_request import InitCheckoutPaymentRequest
from .init_garanti_pay_payment_request import InitGarantiPayPaymentRequest
from .init_juzdan_payment_request import InitJuzdanPaymentRequest
Expand Down Expand Up @@ -77,3 +78,4 @@
from .update_payout_account_request import UpdatePayoutAccountRequest
from .update_product_request import UpdateProductRequest
from .update_wallet_request import UpdateWalletRequest
from .verify_card_request import VerifyCardRequest
1 change: 1 addition & 0 deletions craftgate/request/dto/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
from .tokenized_card import TokenizedCard
from .update_merchant_pos_commission import UpdateMerchantPosCommission
from .update_merchant_pos_user import UpdateMerchantPosUser
from .verify_card import VerifyCard
21 changes: 21 additions & 0 deletions craftgate/request/dto/verify_card.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from typing import Optional


class VerifyCard(object):
def __init__(
self,
card_holder_name: Optional[str] = None,
card_number: Optional[str] = None,
expire_year: Optional[str] = None,
expire_month: Optional[str] = None,
cvc: Optional[str] = None,
card_alias: Optional[str] = None,
card_user_key: Optional[str] = None
) -> None:
self.card_holder_name = card_holder_name
self.card_number = card_number
self.expire_year = expire_year
self.expire_month = expire_month
self.cvc = cvc
self.card_alias = card_alias
self.card_user_key = card_user_key
25 changes: 25 additions & 0 deletions craftgate/request/init_checkout_card_verify_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from decimal import Decimal
from typing import Optional

from craftgate.model.card_verification_auth_type import CardVerificationAuthType
from craftgate.model.currency import Currency


class InitCheckoutCardVerifyRequest(object):
def __init__(
self,
verification_price: Optional[Decimal] = None,
currency: Optional[Currency] = None,
conversation_id: Optional[str] = None,
callback_url: Optional[str] = None,
card_user_key: Optional[str] = None,
payment_authentication_type: Optional[CardVerificationAuthType] = None,
ttl: Optional[int] = None
) -> None:
self.verification_price = verification_price
self.currency = currency
self.conversation_id = conversation_id
self.callback_url = callback_url
self.card_user_key = card_user_key
self.payment_authentication_type = payment_authentication_type
self.ttl = ttl
26 changes: 26 additions & 0 deletions craftgate/request/verify_card_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from decimal import Decimal
from typing import Optional

from craftgate.model.card_verification_auth_type import CardVerificationAuthType
from craftgate.model.currency import Currency
from craftgate.request.dto.verify_card import VerifyCard


class VerifyCardRequest(object):
def __init__(
self,
card: Optional[VerifyCard] = None,
payment_authentication_type: Optional[CardVerificationAuthType] = None,
verification_price: Optional[Decimal] = None,
currency: Optional[Currency] = None,
client_ip: Optional[str] = None,
conversation_id: Optional[str] = None,
callback_url: Optional[str] = None
) -> None:
self.card = card
self.payment_authentication_type = payment_authentication_type
self.verification_price = verification_price
self.currency = currency
self.client_ip = client_ip
self.conversation_id = conversation_id
self.callback_url = callback_url
2 changes: 2 additions & 0 deletions craftgate/response/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from .fund_transfer_deposit_payment_response import FundTransferDepositPaymentResponse
from .init_bkm_express_response import InitBkmExpressResponse
from .init_bnpl_payment_response import InitBnplPaymentResponse
from .init_checkout_card_verify_response import InitCheckoutCardVerifyResponse
from .init_checkout_payment_response import InitCheckoutPaymentResponse
from .init_garanti_pay_payment_response import InitGarantiPayPaymentResponse
from .init_juzdan_payment_response import InitJuzdanPaymentResponse
Expand Down Expand Up @@ -70,5 +71,6 @@
from .wallet_transaction_list_response import WalletTransactionListResponse
from .wallet_transaction_refundable_amount_response import WalletTransactionRefundableAmountResponse
from .wallet_transaction_response import WalletTransactionResponse
from .verify_card_response import VerifyCardResponse
from .withdraw_list_response import WithdrawListResponse
from .withdraw_response import WithdrawResponse
14 changes: 14 additions & 0 deletions craftgate/response/init_checkout_card_verify_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from datetime import datetime
from typing import Optional


class InitCheckoutCardVerifyResponse(object):
def __init__(
self,
token: Optional[str] = None,
page_url: Optional[str] = None,
token_expire_date: Optional[datetime] = None
) -> None:
self.token = token
self.page_url = page_url
self.token_expire_date = token_expire_date
24 changes: 24 additions & 0 deletions craftgate/response/verify_card_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from typing import Optional

from craftgate.model.card_verify_status import CardVerifyStatus
from craftgate.model.refund_status import RefundStatus


class VerifyCardResponse(object):
def __init__(
self,
card_user_key: Optional[str] = None,
card_token: Optional[str] = None,
html_content: Optional[str] = None,
redirect_url: Optional[str] = None,
merchant_callback_url: Optional[str] = None,
refund_status: Optional[RefundStatus] = None,
card_verify_status: Optional[CardVerifyStatus] = None
) -> None:
self.card_user_key = card_user_key
self.card_token = card_token
self.html_content = html_content
self.redirect_url = redirect_url
self.merchant_callback_url = merchant_callback_url
self.refund_status = refund_status
self.card_verify_status = card_verify_status
53 changes: 47 additions & 6 deletions tests/test_payment_sample.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@
from decimal import Decimal

from craftgate import Craftgate, RequestOptions, PaymentTransaction, FraudCheckParameters
from craftgate.model import AdditionalAction, ApmAdditionalAction, ApmType, CardAssociation, CardProvider, CardType, \
Currency, Loyalty, LoyaltyParams, LoyaltyType, PaymentGroup, PaymentPhase, PaymentStatus, PaymentType, \
from craftgate.model import AdditionalAction, ApmAdditionalAction, ApmType, CardAssociation, CardProvider, \
CardType, CardVerificationAuthType, CardVerifyStatus, Currency, Loyalty, LoyaltyParams, LoyaltyType, \
PaymentGroup, PaymentPhase, PaymentStatus, PaymentType, \
PosApmPaymentProvider, RefundDestinationType, RefundStatus, Reward, WalletTransactionType
from craftgate.request import ApprovePaymentTransactionsRequest, CloneCardRequest, CompleteApmPaymentRequest, \
CompletePosApmPaymentRequest, CompleteThreeDSPaymentRequest, CreateApmPaymentRequest, CreateDepositPaymentRequest, \
CreateFundTransferDepositPaymentRequest, CreatePaymentRequest, DeleteStoredCardRequest, \
DisapprovePaymentTransactionsRequest, Card, GarantiPayInstallment, PaymentItem, InitApmDepositPaymentRequest, \
InitApmPaymentRequest, InitCheckoutPaymentRequest, InitGarantiPayPaymentRequest, InitPosApmPaymentRequest, \
InitThreeDSPaymentRequest, PostAuthPaymentRequest, RefundPaymentRequest, \
DisapprovePaymentTransactionsRequest, Card, GarantiPayInstallment, InitApmDepositPaymentRequest, \
InitApmPaymentRequest, InitCheckoutCardVerifyRequest, InitCheckoutPaymentRequest, \
InitGarantiPayPaymentRequest, InitPosApmPaymentRequest, InitThreeDSPaymentRequest, PaymentItem, \
PostAuthPaymentRequest, RefundPaymentRequest, \
RefundPaymentTransactionMarkAsRefundedRequest, RefundPaymentTransactionRequest, RetrieveLoyaltiesRequest, \
RetrieveProviderCardRequest, SearchStoredCardsRequest, StoreCardRequest, UpdateCardRequest, \
UpdatePaymentTransactionRequest
UpdatePaymentTransactionRequest, VerifyCard, VerifyCardRequest
from craftgate.response import MultiPaymentResponse, PaymentTransactionApprovalListResponse, PaymentTransactionResponse, \
StoredCardListResponse

Expand Down Expand Up @@ -1647,6 +1649,45 @@ def test_should_not_validate_3d_secure_callback_when_hashes_are_not_equal(self):
is_verified = self.payment.is_3d_secure_callback_verified(merchant_key, params)
self.assertFalse(is_verified)

def test_init_checkout_card_verify_with_non_3ds_auth_type(self):
req = InitCheckoutCardVerifyRequest()
req.callback_url = "https://www.your-website.com/craftgate-checkout-card-verify-callback"
req.conversation_id = "456d1297-908e-4bd6-a13b-4be31a6e47d5"
req.payment_authentication_type = CardVerificationAuthType.NON_THREE_DS
req.verification_price = Decimal("10")
req.currency = Currency.TRY

resp = self.payment.init_checkout_card_verify(req)
print(resp)
self.assertIsNotNone(resp)
self.assertIsNotNone(getattr(resp, "page_url", None))
self.assertIsNotNone(getattr(resp, "token", None))
self.assertIsNotNone(getattr(resp, "token_expire_date", None))

def test_verify_card_with_3ds(self):
card = VerifyCard()
card.card_holder_name = "Haluk Demir"
card.card_number = "5258640000000001"
card.expire_year = "2044"
card.expire_month = "07"
card.cvc = "000"
card.card_alias = "My YKB Card"

req = VerifyCardRequest()
req.card = card
req.payment_authentication_type = CardVerificationAuthType.THREE_DS
req.callback_url = "https://www.your-website.com/craftgate-3DSecure-card-verify-callback"
req.conversation_id = "456d1297-908e-4bd6-a13b-4be31a6e47d5"
req.verification_price = Decimal("10")
req.currency = Currency.TRY
req.client_ip = "127.0.0.1"

resp = self.payment.verify_card(req)
print(resp)
self.assertIsNotNone(resp)
self.assertEqual(CardVerifyStatus.THREE_DS_PENDING, resp.card_verify_status)
self.assertIsNotNone(getattr(resp, "html_content", None))


if __name__ == "__main__":
unittest.main()