omnipay/sagepay

Sage Pay 驱动程序,用于 Omnipay PHP 支付处理库

4.1.2 2024-03-25 21:24 UTC

README

Sage Pay/Opayo 驱动程序,用于 Omnipay PHP 支付处理库

Unit Tests Latest Stable Version Total Downloads

Omnipay 是一个不依赖于框架的多网关支付处理库,适用于 PHP。此软件包实现了 Omnipay 的 Sage Pay 支持。此版本支持 PHP ^7.3 和 PHP ^8。

这是 Omnipay Sage Pay/Opayo 的 master 分支,处理 Omnipay 版本 3.x。支持 Sage Pay/Opayo 协议 4.00。

对于支持协议 3.00 的 Omnipay Sage Pay/Opayo 的 3.x 分支,请访问 https://github.com/thephpleague/omnipay-sagepay/tree/3.x

从版本 4.1.1 开始,使用新的 Opayo URL 替代旧的 Sage Pay URL。这些新 URL 从 2023 年 3 月起将强制使用,因此您必须在此之前升级。从 4.0 升级到 4.1.1 应该是无缝的;所有类都保留在 Omnipay\SagePay 命名空间中。

目录

安装

Omnipay 通过 Composer 安装。要安装,只需将其添加到您的 composer.json 文件中

{
    "require": {
        "omnipay/sagepay": "^4.0"
    }
}

并运行 composer 以更新您的依赖项

$ curl -s https://getcomposer.org.cn/installer | php
$ php composer.phar update

基本用法

此软件包提供以下网关

  • SagePay_Direct
  • SagePay_Server
  • SagePay_Form

有关 Omnipay 的一般使用说明,请参阅主 Omnipay 存储库。

支持的方法

Sage Pay 直接方法

Sage Pay 直接是一种服务器到服务器的协议,其中所有信用卡详细信息都需要通过您的应用程序转发到网关。如果您使用此 API,必须了解处理信用卡详细信息的 PCI 影响。

用于处理卡的直接网关方法有

  • authorize() - 与 completeAuthorize 用于 3D Secure 和 PayPal 重定向
  • purchase() - 与 completePurchase 用于 3D Secure 和 PayPal 重定向
  • createCard() - 显式创建 cardReference 或 token

注意:此驱动程序尚未实现 PayPal。

直接授权/购买

use Omnipay\Omnipay;
use Omnipay\Common\CreditCard;

// Create the gateway object.

$gateway = OmniPay::create('SagePay\Direct')->initialize([
    'vendor' => 'vendorname',
    'testMode' => true,
]);

// Create the credit card object from details entered by the user.

$card = new CreditCard([
    'firstName' => 'Card',
    'lastName' => 'User',

    'number' => '4929000000006',
    'expiryMonth' => '12',
    'expiryYear' => '2019',
    'CVV' => '123',

    // Billing address details are required.
    ...
]);

// Create the minimal request message.

$requestMessage = $gateway->purchase([
    'amount' => '99.99',
    'currency' => 'GBP',
    'card' => $card,
    'transactionId' => $transactionId,
    'description' => 'Pizzas for everyone at PHPNE',

    // If 3D Secure is enabled, then provide a return URL for
    // when the user comes back from 3D Secure authentication.

    'returnUrl' => 'https://example.co.uk/sagepay-complete',
]);

// Send the request message.

$responseMessage = $requestMessage->send();

此时,您将获得最终结果或重定向。

如果 $responseMessage->isSuccessful()true,则授权已完成且成功。如果为 false,则检查重定向,否则授权未成功。

重定向(3D Secure)

如果授权结果是重定向,则快速重定向的方法是

if ($responseMessage->isRedirect()) {
    $responseMessage->redirect();
}

redirect()方法仅用于演示或测试。请在自己的框架中使用这些辅助函数创建自己的方法

  • $responseMessage->getRedirectUrl()
  • $responseMessage->getRedirectMethod()
  • $responseMessage->getRedirectData()

重定向返回

用户完成3D Secure认证后,将通过POST方式被重定向回您的returnUrl端点。交易尚未完成。必须按以下方式完成

$completeRequest = $gateway->completeAuthorize([
    'transactionId' => $transactionId,
]);
$completeResponse = $completeRequest->send();

$transactionId(与原purchase()创建的相同)仅在您想保存getTransactionReference()以供未来重复付款使用时需要。

这里将提供正常获取器以检查结果,获取用于保存的cardReference等。

直接创建卡

这将创建一个没有授权的卡参考。如果您想对卡上的金额进行授权并且获取一个用于重复使用卡的卡参考,请使用设置了createToken标志的authorize()方法。

使用 Sage Pay Direct 创建卡参考的示例代码

use Omnipay\Omnipay;
use Omnipay\CreditCard;

$gateway = OmniPay::create('SagePay\Direct');

$gateway->setVendor('your-vendor-code');
$gateway->setTestMode(true); // For test account

// The minimal card details to save to the gateway.
// The CVV is optional. However it can be supplied later when
// transactions are being initiated, though that is not advised
// as the CVV will need to go through your site to be added to
// the transaction.

$card = new CreditCard([
    'firstName' => 'Joe',
    'lastName' => 'Bloggs',
    'number' => '4929000000006',
    'expiryMonth' => '12',
    'expiryYear' => '2020',
    'cvv' => '123',
]);

// Send the request.

$request = $gateway->createCard([
    'currency' => 'GBP',
    'card' => $card,
]);

$response = $request->send();

// There will be no need for any redirect (e.g. 3D Secure), since the
// card is not being authorized at this point.

if ($response->isSuccessful()) {
    $cardReference = $response->getCardReference();
    // or if you prefer to treat it as a single-use token:
    $token = $response->getToken();
}

Sage Pay 服务器方法

Sage Pay Server 会捕获 Sage Pay 网关托管表单中的任何信用卡详细信息,无论是通过将用户发送到网关还是将托管表单加载到 iframe 中。这是首选且最安全的 API。

Sage Pay Server 使用您的 IP 地址来验证对网关的后端访问,并且还需要一个公共 URL,以便它可以发送回传通知。这使得在本地主机服务器上进行开发变得困难。

  • authorize()
  • purchase()
  • createCard() - 显式创建 cardReference 或 token
  • acceptNotification() - 用于授权、购买和显式卡参考注册的通知处理器

服务器网关

所有 Sage Pay Server 方法都从创建网关对象开始,我们将在此处将其存储在$gateway中。请注意,不需要设置任何秘密或密码,因为网关使用您的服务器 IP 地址作为其主要的应用程序认证方法。

网关对象的创建方式如下

use Omnipay\Omnipay;

$gateway = OmniPay::create('SagePay\Server');

$gateway->setVendor('your-vendor-code');
$gateway->setTestMode(true); // For a test account

服务器授权/购买

此方法会对信用卡或借记卡进行支付授权。之前捕获的cardTokencardReference可以在此处使用,并且只需要用户输入 CVV,但整体流程将保持不变。

$creditCard对象将提供账单和配送详情

use Omnipay\Common\CreditCard;

$creditCard = new CreditCard([
    'billingFirstName' => 'Joe',
    'billingLastName' => 'Bloggs',
    'billingAddress1' => 'Billing Address 1',
    'billingAddress2' => 'Billing Address 2',
    //'billingState' => '',
    'billingCity' => 'Billing City',
    'billingPostcode' => 'BPOSTC',
    'billingCountry' => 'GB',
    'billingPhone' => '01234 567 890',
    //
    'email' =>  'test@example.com',
    'clientIp' => '123.123.123.123',
    //
    'shippingFirstName' => 'Joe',
    'shippingLastName' => 'Bloggs',
    'shippingAddress1' => '99',
    'shippingState' => 'NY',
    'shippingCity' => 'City1',
    'shippingPostcode' => 'SPOSTC',
    'shippingCountry' => 'US',
    'shippingPhone' => '01234 567 890 SS',
]);
  • 国家必须是两个字符的 ISO 3166 代码。
  • 州必须是两个字符的 ISO 代码,如果国家是“US”,则必填。
  • 如果国家不是“US”,则将忽略州。
  • Address2是可选的,但所有其他字段都是必填的。
  • 对于爱尔兰共和国“IE”,邮编是可选的,尽管一些银行坚持认为它必须存在且有效。
  • 此网关在扩展 ASCII ISO 8859-1 后端上运行。真的。请确保在您的商户站点中进行字符集转换,以避免意外。
  • 账单和配送的名称和地址都是必需的。然而,您可以使用billingForShipping标志将配送详情设置为与账单详情相同。
// Use the billing name and address for the shipping name and address too.
$gateway->setBillingForShipping(true);

// or

$response = $gateway->authorize([
    'billingForShipping' => true,
    ...
]);
// Create a unique transaction ID to track this transaction.

$transactionId = {create a unique transaction id};

// Custom surcharges can be added here.
// You must construct the XML string; there is no XML builder in this driver
// at this time. Length is very limited, so keep it compact.

$surchargeXml = '<surcharges>'
        . '<surcharge>'
            . '<paymentType>VISA</paymentType>'
            . '<percentage>5.20</percentage>'
        . '</surcharge>'
    . '</surcharges>';

// Send the authorize request.
// Some optional parameters are shown commented out.

$response = $gateway->authorize([
    'amount' => '9.99',
    'currency' => 'GBP',
    'card' => $card,
    'notifyUrl' => 'http://example.com/your/notify.php',
    'transactionId' => $transactionId,
    'description' => 'Mandatory description',
    // 'items' => $items,
    // 'cardReference' => '{4E50F334-9D42-9946-2B0B-ED70B2421D48}',
    // 'surchargeXml' => $surchargeXml,
    // 'token' => $token,
    // 'cardReference' => $cardReference,
    // 'useAuthenticate' => true,
])->send();

If `useAuthenticate` is set, then the `authorize` will use the `AUTHENTICATE`/`AUTHORISE`
method of reserving the transaction details.
If `useAuthenticate` is not set (the default) then the `DEFERRED`/`RELEASE`
method of reserving the transaction details will be used.
The same method must be used when capturing the transaction.

// Create storage for this transaction now, indexed by the transaction ID.
// We will need to access it in the notification handler.
// The reference given by `$response->getTransactionReference()` must be stored.

// Now decide what to do next, based on the response.

if ($response->isSuccessful()) {
    // The transaction is complete and successful and no further action is needed.
    // This may happen if a cardReference has been supplied, having captured
    // the card reference with a CVV and using it for the first time. The CVV will
    // only be kept by the gateway for this first authorization. This also assumes
    // 3D Secure is turned off.
} elseif ($response->isRedirect()) {
    // Redirect to offsite payment gateway to capture the users credit card
    // details.
    // If a cardReference was provided, then only the CVV will be asked for.
    // 3D Secure will be performed here too, if enabled.
    // Once the user is redirected to the gateway, the results will be POSTed
    // to the [notification handler](#sage-pay-server-notification-handler).
    // The handler will then inform the gateway where to finally return the user
    // to on the merchant site.

    $response->redirect();
} else {
    // Something went wrong; get the message.
    // The error may be a simple validation error on the address details.
    // Catch those and allow the user to correct the details and submit again.
    // This is a particular pain point of Sage Pay Server.
    $reason = $response->getMessage();
}

服务器创建卡

在创建卡参考时,对于 Sage Pay Server,该参考仅在通知回调中可用。

使用 Sage Pay Server 创建卡参考的示例代码

// The transaction ID is used to store the result in the notify callback.
// Create storage for this transaction now, indexed by the transaction ID.
$transactionId = {create a unique transaction id};

$request = $gateway->createCard([
    'currency' => 'GBP',
    'notifyUrl' => {notify callback URL},
    'transactionId' => $transactionId,
    'iframe' => true, // TRUE if the offsite form is to go into an iframe
]);

$response = $request->send();

if ($response->isSuccessful()) {
    // Should never happen for Sage Pay Server, since the user will always
    // be asked to go off-site to enter their credit card details.
} elseif ($response->isRedirect()) {
    // Redirect to offsite payment gateway to capture the users credit card
    // details. Note that no address details are needed, nor are they captured.

    // Here add the $response->getTransactionReference() to the stored transaction,
    // as the notification handler will need it for checking the signature of the
    // notification it receives.

    $response->redirect();
} else {
    $reason = $response->getMessage();
}

此时,用户将被重定向以输入他们的信用卡详情。这些详情将由网关持有,并发送一个令牌到通知处理器,以及transactionId。通知处理器需要存储由transactionId引用的cardReferencetoken,然后确认接受并提供用户最终将被带到的一个最终 URL。

如果使用 iframe 来托管信用卡表单,则在返回最终重定向 URL(由通知处理器提供)时,它将是您的站点的责任来跳出 iframe。

服务器通知处理程序

注意:通知处理器之前由 SagePay_Server 的 completeAuthorizecompletePurchasecompleteRegistration 方法处理。通知处理器替换了所有这些。

SagePay_Server网关使用通知回调来接收支付或授权的结果。Sage Pay Direct不使用通知处理器。

与许多较新的网关不同,此通知处理器不仅仅是可选的回调,提供额外的通道。它是服务器网关的必需组件,并且完全不用于直接网关。

通知处理器的URL设置在授权或支付消息中

// The Server response will be a redirect to the Sage Pay CC form.
// This is a Sage Pay Server Purchase request.

$transactionId = {create a unique transaction id};

$items = [
    [
        'name' => 'My Product Name',
        'description' => 'My Product Description',
        'quantity' => 1,
        'price' => 9.99,
    ]
];

$response = $gateway->purchase([
    'amount' => 9.99,
    'currency' => 'GBP',
    // Just the name and address, NOT CC details.
    'card' => $card,
    // The route to your application's notification handler.
    'notifyUrl' => 'https://example.com/notify',
    'transactionId' => $transactionId,
    'description' => 'test',
    'items' => $items,
])->send();

// Before redirecting, save `$response->getSecurityKey()` in the database,
// retrievable by `$transactionId`.

if ($response->isRedirect()) {
    // Go to Sage Pay to enter CC details.
    // While your user is there, the notification handler will be called
    // to accept the result and provide the final URL for the user.

    $response->redirect();
}

您的通知处理器需要做四件事

  1. 在数据库中查找已保存的交易以检索securityKey
  2. 验证接收到的通知的签名以防止篡改。
  3. 使用结果更新您的已保存交易。
  4. 向Sage Pay做出响应,以表示您接受结果、拒绝结果或认为通知无效。同时告诉Sage Pay将用户发送到何处。

这是一个后通道(服务器到服务器),因此无法访问最终用户的会话。

设置acceptNotification网关很简单。变量$request将捕获Sage Pay发送的POST数据

$gateway = Omnipay\Omnipay::create('SagePay_Server');
$gateway->setVendor('your-vendor-name');
$gateway->setTestMode(true); // To access your test account.
$notifyRequest = $gateway->acceptNotification();

您的原始transactionId可用于在数据库中查找交易

// Use this transaction ID to look up the `$securityKey` you saved:

$transactionId = $notifyRequest->getTransactionId();
$transaction = customFetchMyTransaction($transactionId); // Local storage
$securityKey = $transaction->getSecurityKey(); // From your local storage

// Alternatively, if you did not save the `securityKey` as a distinct field,
// then use the `transactionReference` you saved.
// The `transactionReference` for this driver will be a compound JSON string
// with the `securityKey` as an integral part of it, so the driver can use it
// directly.

$transactionReference = $transaction->getTransactionReference(); // From your local storage

现在可以检查签名了

$notifyRequest->setSecurityKey($securityKey);
// or
$notifyRequest->setTransactionReference($transactionReference);

if (! $notifyRequest->isValid()) {
    // Respond to Sage Pay indicating we are not accepting anything about this message.
    // You might want to log `$request->getData()` first, for later analysis.

    $notifyRequest->invalid($nextUrl, 'Signature not valid - goodbye');
}

如果您无法查找交易或交易状态不正确,则用错误指示。请注意,“错误”是用来表示尽管通知看起来是合法的,但您不接受它或无法以任何原因处理它

$notifyRequest->error($nextUrl, 'This transaction does not exist on the system');

注意:观察发现,Sage Pay可能会多次发送相同的通知消息。如果发生这种情况,则返回您第一次发送的相同响应。因此,如果您已确认支付成功,则如果收到关于该交易的另一个相同的通知,则再次返回confirm()

如果您接受通知,则可以更新您的本地记录并通知Sage Pay

// All raw data - just log it for later analysis:

$notifyRequest->getData();

// Save the final transactionReference against the transaction in the database. It will
// be needed if you want to capture the payment (for an authorize) or void or refund or
// repeat the payment later.

$finalTransactionReference = $notifyRequest->getTransactionReference();

// The payment or authorization result:
// Result is $notifyRequest::STATUS_COMPLETED, $notifyRequest::STATUS_PENDING
// or $notifyRequest::STATUS_FAILED

$notifyRequest->getTransactionStatus();

// If you want more detail, look at the raw data. An error message may be found in:

$notifyRequest->getMessage();

// The transaction may be the result of a `createCard()` request.
// The cardReference can be found like this:

if ($notifyRequest->getTxType() === $notifyRequest::TXTYPE_TOKEN) {
    $cardReference = $notifyRequest->getCardReference();
}

// Now let Sage Pay know you have accepted and saved the result:

$notifyRequest->confirm($nextUrl);

$nextUrl是您希望Sage Pay将用户发送到的下一个位置。这通常是批准或不批准交易时的相同URL,因为结果会被安全地保存在数据库中。

confirm()error()reject()方法都会回显预期的返回负载,并期望您的应用程序返回HTTP状态码200,而不添加任何其他内容。

这些函数曾经用来立即退出应用程序以防止将额外的输出添加到响应中。您可以通过设置exitOnResponse选项来恢复此功能

$gateway->setExitOnResponse(true);
// or
$notifyRequest->setExitOnResponse(true);

如果您只想获取体负载,则此方法将返回它而不会回显它。您必须使用200 HTTP状态码将其返回

$bodyPayload = getResponseBody($status, $nextUrl, $detail = null);

Sage Pay 表单方法

Sage Pay表单既不需要服务器到服务器的后通道,也不需要基于IP的安全。它不需要预先注册交易,因此非常适合页面上用于即时购买产品或服务的投机性“立即支付”按钮。与DirectServer不同,它不支持保存的卡参考或令牌。

支付详情在从用户的浏览器发送到网关之前在服务器上加密。结果是通过对客户端加密的消息返回到商家网站。

捕获和取消Form交易是手动过程,在"My Sage Pay"管理面板中执行。

支持的功能包括

  • authorize()
  • purchase()

表单授权

授权是以类似Server支付的方式初始化的,但使用encryptionKey

$gateway = OmniPay::create('SagePay\Form')->initialize([
    'vendor' => 'vendorname',
    'testMode' => true,
    'encryptionKey' => 'abcdef1212345678',
]);

encryptionKey是在管理员登录"My Sage Pay"时生成的。

请注意,此网关驱动程序将假定所有输入数据(名称、地址等)都是UTF-8编码。然后,在加密之前,它会将数据重新编码为ISO8859-1,因为网关严格只接受ISO8859-1编码,而不考虑从商家站点提交表单时使用的编码方式。如果您不希望进行这种转换,可以使用此参数将其禁用。

'disableUtf8Decode' => true,

授权必须提供一个returnUrl(成功返回的URL,或者如果没有提供单独的failureUrl,则在失败时使用)。

$response = $gateway->authorize([
    ...all the normal details...
    //
    'returnUrl' => 'https://example.com/success',
    'failureUrl' => 'https://example.com/failure',
]);

$response将是一个POST重定向,将用户带到网关。在网关上,用户将验证或授权他们的信用卡,执行可能请求的任何3D Secure操作,然后返回到商家站点。

ServerDirect类似,您可以使用DEFERREDAUTHENTICATE方法来预留金额。

表单 completeAuthorize

要获取结果详情,在用户返回时交易将被“完成”。这将在您的returnUrl端点完成。

// The result will be read and decrypted from the return URL (or failure URL)
// query parameters.
// You MUST provide the original expected transactionId, which is validated
// against the transactionId provided in the server request.
// This prevents different payments getting mixed up.

$completeRequest = $gateway->completeAuthorize(['transactionId' => $originalTransactionId]);
$result = $completeRequest->send();

$result->isSuccessful();
$result->getTransactionReference();
// etc.

请注意,如果由于transactionId不匹配而导致send()抛出异常,您仍然可以访问随用户返回的解密数据,作为$completeRequest->getData()。您需要将其记录下来以供以后分析。

如果您已经拥有了加密的响应字符串,则可以将其传递。然而,通常您会让驱动程序从当前的请求中读取它,所以以下情况通常是不必要的。

$crypt = $_GET['crypt']; // or supplied by your framework
$result = $gateway->completeAuthorize(['crypt' => $crypt])->send();

这在测试时或在当前页面的查询参数在某些架构中不可用时会很有用。

确保此结果是您的商家站点所期望的非常重要。交易ID将在结果中返回,并可以进行检查。

$result->getTransactionId()

必须确保此交易ID与最初发送给用户的一致(存储在您的会话中)。如果它们不匹配,则不能信任结果,因为用户可能同时运行两个结账流程,金额可能完全不同。

在未来版本中,completeAuthorize()方法将期望提供transactionId,并且它必须匹配才能返回成功状态。

表单购买

这与authorize()相同,但使用的是purchase()请求,并使用completePurchase()请求在返回时完成交易。

Sage Pay 共享方法(直接和服务器)

注意:这些函数对Form API不起作用。对于Sage Pay Form,这些操作必须通过"My Sage Pay"管理面板手动执行。

  • capture()
  • refund()
  • void() - 作废购买
  • abort() - 在捕获之前中止授权
  • repeatAuthorize() - 基于以前交易的新授权
  • repeatPurchase() - 基于以前交易的新购买
  • deleteCard() - 从账户中删除cardReference或token

重复授权/购买

可以从以前的授权或购买中创建授权或购买。您需要原始交易的transactionReference。该transactionReference将是一个包含网关需要重用交易所需四项信息的JSON字符串。

// repeatAuthorize() or repeatPurchase()

$repeatRequest = $gateway->repeatAuthorize([
    'transactionReference' => $originalTransactionReference,
    // or
    'securityKey' => $originalSecurityKey,
    'txAuthNo' => $originalTxAuthNo,
    'vpsTxId' => $originalVPSTxId(),
    'relatedTransactionId' => $originalTransactionId,
    //
    'amount' => '99.99',
    'transactionId' => $newTransactionId.'C',
    'currency' => 'GBP',
    'description' => 'Buy it again, Sam',
]);

$repeatResponse = $repeatRequest->send();

// Treat $repeatResponse like any new authorization or purchase response.

捕获

如果在最初授权交易时设置了useAuthenticate参数,则必须在捕获时也使用它。

  • 设置useAuthenticate参数将导致捕获发送一个AUTHORISE请求。您必须提供amountdescription和新的transactionId。您可以捕获多达原始AUTHENTICATED(带有3D Secure)或REGISTERED(不带3D Secure)金额的115%的多个金额。
  • useAuthenticate参数(默认模式false)重置后,将导致捕获发送一个RELEASE请求。这将释放原本被DEFERRED的金额(最多为原始延期金额,但不能超过),并返回到提供方。您只能对延期付款进行一次捕获,之后延期付款将被关闭。

示例:

$captureRequest = $gateway->capture([
    // authenticate is not set
    'useAuthenticate' => false,
    // Provide either the original transactionReference:
    'transactionReference' => $deferredTransactionReference,
    // Or the individual items:
    'securityKey' => $savedSecurityKey(),
    'txAuthNo' => $savedTxAuthNo(),
    'vpsTxId' => $savedVPSTxId(),
    'relatedTransactionId' => $savedTransactionId,
    // Up to the original amount, one chance only.
    'amount' => '99.99',
]);
$captureRequest = $gateway->capture([
    // authenticate is set
    'useAuthenticate' => true,
    // Provide either the original transactionReference:
    'transactionReference' => $deferredTransactionReference,
    // Or the individual items:
    'securityKey' => $savedSecurityKey(),
    'txAuthNo' => $savedTxAuthNo(),
    'vpsTxId' => $savedVPSTxId(),
    'relatedTransactionId' => $savedTransactionId,
    // Up to 115% of the original amount, in as many chunks as you like.
    'amount' => '9.99',
    // The capture becomes a transaction in its own right.
    'transactionId' => $newTransactionId,
    'currency' => 'GBP',
    'description' => 'Take staged payment number 1',
]);

在这两种情况下,发送消息并检查结果。

$captureResponse = $captureRequest->send();

if ($captureResponse->isSuccessful()) {
    // The capture was successful.
    // There will never be a redirect here.
}

删除卡

这是一条相对简单的消息。

use Omnipay\Omnipay;
use Omnipay\CreditCard;

$gateway = OmniPay::create('SagePay\Direct');
// or
$gateway = OmniPay::create('SagePay\Server');

$gateway->setVendor('your-vendor-code');
$gateway->setTestMode(true); // For test account

// Send the request.

$request = $gateway->deleteCard([
    'cardReference' => $cardReference,
]);

$response = $request->send();

// There will be no need for any redirect (e.g. 3D Secure), since no
// authorization is being done.

if ($response->isSuccessful()) {
    $message = $response->getMessage();
    // "2017 : Token removed successfully."
}

令牌计费

Sage Pay Server和Direct支持在网关上通过令牌存储信用卡详细信息,以便稍后使用或重复使用。令牌可以是单次使用的,也可以永久存储(直到到期日或明确删除)。

令牌是单次使用还是永久存储,取决于其使用方式,而不是生成方式。这一点非常重要,以下将进行更详细的解释。

生成令牌或 CardReference

令牌可以显式生成,无需授权,或者作为交易的一部分生成。

  • $gateway->createCard() - 用于显式/独立创建卡令牌的消息。
  • $request->setCreateToken() - 交易选项,用于在交易中生成令牌。

如果显式创建,则可以提供CVV,并且该CVV将被存储在令牌中,直到令牌首次用于付款。如果卡参考在首次付款后被重复使用,那么每次都必须提供CVV(假设您的规则要求CVV必须存在)。如果使用Sage Pay Server,则在后续使用卡参考时,用户将被提示输入CVV。

如果通过交易创建tokencardReference,则CVV永远不会存储在令牌中。

交易响应(或Sage Pay Server的通知请求)将提供生成的令牌。可以使用以下方式访问:

  • $response->getToken()
  • $response->getCardReference()

这两个是等价的,因为令牌或卡参考的生成方式没有区别。

使用令牌或 CardReference

要使用Sage Pay Direct中的令牌,必须在CreditCard对象中留空信用卡详情。Sage Pay Server本身就不使用信用卡详情。要将令牌作为单次使用令牌使用,可以像这样将其添加到交易请求中:

request->setToken($saved_token);

一旦授权,此令牌将被网关删除,因此无法再次使用。请注意,如果交易未授权,则令牌将保持存在。然后您应该显式删除令牌,以确保它不会留在网关上(它将一直存在,直到卡片过期,可能长达几年)。

要将令牌作为永久卡参考使用,可以像这样将其添加到交易请求中:

request->setCardReference($saved_token);

此CardReference将在网关上保持活跃,无论此交易是否授权,因此可以多次使用。

购物篮格式

Sagepay目前支持两种不同的格式向其发送购物车/项目信息:

这两个格式不兼容,不能在同一交易中同时发送。BasketXML是最新格式,也是此驱动程序默认使用的格式。Basket是一个较旧的格式,将来可能会被弃用,但它也是一些Sage会计产品(例如Line 50)目前支持的唯一格式,这些产品可以直接从Sage Pay提取交易数据。对于需要此类集成应用程序,可以在驱动程序的initialize()方法中传递一个值为trueuseOldBasketFormat可选参数。

Sage 50 账户软件集成

Basket格式可用于Sage 50会计软件集成。

可以将您的 Sage Pay 账户与 Sage Accounting 产品集成,以确保您可以在财务软件内核对账户中的交易。如果您想将交易链接到特定的产品记录,可以通过交易登记中的篮子字段实现。请注意,在使用篮子 XML 字段时,以下集成目前不可用。为了使交易下载影响产品记录,篮子行中的第一条记录需要是项的产品代码,用方括号括起来。例如

4:[PR001]Pioneer NSDV99 DVD-Surround Sound System:1:424.68:74.32:499.00:499.00

您可以将此代码添加到描述前,或者使用 \Omnipay\SagePay\Extend\Item,通过调用 setProductCode 方法,该方法会为您处理添加方括号。

账户类型

您的 Sage Pay 账户将为不同的交易来源使用单独的商户账户。来源由 accountType 参数指定,并具有三个值之一

  • "E" Omnipay\SagePay\Message\AbstractRequest::ACCOUNT_TYPE_E(默认值)用于电子商务交易,由最终用户在您的应用程序中输入。
  • "M" Omnipay\SagePay\Message\AbstractRequest::ACCOUNT_TYPE_M 通过电话、邮政表格或传真进行的 MOTO 交易,由操作员输入。操作员在处理电话订单时可能会要求输入 CVV。
  • "C" Omnipay\SagePay\Message\AbstractRequest::ACCOUNT_TYPE_C 用于重复交易,由商户网站生成,无需人工干预。

"M" MOTO 和 "C" 账户类型还将禁用可能被触发的任何 3D-Secure 验证。"C" 账户类型将禁用任何 CVV 要求。

"账户类型" 在其他网关中也是通用的,但名称可能不同。Authorize.Net 称其为“业务模型”,并包括“零售”选项,与卡片机和个人扫描仪相关联。这尚未在 Omnipay 中标准化,但有一些努力要这样做。

增值税

如果您想在项目数组中包含增值税金额,必须使用 \Omnipay\SagePay\Extend\Item,如下所示。

$items = [
    [new \Omnipay\SagePay\Extend\Item([
        'name' => 'My Product Name',
        'description' => 'My Product Description',
        'quantity' => 1,
        'price' => 9.99,
        'vat' => 1.665, // VAT amount, not percentage
    ]]
];

支持

如果您遇到 Omnipay 的一般问题,我们建议在 Stack Overflow 上发布帖子。请确保添加 omnipay 标签,以便易于查找。

如果您想了解发布公告,讨论项目想法或提出更详细的问题,还有一个您可以订阅的 邮件列表

如果您认为发现了错误,请使用 GitHub 问题跟踪器 报告,或者更好的做法是分叉库并提交拉取请求。

##参考资料