要在Magento 2中添加新的付款选项,您需要构建一个自定义付款模块,在结账时呈现付款方法,并配置模块以与Magento的系统一起处理付款数据。
Magento是一个灵活的开源平台,不需要修改本地Magento代码。根据现有的Magento结账模块,将自定义付款方法创建为单独的模块。
注意:在建立Magento网站时,选择正确的支付网关,以提供平稳的支付流,对于您的电子商务业务的增长和发展至关重要。
1 创建支付模块
app/code/CCBill/CustomPaymentOption/registration.php
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'CCBill_CustomPaymentOption',
__DIR__
);
app/code/CCBill/CustomPaymentOption/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="CCBill_ CustomPaymentOption" setup_version="2.2.0">
<sequence>
<module name="Magento_Sales"/>
<module name="Magento_Payment"/>
<module name="Magento_Checkout"/>
</sequence>
</module>
</config>
2 定义config
app/code/CCBill/CustomPaymentOption/etc/adminhtml/system.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd">
<system>
<section id="payment">
<group id="ccbill_custompaymentoption" translate="label comment" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Custom Payment Option</label>
<field id="active" translate="label" type="select" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Enabled</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
</field>
<field id="title" translate="label" type="text" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Title</label>
</field>
<field id="cctypes" translate="label" type="multiselect" sortOrder="75" showInDefault="1" showInWebsite="1" showInStore="0">
<label>Credit Card Types</label>
<source_model>Magento\Payment\Model\Source\Cctype</source_model>
</field>
</group>
</section>
</system>
</config>
3 添加默认的系统配置
app/code/CCBill/CustomPaymentOption/etc/config.xml
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd">
<default>
<payment>
<ccbill_custompaymentoption>
<title>Custom Payment Option</title>
<active>1</active>
<payment_action>preferred_method</payment_action>
<model>CCBill\CustomPaymentOption\Model\PaymenMethod</model>
<order_status>pending_payment</order_status>
</ccbill_custompaymentoption>
</payment>
</default>
</config>
4 model
app/code/CCBill/CustomPaymentOption/Model/custompaymentoption.php
<?php
namespace CCBill\CustomPaymentOption\Model;
class CustomPaymentOption extends \Magento\Payment\Model\Method\Cc
{
const METHOD_CODE = 'ccbill_custompaymentoption';
protected $_code = self::METHOD_CODE;
protected $_custompayments;
protected $_isGateway = true;
protected $_canCapture = true;
protected $_canCapturePartial = true;
protected $_canRefund = true;
protected $_minOrderTotal = 0;
protected $_supportedCurrencyCodes = array('USD','GBP','EUR');
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory,
\Magento\Framework\Api\AttributeValueFactory $customAttributeFactory,
\Magento\Payment\Helper\Data $paymentData,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Payment\Model\Method\Logger $logger,
\Magento\Framework\Module\ModuleListInterface $moduleList,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Extension\Extension $Extension,
array $data = array()
) {
parent::__construct(
$context,
$registry,
$extensionFactory,
$customAttributeFactory,
$paymentData,
$scopeConfig,
$logger,
$moduleList,
$localeDate,
null,
null,
$data
);
$this->_code = 'Extension';
$this->_Extension = $Extension;
$this->_Extension->setApiKey($this->getConfigData('api_key'));
$this->_minOrderTotal = $this->getConfigData('min_order_total');
}
public function canUseForCurrency($currencyCode)
{
if (!in_array($currencyCode, $this->_supportedCurrencyCodes)) {
return false;
}
return true;
}
public function capture(\Magento\Payment\Model\InfoInterface $payment, $amount)
{
$order = $payment->getOrder();
$billing = $order->getBillingAddress();
try{
$charge = \Extension\Charge::create(array(
'amount' => $amount*100,
'currency' => strtolower($order->getBaseCurrencyCode()),
'card' => array(
'number' => $payment->getCcNumber(),
'exp_month' => sprintf('%02d',$payment->getCcExpMonth()),
'exp_year' => $payment->getCcExpYear(),
'cvc' => $payment->getCcCid(),
'name' => $billing->getName(),
'address_line1' => $billing->getStreet(1),
'address_line2' => $billing->getStreet(2),
'address_zip' => $billing->getPostcode(),
'address_state' => $billing->getRegion(),
'address_country' => $billing->getCountry(),
),
'description' => sprintf('#%s, %s', $order->getIncrementId(), $order->getCustomerEmail())
));
$payment->setTransactionId($charge->id)->setIsTransactionClosed(0);
return $this;
}catch (\Exception $e){
$this->debugData(['exception' => $e->getMessage()]);
throw new \Magento\Framework\Validator\Exception(__('Payment capturing error.'));
}
}
public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount)
{
$transactionId = $payment->getParentTransactionId();
try {
\Extension\Charge::retrieve($transactionId)->refund();
} catch (\Exception $e) {
$this->debugData(['exception' => $e->getMessage()]);
throw new \Magento\Framework\Validator\Exception(__('Payment refunding error.'));
}
$payment
->setTransactionId($transactionId . '-' . \Magento\Sales\Model\Order\Payment\Transaction::TYPE_REFUND)
->setParentTransactionId($transactionId)
->setIsTransactionClosed(1)
->setShouldCloseParentTransaction(1);
return $this;
}
public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null){
$this->_minOrderTotal = $this->getConfigData('min_order_total');
if($quote && $quote->getBaseGrandTotal() < $this->_minOrderTotal) {
return false;
}
return $this->getConfigData('api_key', ($quote ? $quote->getStoreId() : null))
&& parent::isAvailable($quote);
}
}
要检查新的付款方式是否可用,请访问Magento Admin并转到 Stores>Configuration
确认设置与配置中定义的值相对应config.xml和系统system.xml文件
5 配置依赖
app/code/CCBill/CustomPaymentOption/etc/frontend/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Payment\Model\CcGenericConfigProvider">
<arguments>
<argument name="methodCodes" xsi:type="array">
<item name="CustomPaymentOption" xsi:type="const">CCBill\CustomPaymentOption\Model\Payment::METHOD_CODE</item>
</argument>
</arguments>
</type>
</config>
6 配置前端js
app/code/CCBill/CustomPaymentOption/view/frontend/web/js/view/payment/custompayments.js
define(
[
'uiComponent',
'Magento_Checkout/js/model/payment/renderer-list'
],
function (
Component,
rendererList
) {
'use strict';
rendererList.push(
{
type: 'ccbill_custompaymentopyion',
component: 'CCBill_CustomPaymentOption/js/view/payment/method-renderer/custompayments'
}
);
app/code/CCBill/CustomPaymentOption/view/frontend/web/js/view/payment/method-renderer/a.js
define(
[
'Magento_Payment/js/view/payment/cc-form',
'jquery',
'Magento_Checkout/js/action/place-order',
'Magento_Checkout/js/model/full-screen-loader',
'Magento_Checkout/js/model/payment/additional-validators',
'Magento_Payment/js/model/credit-card-validation/validator'
],
function (Component, $) {
'use strict';
return Component.extend({
defaults: {
template: 'CCBill_CustomPaymentOption/payment/custompayments'
},
getCode: function() {
return 'ccbill_custompaymentoption';
},
isActive: function() {
return true;
},
validate: function() {
var $form = $('#' + this.getCode() + '-form');
return $form.validation() && $form.validation('isValid');
}
});
}
);
7 配置模板
app/code/CCBill/CustomPaymentOption/view/frontend/web/js/view/payment/custompayments.html
<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}">
<div class="payment-method-title field choice">
<input type="radio"
name="payment[method]"
class="radio"
data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/>
<label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label>
</div>
<div class="payment-method-content">
<!-- ko foreach: getRegion('messages') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
<div class="payment-method-billing-address">
<!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<form class="form" data-bind="attr: {'id': getCode() + '-form'}">
<!-- ko template: 'Magento_Payment/payment/cc-form' --><!-- /ko -->
</form>
<div class="checkout-agreements-block">
<!-- ko foreach: $parent.getRegion('before-place-order') -->
<!-- ko template: getTemplate() --><!-- /ko -->
<!--/ko-->
</div>
<div class="actions-toolbar">
<div class="primary">
<button class="action primary checkout"
type="submit"
data-bind="
click: placeOrder,
attr: {title: $t('Place Order')},
css: {disabled: !isPlaceOrderActionAllowed()},
enable: (getCode() == isChecked())
"
disabled>
<span data-bind="text: $t('Place Order')"></span>
</button>
</div>
</div>
</div>
</div
8 在页面显示支付
app/code/CCBill/CustomPaymentOption/view/frontend/layout/checkout_index_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="steps" xsi:type="array">
<item name="children" xsi:type="array">
<item name="billing-step" xsi:type="array">
<item name="component" xsi:type="string">uiComponent</item>
<item name="children" xsi:type="array">
<item name="payment" xsi:type="array">
<item name="children" xsi:type="array">
<item name="renders" xsi:type="array">
<!-- merge payment method renders here -->
<item name="children" xsi:type="array">
<item name="paymentoptions-payments" xsi:type="array">
<item name="component" xsi:type="string">CCBill_CustomPaymentOption/js/view/payment/paymentoptions</item>
<item name="methods" xsi:type="array">
<item name="CustomPaymentOptions" xsi:type="array">
<item name="isBillingAddressRequired" xsi:type="boolean">true</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>