@akinon/pz-masterpass-rest 2.0.18-rc.0 → 2.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +1 -9
- package/docs/USAGE.md +61 -332
- package/package.json +2 -2
- package/src/components/card-list.tsx +2 -72
- package/src/components/credit-card-form.tsx +1 -1
- package/src/components/installment-list.tsx +1 -1
- package/src/components/otp-modal.tsx +4 -12
- package/src/hooks/useMasterpassAccount.ts +5 -21
- package/src/hooks/useMasterpassPayment.ts +13 -112
- package/src/index.ts +0 -2
- package/src/redux/api.ts +1 -82
- package/src/redux/reducer.ts +3 -35
- package/src/types/custom-render.types.ts +1 -47
- package/src/types/payment.types.ts +0 -13
- package/src/utils/card-utils.ts +1 -1
- package/src/views/masterpass-rest-option.tsx +9 -133
- package/src/components/reward-selection-modal.tsx +0 -194
- package/src/utils/reward-utils.ts +0 -41
package/CHANGELOG.md
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
# @akinon/pz-masterpass-rest
|
|
2
2
|
|
|
3
|
-
## 2.0.18
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- 823a4449: ZERO-4193: Upgrade TypeScript to version 5.2.2 across multiple packages
|
|
8
|
-
- 5da13fff: ZERO-4358: fix masterpass-rest guest checkout flow
|
|
9
|
-
- fb4aa9b4: ZERO-4333: update maxLength for cardNumber input and enhance button styling in installment list
|
|
10
|
-
- d51fa68e: ZERO-4399: add card rewards to pz-masterpass-rest
|
|
11
|
-
- 63a72000: ZERO-3895: enhance payment processing with additional fields support
|
|
3
|
+
## 2.0.18
|
|
12
4
|
|
|
13
5
|
## 2.0.17
|
|
14
6
|
|
package/docs/USAGE.md
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
- [LinkModal](#5-linkmodal)
|
|
16
16
|
- [OTPModal](#6-otpmodal)
|
|
17
17
|
- [ConfirmationModal](#7-confirmationmodal)
|
|
18
|
-
- [RewardSelectionModal](#7b-rewardselectionmodal)
|
|
19
18
|
- [ErrorDisplay](#8-errordisplay)
|
|
20
19
|
- [LoadingState](#9-loadingstate)
|
|
21
20
|
- [EmptyState](#10-emptystate)
|
|
@@ -77,7 +76,6 @@ export default MasterpassRest
|
|
|
77
76
|
| `environment` | `'production' \| 'development'` | `undefined` | SDK environment |
|
|
78
77
|
| `texts` | `MasterpassRestOptionTexts` | `defaultTexts` | UI text overrides for localization |
|
|
79
78
|
| `customRender` | `MasterpassRestOptionCustomRender` | `undefined` | Custom render functions |
|
|
80
|
-
| `enableRewards` | `boolean` | `false` | Opt in to the card rewards (FBB/BNS) feature. Requires backend support for `MasterpassRestRewardListPage` and `MasterpassRestRewardSelectionPage`. |
|
|
81
79
|
|
|
82
80
|
```tsx
|
|
83
81
|
<PluginModule
|
|
@@ -92,28 +90,6 @@ export default MasterpassRest
|
|
|
92
90
|
/>
|
|
93
91
|
```
|
|
94
92
|
|
|
95
|
-
### Enabling the Rewards feature
|
|
96
|
-
|
|
97
|
-
The card rewards feature (FBB / BNS query + selection) is **disabled by default** to keep existing integrations unaffected. To opt in:
|
|
98
|
-
|
|
99
|
-
```tsx
|
|
100
|
-
<MasterpassRestOption
|
|
101
|
-
locale="tr"
|
|
102
|
-
currency="try"
|
|
103
|
-
enableRewards
|
|
104
|
-
/>
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
When `enableRewards` is `true`:
|
|
108
|
-
- After a saved card is selected, the package automatically calls `MasterpassRestRewardListPage` to fetch available rewards.
|
|
109
|
-
- A "Use Rewards" CTA appears inline on the selected card (default `CardList`).
|
|
110
|
-
- A modal is mounted at the bottom of the view for selection (`RewardSelectionModal`).
|
|
111
|
-
- On confirm, the selection is sent to `MasterpassRestRewardSelectionPage`. The chosen rewards are then forwarded to Masterpass via `additional_fields.rewardList` server-side during `prepareMasterpassOrder` — no frontend wiring needed.
|
|
112
|
-
|
|
113
|
-
Both backend pages must exist on your environment. If they don't, the package silently falls back (no rewards shown, no UI errors), but you'll see failed network requests in devtools.
|
|
114
|
-
|
|
115
|
-
See [RewardSelectionModal](#7b-rewardselectionmodal) for custom render options including a no-modal inline pattern.
|
|
116
|
-
|
|
117
93
|
---
|
|
118
94
|
|
|
119
95
|
## Custom Rendering
|
|
@@ -131,7 +107,6 @@ type MasterpassRestOptionCustomRender = {
|
|
|
131
107
|
linkModal?: (props: LinkModalProps) => ReactElement
|
|
132
108
|
otpModal?: (props: OTPModalProps) => ReactElement
|
|
133
109
|
confirmationModal?: (props: ConfirmationModalProps) => ReactElement
|
|
134
|
-
rewardSelectionModal?: (props: RewardSelectionModalProps) => ReactElement
|
|
135
110
|
errorDisplay?: (props: ErrorDisplayProps) => ReactElement
|
|
136
111
|
loadingState?: (props: LoadingStateProps) => ReactElement
|
|
137
112
|
emptyState?: (props: EmptyStateProps) => ReactElement
|
|
@@ -196,58 +171,35 @@ Displays the user's saved cards with selection, CVC input, and remove functional
|
|
|
196
171
|
|
|
197
172
|
```typescript
|
|
198
173
|
type CardListProps = {
|
|
199
|
-
cards: any[]
|
|
200
|
-
onCardSelect: (card: any) => void
|
|
201
|
-
selectedCard?: any | null
|
|
202
|
-
onRemove?: (card: any) => void
|
|
203
|
-
removingCardId?: string | null
|
|
204
|
-
cvc?: string
|
|
205
|
-
onCvcChange?: (cvc: string) => void
|
|
206
|
-
cvcRequired?: boolean
|
|
207
|
-
|
|
208
|
-
availableRewards?: RewardItem[]
|
|
209
|
-
selectedRewards?: RewardItem[]
|
|
210
|
-
isLoadingRewards?: boolean
|
|
211
|
-
isConfirmingRewards?: boolean
|
|
212
|
-
onOpenRewardModal?: () => void
|
|
213
|
-
onConfirmRewards?: (selected: RewardItem[]) => Promise<void> | void
|
|
214
|
-
rewardCurrency?: string
|
|
215
|
-
rewardPayableAmount?: string | number | null
|
|
216
|
-
|
|
174
|
+
cards: any[] // Array of CardModel objects
|
|
175
|
+
onCardSelect: (card: any) => void // Called when a card is selected
|
|
176
|
+
selectedCard?: any | null // Currently selected card
|
|
177
|
+
onRemove?: (card: any) => void // Called to initiate card removal
|
|
178
|
+
removingCardId?: string | null // Card being removed (shows loader)
|
|
179
|
+
cvc?: string // Current CVC input value
|
|
180
|
+
onCvcChange?: (cvc: string) => void // CVC input change handler
|
|
181
|
+
cvcRequired?: boolean // Whether CVC field is shown
|
|
217
182
|
texts: MasterpassRestOptionTexts
|
|
218
183
|
}
|
|
219
184
|
```
|
|
220
185
|
|
|
221
|
-
`cards`, `onCardSelect`, `selectedCard`, `onRemove`, `removingCardId`, `cvc`, `onCvcChange`, `cvcRequired` are the standard card props. The reward props are only populated when `enableRewards` is set on `MasterpassRestOption`; when disabled they are `undefined` and existing card-list themes keep working unchanged.
|
|
222
|
-
|
|
223
|
-
Reward prop behavior:
|
|
224
|
-
- `availableRewards` — list returned by `MasterpassRestRewardListPage` for the currently selected card.
|
|
225
|
-
- `selectedRewards` — what the user has confirmed so far (persisted in Redux).
|
|
226
|
-
- `isLoadingRewards` — true while the list is being fetched.
|
|
227
|
-
- `isConfirmingRewards` — true while the selection is being posted.
|
|
228
|
-
- `onOpenRewardModal` — opens the default `RewardSelectionModal`.
|
|
229
|
-
- `onConfirmRewards` — bypasses the modal entirely; posts a selection directly. The cumulative cap (special → general) is applied inside before the network call.
|
|
230
|
-
- `rewardCurrency` — display-only ISO code, e.g. `'TRY'`.
|
|
231
|
-
- `rewardPayableAmount` — the order's unpaid amount as a string. Pass this to `getCappedRewardTotal(selected, rewardPayableAmount)` if you render the redeemable total in your inline picker.
|
|
232
|
-
|
|
233
186
|
**CardModel structure (each item in `cards` array):**
|
|
234
187
|
|
|
235
188
|
```typescript
|
|
236
189
|
interface CardModel {
|
|
237
|
-
cardAlias: string
|
|
238
|
-
maskedCardNumber: string
|
|
239
|
-
uniqueCardNumber: string
|
|
190
|
+
cardAlias: string // 'My Visa Card'
|
|
191
|
+
maskedCardNumber: string // '534261******1234'
|
|
192
|
+
uniqueCardNumber: string // Unique identifier
|
|
240
193
|
cardType: 'Credit' | 'Debit' | 'Unknown' | ''
|
|
241
|
-
cardBin: string
|
|
194
|
+
cardBin: string // First 6 digits
|
|
242
195
|
isDefaultCard: boolean
|
|
243
196
|
expireSoon: boolean
|
|
244
197
|
isExpired: boolean
|
|
245
198
|
cardValidationType: 'OTP' | 'RTA' | '_3D' | 'Unknown' | ''
|
|
199
|
+
// ...more fields
|
|
246
200
|
}
|
|
247
201
|
```
|
|
248
202
|
|
|
249
|
-
`cardAlias` is the user-friendly name (e.g. `"My Visa Card"`); `cardBin` is the first 6 digits; `uniqueCardNumber` is the stable identifier. More fields are available — see `account.types.ts`.
|
|
250
|
-
|
|
251
203
|
**Example:**
|
|
252
204
|
|
|
253
205
|
```tsx
|
|
@@ -282,6 +234,7 @@ customRender: {
|
|
|
282
234
|
</button>
|
|
283
235
|
</div>
|
|
284
236
|
|
|
237
|
+
{/* CVC input for selected card */}
|
|
285
238
|
{selectedCard?.uniqueCardNumber === card.uniqueCardNumber && (
|
|
286
239
|
<input
|
|
287
240
|
type="text"
|
|
@@ -644,105 +597,6 @@ customRender: {
|
|
|
644
597
|
|
|
645
598
|
---
|
|
646
599
|
|
|
647
|
-
### 7b. RewardSelectionModal
|
|
648
|
-
|
|
649
|
-
Modal that lets the customer pick which card rewards (FBB / BNS) to apply. Only mounted when `enableRewards={true}` is passed to `MasterpassRestOption`. Requires backend support for `MasterpassRestRewardListPage` and `MasterpassRestRewardSelectionPage`.
|
|
650
|
-
|
|
651
|
-
**Props:**
|
|
652
|
-
|
|
653
|
-
```typescript
|
|
654
|
-
type RewardSelectionModalProps = {
|
|
655
|
-
open: boolean
|
|
656
|
-
onClose: () => void
|
|
657
|
-
onConfirm: (selected: RewardItem[]) => Promise<void> | void
|
|
658
|
-
rewards: RewardItem[]
|
|
659
|
-
selectedRewards: RewardItem[]
|
|
660
|
-
isLoading?: boolean
|
|
661
|
-
currency?: string
|
|
662
|
-
payableAmount?: string | number | null
|
|
663
|
-
texts: MasterpassRestOptionTexts
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
type RewardItem = {
|
|
667
|
-
type: 'special' | 'general'
|
|
668
|
-
amount: number | string
|
|
669
|
-
name?: 'FBB' | 'BNS'
|
|
670
|
-
}
|
|
671
|
-
```
|
|
672
|
-
|
|
673
|
-
`RewardItem.type` is the category — `'special'` maps to `FBB`, `'general'` maps to `BNS`. `amount` is what the backend currently returns (string like `"180.00"`); both `string` and `number` are accepted. `name` is the optional raw code.
|
|
674
|
-
|
|
675
|
-
#### Cumulative cap behavior
|
|
676
|
-
|
|
677
|
-
When `payableAmount` is provided, the modal shows the **actual amount that will be redeemed**, not the full reward value. The cap is cumulative across both categories with a fixed priority — `special` first, then `general`:
|
|
678
|
-
|
|
679
|
-
```
|
|
680
|
-
payable = 100.00
|
|
681
|
-
special reward = 180.00 → 100.00 used (capped, remaining = 0)
|
|
682
|
-
general reward = 50.00 → 0.00 used (no budget left)
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
When a reward is selected and capped, the modal:
|
|
686
|
-
- Shows the full reward amount struck through.
|
|
687
|
-
- Displays a green note below it using `texts.rewardCappedNoticeText` with `{amount}` replaced by the actual redeemed value.
|
|
688
|
-
|
|
689
|
-
`confirmRewards` applies the same cap before sending the selection to `MasterpassRestRewardSelectionPage`, so the backend payload is always `special + general ≤ payable`.
|
|
690
|
-
|
|
691
|
-
**Example — override with your own modal:**
|
|
692
|
-
|
|
693
|
-
```tsx
|
|
694
|
-
{
|
|
695
|
-
customRender: {
|
|
696
|
-
rewardSelectionModal: ({ open, onClose, onConfirm, rewards, ...props }) => (
|
|
697
|
-
<MyRewardModal
|
|
698
|
-
isOpen={open}
|
|
699
|
-
onDismiss={onClose}
|
|
700
|
-
onApply={onConfirm}
|
|
701
|
-
items={rewards}
|
|
702
|
-
{...props}
|
|
703
|
-
/>
|
|
704
|
-
)
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
```
|
|
708
|
-
|
|
709
|
-
**Example — render rewards inline (no modal at all) via CardList:**
|
|
710
|
-
|
|
711
|
-
Brands that prefer an inline picker instead of a modal can use the new reward props on `CardListProps`:
|
|
712
|
-
|
|
713
|
-
```tsx
|
|
714
|
-
{
|
|
715
|
-
customRender: {
|
|
716
|
-
cardList: (props) => (
|
|
717
|
-
<MyCardList
|
|
718
|
-
cards={props.cards}
|
|
719
|
-
onCardSelect={props.onCardSelect}
|
|
720
|
-
selectedCard={props.selectedCard}
|
|
721
|
-
renderRewards={(card) =>
|
|
722
|
-
props.availableRewards?.length ? (
|
|
723
|
-
<InlineRewardPicker
|
|
724
|
-
rewards={props.availableRewards}
|
|
725
|
-
selected={props.selectedRewards ?? []}
|
|
726
|
-
loading={props.isLoadingRewards}
|
|
727
|
-
confirming={props.isConfirmingRewards}
|
|
728
|
-
payableAmount={props.rewardPayableAmount}
|
|
729
|
-
onConfirm={props.onConfirmRewards}
|
|
730
|
-
/>
|
|
731
|
-
) : null
|
|
732
|
-
}
|
|
733
|
-
{...props}
|
|
734
|
-
/>
|
|
735
|
-
)
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
```
|
|
739
|
-
|
|
740
|
-
`onConfirmRewards` bypasses the default modal entirely — your inline picker calls it directly with the user's selection, the package applies the cumulative cap and posts to `MasterpassRestRewardSelectionPage`. For showing the capped redeemable total in your inline picker, use `getCappedRewardTotal(selected, props.rewardPayableAmount)` from `'@akinon/pz-masterpass-rest'`.
|
|
741
|
-
|
|
742
|
-
When you go this route, leave `customRender.rewardSelectionModal` unset — the default modal still won't show because your CardList handles selection via `onConfirmRewards` directly.
|
|
743
|
-
|
|
744
|
-
---
|
|
745
|
-
|
|
746
600
|
### 8. ErrorDisplay
|
|
747
601
|
|
|
748
602
|
Shown at the bottom of the payment area when an error occurs.
|
|
@@ -879,21 +733,16 @@ type MasterpassRestOptionRenderProps = {
|
|
|
879
733
|
handleOTPSubmit: (otp: string) => Promise<{ success: boolean; message?: string }>
|
|
880
734
|
onCloseError: () => void
|
|
881
735
|
|
|
736
|
+
// Loading States
|
|
882
737
|
isCheckoutLoading: boolean
|
|
883
738
|
isInstallmentLoading: boolean
|
|
884
739
|
isPrepareLoading: boolean
|
|
885
740
|
isFinalizeLoading: boolean
|
|
886
|
-
isProcessingPayment: boolean
|
|
887
|
-
isRewardsQueryLoading: boolean
|
|
888
|
-
isRewardsSelectLoading: boolean
|
|
889
|
-
|
|
890
|
-
openRewardModal: () => void
|
|
891
|
-
closeRewardModal: () => void
|
|
892
|
-
handleConfirmRewards: (selected: RewardItem[]) => Promise<void>
|
|
893
|
-
payableAmount: string | null
|
|
894
741
|
|
|
742
|
+
// Texts
|
|
895
743
|
texts: MasterpassRestOptionTexts
|
|
896
744
|
|
|
745
|
+
// Default Components (use these to avoid reimplementing everything)
|
|
897
746
|
components: {
|
|
898
747
|
PaymentMethodSelector: React.ComponentType<PaymentMethodSelectorProps>
|
|
899
748
|
CardList: React.ComponentType<CardListProps>
|
|
@@ -902,75 +751,10 @@ type MasterpassRestOptionRenderProps = {
|
|
|
902
751
|
LinkModal: React.ComponentType<LinkModalProps>
|
|
903
752
|
OTPModal: React.ComponentType<OTPModalProps>
|
|
904
753
|
ConfirmationModal: React.ComponentType<ConfirmationModalProps>
|
|
905
|
-
RewardSelectionModal: React.ComponentType<RewardSelectionModalProps>
|
|
906
754
|
}
|
|
907
755
|
}
|
|
908
756
|
```
|
|
909
757
|
|
|
910
|
-
`isProcessingPayment` is the orchestration-level flag that stays `true` for the entire payment flow (refresh → prepare → Masterpass SDK → finalize). If your `fullRender` exposes a "Proceed to Payment" button, OR it together with `isPrepareLoading` and `isFinalizeLoading` and pass that to your `InstallmentList.paymentLoading` — otherwise the button briefly re-enables between the prepare and finalize steps and double-clicks slip through.
|
|
911
|
-
|
|
912
|
-
#### Opting in to rewards from `fullRender`
|
|
913
|
-
|
|
914
|
-
If your `fullRender` replaces the package's default view, it also bypasses the default `RewardSelectionModal` mount and the inline reward CTA on the default `CardList`. To enable rewards in a `fullRender` integration:
|
|
915
|
-
|
|
916
|
-
1. Pass `enableRewards={true}` on `MasterpassRestOption` so the package auto-fetches rewards on card selection and exposes the modal helpers via render props.
|
|
917
|
-
2. Mount `components.RewardSelectionModal` alongside your other modals, wired to `modalState.showRewardModal`, `closeRewardModal`, `handleConfirmRewards`, `paymentState.availableRewards`, `paymentState.selectedRewards`, `isRewardsSelectLoading`, and `payableAmount`.
|
|
918
|
-
3. In whichever component renders the saved-card list, expose an "Use Rewards" trigger that calls `openRewardModal` once `paymentState.availableRewards.length > 0`. If you use `components.CardList`, pass the reward props through (`availableRewards`, `selectedRewards`, `isLoadingRewards`, `onOpenRewardModal`, `rewardCurrency`, `rewardPayableAmount`) and it will render the inline CTA for you.
|
|
919
|
-
|
|
920
|
-
Minimal sketch:
|
|
921
|
-
|
|
922
|
-
```tsx
|
|
923
|
-
<MasterpassRestOption
|
|
924
|
-
enableRewards
|
|
925
|
-
customRender={{
|
|
926
|
-
fullRender: (props) => {
|
|
927
|
-
const {
|
|
928
|
-
paymentState,
|
|
929
|
-
modalState,
|
|
930
|
-
components: { CardList, RewardSelectionModal },
|
|
931
|
-
openRewardModal,
|
|
932
|
-
closeRewardModal,
|
|
933
|
-
handleConfirmRewards,
|
|
934
|
-
isRewardsQueryLoading,
|
|
935
|
-
isRewardsSelectLoading,
|
|
936
|
-
payableAmount,
|
|
937
|
-
texts
|
|
938
|
-
} = props
|
|
939
|
-
|
|
940
|
-
return (
|
|
941
|
-
<>
|
|
942
|
-
<CardList
|
|
943
|
-
{...cardListProps}
|
|
944
|
-
availableRewards={paymentState.availableRewards}
|
|
945
|
-
selectedRewards={paymentState.selectedRewards}
|
|
946
|
-
isLoadingRewards={paymentState.isLoadingRewards || isRewardsQueryLoading}
|
|
947
|
-
isConfirmingRewards={isRewardsSelectLoading}
|
|
948
|
-
onOpenRewardModal={openRewardModal}
|
|
949
|
-
rewardCurrency="TRY"
|
|
950
|
-
rewardPayableAmount={payableAmount}
|
|
951
|
-
texts={texts}
|
|
952
|
-
/>
|
|
953
|
-
|
|
954
|
-
<RewardSelectionModal
|
|
955
|
-
open={modalState.showRewardModal}
|
|
956
|
-
onClose={closeRewardModal}
|
|
957
|
-
onConfirm={handleConfirmRewards}
|
|
958
|
-
rewards={paymentState.availableRewards}
|
|
959
|
-
selectedRewards={paymentState.selectedRewards}
|
|
960
|
-
isLoading={isRewardsSelectLoading}
|
|
961
|
-
currency="TRY"
|
|
962
|
-
payableAmount={payableAmount}
|
|
963
|
-
texts={texts}
|
|
964
|
-
/>
|
|
965
|
-
</>
|
|
966
|
-
)
|
|
967
|
-
}
|
|
968
|
-
}}
|
|
969
|
-
/>
|
|
970
|
-
```
|
|
971
|
-
|
|
972
|
-
Without `enableRewards`, the package does not call `MasterpassRestRewardListPage`, no reward state is populated, and the helpers stay no-ops — existing `fullRender` brands keep behaving identically until they explicitly opt in.
|
|
973
|
-
|
|
974
758
|
**Example - Custom layout with default components:**
|
|
975
759
|
|
|
976
760
|
```tsx
|
|
@@ -1000,7 +784,6 @@ customRender: {
|
|
|
1000
784
|
isInstallmentLoading,
|
|
1001
785
|
isPrepareLoading,
|
|
1002
786
|
isFinalizeLoading,
|
|
1003
|
-
isProcessingPayment,
|
|
1004
787
|
texts,
|
|
1005
788
|
components
|
|
1006
789
|
} = props
|
|
@@ -1057,13 +840,14 @@ customRender: {
|
|
|
1057
840
|
selectedInstallment={paymentState.selectedInstallment}
|
|
1058
841
|
isLoading={isInstallmentLoading || isPrepareLoading}
|
|
1059
842
|
onProceedToPayment={handleProceedToPayment}
|
|
1060
|
-
paymentLoading={
|
|
843
|
+
paymentLoading={isFinalizeLoading}
|
|
1061
844
|
texts={texts}
|
|
1062
845
|
/>
|
|
1063
846
|
)}
|
|
1064
847
|
</div>
|
|
1065
848
|
</div>
|
|
1066
849
|
|
|
850
|
+
{/* Modals - use default components */}
|
|
1067
851
|
<LinkModal
|
|
1068
852
|
open={modalState?.showLinkModal ?? false}
|
|
1069
853
|
onClose={() => updateModalState({ showLinkModal: false })}
|
|
@@ -1096,12 +880,14 @@ All user-facing strings can be overridden via the `texts` prop. Pass only the ke
|
|
|
1096
880
|
locale: 'tr',
|
|
1097
881
|
currency: 'try',
|
|
1098
882
|
texts: {
|
|
883
|
+
// Titles
|
|
1099
884
|
title: 'Masterpass ile Ode',
|
|
1100
885
|
selectCardTitle: 'Kart Secin',
|
|
1101
886
|
newCardTitle: 'Yeni Kart ile Ode',
|
|
1102
887
|
installmentOptionsTitle: 'Taksit Secenekleri',
|
|
1103
888
|
enterCardDetailsTitle: 'Kart Bilgilerini Girin',
|
|
1104
889
|
|
|
890
|
+
// Form labels
|
|
1105
891
|
cardNumberLabel: 'Kart Numarasi',
|
|
1106
892
|
cardholderNameLabel: 'Kart Uzerindeki Isim',
|
|
1107
893
|
expiryDateLabel: 'Son Kullanma Tarihi',
|
|
@@ -1109,50 +895,43 @@ All user-facing strings can be overridden via the `texts` prop. Pass only the ke
|
|
|
1109
895
|
saveCardLabel: 'Bu karti gelecek odemeler icin kaydet',
|
|
1110
896
|
addCardButton: 'Kart Ekle',
|
|
1111
897
|
|
|
898
|
+
// Payment method
|
|
1112
899
|
savedCardsText: 'Kayitli Kartlar',
|
|
1113
900
|
newCardText: 'Yeni Kart',
|
|
1114
901
|
|
|
902
|
+
// Installments
|
|
1115
903
|
singlePaymentText: 'Tek Cekim',
|
|
1116
|
-
installmentsText: '{count} Taksit',
|
|
904
|
+
installmentsText: '{count} Taksit', // {count} is replaced dynamically
|
|
1117
905
|
noInterestText: 'Faizsiz',
|
|
1118
906
|
proceedToPaymentText: 'Odemeye Devam Et',
|
|
1119
907
|
processingPaymentText: 'Odeme Isleniyor...',
|
|
1120
908
|
|
|
909
|
+
// Card list
|
|
1121
910
|
defaultCardText: 'Varsayilan',
|
|
1122
911
|
expiresSoonText: 'Suresi Yakinda Dolacak',
|
|
1123
912
|
|
|
913
|
+
// Modals
|
|
1124
914
|
linkModalDescription: '<PHONE_NUMBER> numarasi ile Masterpass hesabinizdaki kartlari gormek ister misiniz?',
|
|
1125
915
|
linkAccountButton: 'Evet, istiyorum',
|
|
1126
916
|
linkModalCancelButton: 'Hayir, istemiyorum',
|
|
1127
917
|
removeCardMessage: '<{cardAlias}> kartini Masterpass altyapisindan silmek istediginize emin misiniz?',
|
|
1128
918
|
|
|
1129
|
-
|
|
1130
|
-
rewardModalTitle: 'Kart Puanlarini Kullan',
|
|
1131
|
-
rewardModalDescription: 'Bu siparise uygulamak istediginiz puanlari secin.',
|
|
1132
|
-
rewardModalEmptyMessage: 'Bu kart icin uygun puan yok.',
|
|
1133
|
-
rewardModalConfirmText: 'Uygula',
|
|
1134
|
-
rewardModalCancelText: 'Vazgec',
|
|
1135
|
-
rewardModalLoadingText: 'Uygulaniyor...',
|
|
1136
|
-
rewardSelectedSummaryText: '{count} puan uygulandi',
|
|
1137
|
-
rewardAvailableSummaryText: '{count} puan mevcut',
|
|
1138
|
-
rewardCategorySpecialText: 'Ozel Puanlar',
|
|
1139
|
-
rewardCategoryGeneralText: 'Genel Puanlar',
|
|
1140
|
-
rewardCappedNoticeText: '{amount} kullanilacak',
|
|
1141
|
-
rewardFailedToLoadText: 'Puanlar yuklenemedi',
|
|
1142
|
-
rewardFailedToSelectText: 'Puanlar uygulanamadi',
|
|
1143
|
-
|
|
919
|
+
// Verification
|
|
1144
920
|
rtaVerificationTitle: 'Guvenlik Dogrulamasi',
|
|
1145
921
|
bankOtpVerificationTitle: 'Banka Dogrulamasi',
|
|
1146
922
|
cvvVerificationTitle: 'CVV Dogrulamasi',
|
|
1147
923
|
verifyButton: 'Dogrula',
|
|
1148
924
|
|
|
925
|
+
// Errors
|
|
1149
926
|
paymentErrorTitle: 'Odeme Hatasi',
|
|
1150
927
|
cardNumberRequiredText: 'Kart numarasi zorunludur',
|
|
1151
928
|
cardNumberInvalidText: 'Gecerli bir kart numarasi girin',
|
|
1152
929
|
|
|
930
|
+
// Loading
|
|
1153
931
|
loadingMessage: 'Odeme sistemi hazirlaniyor...',
|
|
1154
932
|
scriptLoadingMessage: 'Odeme altyapisi yukleniyor...',
|
|
1155
933
|
|
|
934
|
+
// Session
|
|
1156
935
|
sessionExpiredTitle: 'Oturum Suresi Doldu',
|
|
1157
936
|
sessionExpiredMessage: 'Oturumunuz zaman asimina ugradi. Devam etmek icin islemi yeniden baslatin.',
|
|
1158
937
|
sessionExpiredButton: 'Yeniden Basla'
|
|
@@ -1172,9 +951,6 @@ Some text keys support placeholders:
|
|
|
1172
951
|
| `removeCardMessage` | `{cardAlias}` | Name of the card being removed |
|
|
1173
952
|
| `cvcHelpText` | `{length}`, `{side}` | CVC digit count and card side |
|
|
1174
953
|
| `linkModalDescription` | `<PHONE_NUMBER>` | User's phone number (auto-replaced by SDK) |
|
|
1175
|
-
| `rewardSelectedSummaryText` | `{count}` | Number of selected rewards |
|
|
1176
|
-
| `rewardAvailableSummaryText` | `{count}` | Number of available rewards for the selected card |
|
|
1177
|
-
| `rewardCappedNoticeText` | `{amount}` | Capped redeemable amount (e.g. `"100.00 TRY"`) |
|
|
1178
954
|
|
|
1179
955
|
---
|
|
1180
956
|
|
|
@@ -1236,101 +1012,53 @@ const {
|
|
|
1236
1012
|
|
|
1237
1013
|
### `useMasterpassPayment`
|
|
1238
1014
|
|
|
1239
|
-
Handles the payment processing flow
|
|
1015
|
+
Handles the payment processing flow.
|
|
1240
1016
|
|
|
1241
1017
|
```typescript
|
|
1242
1018
|
import { useMasterpassPayment } from '@akinon/pz-masterpass-rest'
|
|
1243
1019
|
|
|
1244
1020
|
const {
|
|
1245
|
-
paymentState,
|
|
1021
|
+
paymentState, // selectedCard, selectedInstallment, installments, etc.
|
|
1246
1022
|
isCheckoutLoading,
|
|
1247
1023
|
isInstallmentLoading,
|
|
1248
1024
|
isPrepareLoading,
|
|
1249
1025
|
isFinalizeLoading,
|
|
1250
|
-
|
|
1251
|
-
isRewardsSelectLoading,
|
|
1252
|
-
payableAmount,
|
|
1253
|
-
handleCardSelect,
|
|
1026
|
+
handleCardSelect, // Select a saved card (triggers BIN check)
|
|
1254
1027
|
handleInstallmentSelect,
|
|
1255
|
-
processPayment,
|
|
1256
|
-
processDirectPayment
|
|
1257
|
-
|
|
1258
|
-
openRewardModal,
|
|
1259
|
-
closeRewardModal,
|
|
1260
|
-
confirmRewards
|
|
1261
|
-
} = useMasterpassPayment({ enableRewards: true })
|
|
1028
|
+
processPayment, // Stored card payment
|
|
1029
|
+
processDirectPayment // New card payment
|
|
1030
|
+
} = useMasterpassPayment()
|
|
1262
1031
|
```
|
|
1263
1032
|
|
|
1264
|
-
`paymentState` carries the live selection state (`selectedCard`, `selectedInstallment`, `installments`, plus `availableRewards`, `selectedRewards`, `isLoadingRewards` when rewards are enabled).
|
|
1265
|
-
|
|
1266
|
-
`useMasterpassPayment` accepts a single options arg `{ enableRewards?: boolean }` — default `false`. When `false`, `handleCardSelect` skips the reward fetch, and the reward state stays empty. Pass `true` only when you are also using `<MasterpassRestOption enableRewards />` (or rendering the rewards UI yourself); otherwise the package never hits `MasterpassRestRewardListPage`.
|
|
1267
|
-
|
|
1268
|
-
`payableAmount` is read from `state.checkout.preOrder.unpaid_amount` (falling back to `total_amount_with_interest`). Pass it to `getCappedRewardTotal` / `getCappedRewardAmounts` if you are building a custom rewards UI.
|
|
1269
|
-
|
|
1270
|
-
`confirmRewards(selected)` applies the cumulative cap (`special` first, then `general`) and posts to `MasterpassRestRewardSelectionPage`. It returns `{ success: true }` on success or `{ success: false, message }` on failure.
|
|
1271
|
-
|
|
1272
1033
|
---
|
|
1273
1034
|
|
|
1274
1035
|
## Exported Utilities
|
|
1275
1036
|
|
|
1276
1037
|
```typescript
|
|
1277
1038
|
import {
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
createCreditCardFormSchema
|
|
1039
|
+
// Card utilities
|
|
1040
|
+
formatCardNumber, // '5342610000001234' -> '5342 6100 0000 1234'
|
|
1041
|
+
formatExpiryDate, // '1227' -> '12/27'
|
|
1042
|
+
formatCVV, // Strips non-digits, max 4 chars
|
|
1043
|
+
detectCardType, // Returns 'visa' | 'mastercard' | 'amex' | 'troy' | 'discover' | 'unknown'
|
|
1044
|
+
getCvcLength, // Returns 3 (or 4 for Amex)
|
|
1045
|
+
maskCardNumber, // '5342610000001234' -> '****1234'
|
|
1046
|
+
validateCardNumber, // Luhn algorithm validation
|
|
1047
|
+
getCardBIN, // Returns first 6 digits
|
|
1048
|
+
getCardIcon, // Returns logo image object by BIN
|
|
1049
|
+
|
|
1050
|
+
// Payment utilities
|
|
1051
|
+
isTokenExpired, // Check JWT token expiration
|
|
1052
|
+
getTransactionType, // Returns 'PURCHASE' or 'PURCHASE_3D'
|
|
1053
|
+
formatAmountForPayment, // '1500.00' -> '150000'
|
|
1054
|
+
createPaymentRequest, // Builds stored card payment request
|
|
1055
|
+
createDirectPaymentRequest, // Builds new card payment request
|
|
1056
|
+
|
|
1057
|
+
// Validation
|
|
1058
|
+
createCreditCardFormSchema // Returns Yup validation schema
|
|
1300
1059
|
} from '@akinon/pz-masterpass-rest'
|
|
1301
1060
|
```
|
|
1302
1061
|
|
|
1303
|
-
**Card utilities** — `formatCardNumber` (`'5342610000001234'` → `'5342 6100 0000 1234'`), `formatExpiryDate` (`'1227'` → `'12/27'`), `formatCVV` (strips non-digits, max 4 chars), `detectCardType` (returns `'visa' | 'mastercard' | 'amex' | 'troy' | 'discover' | 'unknown'`), `getCvcLength` (returns `3`, or `4` for Amex), `maskCardNumber` (`'5342610000001234'` → `'****1234'`), `validateCardNumber` (Luhn), `getCardBIN` (first 6 digits), `getCardIcon` (logo image object by BIN).
|
|
1304
|
-
|
|
1305
|
-
**Payment utilities** — `isTokenExpired` checks the JWT expiry, `getTransactionType` returns `'PURCHASE'` / `'PURCHASE_3D'`, `formatAmountForPayment` (`'1500.00'` → `'150000'`), `createPaymentRequest` / `createDirectPaymentRequest` build the SDK request body.
|
|
1306
|
-
|
|
1307
|
-
**Reward utilities** — used internally and exported for custom UIs:
|
|
1308
|
-
|
|
1309
|
-
```typescript
|
|
1310
|
-
parseRewardAmount(amount: number | string): number
|
|
1311
|
-
|
|
1312
|
-
getCappedRewardAmounts(
|
|
1313
|
-
selected: RewardItem[],
|
|
1314
|
-
payableAmount?: string | number | null
|
|
1315
|
-
): Record<'special' | 'general', number>
|
|
1316
|
-
|
|
1317
|
-
getCappedRewardTotal(
|
|
1318
|
-
selected: RewardItem[],
|
|
1319
|
-
payableAmount?: string | number | null
|
|
1320
|
-
): number
|
|
1321
|
-
|
|
1322
|
-
REWARD_PRIORITY: ['special', 'general']
|
|
1323
|
-
```
|
|
1324
|
-
|
|
1325
|
-
- `parseRewardAmount` safely parses backend string amounts (e.g. `"180.00"`) to a number; returns `0` for invalid input.
|
|
1326
|
-
- `getCappedRewardAmounts` applies the cumulative cap (`special` first, then `general`) and returns the actual amounts that will be redeemed per category.
|
|
1327
|
-
- `getCappedRewardTotal` is the sum of the capped amounts — use this when rendering a "X TRY will be applied" total.
|
|
1328
|
-
- `REWARD_PRIORITY` is the fixed order in which the cap is applied. Exported so custom UIs can iterate in the same order.
|
|
1329
|
-
|
|
1330
|
-
`payableAmount` is the order's unpaid amount. If `null` / `undefined` / unparseable, no cap is applied (returns the full reward amounts) — this matches the behavior in the package and is safe as a fallback.
|
|
1331
|
-
|
|
1332
|
-
**Validation** — `createCreditCardFormSchema` returns the Yup schema used by the default `CreditCardForm`.
|
|
1333
|
-
|
|
1334
1062
|
---
|
|
1335
1063
|
|
|
1336
1064
|
## Type Definitions
|
|
@@ -1339,6 +1067,7 @@ All types are exported and can be imported for use in custom components:
|
|
|
1339
1067
|
|
|
1340
1068
|
```typescript
|
|
1341
1069
|
import type {
|
|
1070
|
+
// Component props
|
|
1342
1071
|
PaymentMethodSelectorProps,
|
|
1343
1072
|
CardListProps,
|
|
1344
1073
|
CreditCardFormProps,
|
|
@@ -1346,7 +1075,6 @@ import type {
|
|
|
1346
1075
|
LinkModalProps,
|
|
1347
1076
|
OTPModalProps,
|
|
1348
1077
|
ConfirmationModalProps,
|
|
1349
|
-
RewardSelectionModalProps,
|
|
1350
1078
|
ErrorDisplayProps,
|
|
1351
1079
|
LoadingStateProps,
|
|
1352
1080
|
EmptyStateProps,
|
|
@@ -1354,6 +1082,7 @@ import type {
|
|
|
1354
1082
|
MasterpassRestOptionCustomRender,
|
|
1355
1083
|
MasterpassRestOptionTexts,
|
|
1356
1084
|
|
|
1085
|
+
// Data types
|
|
1357
1086
|
CardModel,
|
|
1358
1087
|
CardType,
|
|
1359
1088
|
Installment,
|
|
@@ -1363,21 +1092,21 @@ import type {
|
|
|
1363
1092
|
OTPType,
|
|
1364
1093
|
TransactionType,
|
|
1365
1094
|
InformationModalData,
|
|
1366
|
-
RewardItem,
|
|
1367
|
-
RewardName,
|
|
1368
|
-
RewardCategory,
|
|
1369
1095
|
|
|
1096
|
+
// Account types
|
|
1370
1097
|
AccountAccessRequest,
|
|
1371
1098
|
AccountAccessResponse,
|
|
1372
1099
|
AccountAccessSuccessResponse,
|
|
1373
1100
|
AccountAccessErrorResponse,
|
|
1374
1101
|
CardResponse,
|
|
1375
1102
|
|
|
1103
|
+
// Payment types
|
|
1376
1104
|
PaymentProcessRequest,
|
|
1377
1105
|
DirectPaymentRequest,
|
|
1378
1106
|
DirectPaymentResponse,
|
|
1379
1107
|
MPResponse,
|
|
1380
1108
|
|
|
1109
|
+
// Environment
|
|
1381
1110
|
MasterpassEnvironment
|
|
1382
1111
|
} from '@akinon/pz-masterpass-rest'
|
|
1383
1112
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akinon/pz-masterpass-rest",
|
|
3
|
-
"version": "2.0.18
|
|
3
|
+
"version": "2.0.18",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"types": "src/index.d.ts",
|
|
6
6
|
"description": "Modern React-based Masterpass REST API integration package for ProjectZero e-commerce platform",
|
|
@@ -31,6 +31,6 @@
|
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/react": "18.2.27",
|
|
33
33
|
"@types/react-dom": "18.2.12",
|
|
34
|
-
"typescript": "
|
|
34
|
+
"typescript": "5.2.2"
|
|
35
35
|
}
|
|
36
36
|
}
|