Support paypal details for subscription in admin panel

This commit is contained in:
Phillip Thelen
2025-08-11 16:50:30 +02:00
parent 71c2e19330
commit ba99a65bd4
3 changed files with 63 additions and 2 deletions

View File

@@ -450,7 +450,7 @@
<strong class="col-sm-9 col-form-label">
<span v-if="value === true">Yes</span>
<span v-else-if="value === false">No</span>
<span v-else-if="isDate(value)"
<span v-else-if="value instanceof String && isDate(value)"
v-b-tooltip.hover="value">
{{ formatDate(value) }}
</span>
@@ -467,6 +467,13 @@
:href="playOrdersUrl">
Play Console
</a>
<a
v-else-if="hero.purchased.plan.paymentMethod === 'Paypal'"
class="btn btn-primary btn-sm"
target="_blank"
:href="'https://www.paypal.com/billing/subscriptions/' + paymentDetails.customerId">
PayPal Dashboard
</a>
</div>
</div>
</div>
@@ -605,6 +612,14 @@ const humandReadablePaymentDetails = {
label: 'Next Payment Date',
help: 'The date when the next payment is due. If the subscription is canceled or expired, this may be null.',
},
lastPaymentDate: {
label: 'Last Payment Date',
help: 'The date when the lastpayment was made for the subscription.',
},
failedPayments: {
label: 'Failed Payments',
help: 'Number of times the payment failed for this subscription.',
},
}
export default {

View File

@@ -11,6 +11,7 @@ import {
} from '../../libs/errors';
import apple from '../../libs/payments/apple';
import google from '../../libs/payments/google';
import paypal from '../../libs/payments/paypal';
const api = {};
@@ -218,7 +219,7 @@ api.validateSubscriptionPaymentDetails = {
} else if (user.purchased.plan.paymentMethod === 'Google') {
paymentDetails = await google.getSubscriptionPaymentDetails(userId, user.purchased.plan);
} else if (user.purchased.plan.paymentMethod === 'Paypal') {
throw new NotFound(res.t('paypalSubscriptionNotValidated'));
paymentDetails = await paypal.getSubscriptionPaymentDetails({ user });
} else if (user.purchased.plan.paymentMethod === 'Stripe') {
throw new NotFound(res.t('stripeSubscriptionNotValidated'));
} else if (user.purchased.plan.paymentMethod === 'Amazon Payments') {

View File

@@ -223,6 +223,51 @@ api.subscribeSuccess = async function subscribeSuccess (options = {}) {
});
};
api.getSubscriptionPaymentDetails = async function getSubscriptionPaymentDetails (options = {}) {
const { user, groupId } = options;
let customerId;
if (groupId) {
const groupFields = basicGroupFields.concat(' purchased');
const group = await Group.getGroup({
user, groupId, populateLeader: false, groupFields,
});
if (!group) {
throw new NotFound(i18n.t('groupNotFound'));
}
if (group.leader !== user._id) {
throw new NotAuthorized(i18n.t('onlyGroupLeaderCanManageSubscription'));
}
customerId = group.purchased.plan.customerId;
} else {
customerId = user.purchased.plan.customerId;
}
if (!customerId) throw new NotAuthorized(i18n.t('missingSubscription'));
const customer = await this.paypalBillingAgreementGet(customerId);
if (!customer) throw new NotFound(i18n.t('subscriptionNotFound'));
console.log('PayPal subscription details:', customer);
return {
customerId: customer.id,
originalPurchaseDate: customer.start_date,
expirationDate: customer.agreement_details.ended_at
? customer.agreement_details.ended_at
: null,
nextPaymentDate: customer.agreement_details.next_billing_date
? customer.agreement_details.next_billing_date
: null,
lastPaymentDate: customer.agreement_details.last_payment_date
? customer.agreement_details.last_payment_date
: null,
productId: customer.description,
transactionId: customer.id,
isCanceled: customer.agreement_details.state === 'Inactive',
failedPayments: customer.agreement_details.failed_payment_count,
};
};
/**
* Cancel a PayPal Subscription
*