GuestDeclarationDraft.php 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. <?php
  2. namespace common\models;
  3. use common\components\ActiveRecord;
  4. use common\helpers\GuestDeclarationDraftStatus;
  5. use Yii;
  6. /**
  7. * Durable state for an unauthenticated registration order awaiting payment.
  8. */
  9. class GuestDeclarationDraft extends ActiveRecord
  10. {
  11. public static function tableName()
  12. {
  13. return '{{%GUEST_DECLARATION_DRAFT}}';
  14. }
  15. public function rules()
  16. {
  17. return [
  18. [['ORDER_SN', 'ACCESS_TOKEN_HASH', 'PAYLOAD', 'ORDER_SNAPSHOT', 'STATUS', 'PAY_AMOUNT', 'CURRENCY', 'CREATED_AT', 'EXPIRES_AT'], 'required'],
  19. [['PAYLOAD', 'ORDER_SNAPSHOT', 'PAYMENT_NOTE'], 'string'],
  20. [['PAY_AMOUNT'], 'number'],
  21. [['CREATED_AT', 'EXPIRES_AT', 'PAID_AT', 'COMPLETED_AT'], 'integer'],
  22. [['STATUS'], 'in', 'range' => GuestDeclarationDraftStatus::all()],
  23. [['ORDER_SN'], 'string', 'max' => 32],
  24. [['ACCESS_TOKEN_HASH'], 'string', 'max' => 64],
  25. [['CURRENCY'], 'string', 'max' => 8],
  26. [['PAYMENT_REFERENCE'], 'string', 'max' => 128],
  27. [['USER_ID'], 'string', 'max' => 32],
  28. [['ORDER_SN'], 'unique'],
  29. [['ACCESS_TOKEN_HASH'], 'unique'],
  30. [['PAYMENT_REFERENCE'], 'unique'],
  31. ];
  32. }
  33. public function transitionTo(string $newStatus): bool
  34. {
  35. if (!GuestDeclarationDraftStatus::canTransition($this->STATUS, $newStatus)) {
  36. $this->addError('STATUS', 'Invalid guest declaration draft status transition.');
  37. return false;
  38. }
  39. $this->STATUS = $newStatus;
  40. return $this->save(false, ['STATUS', 'UPDATED_AT']);
  41. }
  42. public static function claimForProcessing(string $orderSn): bool
  43. {
  44. return self::updateAll(
  45. ['STATUS' => GuestDeclarationDraftStatus::PROCESSING, 'UPDATED_AT' => time()],
  46. [
  47. 'AND',
  48. ['ORDER_SN' => $orderSn],
  49. ['STATUS' => GuestDeclarationDraftStatus::PENDING_PAYMENT],
  50. ['>', 'EXPIRES_AT', time()],
  51. ]
  52. ) === 1;
  53. }
  54. public function accessTokenMatches(string $accessToken): bool
  55. {
  56. return $accessToken !== '' && hash_equals($this->ACCESS_TOKEN_HASH, hash('sha256', $accessToken));
  57. }
  58. public function isExpired(?int $now = null): bool
  59. {
  60. return GuestDeclarationDraftStatus::isExpired((int) $this->EXPIRES_AT, $now);
  61. }
  62. public function getPayload(): array
  63. {
  64. $payload = json_decode($this->PAYLOAD, true);
  65. return is_array($payload) ? $payload : [];
  66. }
  67. public function getOrderSnapshot(): array
  68. {
  69. $snapshot = json_decode($this->ORDER_SNAPSHOT, true);
  70. return is_array($snapshot) ? $snapshot : [];
  71. }
  72. }