| 1 |
<?php |
| 2 |
|
| 3 |
namespace FluentCart\App\Modules\PaymentMethods\PayPalGateway; |
| 4 |
|
| 5 |
use FluentCart\App\App; |
| 6 |
use FluentCart\App\Modules\PaymentMethods\PayPalGateway\API\API; |
| 7 |
use FluentCart\App\Modules\PaymentMethods\PayPalGateway\API\PayPalPartner; |
| 8 |
use FluentCart\App\Modules\PaymentMethods\PayPalGateway\API\Webhook; |
| 9 |
use FluentCart\App\Vite; |
| 10 |
use FluentCart\Framework\Http\Request\Request; |
| 11 |
use FluentCart\Framework\Support\Arr; |
| 12 |
|
| 13 |
class ConnectConfig |
| 14 |
{ |
| 15 |
public static function getConnectConfig() |
| 16 |
{ |
| 17 |
$PaypalSettings = new PayPalSettingsBase(); |
| 18 |
$settings = $PaypalSettings->get(); |
| 19 |
|
| 20 |
$testAccountInfo = self::getAccountInfo($settings, 'test'); |
| 21 |
$liveAccountInfo = self::getAccountInfo($settings, 'live'); |
| 22 |
|
| 23 |
$testConnectRedirect = admin_url('?fluent-cart=fluent_cart_payment_authenticate&payment_method=paypal&type=connect&mode=test'); |
| 24 |
$liveConnectRedirect = admin_url('?fluent-cart=fluent_cart_payment_authenticate&payment_method=paypal&type=connect&mode=live'); |
| 25 |
|
| 26 |
return [ |
| 27 |
'connect_config' => [ |
| 28 |
'test_redirect' => $testConnectRedirect, |
| 29 |
'live_redirect' => $liveConnectRedirect, |
| 30 |
'image_url' => Vite::getAssetUrl('images/payment-methods/paypal-icon.png'), |
| 31 |
'disconnect_note' => __('Disconnecting your PayPal account will prevent you from offering PayPal services and products on your website. Do you wish to continue?', 'fluent-cart') |
| 32 |
], |
| 33 |
'test_account' => $testAccountInfo, |
| 34 |
'live_account' => $liveAccountInfo, |
| 35 |
'settings' => $settings |
| 36 |
]; |
| 37 |
} |
| 38 |
|
| 39 |
public static function parseConnectInfos($vendorData) |
| 40 |
{ |
| 41 |
if (!$vendorData || !Arr::get($vendorData, 'permissionsGranted')) { |
| 42 |
echo '<div class="fct_message fct_message_error">' . esc_html(__('Invalid PayPal Request. Please try configuring paypal payment gateway again!', 'fluent-cart')) . '</div>'; |
| 43 |
die(); |
| 44 |
} |
| 45 |
|
| 46 |
$settingsInstance = App::gateway('paypal')->settings; |
| 47 |
|
| 48 |
$mode = Arr::get($vendorData, 'mode'); |
| 49 |
|
| 50 |
/* |
| 51 |
* @todo will verify later |
| 52 |
* we need to verify merchant manually after they create account |
| 53 |
* |
| 54 |
// start verifications if merchant able to receive payments |
| 55 |
$sellerAccessToken = fluent_cart_get_option('_paypal_partner_connect_access_token_' . Arr::get($vendorData, 'mode')); |
| 56 |
|
| 57 |
$accountData = (new PayPalPartner($mode))->verifyMerchant(Arr::get($sellerAccessToken, 'access_token'), Arr::get($vendorData, 'merchantIdInPayPal')); |
| 58 |
|
| 59 |
if (is_wp_error($accountData)) { |
| 60 |
echo '<div class="fct_message fct_message_error">' . esc_html($accountData->get_error_message()) . '</div>'; |
| 61 |
} |
| 62 |
|
| 63 |
if (!Arr::get($accountData, 'payments_receivable')) { |
| 64 |
echo '<div class="fct_message fct_message_error"> |
| 65 |
<p style="color: #b94a48; background: #f2dede; padding: 12px 16px; border-radius: 4px; border: 1px solid #ebccd1; margin: 0; max-width: 460px; margin:0 auto; margin-top: 10%;"> |
| 66 |
Attention: You currently cannot receive payments due to restriction on your PayPal account. Please reach out to PayPal Customer Support or connect to <a href="https://www.paypal.com" style="color: #31708f; text-decoration: underline;">https://www.paypal.com</a> for more information. |
| 67 |
</p> |
| 68 |
</div>'; |
| 69 |
die(); |
| 70 |
} |
| 71 |
|
| 72 |
if (!Arr::get($accountData, 'primary_email_confirmed')) { |
| 73 |
echo '<div class="fct_message fct_message_error"> |
| 74 |
<p style="color: #b94a48; background: #f2dede; padding: 12px 16px; border-radius: 4px; border: 1px solid #ebccd1; margin: 0; max-width: 460px; margin:0 auto; margin-top: 10%;line-height: 1.7rem;"> |
| 75 |
Attention: Please confirm your email address on <a href="https://www.paypal.com/businessprofile/settings" style="color: #31708f; text-decoration: underline;">https://www.paypal.com/businessprofile/settings</a> in order to receive payments! You currently cannot receive payments. |
| 76 |
</p> |
| 77 |
</div>'; |
| 78 |
die(); |
| 79 |
} |
| 80 |
|
| 81 |
* |
| 82 |
*/ |
| 83 |
|
| 84 |
// update all data that verified |
| 85 |
$data = [ |
| 86 |
$mode . '_email_address' => sanitize_text_field(Arr::get($vendorData, 'merchantId')), |
| 87 |
$mode . '_account_status' => sanitize_text_field(Arr::get($vendorData, 'accountStatus')), |
| 88 |
]; |
| 89 |
$settingsInstance->updateNonSensitiveData($data); |
| 90 |
|
| 91 |
wp_redirect(admin_url('admin.php?page=fluent-cart#/settings/payments/paypal')); |
| 92 |
} |
| 93 |
|
| 94 |
public function getSellerAuthToken(Request $request) |
| 95 |
{ |
| 96 |
|
| 97 |
$authCode = $request->getSafe('authCode', 'sanitize_text_field'); |
| 98 |
$clientId = $request->getSafe('sharedId', 'sanitize_text_field'); |
| 99 |
$mode = $request->getSafe('mode', 'sanitize_text_field'); |
| 100 |
$paypalConnect = new PayPalPartner($mode); |
| 101 |
|
| 102 |
try { |
| 103 |
|
| 104 |
$response = $paypalConnect->exchangeAuthCode($clientId, $authCode); |
| 105 |
|
| 106 |
if (isset($response['access_token'])) { |
| 107 |
$endpoint = "/v1/customer/partners/" . $paypalConnect->getPartnerId() . "/merchant-integrations/credentials/"; |
| 108 |
|
| 109 |
// retrieve the merchant client ID and client secret |
| 110 |
$credentials = $paypalConnect->makeMerchantRequest($endpoint, $response['access_token']); |
| 111 |
|
| 112 |
if (is_wp_error($credentials)) { |
| 113 |
wp_send_json([ |
| 114 |
'message' => $credentials->get_error_message() |
| 115 |
], 422); |
| 116 |
} |
| 117 |
if (is_array($credentials)) { |
| 118 |
static::prepareSettingToSave($credentials, $mode); |
| 119 |
} |
| 120 |
//update the existing access token for after redirect verification |
| 121 |
fluent_cart_update_option('_paypal_partner_connect_access_token_' . $mode, $response); |
| 122 |
} |
| 123 |
|
| 124 |
if (isset($response['error'])) { |
| 125 |
throw new \Exception($response['error_description']); |
| 126 |
} |
| 127 |
} catch (\Exception $exception) { |
| 128 |
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped |
| 129 |
throw new \Exception($exception->getMessage()); |
| 130 |
} |
| 131 |
} |
| 132 |
|
| 133 |
|
| 134 |
public static function prepareSettingToSave($credentials, $mode = 'live') |
| 135 |
{ |
| 136 |
$clientId = Arr::get($credentials, 'client_id'); |
| 137 |
$clientSecret = Arr::get($credentials, 'client_secret'); |
| 138 |
|
| 139 |
$data = [ |
| 140 |
$mode . '_client_id' => $clientId, |
| 141 |
$mode . '_client_secret' => $clientSecret, |
| 142 |
$mode . '_account_id' => Arr::get($credentials, 'payer_id'), |
| 143 |
'provider' => 'connect', |
| 144 |
'is_active' => 'yes', |
| 145 |
'payment_mode' => $mode |
| 146 |
]; |
| 147 |
|
| 148 |
$payPalInstance = App::gateway('paypal'); |
| 149 |
|
| 150 |
$oldSettings = $payPalInstance->settings->get(); |
| 151 |
$settingsData = wp_parse_args($data, $oldSettings); |
| 152 |
$payPalInstance->updateSettings($settingsData); |
| 153 |
|
| 154 |
//create webhook and setup endpoints |
| 155 |
(new Webhook())->registerWebhook($mode); |
| 156 |
} |
| 157 |
|
| 158 |
public static function verifyAuthorizeSuccess($data) |
| 159 |
{ |
| 160 |
$response = wp_remote_post(self::$connectBase . 'paypal-verify-code', [ |
| 161 |
'method' => 'POST', |
| 162 |
'timeout' => 60, |
| 163 |
'redirection' => 5, |
| 164 |
'httpversion' => '1.0', |
| 165 |
'sslverify' => false, |
| 166 |
'blocking' => true, |
| 167 |
'headers' => array(), |
| 168 |
'body' => $data, |
| 169 |
'cookies' => array() |
| 170 |
]); |
| 171 |
|
| 172 |
if (is_wp_error($response)) { |
| 173 |
$message = $response->get_error_message(); |
| 174 |
echo '<div class="fct_message fct_message_error">' . esc_html($message) . '</div>'; |
| 175 |
return; |
| 176 |
} |
| 177 |
|
| 178 |
$response = json_decode(wp_remote_retrieve_body($response), true); |
| 179 |
|
| 180 |
if (empty($response['paypal_user_id'])) { |
| 181 |
$message = Arr::get($response, 'message'); |
| 182 |
if (!$message) { |
| 183 |
$message = __('Invalid PayPal Request. Please configure paypal payment gateway again', 'fluent-cart'); |
| 184 |
} |
| 185 |
echo '<div class="fct_message fct_message_error">' . esc_html($message) . '</div>'; |
| 186 |
return; |
| 187 |
} |
| 188 |
|
| 189 |
$payPalInstance = App::gateway('paypal'); |
| 190 |
$settings = $payPalInstance->settings->get(); |
| 191 |
|
| 192 |
$settings['provider'] = 'connect'; |
| 193 |
|
| 194 |
$settings['is_active'] = 'yes'; |
| 195 |
|
| 196 |
if (!empty($response['livemode'])) { |
| 197 |
$settings['payment_mode'] = 'live'; |
| 198 |
$settings['live_account_id'] = $response['paypal_user_id']; |
| 199 |
$settings['live_publishable_key'] = $response['paypal_publishable_key']; |
| 200 |
$settings['live_secret_key'] = $response['access_token']; |
| 201 |
} else { |
| 202 |
$settings['payment_mode'] = 'test'; |
| 203 |
$settings['test_account_id'] = $response['paypal_user_id']; |
| 204 |
$settings['test_publishable_key'] = $response['paypal_publishable_key']; |
| 205 |
$settings['test_secret_key'] = $response['access_token']; |
| 206 |
} |
| 207 |
|
| 208 |
$payPalInstance->updateSettings($settings); |
| 209 |
} |
| 210 |
|
| 211 |
private static function getAccountInfo($settings, $mode) |
| 212 |
{ |
| 213 |
if (Arr::get($settings, 'provider') !== 'connect') { |
| 214 |
return false; |
| 215 |
} |
| 216 |
return API::retrieveAccount($settings, $mode); |
| 217 |
} |
| 218 |
|
| 219 |
public static function disconnect($mode, $sendResponse = true) |
| 220 |
{ |
| 221 |
$payPalInstance = App::gateway('paypal'); |
| 222 |
$paypalSettings = $payPalInstance->settings->get(); |
| 223 |
|
| 224 |
if (empty($paypalSettings[$mode . '_account_id'])) { |
| 225 |
if ($sendResponse) { |
| 226 |
wp_send_json([ |
| 227 |
'message' => __('Selected Account does not exist', 'fluent-cart') |
| 228 |
], 422); |
| 229 |
} |
| 230 |
return false; |
| 231 |
} |
| 232 |
|
| 233 |
$paypalSettings[$mode . '_account_id'] = ''; |
| 234 |
$paypalSettings[$mode . '_publishable_key'] = ''; |
| 235 |
$paypalSettings[$mode . '_secret_key'] = ''; |
| 236 |
$paypalSettings[$mode . '_webhook_events'] = []; |
| 237 |
$paypalSettings[$mode . '_webhook_id'] = ''; |
| 238 |
$paypalSettings[$mode . '_client_id'] = ''; |
| 239 |
$paypalSettings[$mode . '_client_secret'] = ''; |
| 240 |
|
| 241 |
if ($mode == 'live') { |
| 242 |
$alternateMode = 'test'; |
| 243 |
} else { |
| 244 |
$alternateMode = 'live'; |
| 245 |
} |
| 246 |
|
| 247 |
if (empty($paypalSettings[$alternateMode . '_account_id'])) { |
| 248 |
$paypalSettings['is_active'] = 'no'; |
| 249 |
$paypalSettings['payment_mode'] = 'test'; |
| 250 |
} else { |
| 251 |
$paypalSettings['payment_mode'] = $alternateMode; |
| 252 |
} |
| 253 |
|
| 254 |
$sendResponse = $payPalInstance->updateSettings($paypalSettings); |
| 255 |
|
| 256 |
if ($sendResponse) { |
| 257 |
wp_send_json([ |
| 258 |
'message' => __('PayPal settings has been disconnected', 'fluent-cart'), |
| 259 |
'settings' => $paypalSettings |
| 260 |
], 200); |
| 261 |
} |
| 262 |
|
| 263 |
return true; |
| 264 |
} |
| 265 |
} |
| 266 |
|