Introduce pay upon invoice gateway (WIP)

This commit is contained in:
dinamiko 2022-03-07 12:54:02 +01:00
parent 3afb73d34c
commit 18220769a2
6 changed files with 264 additions and 0 deletions

View file

@ -0,0 +1,8 @@
document.addEventListener('DOMContentLoaded', () => {
const script = document.createElement('script');
script.setAttribute('src', 'https://c.paypal.com/da/r/fb.js');
console.log(script)
document.body.append(script);
});

View file

@ -29,6 +29,8 @@ use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint;
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice\OrderEndpoint;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice\PayUponInvoiceGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
@ -2118,4 +2120,19 @@ return array(
$container->get( 'wcgateway.settings' )
);
},
'wcgateway.pay-upon-invoice-order-endpoint' => static function (ContainerInterface $container): OrderEndpoint {
return new OrderEndpoint(
$container->get( 'api.host' ),
$container->get( 'api.bearer' ),
$container->get( 'api.factory.order' ),
$container->get( 'woocommerce.logger.woocommerce' )
);
},
'wcgateway.pay-upon-invoice-gateway' => static function (ContainerInterface $container): PayUponInvoiceGateway {
return new PayUponInvoiceGateway(
$container->get( 'wcgateway.pay-upon-invoice-order-endpoint' ),
$container->get( 'api.factory.purchase-unit' ),
$container->get( 'woocommerce.logger.woocommerce' )
);
},
);

View file

@ -0,0 +1,120 @@
<?php
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice;
use Psr\Log\LoggerInterface;
use RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory;
class OrderEndpoint {
use RequestTrait;
/**
* @var string
*/
protected $host;
/**
* @var Bearer
*/
protected $bearer;
/**
* @var OrderFactory
*/
protected $order_factory;
/**
* @var LoggerInterface
*/
protected $logger;
public function __construct( string $host, Bearer $bearer, OrderFactory $order_factory, LoggerInterface $logger) {
$this->host = $host;
$this->bearer = $bearer;
$this->order_factory = $order_factory;
$this->logger = $logger;
}
/**
* Creates an order.
*
* @param PurchaseUnit[] $items The purchase unit items for the order.
* @return Order
*/
public function create( array $items ): Order {
$data = array(
'intent' => 'CAPTURE',
'processing_instruction' => 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL',
'purchase_units' => array_map(
static function ( PurchaseUnit $item ): array {
return $item->to_array();
},
$items
),
'payment_source' => array (
'pay_upon_invoice' => array(
'name' => array(
'given_name' => 'John',
'surname' => 'Doe',
),
'email' => 'buyer@example.com',
'birth_date' => '1990-01-01',
'phone' => array(
'national_number' => '6912345678',
'country_code' => '49',
),
'billing_address' => array(
'address_line_1' => 'Schönhauser Allee 84',
'admin_area_2' => 'Berlin',
'postal_code' => '10439',
'country_code' => 'DE',
),
'experience_context' => array(
'locale' => 'en-DE',
'brand_name' => 'EXAMPLE INC',
'logo_url' => 'https://example.com/logoUrl.svg',
'customer_service_instructions' => array(
'Customer service phone is +49 6912345678.',
),
),
),
),
);
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v2/checkout/orders';
$args = array(
'method' => 'POST',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
'Prefer' => 'return=representation',
'PayPal-Client-Metadata-Id' => 'd4e0d7b9-4f75-43f9-9437-d8a57c901585',
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
),
'body' => wp_json_encode( $data ),
);
$response = $this->request( $url, $args );
if ( is_wp_error( $response ) ) {
throw new RuntimeException($response->get_error_message());
}
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 201 !== $status_code ) {
throw new PayPalApiException($json, $status_code);
}
return $this->order_factory->from_paypal_response( $json );
}
}

View file

@ -0,0 +1,96 @@
<?php
/**
* The Pay upon invoice Gateway
*
* @package WooCommerce\PayPalCommerce\WcGateway\Gateway
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice;
use Psr\Log\LoggerInterface;
use RuntimeException;
use WC_Order;
use WC_Payment_Gateway;
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
class PayUponInvoiceGateway extends WC_Payment_Gateway {
const ID = 'ppcp-pay-upon-invoice-gateway';
/**
* @var OrderEndpoint
*/
protected $order_endpoint;
/**
* @var PurchaseUnitFactory
*/
protected $purchase_unit_factory;
/**
* @var LoggerInterface
*/
protected $logger;
public function __construct(
OrderEndpoint $order_endpoint,
PurchaseUnitFactory $purchase_unit_factory,
LoggerInterface $logger
)
{
$this->id = self::ID;
$this->method_title = __('Pay Upon Invoice', 'woocommerce-paypal-payments');
$this->method_description = __('Once you place an order, pay within 30 days. Our payment partner Ratepay will send you payment instructions.', 'woocommerce-paypal-payments');
$this->title = $this->method_title;
$this->description = $this->method_description;
$this->init_form_fields();
$this->init_settings();
add_action(
'woocommerce_update_options_payment_gateways_' . $this->id,
array(
$this,
'process_admin_options',
)
);
$this->order_endpoint = $order_endpoint;
$this->purchase_unit_factory = $purchase_unit_factory;
$this->logger = $logger;
}
/**
* Initialize the form fields.
*/
public function init_form_fields() {
$this->form_fields = array(
'enabled' => array(
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
'label' => __( 'Pay upon Invoice', 'woocommerce-paypal-payments' ),
'default' => 'yes'
),
);
}
public function process_payment($order_id)
{
$wc_order = new WC_Order( $order_id );
$wc_order->update_status('on-hold', __('Awaiting Pay Upon Invoice payment', 'woocommerce-paypal-payments'));
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
try {
$this->order_endpoint->create(array( $purchase_unit ));
} catch (RuntimeException $exception) {
$error = $exception->getMessage();
$this->logger->error($error);
// TODO display error in the screen
}
}
}

View file

@ -205,6 +205,9 @@ class WCGatewayModule implements ModuleInterface {
if ( $dcc_applies->for_country_currency() ) {
$methods[] = $container->get( 'wcgateway.credit-card-gateway' );
}
$methods[] = $container->get('wcgateway.pay-upon-invoice-gateway');
return (array) $methods;
}
);
@ -268,6 +271,25 @@ class WCGatewayModule implements ModuleInterface {
return $disabler->handler( (array) $methods );
}
);
add_action('wp_footer', function () { ?>
<script type="application/json" fncls="fnparams-dede7cc5-15fd-4c75-a9f4-36c430ee3a99">
{
"f":"change_this_to_32char_guid",
"s":"flowid_provided_to_you"
}
</script>
<?php });
add_action('wp_enqueue_scripts', function () use($container) {
$gateway_module_url = $container->get('wcgateway.url');
wp_enqueue_script(
'ppcp-fraudnet',
trailingslashit($gateway_module_url) . 'assets/js/fraudnet.js',
array(),
1
);
});
}
/**

View file

@ -7,6 +7,7 @@ module.exports = {
target: 'web',
entry: {
'gateway-settings': path.resolve('./resources/js/gateway-settings.js'),
'fraudnet': path.resolve('./resources/js/fraudnet.js'),
},
output: {
path: path.resolve(__dirname, 'assets/'),