1 | <?php |
||
8 | class Create implements MethodInterface |
||
9 | { |
||
10 | const CARD = 'card'; |
||
11 | const RECURRING = 'recurring'; |
||
12 | |||
13 | private $attributes; |
||
14 | |||
15 | public function __construct(array $attributes) |
||
16 | { |
||
17 | $this->attributes = $attributes; |
||
18 | } |
||
19 | |||
20 | public function getAction() |
||
21 | { |
||
22 | return 'payments'; |
||
23 | } |
||
24 | |||
25 | public function getMethod() |
||
26 | { |
||
27 | return MethodInterface::POST; |
||
28 | } |
||
29 | |||
30 | public function getAttributes() |
||
31 | { |
||
32 | return $this->attributes; |
||
33 | } |
||
34 | |||
35 | public function createResultObject() |
||
36 | { |
||
37 | return new Payment(); |
||
38 | } |
||
39 | |||
40 | public function getValidationConstraints() |
||
41 | { |
||
42 | return new Assert\Collection([ |
||
43 | 'amount' => $this->buildElement('float', 1), |
||
44 | 'currency' => $this->buildElement('string', 1, ['min' => 3,'max' => 3]), |
||
45 | 'settle' => $this->buildElement('bool'), |
||
46 | 'order_id' => $this->buildElement('string', 0, ['min' => 2,'max' => 50]), |
||
47 | 'description' => $this->buildElement('string', 0, ['max' => 255]), |
||
48 | 'country' => $this->buildElement('string', 1, ['min' => 2,'max' => 2]), |
||
49 | 'payment_method' => new Assert\Required([ |
||
50 | new Assert\Type(['type' => 'string']), |
||
51 | new Assert\Choice([ |
||
52 | 'choices' => [ |
||
53 | self::CARD, |
||
54 | self::RECURRING |
||
55 | ] |
||
56 | ]) |
||
57 | ]), |
||
58 | 'payment_instrument' => $this->getPaymentInstrumentConstraints( |
||
59 | $this->getAttributes()['payment_method'] |
||
60 | ), |
||
61 | 'threeDS2Data' => new Assert\Optional([$this->getTrheeDS2DataConstraints()]) |
||
62 | ]); |
||
63 | } |
||
64 | |||
65 | private function getPaymentInstrumentConstraints($method) |
||
66 | { |
||
67 | switch ($method) { |
||
68 | case self::CARD: |
||
69 | return new Assert\Collection([ |
||
70 | 'pan' => new Assert\Required([ |
||
71 | new Assert\NotBlank(), |
||
72 | new Assert\Luhn() |
||
73 | ]), |
||
74 | 'exp_year' => $this->buildElement( |
||
75 | 'integer', 1, |
||
76 | ['min' => 4,'max' => 4], |
||
77 | new Assert\Range(['min' => date('Y')]), |
||
78 | ), |
||
|
|||
79 | 'exp_month' => $this->buildElement('integer', 1), |
||
80 | 'cvc' => $this->buildElement('string', 1, ['min' => 3, 'max' => 4]), |
||
81 | 'holder' => $this->buildElement('string', 1, ['max' => 32]), |
||
82 | ]); |
||
83 | case self::RECURRING: |
||
84 | return new Assert\Collection([ |
||
85 | 'payment_id' => $this->buildElement('string', 1), |
||
86 | ]); |
||
87 | } |
||
88 | |||
89 | throw new \InvalidArgumentException( |
||
90 | sprintf( |
||
91 | 'Payment instrument for payment method "%s" is not expected', |
||
92 | $method |
||
93 | ) |
||
94 | ); |
||
95 | } |
||
96 | |||
97 | private function getTrheeDS2DataConstraints() |
||
98 | { |
||
99 | return new Assert\Collection([ |
||
100 | 'notificationUrl' => $this->buildElement('string', 1), |
||
101 | 'browserInfo' => $this->getBrowserInfoConstraints(), |
||
102 | 'billingAddress' => $this->getAdressConstraints('billingAddress'), |
||
103 | 'deliveryAddress' => $this->getAdressConstraints('deliveryAddress'), |
||
104 | 'cardHolderInfo' => $this->getCardHolderInfoConstraints(), |
||
105 | ]); |
||
106 | } |
||
107 | |||
108 | private function getBrowserInfoConstraints() |
||
109 | { |
||
110 | return new Assert\Collection([ |
||
111 | 'acceptHeader' => $this->buildElement('string', 1), |
||
112 | 'browserLanguage' => $this->buildElement('string', 1), // TODO should implement standard IETF BCP 47 (https://tools.ietf.org/html/bcp47) |
||
113 | 'screenWidth' => $this->buildElement('integer', 1), |
||
114 | 'screenHeight' => $this->buildElement('integer', 1), |
||
115 | 'challengeWindowSize' => $this->buildElement('string', 1), |
||
116 | 'userAgent' => $this->buildElement('string', 1), |
||
117 | 'colorDepth' => $this->buildElement('integer', 1), |
||
118 | 'timeZone' => $this->buildElement('integer', 1), |
||
119 | 'ipAddress' => $this->buildElement('string'), |
||
120 | 'javaEnabled' => $this->buildElement('bool'), |
||
121 | 'javascriptEnabled' => $this->buildElement('bool'), |
||
122 | ]); |
||
123 | } |
||
124 | |||
125 | private function getAdressConstraints() |
||
126 | { |
||
127 | return new Assert\Collection([ |
||
128 | 'address_line1' => $this->buildElement('string', 1, ['max'=>50]), |
||
129 | 'address_line2' => $this->buildElement('string', 1, ['max'=>50]), |
||
130 | 'address_line3' => $this->buildElement('string', 0, ['max'=>50]), |
||
131 | 'city' => $this->buildElement('string', 1, ['max'=>50]), |
||
132 | 'country' => $this->buildElement('string', 1, ['max'=>10]), // TODO ISO 3166-1 alpha-2 country code. |
||
133 | 'postal_code' => $this->buildElement('string', 1, ['max'=>16]), |
||
134 | 'state' => $this->buildElement('string', 0, ['max'=>14]), // TODO country subdivision code defined in ISO 3166-2 |
||
135 | ]); |
||
136 | } |
||
137 | |||
138 | private function getCardHolderInfoConstraints() |
||
139 | { |
||
140 | return new Assert\Collection([ |
||
141 | 'email_address' => new Assert\Optional([ |
||
142 | new Assert\Email(['mode'=>'loose']) |
||
143 | ]), |
||
144 | 'mobile_phone_number' => $this->buildElement('string'), |
||
145 | 'work_phone_number' => $this->buildElement('string'), |
||
146 | 'home_phone_number' => $this->buildElement('string'), |
||
147 | ]); |
||
148 | } |
||
149 | |||
150 | private function buildElement($typeValue, $isRequired=0, $length=0, $args=0) |
||
165 |