mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-10-31 10:17:33 -04:00 
			
		
		
		
	Stripe: Alipay implementation
This commit is contained in:
		
							parent
							
								
									18892220c7
								
							
						
					
					
						commit
						b6ad39b8e2
					
				| @ -120,7 +120,7 @@ class PaymentController extends Controller | ||||
| 
 | ||||
|         return $gateway | ||||
|             ->driver(auth()->user()->client) | ||||
|             ->setPaymentMethod('App\\PaymentDrivers\\Stripe\\ACH') | ||||
|             ->setPaymentMethod('App\\PaymentDrivers\\Stripe\\Alipay') | ||||
|             ->processPaymentView($data); | ||||
|     } | ||||
| 
 | ||||
| @ -130,7 +130,7 @@ class PaymentController extends Controller | ||||
| 
 | ||||
|         return $gateway | ||||
|             ->driver(auth()->user()->client) | ||||
|             ->setPaymentMethod('App\\PaymentDrivers\\Stripe\\ACH') | ||||
|             ->setPaymentMethod('App\\PaymentDrivers\\Stripe\\Alipay') | ||||
|             ->processPaymentResponse($request); | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										113
									
								
								app/PaymentDrivers/Stripe/Alipay.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								app/PaymentDrivers/Stripe/Alipay.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,113 @@ | ||||
| <?php | ||||
| 
 | ||||
| /** | ||||
|  * Invoice Ninja (https://invoiceninja.com) | ||||
|  * | ||||
|  * @link https://github.com/invoiceninja/invoiceninja source repository | ||||
|  * | ||||
|  * @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com) | ||||
|  * | ||||
|  * @license https://opensource.org/licenses/AAL | ||||
|  */ | ||||
| 
 | ||||
| namespace App\PaymentDrivers\Stripe; | ||||
| 
 | ||||
| use App\Events\Payment\PaymentWasCreated; | ||||
| use App\Jobs\Mail\PaymentFailureMailer; | ||||
| use App\Jobs\Util\SystemLogger; | ||||
| use App\Models\GatewayType; | ||||
| use App\Models\Payment; | ||||
| use App\Models\PaymentType; | ||||
| use App\Models\SystemLog; | ||||
| use App\PaymentDrivers\StripePaymentDriver; | ||||
| 
 | ||||
| class Alipay | ||||
| { | ||||
|     /** @var StripePaymentDriver */ | ||||
|     public $stripe; | ||||
| 
 | ||||
|     public function __construct(StripePaymentDriver $stripe) | ||||
|     { | ||||
|         $this->stripe = $stripe; | ||||
|     } | ||||
| 
 | ||||
|     public function paymentView(array $data) | ||||
|     { | ||||
|         $data['gateway'] = $this->stripe; | ||||
|         $data['return_url'] = $this->buildReturnUrl($data); | ||||
|         $data['currency'] = $this->stripe->client->getCurrencyCode(); | ||||
|         $data['stripe_amount'] = $this->stripe->convertToStripeAmount($data['amount_with_fee'], $this->stripe->client->currency()->precision); | ||||
| 
 | ||||
|         return render('gateways.stripe.alipay.pay', $data); | ||||
|     } | ||||
| 
 | ||||
|     private function buildReturnUrl($data): string | ||||
|     { | ||||
|         return route('client.payments.response', [ | ||||
|             'company_gateway_id' => $this->stripe->company_gateway->id, | ||||
|             'gateway_type_id' => GatewayType::SOFORT, | ||||
|             'hashed_ids' => implode(",", $data['hashed_ids']), | ||||
|             'amount' => $data['amount'], | ||||
|             'fee' => $data['fee'], | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
|     public function paymentResponse($request) | ||||
|     { | ||||
|         $state = array_merge($request->all(), []); | ||||
|         $amount = $state['amount'] + $state['fee']; | ||||
|         $state['amount'] = $this->stripe->convertToStripeAmount($amount, $this->stripe->client->currency()->precision); | ||||
| 
 | ||||
|         if ($request->redirect_status == 'succeeded') { | ||||
|             return $this->processSuccesfulRedirect($state); | ||||
|         } | ||||
| 
 | ||||
|         return $this->processUnsuccesfulRedirect($state); | ||||
|     } | ||||
| 
 | ||||
|     public function processSuccesfulRedirect($state) | ||||
|     { | ||||
|         $state['charge_id'] = $state['source']; | ||||
| 
 | ||||
|         $this->stripe->init(); | ||||
| 
 | ||||
|         $state['payment_type'] = PaymentType::ALIPAY; | ||||
| 
 | ||||
|         $data = [ | ||||
|             'payment_method' => $state['charge_id'], | ||||
|             'payment_type' => $state['payment_type'], | ||||
|             'amount' => $state['amount'], | ||||
|         ]; | ||||
| 
 | ||||
|         $payment = $this->stripe->createPayment($data, Payment::STATUS_PENDING); | ||||
| 
 | ||||
|         if (isset($state['hashed_ids'])) { | ||||
|             $this->stripe->attachInvoices($payment, $state['hashed_ids']); | ||||
|         } | ||||
| 
 | ||||
|         event(new PaymentWasCreated($payment, $payment->company)); | ||||
| 
 | ||||
|         $logger_message = [ | ||||
|             'server_response' => $state, | ||||
|             'data' => $data | ||||
|         ]; | ||||
| 
 | ||||
|         SystemLogger::dispatch($logger_message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_SUCCESS, SystemLog::TYPE_STRIPE, $this->stripe->client); | ||||
| 
 | ||||
|         return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]); | ||||
|     } | ||||
| 
 | ||||
|     public function processUnsuccesfulRedirect($state) | ||||
|     { | ||||
|         PaymentFailureMailer::dispatch($this->stripe->client, $state['charge']->failure_message, $this->stripe->client->company, $state['amount']); | ||||
| 
 | ||||
|         $message = [ | ||||
|             'server_response' => $state['charge'], | ||||
|             'data' => $state, | ||||
|         ]; | ||||
| 
 | ||||
|         SystemLogger::dispatch($message, SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_STRIPE, $this->stripe->client); | ||||
| 
 | ||||
|         throw new \Exception('Failed to process the payment.', 1); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										54
									
								
								resources/js/clients/payments/alipay.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								resources/js/clients/payments/alipay.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,54 @@ | ||||
| /** | ||||
|  * Invoice Ninja (https://invoiceninja.com)
 | ||||
|  * | ||||
|  * @link https://github.com/invoiceninja/invoiceninja source repository
 | ||||
|  * | ||||
|  * @copyright Copyright (c) 2020. Invoice Ninja LLC (https://invoiceninja.com)
 | ||||
|  * | ||||
|  * @license https://opensource.org/licenses/AAL
 | ||||
|  */ | ||||
| 
 | ||||
| class ProcessAlipay { | ||||
|     constructor(key) { | ||||
|         this.key = key; | ||||
|         this.errors = document.getElementById('errors'); | ||||
|     } | ||||
| 
 | ||||
|     setupStripe = () => { | ||||
|         this.stripe = Stripe(this.key); | ||||
| 
 | ||||
|         return this; | ||||
|     }; | ||||
| 
 | ||||
|     handle = () => { | ||||
|         let data = { | ||||
|             type: 'alipay', | ||||
|             amount: document.querySelector('meta[name="amount"]').content, | ||||
|             currency: document.querySelector('meta[name="currency"]').content, | ||||
|             redirect: { | ||||
|                 return_url: document.querySelector('meta[name="return-url"]') | ||||
|                     .content, | ||||
|             }, | ||||
|         }; | ||||
| 
 | ||||
|         document.getElementById('pay-now').addEventListener('submit', (e) => { | ||||
|             e.preventDefault(); | ||||
| 
 | ||||
|             this.stripe.createSource(data).then(function(result) { | ||||
|                 if (result.hasOwnProperty('source')) { | ||||
|                     return (window.location = result.source.redirect.url); | ||||
|                 } | ||||
| 
 | ||||
|                 this.errors.textContent = ''; | ||||
|                 this.errors.textContent = result.error.message; | ||||
|                 this.errors.hidden = false; | ||||
|             }); | ||||
|         }); | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| const publishableKey = document.querySelector( | ||||
|     'meta[name="stripe-publishable-key"]' | ||||
| ).content; | ||||
| 
 | ||||
| new ProcessAlipay(publishableKey).setupStripe().handle(); | ||||
| @ -0,0 +1,57 @@ | ||||
| @extends('portal.ninja2020.layout.app') | ||||
| @section('meta_title', ctrans('texts.alipay')) | ||||
| 
 | ||||
| @push('head') | ||||
|     <meta name="stripe-publishable-key" content="{{ $gateway->getPublishableKey() }}"> | ||||
|     <meta name="return-url" content="{{ $return_url }}"> | ||||
|     <meta name="currency" content="{{ $currency }}"> | ||||
|     <meta name="amount" content="{{ $stripe_amount }}"> | ||||
| @endpush | ||||
| 
 | ||||
| @section('body') | ||||
|     <div class="container mx-auto"> | ||||
|         <div class="grid grid-cols-6 gap-4"> | ||||
|             <div class="col-span-6 md:col-start-2 md:col-span-4"> | ||||
|                 <div class="alert alert-failure mb-4" hidden id="errors"></div> | ||||
|                 <div class="bg-white shadow overflow-hidden sm:rounded-lg"> | ||||
|                     <div class="px-4 py-5 border-b border-gray-200 sm:px-6"> | ||||
|                         <h3 class="text-lg leading-6 font-medium text-gray-900"> | ||||
|                             {{ ctrans('texts.pay_now') }} | ||||
|                         </h3> | ||||
|                         <p class="mt-1 max-w-2xl text-sm leading-5 text-gray-500"> | ||||
|                             {{ ctrans('texts.complete_your_payment') }} | ||||
|                         </p> | ||||
|                     </div> | ||||
|                     <form action="#" method="POST" id="pay-now"> | ||||
|                         <div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center"> | ||||
|                             <dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> | ||||
|                                 {{ ctrans('texts.payment_type') }} | ||||
|                             </dt> | ||||
|                             <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> | ||||
|                                 {{ ctrans('texts.alipay') }} | ||||
|                             </dd> | ||||
|                         </div> | ||||
|                         <div class="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6 flex items-center"> | ||||
|                             <dt class="text-sm leading-5 font-medium text-gray-500 mr-4"> | ||||
|                                 {{ ctrans('texts.amount') }} | ||||
|                             </dt> | ||||
|                             <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2"> | ||||
|                                <span class="font-bold">{{ App\Utils\Number::formatMoney($amount, $client) }}</span> | ||||
|                             </dd> | ||||
|                         </div> | ||||
|                         <div class="bg-gray-50 px-4 py-5 flex justify-end"> | ||||
|                             <button class="button button-primary"> | ||||
|                                 {{ ctrans('texts.pay_now') }} | ||||
|                             </button> | ||||
|                         </div> | ||||
|                     </form> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| @endsection | ||||
| 
 | ||||
| @push('footer') | ||||
|     <script src="https://js.stripe.com/v3/"></script> | ||||
|     <script src="{{ asset('js/clients/payments/alipay.js') }}"></script> | ||||
| @endpush  | ||||
							
								
								
									
										4
									
								
								webpack.mix.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								webpack.mix.js
									
									
									
									
										vendored
									
									
								
							| @ -26,6 +26,10 @@ mix.js("resources/js/app.js", "public/js") | ||||
|         "resources/js/clients/payments/sofort.js", | ||||
|         "public/js/clients/payments/sofort.js" | ||||
|     ) | ||||
|     .js( | ||||
|         "resources/js/clients/payments/alipay.js", | ||||
|         "public/js/clients/payments/alipay.js" | ||||
|     ) | ||||
|     .js( | ||||
|         "resources/js/clients/quotes/action-selectors.js", | ||||
|         "public/js/clients/quotes/action-selectors.js" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user