Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OWA-85: New payment flow #593

Open
wants to merge 195 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 184 commits
Commits
Show all changes
195 commits
Select commit Hold shift + click to select a range
ef33f18
feat(project): access bridge initial structure
kiremitrov123 Jul 18, 2024
4358d94
feat(project): yarn
kiremitrov123 Jul 18, 2024
88c51b7
feat(project): add lint-staged
kiremitrov123 Jul 18, 2024
e7c582b
feat(project): error for unused imports
kiremitrov123 Jul 19, 2024
3fc50a4
feat(project): remove not needed ls-lint
kiremitrov123 Jul 19, 2024
d6d283b
feat(project): add access tests
kiremitrov123 Jul 20, 2024
d18fe2d
feat(project): rename error message
kiremitrov123 Jul 20, 2024
12cc7f5
feat(project): readme and docs
kiremitrov123 Jul 22, 2024
7399e70
Merge branch 'develop' of https://github.com/jwplayer/ott-web-app int…
kiremitrov123 Jul 22, 2024
ac75a09
chore: rename project in package
kiremitrov123 Jul 22, 2024
5a72ec6
feat(project): include SIMS authorization
kiremitrov123 Jul 22, 2024
aec8347
chore: replace jw/fet with standard prettier config
kiremitrov123 Jul 22, 2024
66e5af9
chore: access-bridge changes to not trigger e2e tests
kiremitrov123 Jul 22, 2024
dada55d
chore: revert web env
kiremitrov123 Jul 22, 2024
478cd3b
feat(project): add stripe products endpoint
kiremitrov123 Jul 23, 2024
7499b37
chore: yarn update
kiremitrov123 Jul 23, 2024
e2e5dc3
feat(project): move types in common package
kiremitrov123 Jul 23, 2024
a88e20b
Merge branch 'IDM-161/IAM-Middleware' of https://github.com/jwplayer/…
kiremitrov123 Jul 23, 2024
c055114
feat(project): update allowed methods
kiremitrov123 Jul 23, 2024
aa8d39a
Merge branch 'IDM-161/IAM-Middleware' of https://github.com/jwplayer/…
kiremitrov123 Jul 23, 2024
c44b17a
chore: rename stripe service fnc name
kiremitrov123 Jul 24, 2024
5f473d5
feat(project): make authorization optional
kiremitrov123 Jul 24, 2024
e1e13aa
Merge branch 'IDM-161/IAM-Middleware' of https://github.com/jwplayer/…
kiremitrov123 Jul 24, 2024
7080e72
feat(project): redefine functions with obj params
kiremitrov123 Jul 24, 2024
81cf353
Merge branch 'IDM-161/IAM-Middleware' of https://github.com/jwplayer/…
kiremitrov123 Jul 24, 2024
5f7c7cf
chore: consistent naming convention
kiremitrov123 Jul 24, 2024
4ad3716
chore: update namings
kiremitrov123 Jul 24, 2024
eabf817
feat(project): add test fixtures
kiremitrov123 Jul 24, 2024
4c2a1cf
Merge branch 'IDM-161/IAM-Middleware' of https://github.com/jwplayer/…
kiremitrov123 Jul 24, 2024
afba6bb
feat(project): add tests for stripe
kiremitrov123 Jul 25, 2024
70b5d9b
feat(project): fine-tune error descriptions
kiremitrov123 Jul 25, 2024
cff8e03
feat(project): use err code enum instead of hardcoded
kiremitrov123 Jul 25, 2024
30cc325
feat(project): add stripe checkout
kiremitrov123 Jul 25, 2024
b5b96e5
chore: move types in common
kiremitrov123 Jul 25, 2024
ed29191
chore: move types in common
kiremitrov123 Jul 25, 2024
36daa91
Merge branch 'IDM-161/IAM-Middleware' of https://github.com/jwplayer/…
kiremitrov123 Jul 25, 2024
2a1ee0e
feat(project): add types in common
kiremitrov123 Jul 25, 2024
54713ec
feat(project): add tests for stripe checkout
kiremitrov123 Jul 26, 2024
e918525
feat(project): add more tests for checkout
kiremitrov123 Jul 28, 2024
0557a39
chore: stripe checkout params
kiremitrov123 Jul 28, 2024
2ba1416
feat(project): add test mocks class
kiremitrov123 Jul 29, 2024
5c2ae2c
feat(project): add metadata in stripe checkout
kiremitrov123 Jul 29, 2024
b5b50c7
feat(project): add viewer from auth token, handle plan external provi…
kiremitrov123 Jul 30, 2024
1284fd6
feat(project): add viewer from auth token, handle plan external provi…
kiremitrov123 Jul 30, 2024
e889ebd
feat(project): update stripe products filter
kiremitrov123 Jul 30, 2024
c4231be
feat(project): use external providers
kiremitrov123 Jul 30, 2024
ce3d54e
chore: update readme
kiremitrov123 Jul 31, 2024
d146dba
Merge branch 'develop' of https://github.com/jwplayer/ott-web-app int…
kiremitrov123 Jul 31, 2024
bcd00ed
Merge branch 'IDM-161/IAM-Middleware' of https://github.com/jwplayer/…
kiremitrov123 Jul 31, 2024
6b1dba3
feat(project): update docs
kiremitrov123 Jul 31, 2024
6724a9f
Merge branch 'IDM-169/stripe-products' of https://github.com/jwplayer…
kiremitrov123 Jul 31, 2024
f84494e
feat(project): add account service
kiremitrov123 Jul 31, 2024
93b7698
Merge branch 'IDM-161/IAM-Middleware' of https://github.com/jwplayer/…
kiremitrov123 Jul 31, 2024
7489d07
feat(project): add accounts service usage
kiremitrov123 Jul 31, 2024
9955d55
chore: remove unused util fnc
kiremitrov123 Jul 31, 2024
2cb2c96
Merge branch 'IDM-161/IAM-Middleware' of https://github.com/jwplayer/…
kiremitrov123 Jul 31, 2024
75a4989
Merge branch 'IDM-169/stripe-products' of https://github.com/jwplayer…
kiremitrov123 Jul 31, 2024
e175c3b
feat(project): add sentry
kiremitrov123 Aug 1, 2024
1a5e30c
fix: new payment flow - draft
mirovladimitrovski Aug 13, 2024
e0b3563
fix: implement redirecting to stripe payment page
mirovladimitrovski Aug 14, 2024
88b3a44
fix: add a missing snapshot
mirovladimitrovski Aug 14, 2024
77e1e85
fix: fully implement stripe redirection with appropriate modals
mirovladimitrovski Aug 15, 2024
5124388
fix: fix endpoint paths and change stripe cancel_url
mirovladimitrovski Aug 15, 2024
ffea960
fix: fix baseUrl for stripe redirecting urls
mirovladimitrovski Aug 15, 2024
5241b1d
fix: implement stripe external link for billing portal
mirovladimitrovski Aug 15, 2024
f5beaf4
feat(project): changes
borkopetrovicc Aug 19, 2024
78f06cb
fix: do not run billing-portal before click
mirovladimitrovski Aug 19, 2024
086c3f8
fix: revert temporary env changes and remove unused env var
mirovladimitrovski Aug 19, 2024
58da68b
fix: store jwp api urls into consts
mirovladimitrovski Aug 20, 2024
26d106c
fix: store jwp api urls into consts
mirovladimitrovski Aug 20, 2024
0ac404a
feat(project): replace node with vite
kiremitrov123 Aug 20, 2024
5d350a1
fix: remove notifications implementation and inplayer.js dependency a…
mirovladimitrovski Aug 20, 2024
3c38ca0
feat(project): refactor server to use express, refactor error handlin…
kiremitrov123 Aug 21, 2024
c7b5718
feat(project): add types for express
kiremitrov123 Aug 21, 2024
c88e831
chore: add .test in the test naimings
kiremitrov123 Aug 21, 2024
0a02f3e
fix: vite version mismatch
kiremitrov123 Aug 21, 2024
5fdfd3c
feat(project): update docs
kiremitrov123 Aug 22, 2024
61e01ea
Merge branch 'develop' of https://github.com/jwplayer/ott-web-app int…
kiremitrov123 Aug 22, 2024
b164ad4
chore: add dummy env variables in the test-unit-snapshot workflow
kiremitrov123 Aug 22, 2024
d7715ce
feat(project): address changes of vite, express and vitest
kiremitrov123 Aug 22, 2024
e9cd076
feat(project): refactor services, decouple plans method
kiremitrov123 Aug 22, 2024
67d8b42
feat(project): update products controller and tests to match the refa…
kiremitrov123 Aug 22, 2024
73d7945
feat(project): refactor app to use vite, express and vitest for testing
kiremitrov123 Aug 22, 2024
24ef0fe
feat(project): load sentry after build
kiremitrov123 Aug 25, 2024
5e13a20
feat(project): add sentry source mapping
kiremitrov123 Aug 25, 2024
08f994b
feat(project): add sentry version and environment
kiremitrov123 Aug 26, 2024
ed41bf4
chore: remove debug sentry
kiremitrov123 Aug 26, 2024
0bb0bd6
feat(project): additional test build for not source mapping on test
kiremitrov123 Aug 26, 2024
239742e
feat(project): add stripe billing portal endpoint
kiremitrov123 Aug 26, 2024
889d299
chore: update readme
kiremitrov123 Aug 26, 2024
8ff899d
Merge branch 'IDM-232/stripe-billing-portal' of https://github.com/jw…
kiremitrov123 Aug 26, 2024
69705da
Merge branch 'IDM-232/stripe-billing-portal' of https://github.com/jw…
kiremitrov123 Aug 26, 2024
c73487f
chore: add stripe dummy secret on test-unit workflow
kiremitrov123 Aug 26, 2024
264a1f6
Merge branch 'IDM-169/stripe-products' of https://github.com/jwplayer…
kiremitrov123 Aug 26, 2024
2797ec3
chore: update checkout params
kiremitrov123 Aug 26, 2024
7fb5808
Merge branch 'IDM-209/stripe-checkout' of https://github.com/jwplayer…
kiremitrov123 Aug 26, 2024
a4e7209
Merge branch 'IDM-220/error-logging' of https://github.com/jwplayer/o…
kiremitrov123 Aug 26, 2024
6120337
feat(project): add cors middleware
kiremitrov123 Aug 26, 2024
27f115b
feat(project): add site_id in the route
kiremitrov123 Aug 26, 2024
e022515
Merge branch 'IDM-209/stripe-checkout' of https://github.com/jwplayer…
kiremitrov123 Aug 26, 2024
8204e15
feat(project): add site_id in the route
kiremitrov123 Aug 26, 2024
636065a
Merge branch 'IDM-232/stripe-billing-portal' of https://github.com/jw…
kiremitrov123 Aug 26, 2024
3a05a13
Merge branch 'IDM-232/stripe-billing-portal' of https://github.com/jw…
kiremitrov123 Aug 26, 2024
54626a0
fix: remove forSiteId option in jwpapiservice
mirovladimitrovski Aug 27, 2024
53aae8e
fix: remove forSiteId option in jwpapiservice
mirovladimitrovski Aug 27, 2024
738e297
fix: split subscription into separate container and component
mirovladimitrovski Aug 27, 2024
53b72c8
fix: complete subscription page
mirovladimitrovski Aug 29, 2024
17d17c1
fix: update jwpapiservice
mirovladimitrovski Aug 29, 2024
ce70f0a
fix: update welcome and payment-cancelled modals ui and text in them
mirovladimitrovski Aug 29, 2024
4e6adc7
fix: update snaps
mirovladimitrovski Aug 29, 2024
c535951
feat(project): use passport service from access bridge
kiremitrov123 Aug 30, 2024
62cedc1
chore: remove unused prop
kiremitrov123 Aug 30, 2024
293d27f
chore: update import paths
kiremitrov123 Aug 30, 2024
0396eaf
feat(project): remove passport on logout
kiremitrov123 Aug 30, 2024
7088868
fix: update middleware base url
mirovladimitrovski Aug 30, 2024
ec1dcf9
fix: update middleware base url
mirovladimitrovski Aug 30, 2024
342dc8a
fix: remove unused const
mirovladimitrovski Aug 30, 2024
a53c56b
fix: fix stripe return urls building
mirovladimitrovski Aug 30, 2024
629cea9
fix: load offers
mirovladimitrovski Aug 30, 2024
82b7612
feat(project): create access service and controller
kiremitrov123 Sep 1, 2024
2856277
feat(project): handle avod for anonymous passport generation
kiremitrov123 Sep 2, 2024
1ae2e04
chore: update import paths in Access Controller
kiremitrov123 Sep 2, 2024
4b3c949
chore: revert env variables
kiremitrov123 Sep 2, 2024
265d44c
feat(project): include expires in the passport stored data
kiremitrov123 Sep 2, 2024
49332cd
feat(project): update init access controller
kiremitrov123 Sep 2, 2024
93b528f
feat(project): move access bridge env variable to ini
kiremitrov123 Sep 3, 2024
e993e7c
feat(project): add refresh passport mechanism
kiremitrov123 Sep 3, 2024
d224273
feat(project): add getEntitledPlans service
kiremitrov123 Sep 5, 2024
1eb9ce3
fix: remove access-bridge
mirovladimitrovski Sep 6, 2024
edad55f
fix: revert some changes
mirovladimitrovski Sep 6, 2024
d2494e7
fix: revert more changes
mirovladimitrovski Sep 6, 2024
1a57cf2
fix: add changes to prevent merge conflict
mirovladimitrovski Sep 6, 2024
ff2832d
fix: revert change conflicting with base branch
mirovladimitrovski Sep 6, 2024
310f373
feat(project): bind access stuff optionally
kiremitrov123 Sep 11, 2024
45e17f5
Merge branch 'develop' of https://github.com/jwplayer/ott-web-app int…
kiremitrov123 Sep 11, 2024
dfadc7b
feat(project): update refresh tokens with generate changes
kiremitrov123 Sep 11, 2024
489daa4
chore: naming typo
kiremitrov123 Sep 11, 2024
f6b6b4c
Merge branch 'IDM-172/generate-passport' of https://github.com/jwplay…
kiremitrov123 Sep 11, 2024
f9ac5f5
chore: register imports order
kiremitrov123 Sep 11, 2024
99493d9
Merge branch 'IDM-172/generate-passport' of https://github.com/jwplay…
kiremitrov123 Sep 11, 2024
a4d4737
Merge branch 'IDM-172/generate-passport' into PS-290-new-payment-flow
mirovladimitrovski Sep 16, 2024
138709f
chore: merge with parent
kiremitrov123 Sep 16, 2024
7086bfb
fix: implement injectable access bridge url
mirovladimitrovski Sep 17, 2024
67aee79
fix: update a test
mirovladimitrovski Sep 17, 2024
382c46a
fix: update jwp api service
mirovladimitrovski Sep 17, 2024
3f98e85
fix: temporary changes
mirovladimitrovski Sep 18, 2024
b57edd8
Revert "fix: temporary changes"
mirovladimitrovski Sep 18, 2024
bddbc28
fix: disable some codecept tests for jwp
mirovladimitrovski Sep 18, 2024
530a0af
fix: disable e2e tests for access bridge
mirovladimitrovski Sep 18, 2024
d9746df
fix: update wording in e2e test reflecting changes in i18n json trans…
mirovladimitrovski Sep 18, 2024
f02b4c7
fix: temp change in test
mirovladimitrovski Sep 18, 2024
8fb1dc8
fix: wait longer for loading overlay to disappear in e2e
mirovladimitrovski Sep 18, 2024
b446e45
fix: increase timeout for login or register in e2e
mirovladimitrovski Sep 19, 2024
3093ebd
fix: increase timeout again
mirovladimitrovski Sep 19, 2024
6f58257
fix: set access method before initializing offers
mirovladimitrovski Sep 19, 2024
b081d51
feat(project): add new way of handling media with passport
kiremitrov123 Sep 19, 2024
e538e40
chore: nit in webapp.dev.ini
kiremitrov123 Sep 19, 2024
557f2e5
fix: add Mock for Access controller in cinema test
kiremitrov123 Sep 19, 2024
783525b
Merge branch 'develop' into IDM-174/use-passport
kiremitrov123 Sep 19, 2024
cd8a277
fix: rerun jwp entitlement endpoint upon login or register
mirovladimitrovski Sep 19, 2024
35062c4
feat(project): merge with develop
kiremitrov123 Sep 19, 2024
bfdc07c
Merge branch 'IDM-174/use-passport' of https://github.com/jwplayer/ot…
kiremitrov123 Sep 19, 2024
7f91564
Merge branch 'develop' into IDM-174/use-passport
kiremitrov123 Sep 19, 2024
392ee47
fix: make language as optional, to fix lint
kiremitrov123 Sep 19, 2024
ac1a09e
Merge branch 'develop' into IDM-174/use-passport
kiremitrov123 Sep 19, 2024
ab6b59d
feat(project): merge with use passport branch
kiremitrov123 Sep 19, 2024
4c87927
Merge branch 'PS-290-new-payment-flow' of https://github.com/jwplayer…
kiremitrov123 Sep 19, 2024
8524e0c
feat(project): move entitled plans to the account controller
kiremitrov123 Sep 20, 2024
e777bd1
Merge branch 'IDM-174/use-passport' of https://github.com/jwplayer/ot…
kiremitrov123 Sep 20, 2024
57d00be
Merge branch 'PS-290-new-payment-flow' of https://github.com/jwplayer…
kiremitrov123 Sep 20, 2024
3aea37c
feat(project): load entitled plan from store
kiremitrov123 Sep 20, 2024
61a1b42
fix: improve an e2e test by waiting for a loader to finish to decreas…
mirovladimitrovski Sep 20, 2024
9378ee9
fix: increase wait time
mirovladimitrovski Sep 20, 2024
6692c93
fix: feedback from comments
mirovladimitrovski Sep 20, 2024
656fcac
fix: replace access method logic with access bridge one
mirovladimitrovski Sep 20, 2024
5cc2013
fix: revert all changes in useEntitlement hook
mirovladimitrovski Sep 20, 2024
169a332
feat(project): refactor usage of entitled plans and access
kiremitrov123 Sep 20, 2024
c5a30f9
chore: merge with new payment flow
kiremitrov123 Sep 20, 2024
ce8c361
feat(project): decouple payment service from checkout and jwp api ser…
kiremitrov123 Sep 23, 2024
69453b7
Merge branch 'develop' of https://github.com/jwplayer/ott-web-app int…
kiremitrov123 Sep 23, 2024
285ed31
Merge branch 'IDM-174/use-passport' of https://github.com/jwplayer/ot…
kiremitrov123 Sep 23, 2024
a56b699
chore: revert envs
kiremitrov123 Sep 23, 2024
e9f56da
OWA-84: Stripe external link to billing portal (#596)
mirovladimitrovski Sep 23, 2024
ec61a8f
Merge branch 'develop' of https://github.com/jwplayer/ott-web-app int…
kiremitrov123 Sep 25, 2024
a3b6c71
fix: tackle pr comments and revert some incorrect changes
mirovladimitrovski Sep 26, 2024
0f0ab49
Merge branch 'develop' into PS-290-new-payment-flow
mirovladimitrovski Sep 26, 2024
aa4d71e
Merge branch 'develop' into PS-290-new-payment-flow
kiremitrov123 Sep 26, 2024
679d348
fix: disable jwp test suites altogether and display loading state in …
mirovladimitrovski Sep 27, 2024
986e1c1
Update packages/ui-react/src/components/PaymentSuccessful/PaymentSucc…
mirovladimitrovski Sep 27, 2024
637748a
fix: address comments
mirovladimitrovski Sep 27, 2024
1d94467
fix: more comments addressed
mirovladimitrovski Sep 27, 2024
1451204
fix: improvement on existing piece of code
mirovladimitrovski Sep 27, 2024
727715c
fix: add missing content type header in billing url
kiremitrov123 Oct 14, 2024
ed6d9dc
Merge branch 'develop' of https://github.com/jwplayer/ott-web-app int…
kiremitrov123 Oct 14, 2024
6aa1b5d
Merge branch 'develop' into PS-290-new-payment-flow
mirovladimitrovski Nov 11, 2024
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
1 change: 0 additions & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"test-watch": "TZ=UTC LC_ALL=en_US.UTF-8 vitest"
},
"dependencies": {
"@inplayer-org/inplayer.js": "^3.13.28",
"broadcast-channel": "^7.0.0",
"date-fns": "^3.6.0",
"fast-xml-parser": "^4.5.0",
Expand Down
35 changes: 19 additions & 16 deletions packages/common/src/controllers/AccessController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { useConfigStore } from '../stores/ConfigStore';
import { INTEGRATION_TYPE } from '../modules/types';
import { getNamedModule } from '../modules/container';
import { useAccountStore } from '../stores/AccountStore';
import { ApiError } from '../utils/api';
import { useAccessStore } from '../stores/AccessStore';

const ACCESS_TOKENS = 'access_tokens';
Expand Down Expand Up @@ -53,7 +52,7 @@ export default class AccessController {
/**
* Retrieves media by its ID using a passport token.
* If no access tokens exist, it attempts to generate them, if the passport token is expired, it attempts to refresh them.
* If an access token retrieval fails or the user is not entitled to the content, an error is thrown.
* If the passport is not accepted, tries to generate new access tokens to get the latest entitled plans.
*/
getMediaById = async (mediaId: string) => {
const { entitledPlan } = useAccountStore.getState();
Expand All @@ -62,23 +61,27 @@ export default class AccessController {
return;
}

try {
const accessTokens = await this.generateOrRefreshAccessTokens();
const getMediaWithPassport = async (forceGenerate: boolean = false) => {
const accessTokens = forceGenerate ? await this.generateAccessTokens() : await this.generateOrRefreshAccessTokens();
if (!accessTokens?.passport) {
throw new Error('Failed to get / generate access tokens and retrieve media.');
throw new Error('Failed to generate / refresh access tokens.');
}
return await this.apiService.getMediaByIdWithPassport({ id: mediaId, siteId: this.siteId, planId: entitledPlan.id, passport: accessTokens.passport });

return await this.apiService.getMediaByIdWithPassport({
id: mediaId,
siteId: this.siteId,
planId: entitledPlan.id,
passport: accessTokens.passport,
});
};

try {
return await getMediaWithPassport();
} catch (error: unknown) {
if (error instanceof ApiError && error.code === 403) {
// If the passport is invalid or expired, refresh the access tokens and try to get the media again.
const accessTokens = await this.refreshAccessTokens();
if (accessTokens?.passport) {
return await this.apiService.getMediaByIdWithPassport({ id: mediaId, siteId: this.siteId, planId: entitledPlan.id, passport: accessTokens.passport });
}

throw new Error('Failed to refresh access tokens and retrieve media.');
}
throw error;
// If the initial attempt fails, it may indicate the passport does not have the latest plans.
// Force new access tokens generation and retry fetching the media.
AntonLantukh marked this conversation as resolved.
Show resolved Hide resolved
// TODO: Revisit this logic once we address the passport update possibility in Q4
AntonLantukh marked this conversation as resolved.
Show resolved Hide resolved
return await getMediaWithPassport(true);
}
};

Expand Down
28 changes: 9 additions & 19 deletions packages/common/src/controllers/AccountController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,7 @@ import SubscriptionService from '../services/integrations/SubscriptionService';
import JWPEntitlementService from '../services/JWPEntitlementService';
import type { Offer } from '../../types/checkout';
import type { Plan } from '../../types/plans';
import type {
Capture,
Customer,
CustomerConsent,
EmailConfirmPasswordInput,
FirstLastNameInput,
GetCaptureStatusResponse,
SubscribeToNotificationsPayload,
} from '../../types/account';
import type { Capture, Customer, CustomerConsent, EmailConfirmPasswordInput, FirstLastNameInput, GetCaptureStatusResponse } from '../../types/account';
import { assertFeature, assertModuleMethod, getModule, getNamedModule } from '../modules/container';
import { INTEGRATION_TYPE } from '../modules/types';
import type { ServiceResponse } from '../../types/service';
Expand Down Expand Up @@ -92,8 +84,8 @@ export default class AccountController {
// set the accessModel before restoring the user session
useConfigStore.setState({ accessModel: this.accountService.accessModel });

await this.loadUserData();
await this.getEntitledPlans();
await this.loadUserData();

useAccountStore.setState({ loading: false });
};
Expand Down Expand Up @@ -173,6 +165,7 @@ export default class AccountController {

if (response) {
await this.accessController?.generateAccessTokens();
await this.getEntitledPlans();
AntonLantukh marked this conversation as resolved.
Show resolved Hide resolved
await this.afterLogin(response.user, response.customerConsents);
return;
}
Expand Down Expand Up @@ -203,6 +196,8 @@ export default class AccountController {

if (response) {
const { user, customerConsents } = response;
await this.accessController?.generateAccessTokens();
await this.getEntitledPlans();
AntonLantukh marked this conversation as resolved.
Show resolved Hide resolved
await this.afterLogin(user, customerConsents, true);

return;
Expand Down Expand Up @@ -395,15 +390,14 @@ export default class AccountController {
// TODO: Support for multiple plans should be added. Revisit this logic once the dependency on plan_id is changed.
getEntitledPlans = async (): Promise<Plan | null> => {
const { config, settings } = useConfigStore.getState();
const siteId = config.siteId;
const isAccessBridgeEnabled = !!settings?.apiAccessBridgeUrl;

// This should be only used when access bridge is defined, regardless of the integration type.
// This should be only available when access bridge is defined, regardless of the integration type.
if (!isAccessBridgeEnabled) {
return null;
}

const response = await this.entitlementService.getEntitledPlans({ siteId });
const response = await this.entitlementService.getEntitledPlans({ siteId: config.siteId });
if (response?.plans?.length) {
// Find the SVOD plan or fallback to the first available plan
const entitledPlan = response.plans.find((plan) => plan.metadata.access_model === 'svod') || response.plans[0];
Expand All @@ -422,7 +416,7 @@ export default class AccountController {
): Promise<unknown> => {
useAccountStore.setState({ loading: true });

const { getAccountInfo } = useAccountStore.getState();
const { getAccountInfo, entitledPlan } = useAccountStore.getState();
const { customerId } = getAccountInfo();
const { accessModel } = useConfigStore.getState();

Expand All @@ -444,7 +438,7 @@ export default class AccountController {
}

const [activeSubscription, transactions, activePayment] = await Promise.all([
this.subscriptionService.getActiveSubscription({ customerId }),
this.subscriptionService.getActiveSubscription({ customerId, entitledPlan }),
this.subscriptionService.getAllTransactions({ customerId }),
this.subscriptionService.getActivePayment({ customerId }),
]);
Expand Down Expand Up @@ -533,10 +527,6 @@ export default class AccountController {
return this.accountService.getAuthData();
};

subscribeToNotifications = async ({ uuid, onMessage }: SubscribeToNotificationsPayload) => {
return this.accountService.subscribeToNotifications({ uuid, onMessage });
};

getFeatures() {
return this.features;
}
Expand Down
20 changes: 18 additions & 2 deletions packages/common/src/controllers/CheckoutController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { useAccountStore } from '../stores/AccountStore';
import { FormValidationError } from '../errors/FormValidationError';
import { determineSwitchDirection } from '../utils/subscription';
import { findDefaultCardMethodId } from '../utils/payments';
import { useConfigStore } from '../stores/ConfigStore';

@injectable()
export default class CheckoutController {
Expand Down Expand Up @@ -62,8 +63,10 @@ export default class CheckoutController {

getSubscriptionOfferIds = () => this.accountService.svodOfferIds;

chooseOffer = async (selectedOffer: Offer) => {
useCheckoutStore.setState({ selectedOffer });
chooseOffer = async (params: { offer: Offer; successUrl: string; cancelUrl: string }) => {
useCheckoutStore.setState({ selectedOffer: params.offer });

return this.checkoutService.chooseOffer(params);
};

initialiseOrder = async (offer: Offer): Promise<void> => {
Expand Down Expand Up @@ -349,6 +352,19 @@ export default class CheckoutController {
return response.responseData;
};

generateBillingPortalUrl = async (returnUrl: string) => {
assertModuleMethod(this.checkoutService.generateBillingPortalUrl, 'generateBillingPortalUrl is not available in checkout service');

// This method should only be available when Access Bridge is being used, regardless of the integration type.
const { settings } = useConfigStore.getState();
const isAccessBridgeEnabled = !!settings?.apiAccessBridgeUrl;
if (!isAccessBridgeEnabled) {
return null;
}

return this.checkoutService.generateBillingPortalUrl(returnUrl);
};

getOffers: GetOffers = (payload) => {
return this.checkoutService.getOffers(payload);
};
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/modules/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import JWPEntitlementService from '../services/JWPEntitlementService';
import FavoriteService from '../services/FavoriteService';
import ConfigService from '../services/ConfigService';
import SettingsService from '../services/SettingsService';
import PaymentService from '../services/PaymentService';

import WatchHistoryController from '../controllers/WatchHistoryController';
import CheckoutController from '../controllers/CheckoutController';
Expand Down Expand Up @@ -57,6 +58,7 @@ container.bind(GenericEntitlementService).toSelf();
container.bind(ApiService).toSelf();
container.bind(SettingsService).toSelf();
container.bind(AccessService).toSelf();
container.bind(PaymentService).toSelf();

// Common controllers
container.bind(AppController).toSelf();
Expand Down
2 changes: 2 additions & 0 deletions packages/common/src/paths.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ export const PATH_USER = `${PATH_USER_BASE}/*`;
export const RELATIVE_PATH_USER_ACCOUNT = 'my-account';
export const RELATIVE_PATH_USER_FAVORITES = 'favorites';
export const RELATIVE_PATH_USER_PAYMENTS = 'payments';
export const RELATIVE_PATH_USER_SUBSCRIPTION = 'subscription';

export const PATH_USER_ACCOUNT = `${PATH_USER_BASE}/${RELATIVE_PATH_USER_ACCOUNT}`;
export const PATH_USER_FAVORITES = `${PATH_USER_BASE}/${RELATIVE_PATH_USER_FAVORITES}`;
export const PATH_USER_PAYMENTS = `${PATH_USER_BASE}/${RELATIVE_PATH_USER_PAYMENTS}`;
export const PATH_USER_SUBSCRIPTIONS = `${PATH_USER_BASE}/${RELATIVE_PATH_USER_SUBSCRIPTION}`;
93 changes: 93 additions & 0 deletions packages/common/src/services/PaymentService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { inject, injectable } from 'inversify';

import { API_ACCESS_BRIDGE_URL, INTEGRATION_TYPE } from '../modules/types';
import type { IntegrationType } from '../../types/config';
import type { Product } from '../../types/payment';
import { logError } from '../logger';
import { getNamedModule } from '../modules/container';

import AccountService from './integrations/AccountService';

@injectable()
export default class PaymentService {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be renamed 🤔? This is actually the AccessBridgeService integration and not a payment service. It might be confusing with the CheckoutService.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Access related methods are in the AccessService, these are the payment related definitions that will be the one source of truth hopefully :D. It is confirmed with @dbudzins for the naming.

private readonly apiAccessBridgeUrl;
private readonly accountService;

private siteId: string = '';

constructor(@inject(API_ACCESS_BRIDGE_URL) apiAccessBridgeUrl: string, @inject(INTEGRATION_TYPE) integrationType: IntegrationType) {
this.apiAccessBridgeUrl = apiAccessBridgeUrl;
this.accountService = getNamedModule(AccountService, integrationType);
}

initialize = async (siteId: string) => {
this.siteId = siteId;
};

getProducts = async (): Promise<Product[]> => {
const url = `${this.apiAccessBridgeUrl}/v2/sites/${this.siteId}/products`;
const response = await fetch(url);

if (!response.ok) {
logError('PaymentService', 'Failed to fetch products.', {
status: response.status,
error: response.json(),
});

return [];
}

return (await response.json()) as Product[];
};

generateCheckoutSessionUrl = async (priceId: string, successUrl: string, cancelUrl: string): Promise<{ url: string | null }> => {
const auth = await this.accountService.getAuthData();

const url = `${this.apiAccessBridgeUrl}/v2/sites/${this.siteId}/checkout`;
const response = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${auth?.jwt}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
price_id: priceId,
success_url: successUrl,
cancel_url: cancelUrl,
}),
});

if (!response.ok) {
logError('PaymentService', `Failed to generate checkout URL. Status: ${response.status}`);
return { url: null };
}

return (await response.json()) as { url: string };
};

generateBillingPortalUrl = async (returnUrl: string): Promise<{ url: string | null }> => {
const auth = await this.accountService.getAuthData();

const url = `${this.apiAccessBridgeUrl}/v2/sites/${this.siteId}/billing-portal`;
const response = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${auth?.jwt}`,
},
body: JSON.stringify({
return_url: returnUrl,
}),
});

if (!response.ok) {
logError('PaymentService', 'Failed to generate billing portal url.', {
status: response.status,
error: response.json(),
});

return { url: null };
}

return (await response.json()) as { url: string };
};
}
3 changes: 0 additions & 3 deletions packages/common/src/services/integrations/AccountService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import type {
GetCustomerConsents,
GetPublisherConsents,
Login,
NotificationsData,
Register,
ResetPassword,
GetSocialURLs,
Expand Down Expand Up @@ -87,8 +86,6 @@ export default abstract class AccountService {

abstract getFavorites: GetFavorites;

abstract subscribeToNotifications: NotificationsData;

abstract getSocialUrls?: GetSocialURLs;

abstract exportAccountData?: ExportAccountData;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {
AddAdyenPaymentDetails,
ChooseOffer,
CreateOrder,
DeletePaymentMethod,
FinalizeAdyenPaymentDetails,
Expand All @@ -19,9 +20,12 @@ import type {
SwitchSubscription,
UpdateOrder,
UpdatePaymentWithPayPal,
GenerateBillingPortalURL,
} from '../../../types/checkout';

export default abstract class CheckoutService {
abstract initializePaymentService: () => void;

abstract getOffers: GetOffers;

abstract createOrder: CreateOrder;
Expand All @@ -38,6 +42,8 @@ export default abstract class CheckoutService {

abstract directPostCardPayment: GetDirectPostCardPayment;

abstract chooseOffer: ChooseOffer;

abstract getOffer?: GetOffer;

abstract getOrder?: GetOrder;
Expand All @@ -61,4 +67,6 @@ export default abstract class CheckoutService {
abstract addAdyenPaymentDetails?: AddAdyenPaymentDetails;

abstract finalizeAdyenPaymentDetails?: FinalizeAdyenPaymentDetails;

abstract generateBillingPortalUrl?: GenerateBillingPortalURL;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import type {
JwtDetails,
Login,
LoginPayload,
NotificationsData,
Register,
RegisterPayload,
ResetPassword,
Expand Down Expand Up @@ -344,10 +343,6 @@ export default class CleengAccountService extends AccountService {
return (this.externalData['favorites'] || []) as SerializedFavorite[];
};

subscribeToNotifications: NotificationsData = async () => {
return false;
};

getSocialUrls: undefined;

exportAccountData: undefined;
Expand Down
Loading
Loading