mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-31 01:17:33 -04:00 
			
		
		
		
	Fixes for text body templates
This commit is contained in:
		
							parent
							
								
									de853b3445
								
							
						
					
					
						commit
						d23866932b
					
				| @ -126,7 +126,7 @@ class BaseEmailEngine implements EngineInterface | ||||
| 
 | ||||
|         if (! empty($this->variables)) { | ||||
| 
 | ||||
|             $text = str_replace(['$paymentLink', '$viewButton', '$view_button', '$viewLink', '$view_link'], '$view_url', $text); | ||||
|             $text = str_replace(['$paymentLink', '$viewButton', '$view_button', '$viewLink', '$view_link'], "\r\n\r\n".'$view_url'."\r\n", $text); | ||||
|             $text = str_replace(array_keys($this->variables), array_values($this->variables), $text); | ||||
|             $text = str_replace(array_keys($this->variables), array_values($this->variables), $text); | ||||
| 
 | ||||
|  | ||||
| @ -16,6 +16,7 @@ use Carbon\Carbon; | ||||
| use App\Models\Invoice; | ||||
| use App\Models\SystemLog; | ||||
| use App\Models\GatewayType; | ||||
| use App\Models\PaymentHash; | ||||
| use App\Models\PaymentType; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Jobs\Util\SystemLogger; | ||||
| @ -30,6 +31,8 @@ class PayPalBasePaymentDriver extends BaseDriver | ||||
| { | ||||
|     use MakesHash; | ||||
| 
 | ||||
|     public string $risk_guid; | ||||
| 
 | ||||
|     public $token_billing = true; | ||||
| 
 | ||||
|     public $can_authorise_credit_card = false; | ||||
| @ -106,6 +109,7 @@ class PayPalBasePaymentDriver extends BaseDriver | ||||
| 
 | ||||
|     public function init() | ||||
|     { | ||||
|         $this->risk_guid = Str::random(32); | ||||
| 
 | ||||
|         $this->api_endpoint_url = $this->company_gateway->getConfigField('testMode') ? 'https://api-m.sandbox.paypal.com' : 'https://api-m.paypal.com'; | ||||
| 
 | ||||
| @ -432,6 +436,7 @@ class PayPalBasePaymentDriver extends BaseDriver | ||||
|             'Accept-Language' => 'en_US', | ||||
|             'PayPal-Partner-Attribution-Id' => 'invoiceninja_SP_PPCP', | ||||
|             'PayPal-Request-Id' => Str::uuid()->toString(), | ||||
|             'PAYPAL-CLIENT-METADATA-ID' => $this->risk_guid, | ||||
|         ], $headers); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -16,6 +16,7 @@ use Carbon\Carbon; | ||||
| use App\Models\Invoice; | ||||
| use App\Models\SystemLog; | ||||
| use App\Models\GatewayType; | ||||
| use App\Models\PaymentHash; | ||||
| use App\Models\PaymentType; | ||||
| use Illuminate\Http\Request; | ||||
| use App\Jobs\Util\SystemLogger; | ||||
| @ -84,6 +85,7 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver | ||||
|      */ | ||||
|     public function processPaymentView($data) | ||||
|     { | ||||
| 
 | ||||
|         $this->init()->checkPaymentsReceivable(); | ||||
| 
 | ||||
|         $data['gateway'] = $this; | ||||
| @ -97,6 +99,7 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver | ||||
|         $data['gateway_type_id'] = $this->gateway_type_id; | ||||
|         $data['merchantId'] = $this->company_gateway->getConfigField('merchantId'); | ||||
|         $data['currency'] = $this->client->currency()->code; | ||||
|         $data['guid'] = $this->risk_guid; | ||||
| 
 | ||||
|         if($this->gateway_type_id == 29) | ||||
|             return render('gateways.paypal.ppcp.card', $data); | ||||
| @ -109,7 +112,6 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver | ||||
|      * Processes the payment response | ||||
|      * | ||||
|      * @param  mixed $request | ||||
|      * @return void | ||||
|      */ | ||||
|     public function processPaymentResponse($request) | ||||
|     { | ||||
| @ -366,4 +368,73 @@ class PayPalPPCPPaymentDriver extends PayPalBasePaymentDriver | ||||
|         return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) | ||||
|     { | ||||
|         $data = []; | ||||
|         $this->payment_hash = $payment_hash; | ||||
| 
 | ||||
|         $data['amount_with_fee'] = $this->payment_hash->data->amount_with_fee; | ||||
|         $data["payment_source"] = [ | ||||
|             "card" => [ | ||||
|                 "vault_id" => $cgt->token, | ||||
|                 "stored_credential" => [ | ||||
|                     "payment_initiator" => "MERCHANT", | ||||
|                     "payment_type" => "UNSCHEDULED", | ||||
|                     "usage" => "SUBSEQUENT", | ||||
|                 ], | ||||
|             ], | ||||
|         ]; | ||||
| 
 | ||||
|         $orderId = $this->createOrder($data); | ||||
| 
 | ||||
|         $r = false; | ||||
| 
 | ||||
|         try { | ||||
| 
 | ||||
|             $r = $this->gatewayRequest("/v2/checkout/orders/{$orderId}", 'get', ['body' => '']); | ||||
| 
 | ||||
|             if($r->status() == 422) { | ||||
|                 //handle conditions where the client may need to try again.
 | ||||
| 
 | ||||
|                 $r = $this->handleDuplicateInvoiceId($orderId); | ||||
| 
 | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } catch(\Exception $e) { | ||||
| 
 | ||||
|             //Rescue for duplicate invoice_id
 | ||||
|             if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false) { | ||||
| 
 | ||||
| 
 | ||||
|                 $r = $this->handleDuplicateInvoiceId($orderId); | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         $response = $r->json(); | ||||
| 
 | ||||
|         $data = [ | ||||
|             'payment_type' => $this->getPaymentMethod((string)$cgt->gateway_type_id), | ||||
|             'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'], | ||||
|             'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'], | ||||
|             'gateway_type_id' => $this->gateway_type_id, | ||||
|         ]; | ||||
| 
 | ||||
|         $payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED); | ||||
| 
 | ||||
|         SystemLogger::dispatch( | ||||
|             ['response' => $response, 'data' => $data], | ||||
|             SystemLog::CATEGORY_GATEWAY_RESPONSE, | ||||
|             SystemLog::EVENT_GATEWAY_SUCCESS, | ||||
|             SystemLog::TYPE_PAYPAL_PPCP, | ||||
|             $this->client, | ||||
|             $this->client->company, | ||||
|         ); | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
|      | ||||
| } | ||||
| @ -20,6 +20,7 @@ use App\Jobs\Util\SystemLogger; | ||||
| use App\Utils\Traits\MakesHash; | ||||
| use App\Exceptions\PaymentFailed; | ||||
| use App\Models\ClientGatewayToken; | ||||
| use App\Models\PaymentHash; | ||||
| use App\PaymentDrivers\PayPal\PayPalBasePaymentDriver; | ||||
| 
 | ||||
| class PayPalRestPaymentDriver extends PayPalBasePaymentDriver | ||||
| @ -30,6 +31,7 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver | ||||
| 
 | ||||
|     public function processPaymentView($data) | ||||
|     { | ||||
|          | ||||
|         $this->init(); | ||||
| 
 | ||||
|         $data['gateway'] = $this; | ||||
| @ -43,6 +45,7 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver | ||||
|         $data['funding_source'] = $this->paypal_payment_method; | ||||
|         $data['gateway_type_id'] = $this->gateway_type_id; | ||||
|         $data['currency'] = $this->client->currency()->code; | ||||
|         $data['guid'] = $this->risk_guid; | ||||
| 
 | ||||
|         if($this->gateway_type_id == 29) | ||||
|             return render('gateways.paypal.ppcp.card', $data); | ||||
| @ -56,7 +59,6 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver | ||||
|      * processPaymentResponse | ||||
|      * | ||||
|      * @param  mixed $request | ||||
|      * @return void | ||||
|      */ | ||||
|     public function processPaymentResponse($request) | ||||
|     { | ||||
| @ -291,7 +293,6 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver | ||||
|      *  | ||||
|      * @param  mixed $request | ||||
|      * @param  array $response | ||||
|      * @return void | ||||
|      */ | ||||
|     public function processTokenPayment($request, array $response) { | ||||
| 
 | ||||
| @ -342,4 +343,72 @@ class PayPalRestPaymentDriver extends PayPalBasePaymentDriver | ||||
|         return redirect()->route('client.payments.show', ['payment' => $this->encodePrimaryKey($payment->id)]); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public function tokenBilling(ClientGatewayToken $cgt, PaymentHash $payment_hash) | ||||
|     { | ||||
|         $data = []; | ||||
|         $this->payment_hash = $payment_hash; | ||||
| 
 | ||||
|         $data['amount_with_fee'] = $this->payment_hash->data->amount_with_fee; | ||||
|         $data["payment_source"] = [ | ||||
|             "card" => [ | ||||
|                 "vault_id" => $cgt->token, | ||||
|                 "stored_credential" => [ | ||||
|                     "payment_initiator" => "MERCHANT", | ||||
|                     "payment_type" => "UNSCHEDULED", | ||||
|                     "usage" => "SUBSEQUENT", | ||||
|                 ], | ||||
|             ], | ||||
|         ]; | ||||
| 
 | ||||
|         $orderId = $this->createOrder($data); | ||||
| 
 | ||||
|         $r = false; | ||||
|                  | ||||
|         try { | ||||
| 
 | ||||
|             $r = $this->gatewayRequest("/v2/checkout/orders/{$orderId}", 'get', ['body' => '']); | ||||
| 
 | ||||
|             if($r->status() == 422) { | ||||
|                 //handle conditions where the client may need to try again.
 | ||||
| 
 | ||||
|                 $r = $this->handleDuplicateInvoiceId($orderId); | ||||
| 
 | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } catch(\Exception $e) { | ||||
| 
 | ||||
|             //Rescue for duplicate invoice_id
 | ||||
|             if(stripos($e->getMessage(), 'DUPLICATE_INVOICE_ID') !== false) { | ||||
| 
 | ||||
| 
 | ||||
|                 $r = $this->handleDuplicateInvoiceId($orderId); | ||||
| 
 | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         $response = $r->json(); | ||||
| 
 | ||||
|         $data = [ | ||||
|             'payment_type' => $this->getPaymentMethod((string)$cgt->gateway_type_id), | ||||
|             'amount' => $response['purchase_units'][0]['payments']['captures'][0]['amount']['value'], | ||||
|             'transaction_reference' => $response['purchase_units'][0]['payments']['captures'][0]['id'], | ||||
|             'gateway_type_id' => $this->gateway_type_id, | ||||
|         ]; | ||||
| 
 | ||||
|         $payment = $this->createPayment($data, \App\Models\Payment::STATUS_COMPLETED); | ||||
| 
 | ||||
|         SystemLogger::dispatch( | ||||
|             ['response' => $response, 'data' => $data], | ||||
|             SystemLog::CATEGORY_GATEWAY_RESPONSE, | ||||
|             SystemLog::EVENT_GATEWAY_SUCCESS, | ||||
|             SystemLog::TYPE_PAYPAL_PPCP, | ||||
|             $this->client, | ||||
|             $this->client->company, | ||||
|         ); | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -180,7 +180,7 @@ class EmailDefaults | ||||
|         $breaks = ["<br />","<br>","<br/>"]; | ||||
|         $this->email->email_object->text_body = str_ireplace($breaks, "\r\n", $this->email->email_object->body); | ||||
|         $this->email->email_object->text_body = strip_tags($this->email->email_object->text_body); | ||||
|         $this->email->email_object->text_body = str_replace(['$view_button','$viewButton'], '$view_url', $this->email->email_object->text_body); | ||||
|         $this->email->email_object->text_body = str_replace(['$view_button','$viewButton'], "\r\n\r\n".'$view_url'."\r\n", $this->email->email_object->text_body); | ||||
| 
 | ||||
|         if ($this->template == 'email.template.custom') { | ||||
|             $this->email->email_object->body = (str_replace('$body', $this->email->email_object->body, str_replace(["\r","\n"], "", $this->email->email_object->settings->email_style_custom))); | ||||
|  | ||||
| @ -29,6 +29,17 @@ | ||||
| @endsection | ||||
| 
 | ||||
| @push('footer') | ||||
| 
 | ||||
| <script type="application/json" fncls="fnparams-dede7cc5-15fd-4c75-a9f4-36c430ee3a99"> | ||||
|     { | ||||
|         "f":"{{ $guid }}", | ||||
|         "s":"paypal.pay"        // unique ID for each web page
 | ||||
|     } | ||||
| </script> | ||||
| 
 | ||||
| <script type="text/javascript" src="https://c.paypal.com/da/r/fb.js"></script> | ||||
| 
 | ||||
| 
 | ||||
| <style type="text/css"> | ||||
| .loader { | ||||
| width: 48px; | ||||
|  | ||||
| @ -75,6 +75,14 @@ | ||||
| @endsection | ||||
| 
 | ||||
| @push('footer') | ||||
| <script type="application/json" fncls="fnparams-dede7cc5-15fd-4c75-a9f4-36c430ee3a99"> | ||||
|     { | ||||
|         "f":"{{ $guid }}", | ||||
|         "s":"paypal.card"        // unique ID for each web page
 | ||||
|     } | ||||
| </script> | ||||
| 
 | ||||
| <script type="text/javascript" src="https://c.paypal.com/da/r/fb.js"></script> | ||||
| 
 | ||||
| @if(isset($merchantId)) | ||||
| <script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}&merchantId={!! $merchantId !!}&components=card-fields"  data-partner-attribution-id="invoiceninja_SP_PPCP"></script> | ||||
| @ -150,6 +158,10 @@ | ||||
|             }) | ||||
|             .catch(error => { | ||||
|                 console.error('Error:', error); | ||||
|                  | ||||
|                 document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`; | ||||
|                 document.getElementById('errors').hidden = false; | ||||
| 
 | ||||
|             }); | ||||
| 
 | ||||
|         }, | ||||
| @ -157,12 +169,20 @@ | ||||
| 
 | ||||
|             window.location.href = "/client/invoices/"; | ||||
|         }, | ||||
|         onError: function(error) { | ||||
|         // onError: function(error) {
 | ||||
| 
 | ||||
|             document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${error.message}`; | ||||
|             document.getElementById('errors').hidden = false; | ||||
| 
 | ||||
|         }, | ||||
|         // console.log("submit catch");
 | ||||
|         // const errorM = parseError(error);
 | ||||
| 
 | ||||
|         // console.log(errorM);
 | ||||
| 
 | ||||
|         // const msg = handle422Error(errorM);
 | ||||
| 
 | ||||
|         //     document.getElementById('errors').textContent = `Sorry, your transaction could not be processed...\n\n${msg.description}`;
 | ||||
|         //     document.getElementById('errors').hidden = false;
 | ||||
| 
 | ||||
|         // },
 | ||||
|         onClick: function (){ | ||||
|             | ||||
|         } | ||||
| @ -213,10 +233,18 @@ | ||||
| 
 | ||||
|         document.querySelector('#pay-now > span').classList.add('hidden'); | ||||
| 
 | ||||
|         cardField.submit().then((response) => { | ||||
|         cardField.submit().then(() => { | ||||
| 
 | ||||
|         }).catch((error) => { | ||||
| 
 | ||||
|             let msg; | ||||
| 
 | ||||
|             if(!['INVALID_NUMBER','INVALID_CVV','INVALID_EXPIRY'].includes(error.message)) | ||||
|             { | ||||
|                 const errorM = parseError(error.message); | ||||
|                 msg = handle422Error(errorM); | ||||
|             } | ||||
| 
 | ||||
|             document.getElementById('pay-now').disabled = false; | ||||
|             document.querySelector('#pay-now > svg').classList.add('hidden'); | ||||
|             document.querySelector('#pay-now > span').classList.remove('hidden'); | ||||
| @ -230,7 +258,9 @@ | ||||
|             else if(error.message == 'INVALID_EXPIRY') { | ||||
|               document.getElementById('errors').textContent = "{{ ctrans('texts.invalid_cvv') }}"; | ||||
|             } | ||||
| 
 | ||||
|             else if(msg.description){ | ||||
|                 document.getElementById('errors').textContent = msg?.description; | ||||
|             } | ||||
|             document.getElementById('errors').hidden = false; | ||||
| 
 | ||||
|         }); | ||||
| @ -242,6 +272,39 @@ | ||||
| 
 | ||||
|   } | ||||
| 
 | ||||
|     function handle422Error(errorData) { | ||||
|         const errorDetails = errorData.details || []; | ||||
|         const detail = errorDetails[0];         | ||||
|         return detail; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     function parseError(errorMessage) | ||||
|     { | ||||
|         try { | ||||
|             JSON.parse(errorMessage); | ||||
|             return errorMessage; | ||||
|         } catch (e) { | ||||
|              | ||||
|         } | ||||
| 
 | ||||
|         const startIndex = errorMessage.indexOf('{'); | ||||
|         const endIndex = errorMessage.lastIndexOf('}'); | ||||
|          | ||||
|         if (startIndex !== -1 && endIndex !== -1 && endIndex > startIndex) { | ||||
|             const jsonString = errorMessage.substring(startIndex, endIndex + 1); | ||||
|             try { | ||||
|                 const json = JSON.parse(jsonString); | ||||
|                 return json; | ||||
|             } catch (error) { | ||||
|                 return null; | ||||
|             } | ||||
|         } else { | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| </script> | ||||
| 
 | ||||
| 
 | ||||
| @ -266,7 +329,6 @@ | ||||
|   if (payWithCreditCardToggle) { | ||||
|       payWithCreditCardToggle | ||||
|           .addEventListener('click', () => { | ||||
|             console.log("Cc"); | ||||
|               document | ||||
|                   .getElementById('save-card--container').style.display = 'grid'; | ||||
|              document | ||||
|  | ||||
| @ -25,6 +25,16 @@ | ||||
| 
 | ||||
| @push('footer') | ||||
| 
 | ||||
| <script type="application/json" fncls="fnparams-dede7cc5-15fd-4c75-a9f4-36c430ee3a99"> | ||||
|     { | ||||
|         "f":"{{ $guid }}", | ||||
|         "s":"paypal.ppcp.pay"        // unique ID for each web page
 | ||||
|     } | ||||
| </script> | ||||
| 
 | ||||
| <script type="text/javascript" src="https://c.paypal.com/da/r/fb.js"></script> | ||||
| 
 | ||||
| 
 | ||||
| <script src="https://www.paypal.com/sdk/js?client-id={!! $client_id !!}¤cy={!! $currency !!}&merchant-id={!! $merchantId !!}&components=buttons,funding-eligibility&intent=capture&enable-funding={!! $funding_source !!}"  data-partner-attribution-id="invoiceninja_SP_PPCP"></script> | ||||
| <script> | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user