diff --git a/database/migrations/create_subscription_tables.php.stub b/database/migrations/create_subscription_tables.php.stub index 9e10fe1..b5d1f17 100644 --- a/database/migrations/create_subscription_tables.php.stub +++ b/database/migrations/create_subscription_tables.php.stub @@ -28,7 +28,7 @@ class CreateSubscriptionTables extends Migration */ Schema::create('dk_subscriptions', function (Blueprint $table) { $table->bigIncrements('id'); - $table->unsignedBigInteger('user_id'); + $table->unsignedBigInteger(app(config('paystacksubscription.model'))->getForeignKey()); $table->string('name'); $table->string('paystack_id')->unique(); $table->string('paystack_status'); @@ -39,7 +39,7 @@ class CreateSubscriptionTables extends Migration $table->timestamp('ends_at')->nullable(); $table->timestamps(); - $table->index(['user_id', 'paystack_status']); + $table->index([app(config('paystacksubscription.model'))->getForeignKey(), 'paystack_status']); }); } diff --git a/src/SubscriptionBuilder.php b/src/SubscriptionBuilder.php index 89463a0..8eed20a 100644 --- a/src/SubscriptionBuilder.php +++ b/src/SubscriptionBuilder.php @@ -1,199 +1,214 @@ owner = $owner; + $this->name = $name; + $this->plan = $plan; + } - use Digikraaft\Paystack\Paystack; - use Digikraaft\Paystack\Plan; - use Digikraaft\Paystack\Subscription as PaystackSubscription; - use Digikraaft\Paystack\Transaction; - use Digikraaft\PaystackSubscription\Exceptions\PaymentFailure; - use Digikraaft\PaystackSubscription\Exceptions\SubscriptionUpdateFailure; + /** + * Add a new Paystack subscription to the Paystack model. + * + * @param string|null $authorization + * @param string $transactionId + * @param array $customerOptions + * @return \Digikraaft\PaystackSubscription\Subscription + * @throws \Digikraaft\PaystackSubscription\Exceptions\PaymentFailure + */ + public function add(string $transactionId = null, string $authorization = null, array $customerOptions = []) + { + return $this->create($transactionId, $authorization, $customerOptions); + } - class SubscriptionBuilder + /** + * Create a new Paystack subscription. + * + * @param string|null $authorization + * @param string|null $transactionId + * @param array $customerOptions + * @return \Digikraaft\PaystackSubscription\Subscription + * + * @throws Exceptions\PaymentFailure + */ + public function create(string $transactionId = null, string $authorization = null, array $customerOptions = []) { + $customer = $this->getPaystackCustomer($customerOptions); - /** - * The model that is subscribing. - * - * @var \Illuminate\Database\Eloquent\Model - */ - protected $owner; - - /** - * The name of the subscription. - * - * @var string - */ - protected string $name; - - /** - * The ID or Code of the plan being subscribed to. - * - * @var string - */ - protected string $plan; - - /** - * The authorization code used to create subscription. - * - * @var string - */ - protected string $authorization; - - /** - * Create a new subscription builder instance. - * - * @param mixed $owner - * @param string $name - * @param string $plan - * @return void - */ - public function __construct($owner, $name, $plan) - { - $this->owner = $owner; - $this->name = $name; - $this->plan = $plan; + if (is_null($authorization)) { + $paystackSubscription = $this->createSubscriptionFromTransaction($transactionId, $customer); + } else { + $paystackSubscription = $this->createSubscriptionFromAuthorization($authorization, $customer); } - /** - * Add a new Paystack subscription to the Paystack model. - * - * @param string|null $authorization - * @param string $transactionId - * @param array $customerOptions - * @return \Digikraaft\PaystackSubscription\Subscription - * @throws \Digikraaft\PaystackSubscription\Exceptions\PaymentFailure - */ - public function add(string $transactionId = null, string $authorization = null, array $customerOptions = []) - { - return $this->create($transactionId, $authorization, $customerOptions); - } + // save authorization to owner + $this->owner->paystack_authorization = $paystackSubscription->authorization->authorization_code; + $this->authorization = $paystackSubscription->authorization->authorization_code; + $this->owner->save(); + + + //retrieve plan code + $plan = Plan::fetch($paystackSubscription->plan->id); + + /** @var \Digikraaft\PaystackSubscription\Subscription $subscription */ + $subscription = Subscription::create([ + 'name' => $this->name, + 'paystack_id' => $paystackSubscription->subscription_code, + 'paystack_status' => $paystackSubscription->status, + 'paystack_plan' => $plan->data->plan_code, + 'quantity' => $paystackSubscription->quantity ?? '1', + 'email_token' => $paystackSubscription->email_token, + 'authorization' => $this->authorization, + 'ends_at' => Carbon::parse($paystackSubscription->next_payment_date), + app(config('paystacksubscription.model'))->getForeignKey() => $this->owner->id, + ]); + + return $subscription; + } - /** - * Create a new Paystack subscription. - * - * @param string|null $authorization - * @param string|null $transactionId - * @param array $customerOptions - * @return \Digikraaft\PaystackSubscription\Subscription - * - * @throws Exceptions\PaymentFailure - */ - public function create(string $transactionId = null, string $authorization = null, array $customerOptions = []) - { - $customer = $this->getPaystackCustomer($customerOptions); - - if (is_null($authorization)) { - $paystackSubscription = $this->createSubscriptionFromTransaction($transactionId, $customer); - } else { - $paystackSubscription = $this->createSubscriptionFromAuthorization($authorization, $customer); - $this->authorization = $paystackSubscription->authorization; - } - - // save authorization to owner - $this->owner->paystack_authorization = $paystackSubscription->authorization->authorization_code; - $this->owner->save(); - - - //retrieve plan code - $plan = Plan::fetch($paystackSubscription->plan->id); - - /** @var \Digikraaft\PaystackSubscription\Subscription $subscription */ - $subscription = Subscription::create([ - 'name' => $this->name, - 'paystack_id' => $paystackSubscription->subscription_code, - 'paystack_status' => $paystackSubscription->status, - 'paystack_plan' => $plan->data->plan_code, - 'quantity' => $paystackSubscription->quantity ?? '1', - 'email_token' => $paystackSubscription->email_token, - 'authorization' => $this->authorization, - 'ends_at' => $paystackSubscription->next_payment_date, - 'user_id' => $this->owner->id, - ]); - -// return dd("sssse3"); - - return $subscription; - } + /** + * Get the Paystack customer instance for the current user and payment method. + * + * @param array $options + * @return \Digikraaft\Paystack\Customer + */ + protected function getPaystackCustomer(array $options = []) + { + return $this->owner->createOrGetPaystackCustomer($options); + } - /** - * Get the Paystack customer instance for the current user and payment method. - * - * @param array $options - * @return \Digikraaft\Paystack\Customer - */ - protected function getPaystackCustomer(array $options = []) - { - return $this->owner->createOrGetPaystackCustomer($options); - } + /** + * Create a new Paystack subscription using authorization code. + * + * @param string|null $authorization + * @param $customer + * @return \Digikraaft\PaystackSubscription\Subscription + */ + protected function createSubscriptionFromAuthorization(string $authorization, $customer) + { + $payload = array_merge( + ['customer' => $customer->data->customer_code], + ['authorization' => $authorization], + ['plan' => $this->plan], + ); - /** - * Create a new Paystack subscription using authorization code. - * - * @param string|null $authorization - * @param $customer - * @return \Digikraaft\PaystackSubscription\Subscription - */ - protected function createSubscriptionFromAuthorization(string $authorization, $customer) - { - $payload = array_merge( - ['customer' => $customer->data->customer_code], - ['authorization' => $authorization], - ['plan' => $this->plan], - ); + Paystack::setApiKey(config('paystacksubscription.secret', env('PAYSTACK_SECRET'))); - Paystack::setApiKey(config('paystacksubscription.secret', env('PAYSTACK_SECRET'))); + try { return PaystackSubscription::create( $payload, )->data; - } - /** - * Create a new Paystack subscription using transaction reference. - * - * @param string $transactionId - * @param $customer - * @return \Digikraaft\PaystackSubscription\Subscription - * @throws \Digikraaft\PaystackSubscription\Exceptions\PaymentFailure - * @throws SubscriptionUpdateFailure - */ - protected function createSubscriptionFromTransaction(string $transactionId, $customer) - { - //verify from Paystack that the transaction was successful - Paystack::setApiKey(config('paystacksubscription.secret', env('PAYSTACK_SECRET'))); - $transaction = Transaction::fetch($transactionId); - if (! $transaction->status || $transaction->data->status != 'success') { - throw PaymentFailure::incompleteTransaction($transaction); - } - - if ($transaction->data->plan->plan_code != $this->plan) { - throw PaymentFailure::invalidTransactionPlan($transaction, $this->plan); - } - - if ($transaction->data->customer->customer_code != $customer->data->customer_code) { - throw SubscriptionUpdateFailure::invalidCustomer(); - } - - - - //check if user is already subscribed to plan. This is to guard against multiple subscriptions with the same transactionId - if ($this->owner->subscribedToPlan($transaction->data->plan->plan_code)) { - throw SubscriptionUpdateFailure::duplicateSubscription($this->owner, $transaction->data->plan->name); - } - - $this->authorization = $transaction->data->authorization->authorization_code; + } catch (\Exception $exception) { $paystackSubscription = \Digikraaft\Paystack\Subscription::list( [ 'perPage' => 1, 'page' => 1, - 'customer' => $transaction->data->customer->id, - 'plan' => $transaction->data->plan->id, + 'customer' => $customer->data->id, ] ); return $paystackSubscription->data->{0}; } } + + /** + * Create a new Paystack subscription using transaction reference. + * + * @param string $transactionId + * @param $customer + * @return \Digikraaft\PaystackSubscription\Subscription + * @throws \Digikraaft\PaystackSubscription\Exceptions\PaymentFailure + * @throws SubscriptionUpdateFailure + */ + protected function createSubscriptionFromTransaction(string $transactionId, $customer) + { + //verify from Paystack that the transaction was successful + Paystack::setApiKey(config('paystacksubscription.secret', env('PAYSTACK_SECRET'))); + + $transaction = Transaction::fetch($transactionId); + + if (! $transaction->status || $transaction->data->status != 'success') { + throw PaymentFailure::incompleteTransaction($transaction); + } + + if ($transaction->data->plan->plan_code != $this->plan) { + throw PaymentFailure::invalidTransactionPlan($transaction, $this->plan); + } + + if ($transaction->data->customer->customer_code != $customer->data->customer_code) { + throw SubscriptionUpdateFailure::invalidCustomer(); + } + + //check if user is already subscribed to plan. This is to guard against multiple subscriptions with the same transactionId + if ($this->owner->subscribedToPlan($transaction->data->plan->plan_code)) { + throw SubscriptionUpdateFailure::duplicateSubscription($this->owner, $transaction->data->plan->name); + } + + $this->authorization = $transaction->data->authorization->authorization_code; + + $paystackSubscription = \Digikraaft\Paystack\Subscription::list( + [ + 'perPage' => 1, + 'page' => 1, + 'customer' => $transaction->data->customer->id, + 'plan' => $transaction->data->plan->id, + ] + ); + + return $paystackSubscription->data->{0}; + } +} diff --git a/src/Traits/ManagesCustomer.php b/src/Traits/ManagesCustomer.php index 50a20c7..e68493c 100644 --- a/src/Traits/ManagesCustomer.php +++ b/src/Traits/ManagesCustomer.php @@ -27,7 +27,7 @@ public function paystackId() */ public function hasPaystackId() { - return ! is_null($this->paystack_id); + return ! (is_null($this->paystackId()) || $this->paystackId() == ''); } /** @@ -57,7 +57,7 @@ public function paystackAuthorization() * * @throws \Digikraaft\PaystackSubscription\Exceptions\InvalidCustomer */ - protected function assertCustomerExists() + protected function assertCustomerExists(): void { if (! $this->hasPaystackId()) { throw InvalidCustomer::doesNotExist($this); @@ -72,7 +72,7 @@ protected function assertCustomerExists() * * @throws \Digikraaft\PaystackSubscription\Exceptions\CustomerAlreadyExist */ - public function createAsPaystackCustomer(array $options = []) + public function createAsPaystackCustomer(array $options = []): PaystackCustomer { if ($this->hasPaystackId()) { throw CustomerAlreadyExist::exists($this); @@ -117,9 +117,9 @@ public function updatePaystackCustomer(array $options = []) * * @param array $options * @return \Digikraaft\Paystack\Customer - * @throws \Digikraaft\PaystackSubscription\Exceptions\InvalidCustomer + * @throws \Digikraaft\PaystackSubscription\Exceptions\InvalidCustomer|CustomerAlreadyExist */ - public function createOrGetPaystackCustomer(array $options = []) + public function createOrGetPaystackCustomer(array $options = []): PaystackCustomer { if ($this->hasPaystackId()) { return $this->asPaystackCustomer(); @@ -131,7 +131,7 @@ public function createOrGetPaystackCustomer(array $options = []) /** * Get the Paystack customer for the model. * - * @return \Digikraaft\Paystack\Customer + * @return array|object * @throws \Digikraaft\PaystackSubscription\Exceptions\InvalidCustomer */ public function asPaystackCustomer() @@ -149,7 +149,7 @@ public function asPaystackCustomer() * * @return string|null */ - public function paystackEmail() + public function paystackEmail(): ?string { return $this->email; }