MOBILE-3974 paypal: Open paypal enrol in browser

main
Dani Palou 2022-02-02 08:46:37 +01:00
parent 4df8dc3c64
commit ee83bfbf99
7 changed files with 53 additions and 66 deletions

View File

@ -1579,8 +1579,10 @@
"core.courses.aria:courseprogress": "block_myoverview", "core.courses.aria:courseprogress": "block_myoverview",
"core.courses.aria:favourite": "course", "core.courses.aria:favourite": "course",
"core.courses.availablecourses": "moodle", "core.courses.availablecourses": "moodle",
"core.courses.browserenrolinstructions": "local_moodlemobileapp",
"core.courses.cannotretrievemorecategories": "local_moodlemobileapp", "core.courses.cannotretrievemorecategories": "local_moodlemobileapp",
"core.courses.categories": "moodle", "core.courses.categories": "moodle",
"core.courses.completeenrolmentbrowser": "local_moodlemobileapp",
"core.courses.confirmselfenrol": "local_moodlemobileapp", "core.courses.confirmselfenrol": "local_moodlemobileapp",
"core.courses.courses": "moodle", "core.courses.courses": "moodle",
"core.courses.downloadcourses": "local_moodlemobileapp", "core.courses.downloadcourses": "local_moodlemobileapp",
@ -1602,9 +1604,9 @@
"core.courses.nosearchresults": "wiki", "core.courses.nosearchresults": "wiki",
"core.courses.notenroled": "completion", "core.courses.notenroled": "completion",
"core.courses.notenrollable": "local_moodlemobileapp", "core.courses.notenrollable": "local_moodlemobileapp",
"core.courses.otherenrolments": "local_moodlemobileapp",
"core.courses.password": "local_moodlemobileapp", "core.courses.password": "local_moodlemobileapp",
"core.courses.paymentrequired": "moodle", "core.courses.paymentrequired": "moodle",
"core.courses.paypalaccepted": "enrol_paypal",
"core.courses.refreshcourses": "local_moodlemobileapp", "core.courses.refreshcourses": "local_moodlemobileapp",
"core.courses.reload": "moodle", "core.courses.reload": "moodle",
"core.courses.removefromfavourites": "block_myoverview", "core.courses.removefromfavourites": "block_myoverview",
@ -1612,7 +1614,6 @@
"core.courses.searchcourses": "moodle", "core.courses.searchcourses": "moodle",
"core.courses.searchcoursesadvice": "local_moodlemobileapp", "core.courses.searchcoursesadvice": "local_moodlemobileapp",
"core.courses.selfenrolment": "local_moodlemobileapp", "core.courses.selfenrolment": "local_moodlemobileapp",
"core.courses.sendpaymentbutton": "enrol_paypal",
"core.courses.show": "block_myoverview", "core.courses.show": "block_myoverview",
"core.courses.showonlyenrolled": "local_moodlemobileapp", "core.courses.showonlyenrolled": "local_moodlemobileapp",
"core.courses.therearecourses": "moodle", "core.courses.therearecourses": "moodle",
@ -2073,7 +2074,6 @@
"core.othergroups": "group", "core.othergroups": "group",
"core.pagea": "moodle", "core.pagea": "moodle",
"core.parentlanguage": "langconfig", "core.parentlanguage": "langconfig",
"core.paymentinstant": "moodle",
"core.percentagenumber": "local_moodlemobileapp", "core.percentagenumber": "local_moodlemobileapp",
"core.phone": "moodle", "core.phone": "moodle",
"core.pictureof": "moodle", "core.pictureof": "moodle",
@ -2339,8 +2339,8 @@
"core.user.webpage": "moodle", "core.user.webpage": "moodle",
"core.userdeleted": "moodle", "core.userdeleted": "moodle",
"core.userdetails": "moodle", "core.userdetails": "moodle",
"core.usernotfullysetup": "error",
"core.usernologin": "local_moodlemobileapp", "core.usernologin": "local_moodlemobileapp",
"core.usernotfullysetup": "error",
"core.users": "moodle", "core.users": "moodle",
"core.usersuspended": "tool_reportbuilder", "core.usersuspended": "tool_reportbuilder",
"core.view": "moodle", "core.view": "moodle",

View File

@ -100,10 +100,9 @@
</ion-item> </ion-item>
<ion-item class="ion-text-wrap" *ngIf="paypalEnabled"> <ion-item class="ion-text-wrap" *ngIf="paypalEnabled">
<ion-label> <ion-label>
<p class="item-heading">{{ 'core.courses.paypalaccepted' | translate }}</p> <p class="item-heading">{{ 'core.courses.otherenrolments' | translate }}</p>
<p *ngIf="isMobile">{{ 'core.paymentinstant' | translate }}</p> <ion-button expand="block" class="ion-margin-top" (click)="browserEnrol()">
<ion-button *ngIf="isMobile" expand="block" class="ion-margin-top" (click)="paypalEnrol()"> {{ 'core.courses.completeenrolmentbrowser' | translate }}
{{ 'core.courses.sendpaymentbutton' | translate }}
</ion-button> </ion-button>
</ion-label> </ion-label>
</ion-item> </ion-item>

View File

@ -12,9 +12,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { Component, OnDestroy, NgZone, OnInit } from '@angular/core'; import { Component, OnDestroy, OnInit } from '@angular/core';
import { IonRefresher } from '@ionic/angular'; import { IonRefresher } from '@ionic/angular';
import { CoreApp } from '@services/app';
import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
@ -30,12 +29,13 @@ import {
import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate'; import { CoreCourseOptionsDelegate } from '@features/course/services/course-options-delegate';
import { CoreCourse, CoreCourseProvider } from '@features/course/services/course'; import { CoreCourse, CoreCourseProvider } from '@features/course/services/course';
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper'; import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
import { Translate } from '@singletons'; import { NgZone, Platform, Translate } from '@singletons';
import { CoreConstants } from '@/core/constants'; import { CoreConstants } from '@/core/constants';
import { CoreCoursesSelfEnrolPasswordComponent } from '../../../courses/components/self-enrol-password/self-enrol-password'; import { CoreCoursesSelfEnrolPasswordComponent } from '../../../courses/components/self-enrol-password/self-enrol-password';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { CoreCourseWithImageAndColor } from '@features/courses/services/courses-helper'; import { CoreCourseWithImageAndColor } from '@features/courses/services/courses-helper';
import { Subscription } from 'rxjs';
/** /**
* Page that allows "previewing" a course and enrolling in it if enabled and not enrolled. * Page that allows "previewing" a course and enrolling in it if enabled and not enrolled.
@ -66,7 +66,6 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
downloadCourseEnabled: boolean; downloadCourseEnabled: boolean;
courseUrl = ''; courseUrl = '';
courseImageUrl?: string; courseImageUrl?: string;
isMobile: boolean;
progress?: number; progress?: number;
protected isGuestEnabled = false; protected isGuestEnabled = false;
@ -75,15 +74,13 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
protected enrolmentMethods: CoreCourseEnrolmentMethod[] = []; protected enrolmentMethods: CoreCourseEnrolmentMethod[] = [];
protected waitStart = 0; protected waitStart = 0;
protected enrolUrl = ''; protected enrolUrl = '';
protected paypalReturnUrl = '';
protected pageDestroyed = false; protected pageDestroyed = false;
protected courseStatusObserver?: CoreEventObserver; protected courseStatusObserver?: CoreEventObserver;
protected courseId!: number; protected courseId!: number;
protected appResumeSubscription: Subscription;
protected waitingForBrowserEnrol = false;
constructor( constructor() {
protected zone: NgZone,
) {
this.isMobile = CoreApp.isMobile();
this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite(); this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite();
if (this.downloadCourseEnabled) { if (this.downloadCourseEnabled) {
@ -94,6 +91,20 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
} }
}, CoreSites.getCurrentSiteId()); }, CoreSites.getCurrentSiteId());
} }
// Refresh the view when the app is resumed.
this.appResumeSubscription = Platform.resume.subscribe(() => {
if (!this.waitingForBrowserEnrol || !this.dataLoaded) {
return;
}
NgZone.run(async () => {
this.waitingForBrowserEnrol = false;
this.dataLoaded = false;
await this.refreshData();
});
});
} }
/** /**
@ -115,7 +126,6 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
const currentSiteUrl = CoreSites.getRequiredCurrentSite().getURL(); const currentSiteUrl = CoreSites.getRequiredCurrentSite().getURL();
this.enrolUrl = CoreTextUtils.concatenatePaths(currentSiteUrl, 'enrol/index.php?id=' + this.courseId); this.enrolUrl = CoreTextUtils.concatenatePaths(currentSiteUrl, 'enrol/index.php?id=' + this.courseId);
this.courseUrl = CoreTextUtils.concatenatePaths(currentSiteUrl, 'course/view.php?id=' + this.courseId); this.courseUrl = CoreTextUtils.concatenatePaths(currentSiteUrl, 'course/view.php?id=' + this.courseId);
this.paypalReturnUrl = CoreTextUtils.concatenatePaths(currentSiteUrl, 'enrol/paypal/return.php');
try { try {
await this.getCourse(); await this.getCourse();
@ -269,53 +279,30 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
} }
/** /**
* Enrol using PayPal. * Enrol in browser.
*/ */
async paypalEnrol(): Promise<void> { async browserEnrol(): Promise<void> {
// We cannot control browser in browser. // Send user to browser to enrol. Warn the user first.
if (!this.isMobile || !CoreSites.getCurrentSite()) { try {
await CoreDomUtils.showConfirm(
Translate.instant('core.courses.browserenrolinstructions'),
undefined,
Translate.instant('core.openinbrowser'),
);
} catch {
// User canceled.
return; return;
} }
let hasReturnedFromPaypal = false; this.waitingForBrowserEnrol = true;
const urlLoaded = (event: InAppBrowserEvent): void => { await CoreSites.getRequiredCurrentSite().openInBrowserWithAutoLogin(
if (event.url.indexOf(this.paypalReturnUrl) != -1) { this.enrolUrl,
hasReturnedFromPaypal = true; undefined,
} else if (event.url.indexOf(this.courseUrl) != -1 && hasReturnedFromPaypal) { {
// User reached the course index page after returning from PayPal, close the InAppBrowser. showBrowserWarning: false,
inAppClosed(); },
window.close(); );
}
};
const inAppClosed = (): void => {
// InAppBrowser closed, refresh data.
unsubscribeAll();
if (!this.dataLoaded) {
return;
}
this.dataLoaded = false;
this.refreshData();
};
const unsubscribeAll = (): void => {
inAppLoadSubscription?.unsubscribe();
inAppExitSubscription?.unsubscribe();
};
// Open the enrolment page in InAppBrowser.
const window = await CoreSites.getRequiredCurrentSite().openInAppWithAutoLogin(this.enrolUrl);
// Observe loaded pages in the InAppBrowser to check if the enrol process has ended.
const inAppLoadSubscription = window.on('loadstart').subscribe((event) => {
// Execute the callback in the Angular zone, so change detection doesn't stop working.
this.zone.run(() => urlLoaded(event));
});
// Observe window closed.
const inAppExitSubscription = window.on('exit').subscribe(() => {
// Execute the callback in the Angular zone, so change detection doesn't stop working.
this.zone.run(inAppClosed);
});
} }
/** /**
@ -486,6 +473,7 @@ export class CoreCoursePreviewPage implements OnInit, OnDestroy {
ngOnDestroy(): void { ngOnDestroy(): void {
this.pageDestroyed = true; this.pageDestroyed = true;
this.courseStatusObserver?.off(); this.courseStatusObserver?.off();
this.appResumeSubscription.unsubscribe();
} }
} }

View File

@ -134,7 +134,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
}); });
} else if (instance === 'paypal') { } else if (instance === 'paypal') {
this.enrolmentIcons.push({ this.enrolmentIcons.push({
label: 'core.courses.paypalaccepted', label: 'core.courses.otherenrolments',
icon: 'fab-paypal', icon: 'fab-paypal',
}); });
} }

View File

@ -6,8 +6,10 @@
"aria:courseprogress": "Course progress:", "aria:courseprogress": "Course progress:",
"aria:favourite": "Course is starred", "aria:favourite": "Course is starred",
"availablecourses": "Available courses", "availablecourses": "Available courses",
"browserenrolinstructions": "We will take you to your device's browser. Once you have completed your enrolment, please come back to this app.",
"cannotretrievemorecategories": "Categories deeper than level {{$a}} cannot be retrieved.", "cannotretrievemorecategories": "Categories deeper than level {{$a}} cannot be retrieved.",
"categories": "Course categories", "categories": "Course categories",
"completeenrolmentbrowser": "Complete enrolment in browser",
"confirmselfenrol": "Are you sure you want to enrol yourself in this course?", "confirmselfenrol": "Are you sure you want to enrol yourself in this course?",
"courses": "Courses", "courses": "Courses",
"downloadcourses": "Download courses", "downloadcourses": "Download courses",
@ -29,9 +31,9 @@
"nosearchresults": "No results", "nosearchresults": "No results",
"notenroled": "You are not enrolled in this course", "notenroled": "You are not enrolled in this course",
"notenrollable": "You cannot enrol yourself in this course.", "notenrollable": "You cannot enrol yourself in this course.",
"otherenrolments": "Other enrolments",
"password": "Enrolment key", "password": "Enrolment key",
"paymentrequired": "This course requires a payment for entry.", "paymentrequired": "This course requires a payment for entry.",
"paypalaccepted": "PayPal payments accepted",
"refreshcourses": "Refresh courses", "refreshcourses": "Refresh courses",
"reload": "Reload", "reload": "Reload",
"removefromfavourites": "Unstar this course", "removefromfavourites": "Unstar this course",
@ -39,7 +41,6 @@
"searchcourses": "Search courses", "searchcourses": "Search courses",
"searchcoursesadvice": "You can use the search courses button to find courses to access as a guest or enrol yourself in courses that allow it.", "searchcoursesadvice": "You can use the search courses button to find courses to access as a guest or enrol yourself in courses that allow it.",
"selfenrolment": "Self enrolment", "selfenrolment": "Self enrolment",
"sendpaymentbutton": "Send payment via PayPal",
"show": "Unarchive", "show": "Unarchive",
"showonlyenrolled": "Show only my courses", "showonlyenrolled": "Show only my courses",
"therearecourses": "There are {{$a}} courses", "therearecourses": "There are {{$a}} courses",

View File

@ -228,7 +228,6 @@
"othergroups": "Other groups", "othergroups": "Other groups",
"pagea": "Page {{$a}}", "pagea": "Page {{$a}}",
"parentlanguage": "", "parentlanguage": "",
"paymentinstant": "Use the button below to pay and be enrolled within minutes!",
"percentagenumber": "{{$a}}%", "percentagenumber": "{{$a}}%",
"phone": "Phone", "phone": "Phone",
"pictureof": "Picture of {{$a}}", "pictureof": "Picture of {{$a}}",

View File

@ -1225,10 +1225,10 @@ export class CoreDomUtilsProvider {
if (options.buttons) { if (options.buttons) {
// Execute dismiss function if any. // Execute dismiss function if any.
const cancelButton = <AlertButton> options.buttons.find( const cancelButton = <AlertButton | undefined> options.buttons.find(
(button) => typeof button != 'string' && button.handler !== undefined && button.role == 'cancel', (button) => typeof button != 'string' && button.handler !== undefined && button.role == 'cancel',
); );
cancelButton.handler?.(null); cancelButton?.handler?.(null);
} }
}, autocloseTime); }, autocloseTime);
} }