Skip to content

Commit 818cb1f

Browse files
authored
Merge pull request #180 from unzerdev/develop
Release 3.5.0
2 parents df721ca + a7cfd16 commit 818cb1f

File tree

21 files changed

+1138
-5
lines changed

21 files changed

+1138
-5
lines changed

.github/workflows/unit-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
php: ['7.4', '8.0', '8.1', '8.2']
15+
php: ['7.4', '8.0', '8.1', '8.2', '8.3']
1616
name: PHP ${{ matrix.php }} unit tests
1717
steps:
1818
- uses: actions/checkout@v3

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres
66
to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [3.5.0](https://github.com/unzerdev/php-sdk/compare/3.4.1..3.5.0)
9+
10+
This version adds support for Google Pay.
11+
12+
### Added
13+
* Add `\UnzerSDK\Resources\PaymentTypes\Googlepay` payment type.
14+
* Add Example for Google Pay.
15+
* Add PHP 8.3 version to composer.json
16+
817
## [3.4.1](https://github.com/unzerdev/php-sdk/compare/3.4.0..3.4.1)
918

1019
Revert deprecation of Sepa Direct Debit type.

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{
22
"name": "unzerdev/php-sdk",
3-
"description": "This is the php sdk to connect to the Unzer rest api.",
3+
"description": "This is the php sdk to connect to the Unzer rest API.",
44
"minimum-stability": "stable",
55
"license": "Apache-2.0",
66
"require": {
7-
"php": "~7.4.0|~8.0.0|~8.1.0|~8.2.0",
7+
"php": "~7.4.0|~8.0.0|~8.1.0|~8.2.0|~8.3.0",
88
"ext-json": "*"
99
},
1010
"require-dev": {

examples/Googlepay/Constants.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
/**
3+
* This file defines the constants needed for the Google Pay example.
4+
*/
5+
6+
require_once __DIR__ . '/../Constants.php';
7+
8+
define('EXAMPLE_URL', EXAMPLE_BASE_FOLDER . 'Googlepay');
9+
define('CONTROLLER_URL', EXAMPLE_URL . '/Controller.php');

examples/Googlepay/Controller.php

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
/**
3+
* This is the controller for the Google Pay example.
4+
* It is called when the pay button on the index page is clicked.
5+
*
6+
* @link https://docs.unzer.com/
7+
*
8+
*/
9+
10+
/** Require the constants of this example */
11+
const TRANSACTION_STATUS_KEY = 'transactionStatus';
12+
const REDIRECT_URL_KEY = 'redirectUrl';
13+
require_once __DIR__ . '/Constants.php';
14+
15+
/** @noinspection PhpIncludeInspection */
16+
/** Require the composer autoloader file */
17+
require_once __DIR__ . '/../../../../autoload.php';
18+
19+
use UnzerSDK\examples\ExampleDebugHandler;
20+
use UnzerSDK\Exceptions\UnzerApiException;
21+
use UnzerSDK\Unzer;
22+
23+
session_start();
24+
session_unset();
25+
26+
$clientMessage = 'Something went wrong. Please try again later.';
27+
$merchantMessage = 'Something went wrong. Please try again later.';
28+
29+
function redirect($url, $merchantMessage = '', $clientMessage = '')
30+
{
31+
$_SESSION['merchantMessage'] = $merchantMessage;
32+
$_SESSION['clientMessage'] = $clientMessage;
33+
header('Location: ' . $url);
34+
die();
35+
}
36+
37+
// These lines are just for this example
38+
$jsonData = json_decode(file_get_contents('php://input'), false);
39+
$paymentTypeId = $jsonData->typeId;
40+
$transactionType = $jsonData->transaction_type ?? 'authorize';
41+
42+
// You will need the id of the payment type created in the frontend (index.php)
43+
if (empty($paymentTypeId)) {
44+
echo json_encode(['result' => false]);
45+
return;
46+
}
47+
48+
$transactionResult = [
49+
TRANSACTION_STATUS_KEY => 'error',
50+
REDIRECT_URL_KEY => ''
51+
];
52+
53+
// Catch API errors, write the message to your log and show the ClientMessage to the client.
54+
try {
55+
// Create an Unzer object using your private key and register a debug handler if you want to.
56+
$unzer = new Unzer(UNZER_PAPI_PRIVATE_KEY);
57+
$unzer->setDebugMode(true)->setDebugHandler(new ExampleDebugHandler());
58+
59+
if ($transactionType === 'charge') {
60+
$charge = new \UnzerSDK\Resources\TransactionTypes\Charge(12.32, 'EUR', RETURN_CONTROLLER_URL);
61+
$transaction = $unzer->performCharge($charge, $paymentTypeId);
62+
} else {
63+
$authorize = new \UnzerSDK\Resources\TransactionTypes\Authorization(12.32, 'EUR', RETURN_CONTROLLER_URL);
64+
$transaction = $unzer->performAuthorization($authorize, $paymentTypeId);
65+
}
66+
67+
// You'll need to remember the paymentId for later in the ReturnController
68+
$_SESSION['PaymentId'] = $transaction->getPaymentId();
69+
$_SESSION['ShortId'] = $transaction->getShortId();
70+
71+
$redirectUrl = $transaction->getRedirectUrl();
72+
73+
if (!empty($redirectUrl)) {
74+
$transactionResult[REDIRECT_URL_KEY] = $redirectUrl;
75+
}
76+
77+
if ($transaction->isSuccess()) {
78+
$transactionResult[TRANSACTION_STATUS_KEY] = 'success';
79+
echo json_encode($transactionResult);
80+
return;
81+
}
82+
if ($transaction->isPending()) {
83+
$transactionResult[TRANSACTION_STATUS_KEY] = 'pending';
84+
85+
echo json_encode($transactionResult);
86+
return;
87+
}
88+
} catch (UnzerApiException $e) {
89+
$_SESSION['merchantMessage'] = $e->getMerchantMessage();
90+
$_SESSION['clientMessage'] = $e->getClientMessage();
91+
} catch (RuntimeException $e) {
92+
$_SESSION['merchantMessage'] = $e->getMessage();
93+
}
94+
95+
echo json_encode($transactionResult);

examples/Googlepay/index.php

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
<?php
2+
3+
/**
4+
* This file provides an example implementation of the Googlepay payment type.
5+
*/
6+
7+
/** Require the constants of this example */
8+
require_once __DIR__ . '/Constants.php';
9+
10+
/** @noinspection PhpIncludeInspection */
11+
/** Require the composer autoloader file */
12+
require_once __DIR__ . '/../../../../autoload.php';
13+
?>
14+
15+
<!DOCTYPE html>
16+
<html lang="en">
17+
<head>
18+
<meta charset="UTF-8"/>
19+
<title>Unzer UI Examples</title>
20+
<script src="https://code.jquery.com/jquery-3.6.0.min.js"
21+
integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
22+
crossorigin="anonymous"></script>
23+
24+
<link rel="stylesheet" href="https://static.unzer.com/v1/unzer.css"/>
25+
<script type="text/javascript" src="https://static.unzer.com/v1/unzer.js"></script>
26+
<script src="https://pay.google.com/gp/p/js/pay.js"></script>
27+
28+
</head>
29+
30+
<body style="margin: 70px 70px 0;">
31+
32+
<p><a href="https://docs.unzer.com/reference/test-data" target="_blank">Click here to open our test data in new tab.</a><br/>
33+
</p>
34+
35+
<form id="payment-form" class="unzerUI form" novalidate>
36+
<!-- This is just for the example - Start -->
37+
<div class="fields inline">
38+
<label for="transaction_type">Chose the transaction type you want to test:</label>
39+
<div class="field">
40+
<div class="unzerUI radio checkbox">
41+
<input type="radio" name="transaction_type" value="authorize" checked="">
42+
<label>Authorize</label>
43+
</div>
44+
</div>
45+
<div class="field">
46+
<div class="unzerUI radio checkbox">
47+
<input type="radio" name="transaction_type" value="charge">
48+
<label>Charge</label>
49+
</div>
50+
</div>
51+
</div>
52+
<!-- This is just for the example - End -->
53+
54+
<div>
55+
<div class="field" id="error-holder" style="color: #9f3a38"> </div>
56+
<div class="button-well">
57+
<div class="applePayButtonContainer">
58+
<div class="apple-pay-button apple-pay-button-black" lang="us"
59+
onclick="setupApplePaySession()"
60+
title="Start Apple Pay" role="link" tabindex="0">
61+
</div>
62+
</div>
63+
</div>
64+
</div>
65+
</form>
66+
67+
<div id="dimmer-holder-googlepay" class="ui active dimmer" style="display: none;">
68+
<div class="ui loader"></div>
69+
</div>
70+
71+
<div id="example-googlepay-stack"></div>
72+
<div id="error-holder-googlepay" class="field" style="text-align: center; color: #9f3a38"></div>
73+
74+
<script>
75+
const unzerInstance = new unzer('<?php echo UNZER_PAPI_PUBLIC_KEY; ?>');
76+
const colors = ['black','white'];
77+
const googlepayChannelId = "<?php echo UNZER_EXAMPLE_GOOGLEPAY_CHANNEL; ?>"
78+
const stackHolder = document.querySelector('#example-googlepay-stack');
79+
80+
const tmpPaymentDataRequestObject = {
81+
gatewayMerchantId: googlepayChannelId,
82+
allowedCardNetworks: [
83+
'MASTERCARD',
84+
'VISA',
85+
'DISCOVER',
86+
'JCB',
87+
],
88+
merchantInfo: {
89+
merchantId: googlepayChannelId,
90+
merchantName: 'Example Merchant'
91+
},
92+
transactionInfo: {
93+
displayItems: [],
94+
countryCode: 'DE',
95+
currencyCode: 'EUR',
96+
totalPrice: '12.00',
97+
},
98+
}
99+
100+
function handleGooglepayError(error) {
101+
let errorMessage = error.customerMessage || error.message || 'Error';
102+
if (error.data && Array.isArray(error.data.errors) && error.data.errors[0]) {
103+
errorMessage = error.data.errors[0].customerMessage || 'Error'
104+
}
105+
106+
document.getElementById('error-holder-googlepay').innerHTML = errorMessage;
107+
108+
return {
109+
status: 'error',
110+
message: errorMessage || 'Unexpected error'
111+
}
112+
}
113+
114+
colors.map(function (color) {
115+
const htmlString = '<div id="example-googlepay-' + color + '" class="field" style="text-align: center; margin: 5px 0"></div>'
116+
return ({
117+
instance: null,
118+
color: color,
119+
htmlString: htmlString
120+
})
121+
}).forEach(function (item) {
122+
stackHolder.insertAdjacentHTML('beforeend', item.htmlString)
123+
item.instance = unzerInstance.Googlepay()
124+
const extendedPaymentDataRequestObject = {
125+
...tmpPaymentDataRequestObject,
126+
buttonColor: item.color,
127+
onPaymentAuthorizedCallback: (paymentData) => {
128+
document.getElementById('error-holder-googlepay').innerHTML = ''
129+
const $form = $('form[id="payment-form"]');
130+
const formObject = QueryStringToObject($form.serialize());
131+
132+
return item.instance.createResource(paymentData)
133+
.then(typeCreationResult => {
134+
document.getElementById('dimmer-holder-googlepay').style.display = 'block';
135+
formObject.typeId = typeCreationResult.id;
136+
137+
return fetch(
138+
'./Controller.php',
139+
{
140+
body: JSON.stringify(formObject),
141+
method: 'POST'
142+
}
143+
)
144+
.then(response => response.json())
145+
.then( transactionResult => {
146+
const status = transactionResult.transactionStatus;
147+
148+
if (status === 'success' || status === 'pending') {
149+
if (transactionResult.redirectUrl.trim().length !== 0) {
150+
window.location.href = transactionResult.redirectUrl;
151+
} else {
152+
window.location.href = '<?php echo RETURN_CONTROLLER_URL; ?>';
153+
}
154+
return { status: 'success' };
155+
}
156+
window.location.href = '<?php echo FAILURE_URL; ?>';
157+
return {
158+
status: 'error',
159+
message: transactionResult.customerMessage || transactionResult.message || 'Unexpected error'
160+
}
161+
})
162+
.catch(function (error) {
163+
return handleGooglepayError(error);
164+
}
165+
)
166+
})
167+
.catch(function (error) {
168+
return handleGooglepayError(error);
169+
})
170+
}
171+
}
172+
173+
const paymentDataRequestObject = item.instance.initPaymentDataRequestObject(extendedPaymentDataRequestObject)
174+
item.instance.create(
175+
{
176+
containerId: 'example-googlepay-' + item.color
177+
},
178+
paymentDataRequestObject
179+
)
180+
})
181+
182+
// Translates query string to object
183+
function QueryStringToObject(queryString) {
184+
const pairs = queryString.slice().split('&');
185+
let result = {};
186+
187+
pairs.forEach(function(pair) {
188+
pair = pair.split('=');
189+
result[pair[0]] = decodeURIComponent(pair[1] || '');
190+
});
191+
return JSON.parse(JSON.stringify(result));
192+
}
193+
194+
</script>
195+
196+
</body>
197+
</html>

examples/_enableExamples.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
define('UNZER_PAPI_EXAMPLES', false);
1313

1414
/* Please set this to your url. It must be reachable over the net
15-
Webhooks will work with https only. However protocol can be changed to http if necessary. */
15+
Webhooks will work with https only. However, protocol can be changed to http if necessary. */
1616
define('UNZER_PAPI_URL', 'https://'.$_SERVER['HTTP_HOST']);
1717

1818
/* Please enter the path from root directory to the example folder */
@@ -26,6 +26,13 @@
2626
define('UNZER_PP_LOGO_URL', 'https://sbx-insights.unzer.com/static/unzerLogo.svg');
2727
define('UNZER_PP_FULL_PAGE_IMAGE_URL', 'https://raw.githubusercontent.com/unzerdev/php-sdk/da9c3fce11264f412e03009606621cc6d9ec0ab1/unzer_logo.svg');
2828

29+
/* ============ PaymentType Specific settings ============ */
30+
31+
/* ------------ Google Pay ------------ */
32+
// Channel of 'googlepay' type. You can find the channel in your keypair config.
33+
define('UNZER_EXAMPLE_GOOGLEPAY_CHANNEL', '');
34+
35+
/* ------------ Apple Pay ------------ */
2936
/* For Apple Pay only, set the path to your Apple Pay Merchant-ID certificate. */
3037
define('UNZER_EXAMPLE_APPLEPAY_MERCHANT_CERT', UNZER_PAPI_FOLDER . '');
3138

examples/index.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,18 @@ function printMessage($type, $title, $text)
155155
Try
156156
</div>
157157
</div>
158+
<div class="card olive">
159+
<div class="content">
160+
<div class="header">
161+
Google Pay
162+
</div>
163+
<div class="description">
164+
</div>
165+
</div>
166+
<div id="tryGooglepayExample" class="ui bottom attached green button" onclick="location.href='Googlepay/';">
167+
Try
168+
</div>
169+
</div>
158170
<div class="card olive">
159171
<div class="content">
160172
<div class="header">

src/Constants/IdStrings.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class IdStrings
2424
public const CARD = 'crd';
2525
public const EPS = 'eps';
2626
public const GIROPAY = 'gro';
27+
public const GOOGLE_PAY = 'gop';
2728
public const HIRE_PURCHASE_DIRECT_DEBIT = 'hdd';
2829
public const IDEAL = 'idl';
2930
public const INSTALLMENT_SECURED = 'ins';
@@ -63,6 +64,7 @@ class IdStrings
6364
self::CARD,
6465
self::EPS,
6566
self::GIROPAY,
67+
self::GOOGLE_PAY,
6668
self::HIRE_PURCHASE_DIRECT_DEBIT,
6769
self::IDEAL,
6870
self::INSTALLMENT_SECURED,

0 commit comments

Comments
 (0)