mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
minor fixes
This commit is contained in:
parent
452d158759
commit
ae4029a3e4
@ -76,6 +76,7 @@ class PaymentType extends StaticModel
|
|||||||
const BACS = 49;
|
const BACS = 49;
|
||||||
const STRIPE_BANK_TRANSFER = 50;
|
const STRIPE_BANK_TRANSFER = 50;
|
||||||
const CASH_APP = 51;
|
const CASH_APP = 51;
|
||||||
|
const VENMO = 25;
|
||||||
|
|
||||||
public array $type_names = [
|
public array $type_names = [
|
||||||
self::CREDIT => 'payment_type_Credit',
|
self::CREDIT => 'payment_type_Credit',
|
||||||
@ -119,6 +120,7 @@ class PaymentType extends StaticModel
|
|||||||
self::Interac_E_Transfer => 'payment_type_Interac E Transfer',
|
self::Interac_E_Transfer => 'payment_type_Interac E Transfer',
|
||||||
self::STRIPE_BANK_TRANSFER => 'bank_transfer',
|
self::STRIPE_BANK_TRANSFER => 'bank_transfer',
|
||||||
self::CASH_APP => 'payment_type_Cash App',
|
self::CASH_APP => 'payment_type_Cash App',
|
||||||
|
self::VENMO => 'payment_type_Venmo',
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function parseCardType($cardName)
|
public static function parseCardType($cardName)
|
||||||
|
@ -12,15 +12,16 @@
|
|||||||
|
|
||||||
namespace App\PaymentDrivers;
|
namespace App\PaymentDrivers;
|
||||||
|
|
||||||
use App\Exceptions\PaymentFailed;
|
|
||||||
use App\Jobs\Util\SystemLogger;
|
|
||||||
use App\Models\GatewayType;
|
|
||||||
use App\Models\Invoice;
|
|
||||||
use App\Models\PaymentType;
|
|
||||||
use App\Models\SystemLog;
|
|
||||||
use App\Utils\Traits\MakesHash;
|
|
||||||
use Omnipay\Common\Item;
|
|
||||||
use Omnipay\Omnipay;
|
use Omnipay\Omnipay;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use Omnipay\Common\Item;
|
||||||
|
use App\Models\SystemLog;
|
||||||
|
use App\Models\GatewayType;
|
||||||
|
use App\Models\PaymentType;
|
||||||
|
use App\Jobs\Util\SystemLogger;
|
||||||
|
use App\Utils\Traits\MakesHash;
|
||||||
|
use App\Exceptions\PaymentFailed;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
|
||||||
class PayPalProPaymentDriver extends BaseDriver
|
class PayPalProPaymentDriver extends BaseDriver
|
||||||
{
|
{
|
||||||
@ -53,13 +54,23 @@ class PayPalProPaymentDriver extends BaseDriver
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
private function initializeOmnipayGateway(): void
|
private function initializeOmnipayGateway(): self
|
||||||
{
|
{
|
||||||
$this->omnipay_gateway = Omnipay::create(
|
$this->omnipay_gateway = Omnipay::create(
|
||||||
$this->company_gateway->gateway->provider
|
$this->company_gateway->gateway->provider
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->omnipay_gateway->initialize((array) $this->company_gateway->getConfig());
|
$this->omnipay_gateway = Omnipay::create('PayPal_Rest');
|
||||||
|
|
||||||
|
// Initialise the gateway
|
||||||
|
$this->omnipay_gateway->initialize(array(
|
||||||
|
'clientId' => 'AdRZZt44vJYAtXirmzMjnvUMoFIloN9kpuSgshQB7SJqLHbgtMP_rcmhy83FYY4a-c3R-_e4wZC8E3oG',
|
||||||
|
'secret' => 'ENPRXSxr6Jy1YQWhh87eN4fSlNVj5uFT2PDmBqPs_QYJD8MXGcsvJATgR8Xc5sOb6T0q1AHCwfmv9B7n',
|
||||||
|
'testMode' => true, // Or false when you are ready for live transactions
|
||||||
|
));
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
// $this->omnipay_gateway->initialize((array) $this->company_gateway->getConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPaymentMethod($payment_method_id)
|
public function setPaymentMethod($payment_method_id)
|
||||||
@ -93,32 +104,19 @@ class PayPalProPaymentDriver extends BaseDriver
|
|||||||
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
|
$this->payment_hash->data = array_merge((array) $this->payment_hash->data, ['amount' => $data['total']['amount_with_fee']]);
|
||||||
$this->payment_hash->save();
|
$this->payment_hash->save();
|
||||||
|
|
||||||
// $response = $this->omnipay_gateway
|
// $data['token'] = base64_decode($this->omnipay_gateway->getToken());
|
||||||
// ->purchase($this->generatePaymentDetails($data))
|
|
||||||
// ->setItems($this->generatePaymentItems($data))
|
|
||||||
// ->send();
|
|
||||||
|
|
||||||
// if ($response->isRedirect()) {
|
$access_token = $this->omnipay_gateway->getToken();
|
||||||
// return $response->redirect();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $this->sendFailureMail($response->getMessage() ?: '');
|
// $r = Http::withToken($access_token)
|
||||||
|
// ->withHeaders(['Accept-Language' => 'en_US'])->post("https://api-m.sandbox.paypal.com/v1/identity/generate-token",[]);
|
||||||
|
|
||||||
// $message = [
|
$r = Http::
|
||||||
// 'server_response' => $response->getMessage(),
|
withToken($access_token)
|
||||||
// 'data' => $this->payment_hash->data,
|
->post('https://api-m.sandbox.paypal.com/v1/identity/generate-token');
|
||||||
// ];
|
|
||||||
|
|
||||||
// SystemLogger::dispatch(
|
dd($r);
|
||||||
// $message,
|
nlog($r->body());
|
||||||
// SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
|
||||||
// SystemLog::EVENT_GATEWAY_FAILURE,
|
|
||||||
// SystemLog::TYPE_PAYPAL,
|
|
||||||
// $this->client,
|
|
||||||
// $this->client->company,
|
|
||||||
// );
|
|
||||||
|
|
||||||
// throw new PaymentFailed($response->getMessage(), $response->getCode());
|
|
||||||
|
|
||||||
return render('gateways.paypal.pay', $data);
|
return render('gateways.paypal.pay', $data);
|
||||||
|
|
||||||
|
@ -2,55 +2,268 @@
|
|||||||
|
|
||||||
@section('gateway_head')
|
@section('gateway_head')
|
||||||
<link href="{{ asset('css/card-js.min.css') }}" rel="stylesheet" type="text/css">
|
<link href="{{ asset('css/card-js.min.css') }}" rel="stylesheet" type="text/css">
|
||||||
|
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
type="text/css"
|
||||||
|
href="https://www.paypalobjects.com/webstatic/en_US/developer/docs/css/cardfields.css"
|
||||||
|
/>
|
||||||
|
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('gateway_content')
|
@section('gateway_content')
|
||||||
|
|
||||||
<form style="display:none" target="hss_iframe" name="form_iframe"
|
<div id="paypal-button-container" class="paypal-button-container"></div>
|
||||||
method="post"
|
<div class="card_container">
|
||||||
action="https://securepayments.paypal.com/webapps/HostedSoleSolutionApp/
|
<form id="card-form">
|
||||||
webflow/sparta/hostedSoleSolutionProcess">
|
<label for="card-number">Card Number</label>
|
||||||
<input type="hidden" name="cmd" value="_hosted-payment">
|
<div id="card-number" class="card_field"></div>
|
||||||
<input type="hidden" name="subtotal" value="{{ $total['amount_with_fee'] }}">
|
<div style="display: flex; flex-direction: row;">
|
||||||
<input type="hidden" name="business" value="{{ $gateway->company_gateway->getConfigField('username') }}">
|
<div>
|
||||||
<input type="hidden" name="paymentaction" value="sale">
|
<label for="expiration-date">Expiration Date</label>
|
||||||
<input type="hidden" name="template" value="templateA">
|
<div id="expiration-date" class="card_field"></div>
|
||||||
<input type="hidden" name="return"
|
</div>
|
||||||
value="https://yourwebsite.com/receipt_page.html">
|
<div style="margin-left: 10px;">
|
||||||
</form>
|
<label for="cvv">CVV</label>
|
||||||
|
<div id="cvv" class="card_field"></div>
|
||||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.payment_type')])
|
</div>
|
||||||
{{ ctrans('texts.credit_card') }}
|
</div>
|
||||||
@endcomponent
|
<label for="card-holder-name">Name on Card</label>
|
||||||
|
<input
|
||||||
@include('portal.ninja2020.gateways.includes.payment_details')
|
type="text"
|
||||||
|
id="card-holder-name"
|
||||||
@component('portal.ninja2020.components.general.card-element', ['title' => ctrans('texts.pay_with')])
|
name="card-holder-name"
|
||||||
<iframe name="hss_iframe" width="570px" height="540px"></iframe>
|
autocomplete="off"
|
||||||
|
placeholder="card holder name"
|
||||||
<form style="display:none" target="hss_iframe" name="form_iframe" id="form_iframe"
|
/>
|
||||||
method="post"
|
<div>
|
||||||
action="https://pilot-payflowpro.paypal.com/">
|
<label for="card-billing-address-street">Billing Address</label>
|
||||||
<input type="hidden" name="cmd" value="_hosted-payment">
|
<input
|
||||||
<input type="hidden" name="subtotal" value="{{ $total['amount_with_fee'] }}">
|
type="text"
|
||||||
<input type="hidden" name="business" value="{{ $gateway->company_gateway->getConfigField('username') }}">
|
id="card-billing-address-street"
|
||||||
<input type="hidden" name="paymentaction" value="sale">
|
name="card-billing-address-street"
|
||||||
<input type="hidden" name="template" value="templateA">
|
autocomplete="off"
|
||||||
<input type="hidden" name="return"
|
placeholder="street address"
|
||||||
value="https://yourwebsite.com/receipt_page.html">
|
/>
|
||||||
</form>
|
</div>
|
||||||
@endcomponent
|
<div>
|
||||||
|
<label for="card-billing-address-unit"> </label>
|
||||||
@include('portal.ninja2020.gateways.includes.save_card')
|
<input
|
||||||
|
type="text"
|
||||||
@include('portal.ninja2020.gateways.includes.pay_now')
|
id="card-billing-address-unit"
|
||||||
|
name="card-billing-address-unit"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="unit"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="card-billing-address-city"
|
||||||
|
name="card-billing-address-city"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="city"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="card-billing-address-state"
|
||||||
|
name="card-billing-address-state"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="state"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="card-billing-address-zip"
|
||||||
|
name="card-billing-address-zip"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="zip / postal code"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="card-billing-address-country"
|
||||||
|
name="card-billing-address-country"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="country code"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<br /><br />
|
||||||
|
<button value="submit" id="submit" class="btn">Pay</button>
|
||||||
|
</form>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('gateway_footer')
|
@section('gateway_footer')
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@push('footer')
|
@push('footer')
|
||||||
<script type="text/javascript">
|
<script src="https://www.paypal.com/sdk/js?components=buttons,hosted-fields&client-id=AdRZZt44vJYAtXirmzMjnvUMoFIloN9kpuSgshQB7SJqLHbgtMP_rcmhy83FYY4a-c3R-_e4wZC8E3oG" data-client-token="{!! $token !!}">
|
||||||
document.getElementById('form_iframe').submit();
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
paypal
|
||||||
|
.Buttons({
|
||||||
|
// Sets up the transaction when a payment button is clicked
|
||||||
|
createOrder: function () {
|
||||||
|
return fetch("/api/orders", {
|
||||||
|
method: "post",
|
||||||
|
// use the "body" param to optionally pass additional order information
|
||||||
|
// like product skus and quantities
|
||||||
|
body: JSON.stringify({
|
||||||
|
cart: [
|
||||||
|
{
|
||||||
|
sku: "213434",
|
||||||
|
quantity: "1",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((order) => order.id);
|
||||||
|
},
|
||||||
|
// Finalize the transaction after payer approval
|
||||||
|
onApprove: function (data) {
|
||||||
|
return fetch(`/api/orders/${data.orderID}/capture`, {
|
||||||
|
method: "post",
|
||||||
|
})
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((orderData) => {
|
||||||
|
// Successful capture! For dev/demo purposes:
|
||||||
|
console.log(
|
||||||
|
"Capture result",
|
||||||
|
orderData,
|
||||||
|
JSON.stringify(orderData, null, 2)
|
||||||
|
);
|
||||||
|
const transaction = orderData.purchase_units[0].payments.captures[0];
|
||||||
|
alert(`Transaction ${transaction.status}: ${transaction.id}
|
||||||
|
|
||||||
|
See console for all available details
|
||||||
|
`);
|
||||||
|
// When ready to go live, remove the alert and show a success message within this page. For example:
|
||||||
|
// var element = document.getElementById('paypal-button-container');
|
||||||
|
// element.innerHTML = '<h3>Thank you for your payment!</h3>';
|
||||||
|
// Or go to another URL: actions.redirect('thank_you.html');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.render("#paypal-button-container");
|
||||||
|
|
||||||
|
// If this returns false or the card fields aren't visible, see Step #1.
|
||||||
|
if (paypal.HostedFields.isEligible()) {
|
||||||
|
let orderId;
|
||||||
|
|
||||||
|
// Renders card fields
|
||||||
|
paypal.HostedFields.render({
|
||||||
|
// Call your server to set up the transaction
|
||||||
|
createOrder: () => {
|
||||||
|
return fetch("/api/orders", {
|
||||||
|
method: "post",
|
||||||
|
// use the "body" param to optionally pass additional order information
|
||||||
|
// like product skus and quantities
|
||||||
|
body: JSON.stringify({
|
||||||
|
cart: [
|
||||||
|
{
|
||||||
|
sku: "cxcxcx",
|
||||||
|
quantity: "333",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((orderData) => {
|
||||||
|
orderId = orderData.id; // needed later to complete capture
|
||||||
|
return orderData.id;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
styles: {
|
||||||
|
".valid": {
|
||||||
|
color: "green",
|
||||||
|
},
|
||||||
|
".invalid": {
|
||||||
|
color: "red",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
number: {
|
||||||
|
selector: "#card-number",
|
||||||
|
placeholder: "4111 1111 1111 1111",
|
||||||
|
},
|
||||||
|
cvv: {
|
||||||
|
selector: "#cvv",
|
||||||
|
placeholder: "123",
|
||||||
|
},
|
||||||
|
expirationDate: {
|
||||||
|
selector: "#expiration-date",
|
||||||
|
placeholder: "MM/YY",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).then((cardFields) => {
|
||||||
|
document.querySelector("#card-form").addEventListener("submit", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
cardFields
|
||||||
|
.submit({
|
||||||
|
// Cardholder's first and last name
|
||||||
|
cardholderName: document.getElementById("card-holder-name").value,
|
||||||
|
// Billing Address
|
||||||
|
billingAddress: {
|
||||||
|
// Street address, line 1
|
||||||
|
streetAddress: document.getElementById(
|
||||||
|
"card-billing-address-street"
|
||||||
|
).value,
|
||||||
|
// Street address, line 2 (Ex: Unit, Apartment, etc.)
|
||||||
|
extendedAddress: document.getElementById(
|
||||||
|
"card-billing-address-unit"
|
||||||
|
).value,
|
||||||
|
// State
|
||||||
|
region: document.getElementById("card-billing-address-state").value,
|
||||||
|
// City
|
||||||
|
locality: document.getElementById("card-billing-address-city")
|
||||||
|
.value,
|
||||||
|
// Postal Code
|
||||||
|
postalCode: document.getElementById("card-billing-address-zip")
|
||||||
|
.value,
|
||||||
|
// Country Code
|
||||||
|
countryCodeAlpha2: document.getElementById(
|
||||||
|
"card-billing-address-country"
|
||||||
|
).value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
fetch(`/api/orders/${orderId}/capture`, {
|
||||||
|
method: "post",
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((orderData) => {
|
||||||
|
// Two cases to handle:
|
||||||
|
// (1) Other non-recoverable errors -> Show a failure message
|
||||||
|
// (2) Successful transaction -> Show confirmation or thank you
|
||||||
|
// This example reads a v2/checkout/orders capture response, propagated from the server
|
||||||
|
// You could use a different API or structure for your 'orderData'
|
||||||
|
const errorDetail =
|
||||||
|
Array.isArray(orderData.details) && orderData.details[0];
|
||||||
|
if (errorDetail) {
|
||||||
|
var msg = "Sorry, your transaction could not be processed.";
|
||||||
|
if (errorDetail.description)
|
||||||
|
msg += "\n\n" + errorDetail.description;
|
||||||
|
if (orderData.debug_id) msg += " (" + orderData.debug_id + ")";
|
||||||
|
return alert(msg); // Show a failure message
|
||||||
|
}
|
||||||
|
// Show a success message or redirect
|
||||||
|
alert("Transaction completed!");
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
alert("Payment could not be captured! " + JSON.stringify(err));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Hides card fields if the merchant isn't eligible
|
||||||
|
document.querySelector("#card-form").style = "display: none";
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
Loading…
x
Reference in New Issue
Block a user