要在 Magento 2 中添加新的支付选项,您需要构建一个自定义支付模块,在结账时呈现支付方式,并将模块配置为与 Magento 的系统一起处理支付数据。
Magento是一个灵活的开源平台,无需修改本机Magento代码。根据现有的Magento结账模块,将自定义付款方式创建为单独的模块。
步骤1:在Magento中注册支付模块
创建注册文件registration.php在支付模块根目录下。在本例中,文件路径为app/code/CCBill/CustomPaymentOption/registration.php。
添加以下代码以在Magento系统中注册模块(组件):
```
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'CCBill_CustomPaymentOption',
__DIR__
);
```
编辑供应商(CCBill)和模块名称(CustomPaymentOption),以匹配您的模块名称。
步骤2:声明支付模块名称
访问自定义模块的app/code/CCBill/CustomPaymentOption/etc/目录并创建一个模块文件module.xml。在模块文件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>
<sequence>
```
标签控制加载顺序,并确保系统在自定义支付模块之前加载列出的组件。
步骤3:添加付款方式配置设置
在Magento管理中配置和显示付款方式通过创建system.xml文件。在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>
```
步骤4:添加默认系统配置值
定义system.xml的默认值。通过创建配置文件config.xml。创建配置文件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>
```
步骤5:创建付款方式模型
访问app/code/CCBill/CustomPaymentOption/Model/目录并创建CustomPaymmentOption.php文件。复制以下代码以在.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管理并进入商店>配置。展开“销售”下拉列表并打开“付款方式”菜单。确认设置system.xml与配置config.xml中定义的值一致。
步骤6:配置依赖注入
要将自定义付款方法注入现有的MagentoCcGenericConfigProvider中,请创建新的di.xml文件,放置di.xml在app/code/CCBill/CustomPaymentOption/etc/frontend/目录下,并将付款方式代码作为参数添加:
```
<?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>
```
配置支付方式模块后,系统需要在商店前端呈现用户界面。
步骤7:添加付款方式渲染器
创建custompayments.js文件在app/code/CCBill/CustomPaymentOption/view/frontend/web/js/view/payment/目录下。添加以下代码:
```
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'
}
);
```
本例中.js文件的主要功能是添加支付方法渲染器。
步骤8:向渲染器声明付款方法
在app/code/CCBill/CustomPaymentOption/view/frontend/web/js/view/payment/method-renderer/目录中创建一个.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');
}
});
}
);
```
步骤9:创建付款方式模板
系统使用Knockout JavaScript框架呈现UI组件。构建包含标题、账单地址和付款方法单选按钮的模板。
在app/code/CCBill/CustomPaymentOption/view/frontend/web/js/view/payment/目录中创建.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>
```
为方便起见,请使用现有Magento支付模块中的模板,.html模板位于<random_module>/frontend/web/template/payment/paymentmodule目录下。
步骤10:在结账时显示付款方式
要在结账页面上显示付款方式,请创建checkout_index_index.xml在app/code/CCBill/CustomPaymentOption/view/frontend/layout/目录下。
```
<?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>
```