remp/crm-wallet-pay-module

CRM 钱包支付模块(支持 Apple Pay 和 Google Pay)

3.4.0 2024-01-22 09:18 UTC

This package is auto-updated.

Last update: 2024-09-20 12:58:21 UTC


README

此模块提供将 Apple Pay 和 Google Pay 支付网关集成到销售漏斗中的功能。

目前该模块支持使用 Tatrabanka 提供商的 网关 实现。此提供商目前不支持周期性支付。

安装

要安装模块,请运行

composer require remp/crm-wallet-pay-module

在您的 app/config/config.neon 文件中启用已安装的扩展

extensions:
	# ...
	- Crm\WalletPayModule\DI\WalletPayModuleExtension

要使模块功能在销售漏斗中可用,请在应用程序根目录中运行此命令以复制资源(或运行 composer install,这将同时安装资源)

# run in CRM root folder
php bin/command.php application:install_assets 

集成

Apple Pay 按钮

配置

在 CRM 设置中(crm.press/admin/config-admin/)的 支付 部分,配置 Apple Pay 选项。这些包括 Apple Pay 商户 ID 证书和密钥的路径(如果加密,包括密码)。有关更多信息,请参阅有关如何 设置 Apple Pay 的官方文档。

要求

Apple Pay 需要 HTTPS 网页,并具有有效的 TLS 证书。

在销售漏斗中使用

首先,在 CRM 管理员的销售漏斗设置中,将“ApplePay 钱包”支付网关添加到允许的网关列表中。

接下来,在销售漏斗 <head> 标签中包含 WalletPay JS 库(如果尚未包含)

<script src="/layouts/wallet-pay-module/js/wallet-pay.js"></script> 

要显示按钮本身,请将以下代码片段插入您的 HTML 文档中的某个位置。注意 hidden 类 - 按钮最初应隐藏,在我们检查 Apple Pay 可用性之前。

<apple-pay-button  buttonstyle="black" type="buy" locale="sk_SK"
  class="hidden" 
  style="--apple-pay-button-width: 100%;
    --apple-pay-button-height: 40px;
    --apple-pay-button-border-radius: 5px;
    --apple-pay-button-padding: 5px 0px;">
</apple-pay-button>

按钮的属性在 官方文档 中描述,包括 CSS 样式

接下来,确保当前浏览器上下文中可使用 Apple Pay

// MERCHANT_ID is ID assigned in the Apple Pay settings
RempWalletPay.checkApplePayAvailability(MERCHANT_ID, function () {
    // called only if button should be displayed
    // remove 'hidden' class to display the button
    document.getElementsByTagName('apple-pay-button')[0].classList.remove('hidden');
});

要初始化按钮,运行 initApplePayButton。最基本的配置

const config = {
  totalPrice: '0.10',
  merchantName: 'Example Merchant s.r.o',
  productName: 'Example Product Name',

  // Function to retrieve sales funnel payment form data (will be sent together with Apple Pay token to backend).
  // Library takes care of response processing and redirect.
  salesFunnelFormData: () => {
    return new FormData(document.getElementById('form'));
  },

  // Optional, function returning true/false depending on whether Apple Pay execution should continue after clicking on the button.
  isValid: () => true, 
};
RempWalletPay.initApplePayButton(config);

或者,您可以提供 onSuccess 回调,该回调允许您处理在支付期间发布的 Apple Pay 令牌

const config = {
    totalPrice: '0.10',
    merchantName: 'Example Merchant s.r.o',
    productName: 'Example Product Name',

    // Callback, called after user confirms the payment in the Apple modal (e.g. by fingerprint).
    // It receives two arguments:
    // - token - Apple Pay token
    // - completePaymentCallback - callback, should be called after backend (un/successfully) ackowledges the payment 
    onSuccess: (token, completePaymentCallback) =>  {
        var fd = new FormData(document.getElementById('form'));
        fd.append('apple_pay_token', token);
          
        fetch('/sales-funnel/sales-funnel-frontend/submit', {
            method: 'POST',
            body: fd,
        })
            .then(response => response.json())
            .then(data => {
                completePaymentCallback(true);
                window.top.location.href = data.apple_pay.redirect_url; // redirect to success page
            })
            .catch(e => completePaymentCallback(false));
    },
    
    // optional, function returning true/false depending on whether Apple Pay execution should continue after clicking on the Pay button.
    isValid: () => some_check_to_see_if_payment_form_is_valid(),
};
RempWalletPay.initApplePayButton(config);

支付按钮更新

要更新按钮的价格或产品名称,请调用

RempWalletPay.updateApplePayButton({
    totalPrice: '0.20', // new price
    // productName: 'new product name',
});

Google Pay

配置

要设置 Google Pay 并获取所需的凭据,请遵循有关 Google Pay for web 的官方文档。

要求

Google Pay 需要 HTTPS 网页,并具有有效的 TLS 证书。

在销售漏斗中使用

首先,在 CRM 管理员的销售漏斗设置中,将“GooglePay 钱包”支付网关添加到允许的网关列表中。

接下来,在销售漏斗 <head> 标签中包含 WalletPay JS 库(如果尚未包含)

<script src="/layouts/wallet-pay-module/js/wallet-pay.js"></script> 

要显示按钮本身,请将以下代码片段插入您的 HTML 文档中的某个位置。

<google-pay-button environment="PRODUCTION" 
                   button-locale="sk"
                   button-color="white" 
                   button-size-mode="fill" 
                   style="width:100%">
</google-pay-button>

按钮的所有属性在 GitHub 文档 中描述。

要初始化按钮,运行 initGooglePayButton。最基本的配置

const config = {
    // price shown to user
    totalPrice: '0.10',
    // merchantId is one of the credentials obtain during configuration
    merchantId: '1234567890',
    // some merchant name to show to user
    merchantName: 'Example merchant',

    // Function to retrieve sales funnel payment form data (will be sent together with Google Pay token to backend).
    // Library takes care of response processing and redirect.
    salesFunnelFormData: () => {
        return new FormData(document.getElementById('form'));
    },

    // Optional, function returning true/false depending on whether Google Pay execution should continue after clicking on the button.
    isValid: () => true, 
    
    // Optional, callback function to show progress during the payment   
    inProgress: (promise) => {
        console.log("Google payment starts"); // here, display some animation 
        promise.then(() => {
            console.log("Google payment starts"); // here, stop the animation
        });
    }
};
RempWalletPay.initGooglePayButton(config);

或者,提供 onSuccess 回调,该回调允许您处理在支付期间发布的 Google Pay 令牌并放置 3DS 对话框 HTML 代码的位置

const config = {
    // price shown to user
    totalPrice: '0.10',
    // merchantId is one of the credentials obtain during configuration
    merchantId: '1234567890',
    // some merchant name to show to user
    merchantName: 'Example merchant',

    // Callback, called after user confirms the payment in the Google Pay dialog.
    // Argument:
    // - token - Google Pay token
    onSuccess: (token) =>  {
        var fd = new FormData(document.getElementById('form'));
        fd.append('google_pay_token', token);

        fetch('/sales-funnel/sales-funnel-frontend/submit', {
            method: 'POST',
            body: fd,
        })
            .then(response => response.json())
            .then(data => {
                // if 'tds_html' attribute is present, 3DS is required
                if (data.google_pay.tds_html) {
                    // helper function to display 3DS html in an iframe modal
                    RempWalletPay.show3ds(data.google_pay.tds_html);
                } else {
                    // redirect to success page (no 3DS requirement to finish the payment)
                    window.top.location.href = data.google_pay.redirect_url;
                }
            });
    },
    
    // Optional, function returning true/false depending on whether Google Pay execution should continue after clicking on the button.
    isValid: () => true,

    // Optional, callback function to show progress during the payment   
    inProgress: (promise) => {
        console.log("Google payment starts"); // here, display some animation 
        promise.then(() => {
            console.log("Google payment starts"); // here, stop the animation
        });
    }
};
RempWalletPay.initGooglePayButton(config);

支付按钮更新

要更新按钮的价格,请调用

RempWalletPay.updateGooglePayButton({
    totalPrice: '0.20', // new price
});

扩展

如果您想使用自己的网关提供商(而不是Tatrabanka),您可以扩展此模块以包含自己的实现。请注意,此模块不支持直接钱包支付。

首先,您需要通过提供Google/Apple支付接口的实现来实施集成。

  • Crm\WalletPayModule\Model\GooglePayWalletInterface
  • Crm\WalletPayModule\Model\ApplePayWalletInterface

准备好后,请在您的config.neon文件中注册它们,并覆盖此模块提供的默认实现。

services:
	applePayWallet: Crm\FooModule\Model\YourProviderApplePayWallet
	googlePayWallet: Crm\FooModule\Model\YourProviderGooglePayWallet

API文档

所有示例都使用http://crm.press作为基础域名。请在执行示例之前将主机更改为您使用的域名。

API响应可以包含以下HTTP状态码

如果可能,响应将包括application/json编码的有效负载,其中包含进一步解释错误的消息。

GET /api/v1/apple-pay/merchant-validation

验证Apple Pay商户身份的API调用。

参数
示例
curl -v –X GET http://crm.press/api/v1/apple-pay/merchant-identity?url=VALIDATION_URL

响应

{
  "epochTimestamp": 1655206603128,
  "expiresAt": 1655210203128,
  "merchantSessionIdentifier": "...",
  "nonce": "SOME_NONCE",
  "merchantIdentifier": "...",
  "domainName": "crm.press",
  "displayName": "CRM",
  "signature": "SIGNATURE_DATA_BASE64",
  "operationalAnalyticsIdentifier": "DEVEL CRM:SOME_ID",
  "retries": 0,
  "pspId": "..."
}

响应可能不同,因为它包含由Apple提供的商户验证服务返回的数据。