Consolidate subscription setup payment intent checking and initial activation when applicable #799

This commit is contained in:
Ramon Gutierrez 2024-08-26 08:01:00 +08:00
parent 40c629eee3
commit 1fd883b07b
6 changed files with 111 additions and 11 deletions

View file

@ -336,7 +336,17 @@ apiv2_subscription_create:
controller: App\Controller\CustomerAppAPI\SubscriptionController::createSubscription
methods: [POST]
apiv2_subscription_payment_intent:
path: /apiv2/subscription/payment_intent/{pid}
controller: App\Controller\CustomerAppAPI\SubscriptionController::getPaymentIntent
apiv2_subscription_finalize:
path: /apiv2/subscription/{id}/finalize
controller: App\Controller\CustomerAppAPI\SubscriptionController::finalizeSubscription
methods: [GET]
#apiv2_subscription_payment_intent:
# path: /apiv2/subscription/payment_intent/{pi_id}
# controller: App\Controller\CustomerAppAPI\SubscriptionController::getPaymentIntent
# methods: [GET]
#apiv2_subscription_activate:
# path: /apiv2/subscription/{id}/activate
# controller: App\Controller\CustomerAppAPI\SubscriptionController::activateSubscription
# methods: [POST]

View file

@ -23,6 +23,7 @@ parameters:
subscription_paymongo_public_key: "%env(SUBSCRIPTION_PAYMONGO_PUBLIC_KEY)%"
subscription_paymongo_secret_key: "%env(SUBSCRIPTION_PAYMONGO_SECRET_KEY)%"
subscription_paymongo_webhook_id: "%env(SUBSCRIPTION_PAYMONGO_WEBHOOK_ID)%"
subscription_months: "%env(SUBSCRIPTION_MONTHS)%"
services:
# default configuration for services in *this* file

View file

@ -148,6 +148,74 @@ class SubscriptionController extends ApiController
]);
}
public function finalizeSubscription(Request $req, $id, PayMongoConnector $pm)
{
// check requirements
$validity = $this->validateRequest($req);
if (!$validity['is_valid']) {
return new ApiResponse(false, $validity['error']);
}
// initialize paymongo connector
$this->initializeSubscriptionPayMongoConnector($pm);
// get subscription
$sub_obj = $this->em->getRepository(Subscription::class)->findOneBy([
'id' => $id,
'status' => SubscriptionStatus::PENDING,
'customer' => $this->session->getCustomer(),
]);
if (empty($sub_obj)) {
return new ApiResponse(false, 'Invalid subscription provided.');
}
// get paymongo subscription so we can verify if the latest invoice is paid or not
$pm_sub = $pm->getSubscription($sub_obj->getExtApiId());
if (empty($pm_sub['response']['data']['id'])) {
return new ApiResponse(false, 'Error retrieving subscription. Please try again later.');
}
// make sure the latest invoice has been paid
// NOTE: ignore this, this is unreliable due to race condition
/*
if ($pm_sub['response']['data']['attributes']['latest_invoice']['status'] !== 'paid') {
return new ApiResponse(false, 'Latest invoice for subscription is not yet paid.');
}
*/
// get payment intent
$pi = $pm->getPaymentIntent($pm_sub['response']['data']['attributes']['latest_invoice']['payment_intent']['id']);
if (empty($pi['response']['data']['id'])) {
return new ApiResponse(false, 'Error retrieving payment intent. Please try again later.');
}
// if the paymongo sub is active, and the payment was successful, update the internal subscription status
if (
$sub_obj->getStatus() === SubscriptionStatus::PENDING &&
$pi['response']['data']['attributes']['status'] === 'succeeded'
) {
$sub_start_date = new DateTime();
$sub_end_date = clone $sub_start_date;
$sub_end_date->modify('+' . $this->getParameter('subscription_months') . ' month');
$sub_obj->setStatus(SubscriptionStatus::ACTIVE)
->setDateStart($sub_start_date)
->setDateEnd($sub_end_date);
$this->em->flush();
}
error_log("PI STATUS: " . $pi['response']['data']['attributes']['status']);
// response
return new ApiResponse(true, '', [
'payment_intent' => $pi['response']['data'],
]);
}
/*
public function getPaymentIntent(Request $req, $pid, PayMongoConnector $pm)
{
// check requirements
@ -172,7 +240,7 @@ class SubscriptionController extends ApiController
]);
}
public function setSubscriptionAsPaid(Request $req, $sub_id, PayMongoConnector $pm)
public function activateSubscription(Request $req, $id, PayMongoConnector $pm)
{
// check requirements
$validity = $this->validateRequest($req);
@ -186,7 +254,7 @@ class SubscriptionController extends ApiController
// get subscription
$obj = $this->em->getRepository(Subscription::class)->findOneBy([
'id' => $sub_id,
'id' => $id,
'status' => SubscriptionStatus::PENDING,
'customer' => $this->session->getCustomer(),
]);
@ -195,6 +263,17 @@ class SubscriptionController extends ApiController
return new ApiResponse(false, 'Invalid subscription provided.');
}
// get paymongo subscription so we can verify if the latest invoice is paid or not
$pm_sub = $pm->getSubscription($obj->getExtApiId());
if (empty($pm_sub['response']['data']['id'])) {
return new ApiResponse(false, 'Error retrieving subscription. Please try again later.');
}
// make sure the latest invoice has been paid
if ($pm_sub['response']['data']['attributes']['latest_invoice']['status'] !== 'succeeded') {
return new ApiResponse(false, 'Latest invoice for subscription is not yet paid.');
}
// mark subscription as paid
$obj->setStatus(SubscriptionStatus::ACTIVE)
->setDateStart(new DateTime());
@ -206,4 +285,5 @@ class SubscriptionController extends ApiController
'success' => true,
]);
}
*/
}

View file

@ -16,6 +16,7 @@ use App\Ramcar\JOStatus;
use App\Ramcar\ServiceType;
use App\Ramcar\TradeInType;
use App\Ramcar\InsuranceApplicationStatus;
use App\Ramcar\SubscriptionStatus;
use App\Service\PayMongoConnector;
use App\Service\PriceTierManager;
use DateTime;
@ -518,9 +519,9 @@ class VehicleController extends ApiController
// get active subscription row
if ($include_active_sub) {
$active_sub = null;
$sobj = $cv->getLatestActiveSubscription();
if (!empty($sobj)) {
$sobj = $cv->getLatestSubscription();
if (!empty($sobj) && $sobj->getStatus() == SubscriptionStatus::ACTIVE) {
$active_sub = $sobj;
}
$row['active_subscription'] = $active_sub;

View file

@ -159,7 +159,8 @@ class Subscription
public function setStatus($status)
{
return $this->status = $status;
$this->status = $status;
return $this;
}
public function getStatus()
@ -169,7 +170,8 @@ class Subscription
public function setExtApiId($ext_api_id)
{
return $this->ext_api_id = $ext_api_id;
$this->ext_api_id = $ext_api_id;
return $this;
}
public function getExtApiId()
@ -179,7 +181,8 @@ class Subscription
public function setMetadata($metadata)
{
return $this->metadata = $metadata;
$this->metadata = $metadata;
return $this;
}
public function getMetadata()

View file

@ -281,6 +281,11 @@ class PayMongoConnector
return $this->doRequest('/v1/subscriptions', 'POST', $body);
}
public function getSubscription($sub_id)
{
return $this->doRequest('/v1/subscriptions/'. $sub_id, 'GET');
}
public function getPaymentIntent($pi_id)
{
return $this->doRequest('/v1/payment_intents/' . $pi_id, 'GET');