Edit File by line
/home/zeestwma/ceyloniy.../wp-conte.../plugins/wpforms-.../src/Integrat.../Stripe
File: Process.php
if ( $message instanceof ApiErrorException ) {
[1000] Fix | Delete
$body = $message->getJsonBody();
[1001] Fix | Delete
$message = isset( $body['error']['message'] ) ? $body['error'] : $message->getMessage();
[1002] Fix | Delete
}
[1003] Fix | Delete
[1004] Fix | Delete
wpforms_log(
[1005] Fix | Delete
$title,
[1006] Fix | Delete
$message,
[1007] Fix | Delete
[
[1008] Fix | Delete
'type' => [ 'payment', $level ],
[1009] Fix | Delete
'form_id' => $this->form_id,
[1010] Fix | Delete
]
[1011] Fix | Delete
);
[1012] Fix | Delete
}
[1013] Fix | Delete
[1014] Fix | Delete
/**
[1015] Fix | Delete
* Collect errors from API and turn it into form errors.
[1016] Fix | Delete
*
[1017] Fix | Delete
* @since 1.8.2
[1018] Fix | Delete
*
[1019] Fix | Delete
* @param string $type Payment time (e.g. 'single' or 'subscription').
[1020] Fix | Delete
*/
[1021] Fix | Delete
protected function process_api_error( $type ) {
[1022] Fix | Delete
[1023] Fix | Delete
$message = $this->api->get_error();
[1024] Fix | Delete
[1025] Fix | Delete
if ( empty( $message ) ) {
[1026] Fix | Delete
return;
[1027] Fix | Delete
}
[1028] Fix | Delete
[1029] Fix | Delete
$message = sprintf(
[1030] Fix | Delete
/* translators: %s - error message. */
[1031] Fix | Delete
esc_html__( 'Payment Error: %s', 'wpforms-lite' ),
[1032] Fix | Delete
$message
[1033] Fix | Delete
);
[1034] Fix | Delete
[1035] Fix | Delete
$this->display_error( $message );
[1036] Fix | Delete
[1037] Fix | Delete
if ( $type === 'subscription' ) {
[1038] Fix | Delete
$title = esc_html__( 'Stripe subscription payment stopped by error', 'wpforms-lite' );
[1039] Fix | Delete
} else {
[1040] Fix | Delete
$title = esc_html__( 'Stripe payment stopped by error', 'wpforms-lite' );
[1041] Fix | Delete
}
[1042] Fix | Delete
[1043] Fix | Delete
$this->log_error( $title, $this->api->get_exception() );
[1044] Fix | Delete
}
[1045] Fix | Delete
[1046] Fix | Delete
/**
[1047] Fix | Delete
* Display form error.
[1048] Fix | Delete
*
[1049] Fix | Delete
* @since 1.8.2
[1050] Fix | Delete
*
[1051] Fix | Delete
* @param string $error Error to display.
[1052] Fix | Delete
*/
[1053] Fix | Delete
private function display_error( $error ) {
[1054] Fix | Delete
[1055] Fix | Delete
if ( ! $error ) {
[1056] Fix | Delete
return;
[1057] Fix | Delete
}
[1058] Fix | Delete
[1059] Fix | Delete
$field_slug = $this->api->get_config( 'field_slug' );
[1060] Fix | Delete
[1061] Fix | Delete
// Check if the form contains a required credit card. If it does
[1062] Fix | Delete
// and there was an error, return the error to the user and prevent
[1063] Fix | Delete
// the form from being submitted. This should not occur under normal
[1064] Fix | Delete
// circumstances.
[1065] Fix | Delete
foreach ( $this->form_data['fields'] as $field ) {
[1066] Fix | Delete
[1067] Fix | Delete
if ( empty( $field['type'] ) || $field_slug !== $field['type'] ) {
[1068] Fix | Delete
continue;
[1069] Fix | Delete
}
[1070] Fix | Delete
[1071] Fix | Delete
if ( ! empty( $field['required'] ) ) {
[1072] Fix | Delete
wpforms()->obj( 'process' )->errors[ $this->form_id ]['footer'] = $error;
[1073] Fix | Delete
[1074] Fix | Delete
return;
[1075] Fix | Delete
}
[1076] Fix | Delete
}
[1077] Fix | Delete
}
[1078] Fix | Delete
[1079] Fix | Delete
/**
[1080] Fix | Delete
* Process card error from Stripe API exception and adds rate limit tracking.
[1081] Fix | Delete
*
[1082] Fix | Delete
* @since 1.8.2
[1083] Fix | Delete
*
[1084] Fix | Delete
* @param ApiErrorException $e Stripe API exception to process.
[1085] Fix | Delete
*/
[1086] Fix | Delete
public function process_card_error( $e ) {
[1087] Fix | Delete
[1088] Fix | Delete
if ( Helpers::get_stripe_mode() === 'test' ) {
[1089] Fix | Delete
return;
[1090] Fix | Delete
}
[1091] Fix | Delete
[1092] Fix | Delete
if ( ! is_a( $e, '\WPForms\Vendor\Stripe\Exception\CardException' ) ) {
[1093] Fix | Delete
return;
[1094] Fix | Delete
}
[1095] Fix | Delete
[1096] Fix | Delete
/**
[1097] Fix | Delete
* Allow to filter Stripe process card error.
[1098] Fix | Delete
*
[1099] Fix | Delete
* @since 1.8.2
[1100] Fix | Delete
*
[1101] Fix | Delete
* @param bool $flag True if any error.
[1102] Fix | Delete
*/
[1103] Fix | Delete
if ( ! apply_filters( 'wpforms_stripe_process_process_card_error', true ) ) { // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
[1104] Fix | Delete
return;
[1105] Fix | Delete
}
[1106] Fix | Delete
[1107] Fix | Delete
$this->rate_limit->increment_attempts();
[1108] Fix | Delete
}
[1109] Fix | Delete
[1110] Fix | Delete
/**
[1111] Fix | Delete
* Check if rate limit is under threshold and passes.
[1112] Fix | Delete
*
[1113] Fix | Delete
* @since 1.8.2
[1114] Fix | Delete
*/
[1115] Fix | Delete
protected function is_rate_limit_ok() {
[1116] Fix | Delete
[1117] Fix | Delete
return $this->rate_limit->is_ok();
[1118] Fix | Delete
}
[1119] Fix | Delete
[1120] Fix | Delete
/**
[1121] Fix | Delete
* Check if any API errors occurs.
[1122] Fix | Delete
*
[1123] Fix | Delete
* @since 1.8.4
[1124] Fix | Delete
*
[1125] Fix | Delete
* @return bool
[1126] Fix | Delete
*/
[1127] Fix | Delete
protected function is_api_errors() {
[1128] Fix | Delete
[1129] Fix | Delete
$this->api->setup_stripe();
[1130] Fix | Delete
[1131] Fix | Delete
$error = $this->api->get_error();
[1132] Fix | Delete
[1133] Fix | Delete
if ( $error ) {
[1134] Fix | Delete
$this->process_api_error( 'general' );
[1135] Fix | Delete
[1136] Fix | Delete
return true;
[1137] Fix | Delete
}
[1138] Fix | Delete
[1139] Fix | Delete
return false;
[1140] Fix | Delete
}
[1141] Fix | Delete
[1142] Fix | Delete
/**
[1143] Fix | Delete
* Check if recurring settings is configured correctly.
[1144] Fix | Delete
*
[1145] Fix | Delete
* @since 1.8.4
[1146] Fix | Delete
*
[1147] Fix | Delete
* @param {array} $settings Settings data.
[1148] Fix | Delete
*
[1149] Fix | Delete
* @return bool
[1150] Fix | Delete
*/
[1151] Fix | Delete
protected function is_recurring_settings_ok( $settings ) {
[1152] Fix | Delete
[1153] Fix | Delete
$error = '';
[1154] Fix | Delete
[1155] Fix | Delete
// Check subscription settings are provided.
[1156] Fix | Delete
if ( empty( $settings['period'] ) || empty( $settings['email'] ) ) {
[1157] Fix | Delete
$error = esc_html__( 'Stripe subscription payment stopped, missing form settings.', 'wpforms-lite' );
[1158] Fix | Delete
}
[1159] Fix | Delete
[1160] Fix | Delete
// Check for required customer email.
[1161] Fix | Delete
if ( ! $error && empty( $this->fields[ $settings['email'] ]['value'] ) ) {
[1162] Fix | Delete
$error = esc_html__( 'Stripe subscription payment stopped, customer email not found.', 'wpforms-lite' );
[1163] Fix | Delete
}
[1164] Fix | Delete
[1165] Fix | Delete
// Before proceeding, check if any basic errors were detected.
[1166] Fix | Delete
if ( $error ) {
[1167] Fix | Delete
$this->log_error( $error );
[1168] Fix | Delete
$this->display_error( $error );
[1169] Fix | Delete
[1170] Fix | Delete
return false;
[1171] Fix | Delete
}
[1172] Fix | Delete
[1173] Fix | Delete
return true;
[1174] Fix | Delete
}
[1175] Fix | Delete
[1176] Fix | Delete
/**
[1177] Fix | Delete
* Process subscription API call.
[1178] Fix | Delete
*
[1179] Fix | Delete
* @since 1.8.4
[1180] Fix | Delete
*
[1181] Fix | Delete
* @param array $args Prepared subscription arguments.
[1182] Fix | Delete
*/
[1183] Fix | Delete
protected function process_subscription( $args ) {
[1184] Fix | Delete
[1185] Fix | Delete
$this->subscription_settings = $args['settings'];
[1186] Fix | Delete
[1187] Fix | Delete
if ( ! Helpers::is_license_ok() && Helpers::is_application_fee_supported() ) {
[1188] Fix | Delete
$args['application_fee_percent'] = 3;
[1189] Fix | Delete
}
[1190] Fix | Delete
[1191] Fix | Delete
// Store spam reason if exists.
[1192] Fix | Delete
if ( isset( $this->form_data['spam_reason'] ) ) {
[1193] Fix | Delete
$args['metadata']['spam_reason'] = $this->form_data['spam_reason'];
[1194] Fix | Delete
}
[1195] Fix | Delete
[1196] Fix | Delete
$this->api->process_subscription( $args );
[1197] Fix | Delete
[1198] Fix | Delete
// Set payment processing flag.
[1199] Fix | Delete
$this->is_payment_processed = true;
[1200] Fix | Delete
[1201] Fix | Delete
// Update the credit card field value to contain basic details.
[1202] Fix | Delete
$this->update_credit_card_field_value();
[1203] Fix | Delete
[1204] Fix | Delete
$this->process_api_error( 'subscription' );
[1205] Fix | Delete
}
[1206] Fix | Delete
[1207] Fix | Delete
/**
[1208] Fix | Delete
* Get base subscription arguments.
[1209] Fix | Delete
*
[1210] Fix | Delete
* @since 1.8.4
[1211] Fix | Delete
*
[1212] Fix | Delete
* @return array
[1213] Fix | Delete
*/
[1214] Fix | Delete
protected function get_base_subscription_args() {
[1215] Fix | Delete
[1216] Fix | Delete
return [
[1217] Fix | Delete
'form_id' => $this->form_id,
[1218] Fix | Delete
'form_title' => sanitize_text_field( $this->form_data['settings']['form_title'] ),
[1219] Fix | Delete
'amount' => $this->amount * wpforms_get_currency_multiplier(),
[1220] Fix | Delete
];
[1221] Fix | Delete
}
[1222] Fix | Delete
[1223] Fix | Delete
/**
[1224] Fix | Delete
* Map WPForms Address field to Stripe format.
[1225] Fix | Delete
*
[1226] Fix | Delete
* @since 1.8.8
[1227] Fix | Delete
*
[1228] Fix | Delete
* @param array $submitted_data Submitted address data.
[1229] Fix | Delete
* @param string $field_id Address field ID.
[1230] Fix | Delete
*
[1231] Fix | Delete
* @return array
[1232] Fix | Delete
*/
[1233] Fix | Delete
private function map_address_field( array $submitted_data, string $field_id ): array {
[1234] Fix | Delete
[1235] Fix | Delete
$line = sanitize_text_field( $submitted_data['address1'] );
[1236] Fix | Delete
$country = '';
[1237] Fix | Delete
[1238] Fix | Delete
if ( isset( $submitted_data['address2'] ) ) {
[1239] Fix | Delete
$line .= ' ' . sanitize_text_field( $submitted_data['address2'] );
[1240] Fix | Delete
}
[1241] Fix | Delete
[1242] Fix | Delete
if ( isset( $submitted_data['country'] ) ) {
[1243] Fix | Delete
$country = sanitize_text_field( $submitted_data['country'] );
[1244] Fix | Delete
} elseif ( $this->form_data['fields'][ $field_id ]['scheme'] !== 'international' ) {
[1245] Fix | Delete
$country = 'US';
[1246] Fix | Delete
}
[1247] Fix | Delete
[1248] Fix | Delete
return [
[1249] Fix | Delete
'line1' => $line,
[1250] Fix | Delete
'state' => isset( $submitted_data['state'] ) ? sanitize_text_field( $submitted_data['state'] ) : '',
[1251] Fix | Delete
'city' => sanitize_text_field( $submitted_data['city'] ),
[1252] Fix | Delete
'postal_code' => sanitize_text_field( $submitted_data['postal'] ),
[1253] Fix | Delete
'country' => $country,
[1254] Fix | Delete
];
[1255] Fix | Delete
}
[1256] Fix | Delete
[1257] Fix | Delete
/**
[1258] Fix | Delete
* Check the submitted payment data whether it was corrupted.
[1259] Fix | Delete
* If so, refund a payment / cancel subscription.
[1260] Fix | Delete
*
[1261] Fix | Delete
* @since 1.8.8.2
[1262] Fix | Delete
*
[1263] Fix | Delete
* @param array $entry Submitted entry data.
[1264] Fix | Delete
*
[1265] Fix | Delete
* @return bool
[1266] Fix | Delete
*/
[1267] Fix | Delete
private function is_submitted_payment_data_corrupted( array $entry ): bool {
[1268] Fix | Delete
[1269] Fix | Delete
// Bail early if there are no payment intents.
[1270] Fix | Delete
if ( empty( $entry['payment_intent_id'] ) ) {
[1271] Fix | Delete
return false;
[1272] Fix | Delete
}
[1273] Fix | Delete
[1274] Fix | Delete
// Get stored corrupted payment intents if exist.
[1275] Fix | Delete
$corrupted_intents = (array) Transient::get( 'corrupted-stripe-intents' );
[1276] Fix | Delete
[1277] Fix | Delete
// We must prevent a processing if payment intent was identified as corrupted.
[1278] Fix | Delete
// Also if the transaction ID exists in DB (transaction ID is unique value).
[1279] Fix | Delete
if ( in_array( $entry['payment_intent_id'], $corrupted_intents, true ) || wpforms()->obj( 'payment' )->get_by( 'transaction_id', $entry['payment_intent_id'] ) ) {
[1280] Fix | Delete
wpforms()->obj( 'process' )->errors[ $this->form_id ]['footer'] = esc_html__( 'Secondary form submission was declined.', 'wpforms-lite' );
[1281] Fix | Delete
[1282] Fix | Delete
return true;
[1283] Fix | Delete
}
[1284] Fix | Delete
[1285] Fix | Delete
$intent = $this->api->retrieve_payment_intent(
[1286] Fix | Delete
$entry['payment_intent_id'],
[1287] Fix | Delete
[
[1288] Fix | Delete
'expand' => [ 'invoice.subscription' ],
[1289] Fix | Delete
]
[1290] Fix | Delete
);
[1291] Fix | Delete
[1292] Fix | Delete
// Round to the nearest whole number because $this->amount can contain a number close to,
[1293] Fix | Delete
// but slightly under it, due to how it is stored in the memory.
[1294] Fix | Delete
$submitted_amount = round( $this->amount * wpforms_get_currency_multiplier() );
[1295] Fix | Delete
[1296] Fix | Delete
// Prevent form submission if a mismatch of the payment amount is detected.
[1297] Fix | Delete
if ( ! empty( $intent ) && (int) $submitted_amount !== (int) $intent->amount ) {
[1298] Fix | Delete
wpforms()->obj( 'process' )->errors[ $this->form_id ]['footer'] = esc_html__( 'Irregular activity detected. Your submission has been declined and payment refunded.', 'wpforms-lite' );
[1299] Fix | Delete
[1300] Fix | Delete
$args = [
[1301] Fix | Delete
'reason' => 'fraudulent',
[1302] Fix | Delete
];
[1303] Fix | Delete
[1304] Fix | Delete
// We can't cancel a payment because it's already paid.
[1305] Fix | Delete
// So we can perform a refund only.
[1306] Fix | Delete
$this->api->refund_payment( $entry['payment_intent_id'], $args );
[1307] Fix | Delete
[1308] Fix | Delete
// Cancel subscription if exists.
[1309] Fix | Delete
if ( ! empty( $intent->invoice->subscription ) ) {
[1310] Fix | Delete
$this->api->cancel_subscription( $intent->invoice->subscription->id );
[1311] Fix | Delete
}
[1312] Fix | Delete
[1313] Fix | Delete
// This payment indent is identified as corrupted.
[1314] Fix | Delete
// Store it in order to prevent re-using it (form re-submitting).
[1315] Fix | Delete
if ( ! in_array( $entry['payment_intent_id'], $corrupted_intents, true ) ) {
[1316] Fix | Delete
$corrupted_intents[] = $entry['payment_intent_id'];
[1317] Fix | Delete
[1318] Fix | Delete
Transient::set( 'corrupted-stripe-intents', $corrupted_intents, WEEK_IN_SECONDS );
[1319] Fix | Delete
}
[1320] Fix | Delete
[1321] Fix | Delete
return true;
[1322] Fix | Delete
}
[1323] Fix | Delete
[1324] Fix | Delete
return false;
[1325] Fix | Delete
}
[1326] Fix | Delete
[1327] Fix | Delete
/**
[1328] Fix | Delete
* Maybe create a subscription schedule if the cycles was set.
[1329] Fix | Delete
*
[1330] Fix | Delete
* @since 1.9.8
[1331] Fix | Delete
*
[1332] Fix | Delete
* @param object $subscription Stripe subscription object.
[1333] Fix | Delete
*/
[1334] Fix | Delete
private function maybe_set_subscription_schedule( object $subscription ): void {
[1335] Fix | Delete
[1336] Fix | Delete
if ( empty( $subscription->metadata['cycles'] ) || $subscription->metadata['cycles'] === 'unlimited' || (int) $subscription->metadata['cycles'] < 1 || empty( $subscription->items->data ) ) {
[1337] Fix | Delete
return;
[1338] Fix | Delete
}
[1339] Fix | Delete
[1340] Fix | Delete
try {
[1341] Fix | Delete
$schedule = SubscriptionSchedule::create(
[1342] Fix | Delete
[
[1343] Fix | Delete
'from_subscription' => $subscription->id,
[1344] Fix | Delete
],
[1345] Fix | Delete
Helpers::get_auth_opts()
[1346] Fix | Delete
);
[1347] Fix | Delete
[1348] Fix | Delete
$subscription_item = $subscription->items->data[0];
[1349] Fix | Delete
[1350] Fix | Delete
$schedule::update(
[1351] Fix | Delete
$schedule->id,
[1352] Fix | Delete
[
[1353] Fix | Delete
'end_behavior' => 'cancel',
[1354] Fix | Delete
'phases' => [
[1355] Fix | Delete
[
[1356] Fix | Delete
'start_date' => $subscription_item->current_period_start,
[1357] Fix | Delete
'items' => [
[1358] Fix | Delete
[
[1359] Fix | Delete
'plan' => $subscription_item->plan->id,
[1360] Fix | Delete
],
[1361] Fix | Delete
],
[1362] Fix | Delete
'iterations' => $subscription->metadata['cycles'],
[1363] Fix | Delete
],
[1364] Fix | Delete
],
[1365] Fix | Delete
],
[1366] Fix | Delete
Helpers::get_auth_opts()
[1367] Fix | Delete
);
[1368] Fix | Delete
} catch ( \Exception $e ) {
[1369] Fix | Delete
[1370] Fix | Delete
wpforms_log(
[1371] Fix | Delete
'Stripe: Unable to create Subscription Schedule.',
[1372] Fix | Delete
$e->getMessage(),
[1373] Fix | Delete
[
[1374] Fix | Delete
'type' => [ 'payment', 'error' ],
[1375] Fix | Delete
]
[1376] Fix | Delete
);
[1377] Fix | Delete
}
[1378] Fix | Delete
}
[1379] Fix | Delete
}
[1380] Fix | Delete
[1381] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function