diff --git a/CHANGELOG.md b/CHANGELOG.md index bf123ca..f2afc9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Solspace Freeform Payments Changelog +## 1.0.0-beta.5 - 2018-11-20 +### Changed +- Updated Stripe settings to allow both LIVE and TEST keys to allow for easy switching into test mode. +- Improved built in error handling on credit card fields in forms. + +### Fixed +- Fixed a bug where Payments would send a 400 error on subsequent recurring payment transactions. + ## 1.0.0-beta.4 - 2018-11-12 ### Changed - Updated Freeform to detect if more than 1 form is loading Payments-enabled forms on the same page, and only load Stripe JS once. diff --git a/composer.json b/composer.json index 7c5a306..400f4ca 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "solspace/craft3-freeform-payments", "description": "Adds payment capabilities to Freeform.", - "version": "1.0.0-beta.4", + "version": "1.0.0-beta.5", "type": "craft-plugin", "authors": [ { @@ -22,7 +22,7 @@ } }, "extra": { - "schemaVersion": "1.0.0", + "schemaVersion": "1.0.2", "handle": "freeform-payments", "class": "Solspace\\FreeformPayments\\FreeformPayments", "name": "Freeform Payments", diff --git a/src/Controllers/WebhooksController.php b/src/Controllers/WebhooksController.php index f2951c7..41f570d 100644 --- a/src/Controllers/WebhooksController.php +++ b/src/Controllers/WebhooksController.php @@ -21,6 +21,7 @@ public function actionStripe() $request = \Craft::$app->request; $payload = $request->getRawBody(); $integrationId = $request->getQueryParam('id'); + /** @var Stripe $integration */ $integration = $this->getPaymentGatewaysService()->getIntegrationObjectById($integrationId); if (!$integration) { @@ -45,34 +46,21 @@ public function actionStripe() //TODO: implement all notification service call as events? //TODO: update payment/subscription status accordingly - $errorMessage = FreeformPayments::t('Event is not linked to freeform submission'); switch ($event->type) { case Event::CHARGE_SUCCEEDED: - $submissionId = $event->data->object->metadata->submission; - if (!$submissionId) { - throw new HttpException(400, $errorMessage); - } + $submissionId = $this->getSubmissionIdFromStripeEvent($event, $integration); $this->getPaymentsNotificationService()->sendChargeSucceeded($submissionId); break; case Event::CHARGE_FAILED: - $submissionId = $event->data->object->metadata->submission; - if (!$submissionId) { - throw new HttpException(400, $errorMessage); - } + $submissionId = $this->getSubmissionIdFromStripeEvent($event, $integration); $this->getPaymentsNotificationService()->sendChargeFailed($submissionId); break; case Event::CUSTOMER_SUBSCRIPTION_CREATED: - $submissionId = $event->data->object->metadata->submission; - if (!$submissionId) { - throw new HttpException(400, $errorMessage); - } + $submissionId = $this->getSubmissionIdFromStripeEvent($event, $integration); $this->getPaymentsNotificationService()->sendSubscriptionCreated($submissionId); break; case Event::CUSTOMER_SUBSCRIPTION_DELETED: - $submissionId = $event->data->object->metadata->submission; - if (!$submissionId) { - throw new HttpException(400, $errorMessage); - } + $submissionId = $this->getSubmissionIdFromStripeEvent($event, $integration); $this->getPaymentsNotificationService()->sendSubscriptionEnded($submissionId); break; case Event::INVOICE_PAYMENT_SUCCEEDED: @@ -98,4 +86,32 @@ public function actionStripe() return ''; } + + /** + * @param Event $event + * @param Stripe $integration + * + * @return mixed + * @throws HttpException + */ + private function getSubmissionIdFromStripeEvent(Event $event, Stripe $integration) + { + $submissionId = $event->data->object->metadata->submission; + if ($submissionId) { + return $submissionId; + } + + $subscriptionId = $event->data->object->source->metadata->subscription; + if ($subscriptionId) { + $subscription = $integration->getSubscriptionDetails($subscriptionId); + + if (isset($subscription['metadata']['submission'])) { + return $subscription['metadata']['submission']; + } + } + + $errorMessage = FreeformPayments::t('Event is not linked to freeform submission'); + + throw new HttpException(400, $errorMessage); + } } diff --git a/src/Integrations/PaymentGateways/Stripe.php b/src/Integrations/PaymentGateways/Stripe.php index 2e026bb..cee2eb1 100644 --- a/src/Integrations/PaymentGateways/Stripe.php +++ b/src/Integrations/PaymentGateways/Stripe.php @@ -27,9 +27,12 @@ class Stripe extends AbstractPaymentGatewayIntegration { - const SETTING_PUBLIC_KEY = 'public_key'; - const SETTING_SECRET_KEY = 'secret_key'; - const SETTING_WEBHOOK_KEY = 'webhook_key'; + const SETTING_PUBLIC_KEY_LIVE = 'public_key_live'; + const SETTING_SECRET_KEY_LIVE = 'secret_key_live'; + const SETTING_PUBLIC_KEY_TEST = 'public_key_test'; + const SETTING_SECRET_KEY_TEST = 'secret_key_test'; + const SETTING_LIVE_MODE = 'live_mode'; + const SETTING_WEBHOOK_KEY = 'webhook_key'; const TITLE = 'Stripe'; const LOG_CATEGORY = 'Stripe'; @@ -87,6 +90,7 @@ public static function fromStripeAmount($amount, $currency) public static function fromStripeInterval($interval, $intervalCount) { $stripeInterval = ['interval' => $interval, 'count' => $intervalCount]; + return array_search($stripeInterval, self::PLAN_INTERVAL_CONVERSION); } @@ -101,18 +105,39 @@ public static function getSettingBlueprints(): array return [ new SettingBlueprint( SettingBlueprint::TYPE_TEXT, - self::SETTING_PUBLIC_KEY, - 'Public Key', - 'Enter your Stripe public key here.', + self::SETTING_PUBLIC_KEY_LIVE, + 'Public Key (Live)', + 'Enter your Stripe LIVE public key here.', + true + ), + new SettingBlueprint( + SettingBlueprint::TYPE_TEXT, + self::SETTING_SECRET_KEY_LIVE, + 'Secret Key (Live)', + 'Enter your Stripe LIVE secret key here.', true ), new SettingBlueprint( SettingBlueprint::TYPE_TEXT, - self::SETTING_SECRET_KEY, - 'Secret Key', - 'Enter your Stripe secret key here.', + self::SETTING_PUBLIC_KEY_TEST, + 'Public Key (Test)', + 'Enter your Stripe TEST public key here.', true ), + new SettingBlueprint( + SettingBlueprint::TYPE_TEXT, + self::SETTING_SECRET_KEY_TEST, + 'Secret Key (Test)', + 'Enter your Stripe TEST secret key here.', + true + ), + new SettingBlueprint( + SettingBlueprint::TYPE_BOOL, + self::SETTING_LIVE_MODE, + 'LIVE mode', + 'Enable this to start using LIVE public and secret keys.', + false + ), new SettingBlueprint( SettingBlueprint::TYPE_TEXT, self::SETTING_WEBHOOK_KEY, @@ -159,7 +184,9 @@ public function checkConnection(): bool */ public function fetchAccessToken(): string { - return $this->getSetting(self::SETTING_SECRET_KEY); + return $this->getSetting( + $this->isLiveMode() ? self::SETTING_SECRET_KEY_LIVE :self::SETTING_SECRET_KEY_TEST + ); } /** @@ -532,6 +559,7 @@ public function getChargeDetails($id) */ public function getSubscriptionDetails($id) { + $this->prepareApi(); try { $subscription = StripeAPI\Subscription::retrieve($id); } catch (\Exception $e) { @@ -553,7 +581,11 @@ public function getSubscriptionDetails($id) */ public function onBeforeSave(IntegrationStorageInterface $model) { - $model->updateAccessToken($this->getSetting(self::SETTING_SECRET_KEY)); + $model->updateAccessToken( + $this->getSetting( + $this->isLiveMode() ? self::SETTING_SECRET_KEY_LIVE :self::SETTING_SECRET_KEY_TEST + ) + ); } /** @@ -586,6 +618,27 @@ public function getExternalDashboardLink(string $resourceId, string $type): stri } } + /** + * @return string + * @throws IntegrationException + */ + public function getPublicKey(): string + { + return $this->getSetting( + $this->isLiveMode() ? self::SETTING_PUBLIC_KEY_LIVE : self::SETTING_PUBLIC_KEY_TEST + ); + } + + + /** + * @return bool + * @throws IntegrationException + */ + protected function isLiveMode(): bool + { + return $this->getSetting(self::SETTING_LIVE_MODE); + } + /** * @param $params * @@ -761,6 +814,10 @@ protected function savePayment($data, int $submissionId) $model->currency = $data['currency']; $model->last4 = $data['source']['card']['last4']; $model->status = $data['paid'] ? PaymentRecord::STATUS_PAID : PaymentRecord::STATUS_FAILED; + $model->metadata = [ + 'chargeId' => $data['id'], + 'card' => $data['source']['card'], + ]; } $handler->save($model); @@ -812,7 +869,11 @@ protected function saveSubscription($data, int $submissionId, string $planResour $model->currency = $data['plan']['currency']; $model->interval = $data['plan']['interval']; if (isset($data['source'])) { - $model->last4 = $data['source']['card']['last4']; + $model->last4 = $data['source']['card']['last4']; + $model->metadata = [ + 'chargeId' => $data['id'], + 'card' => $data['source']['card'], + ]; } $model->status = $data['status']; } diff --git a/src/Models/AbstractPaymentModel.php b/src/Models/AbstractPaymentModel.php index 8136cd4..4f8c819 100644 --- a/src/Models/AbstractPaymentModel.php +++ b/src/Models/AbstractPaymentModel.php @@ -3,9 +3,9 @@ namespace Solspace\FreeformPayments\Models; use craft\base\Model; -use Solspace\Freeform\Library\Payments\PaymentInterface; use Solspace\Freeform\Freeform; use Solspace\Freeform\Library\Integrations\PaymentGateways\PaymentGatewayIntegrationInterface; +use Solspace\Freeform\Library\Payments\PaymentInterface; abstract class AbstractPaymentModel extends Model implements PaymentInterface { @@ -30,6 +30,9 @@ abstract class AbstractPaymentModel extends Model implements PaymentInterface /** @var string */ public $errorMessage; + /** @var array */ + public $metadata; + public $dateCreated; public $dateUpdated; public $uid; @@ -55,7 +58,7 @@ abstract public function getType(): string; public function getIntegration() { if (!$this->integration) { - $paymentGateways = Freeform::getInstance()->paymentGateways; + $paymentGateways = Freeform::getInstance()->paymentGateways; $this->integration = $paymentGateways->getIntegrationObjectById($this->integrationId); } @@ -73,6 +76,7 @@ public function getIntegrationName(): string if (!$integration) { return ''; } + return $integration->getName(); } @@ -87,6 +91,7 @@ public function getServiceProvider(): string if (!$integration) { return ''; } + return $integration->getServiceProvider(); } @@ -99,6 +104,7 @@ public function getExternalDashboardLink(): string if (!$integration || !$this->resourceId) { return ''; } + return $integration->getExternalDashboardLink($this->resourceId, $this->getType()); } diff --git a/src/Models/PaymentModel.php b/src/Models/PaymentModel.php index 7fc76f5..13ff0d4 100644 --- a/src/Models/PaymentModel.php +++ b/src/Models/PaymentModel.php @@ -24,13 +24,4 @@ public function getType(): string { return PaymentInterface::TYPE_SINGLE; } - - /** - * @return array - */ - public function rules(): array - { - return [ - ]; - } } diff --git a/src/Models/SubscriptionModel.php b/src/Models/SubscriptionModel.php index c1d3d12..b562543 100644 --- a/src/Models/SubscriptionModel.php +++ b/src/Models/SubscriptionModel.php @@ -18,6 +18,9 @@ class SubscriptionModel extends AbstractPaymentModel /** @var string */ public $interval; + /** @var int */ + public $intervalCount; + /** @var int */ public $last4; diff --git a/src/Records/PaymentRecord.php b/src/Records/PaymentRecord.php index b1e3d0b..5f4b017 100644 --- a/src/Records/PaymentRecord.php +++ b/src/Records/PaymentRecord.php @@ -11,25 +11,26 @@ namespace Solspace\FreeformPayments\Records; -use craft\db\ActiveRecord; +use Solspace\Commons\Records\SerializableActiveRecord; +use Solspace\Freeform\Elements\Submission; use Solspace\Freeform\Records\IntegrationRecord; use yii\db\ActiveQuery; -use Solspace\Freeform\Elements\Submission; /** * @property string $id - * @property int $submissionId - * @property int $integrationId - * @property int $subscriptionId + * @property int $submissionId + * @property int $integrationId + * @property int $subscriptionId * @property string $resourceId - * @property float $amount + * @property float $amount * @property string $currency - * @property int $last4 + * @property int $last4 * @property string $status + * @property string $metadata * @property string $errorCode * @property string $errorMessage */ -class PaymentRecord extends ActiveRecord +class PaymentRecord extends SerializableActiveRecord { const TABLE = '{{%freeform_payments_payments}}'; @@ -70,4 +71,14 @@ public function getSubscription(): ActiveQuery { return $this->hasOne(SubscriptionRecord::TABLE, ['subscriptionId' => 'id']); } + + /** + * @inheritDoc + */ + protected function getSerializableFields(): array + { + return [ + 'metadata', + ]; + } } diff --git a/src/Records/SubscriptionRecord.php b/src/Records/SubscriptionRecord.php index d6dcf81..4e26e71 100644 --- a/src/Records/SubscriptionRecord.php +++ b/src/Records/SubscriptionRecord.php @@ -11,9 +11,9 @@ namespace Solspace\FreeformPayments\Records; -use craft\db\ActiveRecord; -use yii\db\ActiveQuery; +use Solspace\Commons\Records\SerializableActiveRecord; use Solspace\Freeform\Elements\Submission; +use yii\db\ActiveQuery; /** * @property string $id @@ -24,12 +24,14 @@ * @property string $amount * @property string $currency * @property string $interval + * @property string $intervalCount * @property string $last4 * @property string $status + * @property string $metadata * @property string $errorCode * @property string $errorMessage */ -class SubscriptionRecord extends ActiveRecord +class SubscriptionRecord extends SerializableActiveRecord { const TABLE = '{{%freeform_payments_subscriptions}}'; @@ -56,4 +58,14 @@ public function getPlan(): ActiveQuery { return $this->hasOne(SubscriptionPlanRecord::TABLE, ['planId' => 'id']); } + + /** + * @inheritDoc + */ + protected function getSerializableFields(): array + { + return [ + 'metadata', + ]; + } } diff --git a/src/Services/NotificationService.php b/src/Services/NotificationService.php index 9c2a619..5b141c0 100644 --- a/src/Services/NotificationService.php +++ b/src/Services/NotificationService.php @@ -59,11 +59,15 @@ protected function send(int $submissionId, string $notificationType) { $email = $submission->{$emailFieldHandle}->getValue(); $notifications = $paymentProps->getPaymentNotifications(); + if (isset($notifications[PaymentProperties::NOTIFICATION_TYPE_SUBSCRIPTION_PAYMENT_SUCCEEDED])) { + $notifications[PaymentProperties::NOTIFICATION_TYPE_CHARGE_SUCCEEDED] = $notifications[PaymentProperties::NOTIFICATION_TYPE_SUBSCRIPTION_PAYMENT_SUCCEEDED]; + } + $fields = $form->getLayout()->getFields(); Freeform::getInstance()->mailer->sendEmail( $form, $email, - $notifications[$notificationType], + $notifications[$notificationType] ?? null, $fields, $submission ); diff --git a/src/Services/PaymentsService.php b/src/Services/PaymentsService.php index 8d62df3..365ad86 100644 --- a/src/Services/PaymentsService.php +++ b/src/Services/PaymentsService.php @@ -11,15 +11,14 @@ namespace Solspace\FreeformPayments\Services; +use Solspace\Freeform\Freeform; +use Solspace\Freeform\Library\Composer\Components\Form; +use Solspace\Freeform\Library\Payments\PaymentHandlerInterface; +use Solspace\Freeform\Library\Payments\PaymentInterface; use Solspace\FreeformPayments\Library\Traits\ModelServiceTrait; use Solspace\FreeformPayments\Models\PaymentModel; use Solspace\FreeformPayments\Records\PaymentRecord; -use Solspace\Freeform\Library\Payments\PaymentHandlerInterface; -use Solspace\Freeform\Library\Payments\PaymentInterface; -use Solspace\FreeformPayments\Records\SubscriptionRecord; use yii\db\Query; -use Solspace\Freeform\Freeform; -use Solspace\Freeform\Library\Composer\Components\Form; class PaymentsService implements PaymentHandlerInterface { @@ -29,11 +28,12 @@ class PaymentsService implements PaymentHandlerInterface * Returns payment for submission, only first payment is returned for subscriptions * * @param integer $submissionId + * * @return PaymentInterface|null */ public function getBySubmissionId(int $submissionId) { - $data = $this->getQuery()->where(array('submissionId' => $submissionId))->all(); + $data = $this->getQuery()->where(['submissionId' => $submissionId])->all(); if (!$data) { return null; } @@ -51,17 +51,17 @@ public function getBySubmissionId(int $submissionId) /** * Finds a payment with a matching resource id for specific integration * - * @param string $resourceId + * @param string $resourceId * @param integer $integrationId * * @return PaymentModel|null */ public function getByResourceId(string $resourceId, int $integrationId) { - $data = $this->getQuery()->where(array( - 'resourceId' => $resourceId, + $data = $this->getQuery()->where([ + 'resourceId' => $resourceId, 'integrationId' => $integrationId, - ))->one(); + ])->one(); if (!$data) { return null; @@ -73,7 +73,8 @@ public function getByResourceId(string $resourceId, int $integrationId) /** * Saves payment * - * @param PaymentInterface $model + * @param PaymentInterface|PaymentModel $model + * * @return bool */ public function save(PaymentInterface $model): bool @@ -95,6 +96,7 @@ public function save(PaymentInterface $model): bool $record->currency = $model->currency; $record->last4 = $model->last4; $record->status = $model->status; + $record->metadata = $model->metadata; $record->errorCode = $model->errorCode; $record->errorMessage = $model->errorMessage; @@ -110,7 +112,7 @@ public function getPaymentDetails(int $submissionId, Form $form = null) { if ($form === null) { $submission = Freeform::getInstance()->submissions->getSubmissionById($submissionId); - $form = $submission->getForm(); + $form = $submission->getForm(); } $paymentProperties = $form->getPaymentProperties(); @@ -119,14 +121,14 @@ public function getPaymentDetails(int $submissionId, Form $form = null) return null; } - $integration = Freeform::getInstance()->paymentGateways->getIntegrationObjectById($integrationId); + $integration = Freeform::getInstance()->paymentGateways->getIntegrationObjectById($integrationId); return $integration->getPaymentDetails($submissionId); } public function updatePaymentStatus(int $submissionId, string $status) { - $payment = $this->getBySubmissionId($submissionId); + $payment = $this->getBySubmissionId($submissionId); $payment->status = $status; $this->save($payment); } @@ -143,6 +145,7 @@ protected function getQuery(): Query * Creates model from attributes * * @param array $data + * * @return PaymentModel */ protected function createModel(array $data): PaymentModel diff --git a/src/Services/StripeService.php b/src/Services/StripeService.php index e818638..fd1fc4f 100644 --- a/src/Services/StripeService.php +++ b/src/Services/StripeService.php @@ -15,19 +15,18 @@ use craft\web\View; use Solspace\Freeform\Events\Forms\FormRenderEvent; use Solspace\Freeform\Freeform; +use Solspace\Freeform\Library\Composer\Components\AbstractField; +use Solspace\Freeform\Library\Composer\Components\FieldInterface; +use Solspace\Freeform\Library\Composer\Components\Fields\SubmitField; use Solspace\Freeform\Library\Composer\Components\Form; +use Solspace\Freeform\Library\Composer\Components\Page; +use Solspace\Freeform\Library\Composer\Components\Properties\PaymentProperties; use Solspace\Freeform\Services\SettingsService; -use Solspace\FreeformPayments\FreeformPayments; use Solspace\FreeformPayments\Integrations\PaymentGateways\Stripe; -use Solspace\Freeform\Library\Composer\Components\Properties\PaymentProperties; -use Solspace\Freeform\Library\Composer\Components\Page; -use Solspace\Freeform\Library\Composer\Components\AbstractField; -use Solspace\Freeform\Library\Composer\Components\Fields\SubmitField; -use Solspace\Freeform\Library\Composer\Components\FieldInterface; class StripeService extends Component { - const FIELD_GROUP_TYPES = array(FieldInterface::TYPE_CHECKBOX_GROUP, FieldInterface::TYPE_RADIO_GROUP); + const FIELD_GROUP_TYPES = [FieldInterface::TYPE_CHECKBOX_GROUP, FieldInterface::TYPE_RADIO_GROUP]; /** * Adds honeypot javascript to forms @@ -57,10 +56,11 @@ public function addFormJavascript(FormRenderEvent $event) */ public function getStripeJavascriptScript(Form $form): string { - $paymentFields = $form->getLayout()->getPaymentFields(); - $integrationId = $form->getPaymentProperties()->getIntegrationId(); - $integration = Freeform::getInstance()->paymentGateways->getIntegrationById($integrationId); - $publicKey = $integration->settings[Stripe::SETTING_PUBLIC_KEY]; + $paymentFields = $form->getLayout()->getPaymentFields(); + $integrationId = $form->getPaymentProperties()->getIntegrationId(); + $integration = Freeform::getInstance()->paymentGateways->getIntegrationById($integrationId); + + $publicKey = $integration->getIntegrationObject()->getPublicKey(); $values = $this->getPaymentFieldJSValues($form); $props = $form->getPaymentProperties(); $zeroDecimalCurrencies = json_encode(Stripe::ZERO_DECIMAL_CURRENCIES); @@ -74,7 +74,7 @@ public function getStripeJavascriptScript(Form $form): string $paymentField = $paymentFields[0]; - $script =<<getPaymentFieldMapping(); if (!isset($mapping['amount']) && !isset($mapping['currency'])) { - return array( + return [ 'amount' => $staticAmount, 'currency' => $staticCurrency, - ); + ]; } //process 3 cases, fixed value, value on same page, value on different page @@ -230,10 +230,10 @@ private function getPaymentFieldJSValues($form) $dynamicCurrency = "'{$form->get($mapping['currency'])->getValue()}'"; } - return array( + return [ 'amount' => $elementAmount ?? $dynamicAmount ?? $staticAmount, 'currency' => $elementCurrency ?? $dynamicCurrency ?? $staticCurrency, - ); + ]; } /** diff --git a/src/Services/SubscriptionsService.php b/src/Services/SubscriptionsService.php index 4e7923e..56d3cc7 100644 --- a/src/Services/SubscriptionsService.php +++ b/src/Services/SubscriptionsService.php @@ -11,9 +11,9 @@ namespace Solspace\FreeformPayments\Services; +use Solspace\FreeformPayments\Library\Traits\ModelServiceTrait; use Solspace\FreeformPayments\Models\SubscriptionModel; use Solspace\FreeformPayments\Records\SubscriptionRecord; -use Solspace\FreeformPayments\Library\Traits\ModelServiceTrait; use yii\db\Query; class SubscriptionsService @@ -24,41 +24,47 @@ class SubscriptionsService * Finds a subscription by submission id * * @param integer $submissionId + * * @return SubscriptionModel|null */ - public function getBySubmissionId(int $submissionId) { - $data = $this->getQuery()->where(array('submissionId' => $submissionId))->one(); + public function getBySubmissionId(int $submissionId) + { + $data = $this->getQuery()->where(['submissionId' => $submissionId])->one(); - if (!$data) { + if (!$data) { return null; - } + } - return new SubscriptionModel($data); + return new SubscriptionModel($data); } /** * Finds a subscription by id * * @param integer $id + * * @return SubscriptionModel|null */ - public function getById(int $id) { - $data = $this->getQuery()->where(array('id' => $id))->one(); + public function getById(int $id) + { + $data = $this->getQuery()->where(['id' => $id])->one(); if (!$data) { return null; } return new SubscriptionModel($data); - } + } /** * Saves subscription model * * @param SubscriptionModel $model + * * @return bool */ - public function save(SubscriptionModel $model): bool { + public function save(SubscriptionModel $model): bool + { $isNew = !$model->id; if (!$isNew) { $record = SubscriptionRecord::findOne(['id' => $model->id]); @@ -71,20 +77,22 @@ public function save(SubscriptionModel $model): bool { $record->planId = $model->planId; } - $record->amount = $model->amount; - $record->currency = $model->currency; - $record->interval = $model->interval; - $record->last4 = $model->last4; - $record->status = $model->status; - $record->errorCode = $model->errorCode; - $record->errorMessage = $model->errorMessage; + $record->amount = $model->amount; + $record->currency = $model->currency; + $record->interval = $model->interval; + $record->intervalCount = $model->intervalCount; + $record->last4 = $model->last4; + $record->status = $model->status; + $record->metadata = $model->metadata; + $record->errorCode = $model->errorCode; + $record->errorMessage = $model->errorMessage; return $this->validateAndSave($record, $model); } public function updateSubscriptionStatus(int $submissionId, string $status) { - $subscription = $this->getBySubmissionId($submissionId); + $subscription = $this->getBySubmissionId($submissionId); $subscription->status = $status; $this->save($subscription); } diff --git a/src/migrations/Install.php b/src/migrations/Install.php index cc4ae45..3bdb0b2 100644 --- a/src/migrations/Install.php +++ b/src/migrations/Install.php @@ -36,6 +36,7 @@ protected function defineTableData(): array ->addField('currency', $this->string(3)) ->addField('last4', $this->smallInteger()) ->addField('status', $this->string(20)) + ->addField('metadata', $this->mediumText()) ->addField('errorCode', $this->string(20)) ->addField('errorMessage', $this->string(255)) ->addForeignKey('submissionId', 'freeform_submissions', 'id', ForeignKey::CASCADE) @@ -52,8 +53,10 @@ protected function defineTableData(): array ->addField('amount', $this->float(2)) ->addField('currency', $this->string(3)) ->addField('interval', $this->string(20)) + ->addField('intervalCount', $this->smallInteger()->null()) ->addField('last4', $this->smallInteger()) ->addField('status', $this->string(20)) + ->addField('metadata', $this->mediumText()) ->addField('errorCode', $this->string(20)) ->addField('errorMessage', $this->string(255)) ->addForeignKey('submissionId', 'freeform_submissions', 'id', ForeignKey::CASCADE) diff --git a/src/migrations/m181108_140216_AddMetadataAndIntervalCount.php b/src/migrations/m181108_140216_AddMetadataAndIntervalCount.php new file mode 100644 index 0000000..4131cda --- /dev/null +++ b/src/migrations/m181108_140216_AddMetadataAndIntervalCount.php @@ -0,0 +1,45 @@ +addColumn( + '{{%freeform_payments_payments}}', + 'metadata', + $this->mediumText() + ); + + $this->addColumn( + '{{%freeform_payments_subscriptions}}', + 'metadata', + $this->mediumText() + ); + + $this->addColumn( + '{{%freeform_payments_subscriptions}}', + 'intervalCount', + $this->smallInteger()->null() + ); + } + + /** + * @inheritdoc + */ + public function safeDown() + { + echo "m181108_140216_AddMetadataAndIntervalCount cannot be reverted.\n"; + return false; + } +} diff --git a/src/migrations/m181116_161041_SwitchToLiveAndTestKeysForStripe.php b/src/migrations/m181116_161041_SwitchToLiveAndTestKeysForStripe.php new file mode 100644 index 0000000..82a64ec --- /dev/null +++ b/src/migrations/m181116_161041_SwitchToLiveAndTestKeysForStripe.php @@ -0,0 +1,92 @@ +select(['id', 'settings']) + ->from('{{%freeform_integrations}}') + ->where([ + 'type' => 'payment_gateway', + 'class' => Stripe::class, + ]) + ->all(); + + foreach ($rows as $row) { + $id = $row['id']; + $settings = json_decode($row['settings'], true); + + $settings['live_mode'] = ''; + if (isset($settings['public_key'])) { + $settings['public_key_live'] = $settings['public_key_test'] = $settings['public_key']; + unset($settings['public_key']); + } + + if (isset($settings['secret_key'])) { + $settings['secret_key_live'] = $settings['secret_key_test'] = $settings['secret_key']; + unset($settings['secret_key']); + } + + $this->update( + '{{%freeform_integrations}}', + ['settings' => json_encode($settings)], + ['id' => $id] + ); + } + + return true; + } + + /** + * @inheritdoc + */ + public function safeDown() + { + $rows = (new Query()) + ->select(['id', 'settings']) + ->from('{{%freeform_integrations}}') + ->where([ + 'type' => 'payment_gateway', + 'class' => Stripe::class, + ]) + ->all(); + + foreach ($rows as $row) { + $id = $row['id']; + $settings = json_decode($row['settings'], true); + + $settings['live_mode'] = ''; + if (isset($settings['public_key_test'])) { + $settings['public_key'] = $settings['public_key_test']; + unset($settings['public_key_test'], $settings['public_key_live']); + } + + if (isset($settings['secret_key_test'])) { + $settings['secret_key'] = $settings['secret_key_test']; + unset($settings['secret_key_test'], $settings['secret_key_live']); + } + + $this->update( + '{{%freeform_integrations}}', + ['settings' => json_encode($settings)], + ['id' => $id] + ); + } + + return true; + } +}