Skip to content

Commit bebf981

Browse files
authored
Merge pull request #43 from adrian-tech-enthusiast-c/master
Add support for Accept Hosted Payment Page and Customer Profiles from transactions.
2 parents 59f1fd1 + 1c8fd45 commit bebf981

12 files changed

Lines changed: 638 additions & 2 deletions

src/AuthenticateTestRequest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
namespace CommerceGuys\AuthNet;
4+
5+
use CommerceGuys\AuthNet\DataTypes\MerchantAuthentication;
6+
use CommerceGuys\AuthNet\Request\RequestInterface;
7+
8+
/**
9+
* Represents the authenticateTestRequest endpoint for testing API credentials.
10+
*
11+
* This request verifies that the provided API Login ID and Transaction Key
12+
* are valid and that the merchant is authorized to submit transactions.
13+
*
14+
* Commonly used to validate configuration forms or connectivity.
15+
*
16+
* @link https://developer.authorize.net/api/reference/index.html#gettingstarted-section-section-header
17+
*/
18+
class AuthenticateTestRequest extends BaseApiRequest
19+
{
20+
21+
/**
22+
* Sets the merchant authentication credentials.
23+
*
24+
* @param \CommerceGuys\AuthNet\DataTypes\MerchantAuthentication $merchantAuthentication
25+
*
26+
* @return $this
27+
*/
28+
public function setMerchantAuthentication(MerchantAuthentication $merchantAuthentication): self
29+
{
30+
$this->merchantAuthentication = $merchantAuthentication;
31+
return $this;
32+
}
33+
34+
/**
35+
* Gets the merchant authentication credentials.
36+
*
37+
* @return \CommerceGuys\AuthNet\DataTypes\MerchantAuthentication|null
38+
*/
39+
public function getMerchantAuthentication(): ?MerchantAuthentication
40+
{
41+
return $this->merchantAuthentication;
42+
}
43+
44+
/**
45+
* {@inheritdoc}
46+
*/
47+
protected function attachData(RequestInterface $request): void
48+
{
49+
// Only attach merchant authentication if available.
50+
if ($this->merchantAuthentication) {
51+
$request->addDataType($this->merchantAuthentication);
52+
}
53+
}
54+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace CommerceGuys\AuthNet;
4+
5+
use GuzzleHttp\Client;
6+
use CommerceGuys\AuthNet\Request\RequestInterface;
7+
8+
/**
9+
* Creates a customer profile, payment profile, and shipping address
10+
* from an existing successful transaction.
11+
*
12+
* This request uses a transaction ID (`transId`) from a prior successful
13+
* payment to generate a new customer profile in Authorize.Net.
14+
*
15+
* @link https://developer.authorize.net/api/reference/index.html#customer-profiles-create-a-customer-profile-from-a-transaction
16+
*/
17+
class CreateCustomerProfileFromTransactionRequest extends BaseApiRequest
18+
{
19+
/**
20+
* @var string The transaction ID from a successful payment.
21+
*/
22+
protected $transId;
23+
24+
/**
25+
* Constructs a new CreateCustomerProfileFromTransactionRequest object.
26+
*
27+
* @param Configuration $configuration
28+
* The configuration object containing API credentials.
29+
* @param Client $client
30+
* The HTTP client for making requests.
31+
* @param string $transId
32+
* The transaction ID from an existing successful transaction.
33+
*/
34+
public function __construct(
35+
Configuration $configuration,
36+
Client $client,
37+
$transId
38+
) {
39+
parent::__construct($configuration, $client);
40+
$this->transId = $transId;
41+
}
42+
43+
/**
44+
* {@inheritdoc}
45+
*/
46+
protected function attachData(RequestInterface $request)
47+
{
48+
$request->addData('transId', $this->transId);
49+
}
50+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace CommerceGuys\AuthNet\DataTypes;
4+
5+
/**
6+
* Collection of hosted payment settings.
7+
*/
8+
class HostedPaymentSettings extends BaseDataType
9+
{
10+
11+
/**
12+
* Adds a setting to the hosted payment configuration.
13+
*
14+
* @param Setting $setting
15+
*/
16+
public function addSetting(Setting $setting): void
17+
{
18+
$this->properties[] = ['setting' => $setting->toArray()];
19+
}
20+
21+
/**
22+
* Removes setting from the hosted payment configuration.
23+
*
24+
* @param string $name
25+
*/
26+
public function removeSetting(string $name): void
27+
{
28+
foreach ($this->properties as $key => $property) {
29+
if ($property['setting']['settingName'] == $name) {
30+
unset($this->properties[$key]);
31+
}
32+
}
33+
}
34+
}

src/DataTypes/Setting.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace CommerceGuys\AuthNet\DataTypes;
4+
5+
/**
6+
* Represents a single setting used in HostedPaymentSettings.
7+
*
8+
* @see \CommerceGuys\AuthNet\DataTypes\HostedPaymentSettings
9+
*/
10+
class Setting extends BaseDataType
11+
{
12+
13+
protected $propertyMap = [
14+
'settingName',
15+
'settingValue',
16+
];
17+
18+
/**
19+
* Constructs a new Setting object.
20+
*
21+
* @param string $name
22+
* The name of the setting (e.g., hostedPaymentReturnOptions).
23+
* @param mixed $value
24+
* The value, which will be JSON-encoded if it's an array.
25+
*/
26+
public function __construct(string $name, $value)
27+
{
28+
parent::__construct();
29+
$this->properties['settingName'] = $name;
30+
// Encode the value.
31+
if (is_array($value)) {
32+
$value = json_encode($value, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
33+
}
34+
$this->properties['settingValue'] = $value;
35+
}
36+
37+
}

src/GetCustomerProfileRequest.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
class GetCustomerProfileRequest extends BaseApiRequest
1414
{
1515
protected $customerProfileId;
16+
protected $unmaskExpirationDate = false;
1617

1718
public function __construct(
1819
Configuration $configuration,
@@ -23,8 +24,19 @@ public function __construct(
2324
$this->customerProfileId = $customerProfileId;
2425
}
2526

26-
protected function attachData(RequestInterface $request)
27+
/**
28+
* @param boolean $unmaskExpirationDate
29+
*/
30+
public function setUnmaskExpirationDate($unmaskExpirationDate)
31+
{
32+
$this->unmaskExpirationDate = $unmaskExpirationDate;
33+
}
34+
35+
protected function attachData(RequestInterface $request)
2736
{
2837
$request->addData('customerProfileId', $this->customerProfileId);
38+
if ($this->unmaskExpirationDate) {
39+
$request->addData('unmaskExpirationDate', $this->unmaskExpirationDate);
40+
}
2941
}
3042
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
namespace CommerceGuys\AuthNet;
4+
5+
use CommerceGuys\AuthNet\DataTypes\HostedPaymentSettings;
6+
use CommerceGuys\AuthNet\DataTypes\TransactionRequest;
7+
use CommerceGuys\AuthNet\Request\RequestInterface;
8+
use GuzzleHttp\Client;
9+
10+
/**
11+
* Retrieves a token to launch the Accept Hosted payment form.
12+
*
13+
* @link https://developer.authorize.net/api/reference/index.html#accept-suite-get-an-accept-payment-page
14+
*/
15+
class GetHostedPaymentPageRequest extends BaseApiRequest
16+
{
17+
/**
18+
* @var \CommerceGuys\AuthNet\DataTypes\TransactionRequest|null
19+
*/
20+
protected $transactionRequest;
21+
22+
/**
23+
* @var \CommerceGuys\AuthNet\DataTypes\HostedPaymentSettings|null;
24+
*/
25+
protected $hostedPaymentSettings;
26+
27+
/**
28+
* Constructs a new GetHostedPaymentPageRequest object.
29+
*
30+
* @param Configuration $configuration
31+
* The configuration object containing API credentials.
32+
* @param Client $client
33+
* The HTTP client for making requests.
34+
* @param \CommerceGuys\AuthNet\DataTypes\TransactionRequest|null $transactionRequest
35+
* The transaction request details.
36+
* @param \CommerceGuys\AuthNet\DataTypes\HostedPaymentSettings|null $hostedPaymentSettings
37+
* The settings for the Accept Hosted payment form.
38+
*/
39+
public function __construct(
40+
Configuration $configuration,
41+
Client $client,
42+
TransactionRequest $transactionRequest = null,
43+
HostedPaymentSettings $hostedPaymentSettings = null
44+
) {
45+
parent::__construct($configuration, $client);
46+
$this->transactionRequest = $transactionRequest;
47+
$this->hostedPaymentSettings = $hostedPaymentSettings;
48+
}
49+
50+
/**
51+
* {@inheritdoc}
52+
*/
53+
protected function attachData(RequestInterface $request)
54+
{
55+
// Attach transaction details.
56+
if ($this->transactionRequest) {
57+
$request->addDataType($this->transactionRequest);
58+
}
59+
// Add hosted payment settings.
60+
if ($this->hostedPaymentSettings) {
61+
$request->addDataType($this->hostedPaymentSettings);
62+
}
63+
}
64+
65+
/**
66+
* Sets the transaction request.
67+
*
68+
* @param \CommerceGuys\AuthNet\DataTypes\TransactionRequest $transactionRequest
69+
* The transaction details.
70+
*
71+
* @return $this
72+
*/
73+
public function setTransactionRequest(TransactionRequest $transactionRequest)
74+
{
75+
$this->transactionRequest = $transactionRequest;
76+
return $this;
77+
}
78+
79+
/**
80+
* Sets the hosted payment settings.
81+
*
82+
* @param \CommerceGuys\AuthNet\DataTypes\HostedPaymentSettings $hostedPaymentSettings
83+
*
84+
* @return $this
85+
*/
86+
public function setHostedPaymentSettings(HostedPaymentSettings $hostedPaymentSettings)
87+
{
88+
$this->hostedPaymentSettings = $hostedPaymentSettings;
89+
return $this;
90+
}
91+
}

tests/ARBCreateSubscriptionRequestTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public function testARBCreateSubscriptionRequestCRUD()
2020
{
2121
$interval = new Interval(['length' => 7, 'unit' => 'days']);
2222
$paymentSchedule = new PaymentSchedule([
23-
'startDate' => '2024-08-30',
23+
'startDate' => (new \DateTime('+1 day'))->format('Y-m-d'),
2424
'totalOccurrences' => 9999,
2525
]);
2626
$paymentSchedule->addInterval($interval);

tests/AuthenticateRequestTest.php

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace CommerceGuys\AuthNet\Tests;
4+
5+
use CommerceGuys\AuthNet\AuthenticateTestRequest;
6+
use CommerceGuys\AuthNet\DataTypes\MerchantAuthentication;
7+
use CommerceGuys\AuthNet\Tests\TestBase;
8+
9+
/**
10+
* Tests the AuthenticateTestRequest.
11+
*
12+
* This test verifies that the provided merchant credentials are valid
13+
* using both XML and JSON formats.
14+
*/
15+
class AuthenticateTestRequestTest extends TestBase
16+
{
17+
/**
18+
* Tests the authenticateTestRequest using XML format.
19+
*/
20+
public function testAuthenticateTestXml(): void
21+
{
22+
$request = new AuthenticateTestRequest(
23+
$this->configurationXml,
24+
$this->client
25+
);
26+
27+
// Explicitly set authentication in case configuration does not preload it.
28+
$request->setMerchantAuthentication(new MerchantAuthentication([
29+
'name' => $this->configurationXml->getApiLogin(),
30+
'transactionKey' => $this->configurationXml->getTransactionKey(),
31+
]));
32+
33+
/** @var \CommerceGuys\AuthNet\Response\XmlResponse $response */
34+
$response = $request->execute();
35+
36+
$this->assertEquals('Ok', $response->getResultCode());
37+
$this->assertEquals('I00001', $response->getMessages()[0]->getCode());
38+
$this->assertEquals('Successful.', $response->getMessages()[0]->getText());
39+
}
40+
41+
/**
42+
* Tests the authenticateTestRequest using JSON format.
43+
*/
44+
public function testAuthenticateTestJson(): void
45+
{
46+
$request = new AuthenticateTestRequest(
47+
$this->configurationJson,
48+
$this->client
49+
);
50+
51+
$request->setMerchantAuthentication(new MerchantAuthentication([
52+
'name' => $this->configurationJson->getApiLogin(),
53+
'transactionKey' => $this->configurationJson->getTransactionKey(),
54+
]));
55+
56+
/** @var \CommerceGuys\AuthNet\Response\JsonResponse $response */
57+
$response = $request->execute();
58+
59+
$this->assertEquals('Ok', $response->getResultCode());
60+
$this->assertEquals('I00001', $response->getMessages()[0]->getCode());
61+
$this->assertEquals('Successful.', $response->getMessages()[0]->getText());
62+
}
63+
}

0 commit comments

Comments
 (0)