PluginProbe
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments / 1.0.4
SureCart – Ecommerce Made Easy For Selling Physical Products, Digital Downloads, Subscriptions, Donations, & Payments v1.0.4
4.7.2 4.7.1 4.7.0 4.6.6 4.6.5 4.6.4 4.6.3 4.6.2 4.6.1 4.6.0 4.5.1 4.5.0 4.4.2 4.4.1 4.4.0 4.3.3 4.3.2 4.3.1 4.3.0 4.2.3 4.2.2 4.2.1 1.0.3 1.0.4 1.0.5 All 281 releases
surecart / app / src / Controllers / Rest / OrderController.php
OrderController.php
288 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace SureCart\Controllers\Rest;
4
5 use SureCart\Models\Order;
6 use SureCart\Models\Form;
7 use SureCart\Models\User;
8 use SureCart\WordPress\Users\CustomerLinkService;
9
10 /**
11 * Handle price requests through the REST API
12 */
13 class OrderController extends RestController {
14 /**
15 * Class to make the requests.
16 *
17 * @var string
18 */
19 protected $class = Order::class;
20
21 /**
22 * Middleware before we make the request.
23 *
24 * @param \SureCart\Models\Model $class Model class instance.
25 * @param \WP_REST_Request $request Request object.
26 *
27 * @return \SureCart\Models\Model|\WP_Error
28 */
29 protected function middleware( $class, \WP_REST_Request $request ) {
30 $class = $this->setMode( $class, $request );
31 if ( is_wp_error( $class ) ) {
32 return $class;
33 }
34 $class = $this->maybeSetUser( $class, $request );
35 return $class;
36 }
37
38 /**
39 * Let's set the customer's email and name if they are already logged in.
40 *
41 * @param \SureCart\Models\Model $class Model class instance.
42 * @param \WP_REST_Request $request Request object.
43 *
44 * @return \SureCart\Models\Model|\WP_Error
45 */
46 protected function maybeSetUser( \SureCart\Models\Model $class, \WP_REST_Request $request ) {
47 // we only care about new sessions for now.
48 if ( $request->get_method() !== 'POST' ) {
49 return $class;
50 }
51
52 // get current user.
53 $user = User::current();
54
55 // must be logged in.
56 if ( ! $user ) {
57 return $class;
58 }
59
60 // fetch the user's customer object.
61 $customer = $user->customerId( ! empty( $request['live_mode'] ) ? 'live' : 'test' );
62
63 if ( ! empty( $customer->id ) ) {
64 $class['customer'] = $customer->id;
65 }
66
67 $class['email'] = $customer->email ?? $user->user_email;
68 $class['name'] = $customer->name ?? $user->display_name;
69
70 return $class;
71 }
72
73 /**
74 * We run middleware to make sure the form is in "Test" mode
75 * if a test payment is requested. This prevents the spamming of any
76 * forms on your site that are not in test mode.
77 *
78 * @param \SureCart\Models\Model $class Model class instance.
79 * @param \WP_REST_Request $request Request object.
80 *
81 * @return \SureCart\Models\Model|\WP_Error
82 */
83 protected function setMode( \SureCart\Models\Model $class, \WP_REST_Request $request ) {
84 $mode = 'live';
85 if ( false === $request['live_mode'] && ! current_user_can( 'edit_sc_orders' ) ) {
86 $mode = isset( $request['form_id'] ) ? $this->getFormMode( $request['form_id'] ) : 'live';
87 if ( 'test' !== $mode ) {
88 return new \WP_Error( 'invalid_mode', 'The form is set to live mode, but the request is for test mode.', [ 'status' => 400 ] );
89 }
90 $mode = 'test';
91 }
92 return $class;
93 }
94
95 /**
96 * Get the form mode
97 *
98 * @param integer $id ID of the form.
99 * @return string Mode of the form.
100 */
101 protected function getFormMode( $id ) {
102 return Form::getMode( (int) $id );
103 }
104
105 /**
106 * Finalize an order.
107 *
108 * @param \WP_REST_Request $request Rest Request.
109 *
110 * @return \SureCart\Models\Order|\WP_Error
111 */
112 public function finalize( \WP_REST_Request $request ) {
113 $args = $request->get_params();
114
115 // allow 3rd party validations on fields.
116 $errors = $this->validate( $args, $request );
117
118 // return early if errors.
119 if ( $errors->has_errors() ) {
120 return $errors;
121 }
122
123 $order = new $this->class( [ 'id' => $request['id'] ] );
124 $finalized = $order->setProcessor( $request['processor_type'] )
125 ->where( $request->get_query_params() )
126 ->finalize( array_diff_assoc( $request->get_params(), $request->get_query_params() ) );
127
128 // bail if error.
129 if ( is_wp_error( $finalized ) ) {
130 return $finalized;
131 }
132
133 // the order is paid (probably because of a coupon). Link the customer.
134 $linked = $this->maybeLinkCustomer( $finalized, $request );
135 if ( is_wp_error( $linked ) ) {
136 return $linked;
137 }
138
139 // return the order.
140 return $finalized;
141 }
142
143 /**
144 * Link the customer if the order status is paid only.
145 *
146 * @param \SureCart\Models\Order $order
147 * @param \WP_REST_Request $request
148 *
149 * @return \SureCart\Models\Order|\WP_Error
150 */
151 public function maybeLinkCustomer( $order, $request ) {
152 if ( 'paid' !== $order->status ) {
153 return false;
154 }
155 return $this->linkCustomerId( $order, $request );
156 }
157
158 /**
159 * Confirm an order.
160 *
161 * This force-fetches the order from the API and
162 * creates/syncs a WordPress user account if paid.
163 *
164 * @param \WP_REST_Request $request Rest Request.
165 *
166 * @return \SureCart\Models\Order|\WP_Error
167 */
168 public function confirm( \WP_REST_Request $request ) {
169 $order = $this->middleware( new $this->class(), $request );
170 if ( is_wp_error( $order ) ) {
171 return $order;
172 }
173
174 $order = $order->where(
175 array_merge(
176 $request->get_query_params(),
177 [ 'refresh_status' => true ] // Important: This will force syncing with the processor.
178 )
179 )->with(
180 [
181 'purchases', // Important: we need to make sure we expand the purchase to provide access.
182 ]
183 )->find( $request['id'] );
184
185 if ( is_wp_error( $order ) ) {
186 return $order;
187 }
188
189 if ( 'paid' !== $order->status ) {
190 return new \WP_Error( 'invalid_status', 'The order is not paid.', [ 'status' => 400 ] );
191 }
192
193 // link the customer id to the user.
194 $linked = $this->maybeLinkCustomer( $order, $request );
195 if ( is_wp_error( $linked ) ) {
196 return $linked;
197 }
198
199 // purchase created.
200 if ( ! empty( $order->purchases->data ) ) {
201 foreach ( $order->purchases->data as $purchase ) {
202 if ( empty( $purchase->revoked ) ) {
203 // broadcast the webhook.
204 do_action( 'surecart/purchase_created', $purchase );
205 }
206 }
207 }
208
209 // the order is confirmed.
210 do_action( 'surecart/order_confirmed', $order, $request );
211
212 // return the order.
213 return $order;
214 }
215
216 /**
217 * Link the customer id to the order.
218 *
219 * @param \SureCart\Models\Order $order Order model.
220 * @param \WP_REST_Request $request Request object.
221 * @return \WP_User|\WP_Error
222 */
223 public function linkCustomerId( $order, $request ) {
224 $service = new CustomerLinkService( $order, $request->get_param( 'password' ) );
225 return $service->link();
226 }
227
228 /**
229 * Validate the form.
230 *
231 * @param array $args Arguments.
232 * @param object $request Request.
233 * @return \WP_Error Errors.
234 */
235 public function validate( $args, $request ) {
236 $errors = new \WP_Error();
237
238 // check if they are trying to sign in.
239 $valid_login = $this->maybeValidateLoginCreds( $request->get_param( 'email' ), $request->get_param( 'password' ) );
240 if ( is_wp_error( $valid_login ) ) {
241 $errors->add( $valid_login->get_error_code(), $valid_login->get_error_message() );
242 }
243
244 return apply_filters( 'surecart/checkout/validate', $errors, $args, $request );
245 }
246
247 /**
248 * Check if the user is trying to sign in.
249 * If so, validate credentials before finalizing.
250 *
251 * @param string $email Email.
252 * @param string $password Password.
253 *
254 * @return true|\WP_Error
255 */
256 public function maybeValidateLoginCreds( $email = '', $password = '' ) {
257 // check if the person is signing in using a password and sign them in.
258 if ( $password && $email ) {
259 // user exists, try signing in with password.
260 $user = get_user_by( 'email', $email );
261 // if there's a user, check the username and password before we submit the order.
262 if ( false !== $user ) {
263 return wp_authenticate_username_password( null, $user->user_login, $password );
264 }
265 }
266 return true;
267 }
268
269 /**
270 * Create or login the user.
271 *
272 * @param string $user_email Username.
273 * @param string $password User password.
274 * @return \WP_Error|true
275 */
276 protected function maybeLoginUser( $user_email, $password = '' ) {
277 if ( empty( $password ) ) {
278 return;
279 }
280 return wp_signon(
281 [
282 'user_login' => $user_email,
283 'user_password' => $password,
284 ]
285 );
286 }
287 }
288