-
Notifications
You must be signed in to change notification settings - Fork 2
/
Refund.php
121 lines (118 loc) · 4.58 KB
/
Refund.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<?php
namespace Dfe\SecurePay;
use Df\Payment\Operation\Source\Creditmemo as SCreditmemo;
use Df\Payment\TM;
use Df\Xml\X;
# 2016-08-30
/** @method Method m() */
final class Refund extends \Df\Payment\Operation {
/**
* 2016-09-07
* @override
* @see \Df\Payment\Operation::amountFormat()
* @used-by \Df\Payment\Operation::amountF()
*/
protected function amountFormat(float $a):int {return round(100 * parent::amountFormat($a));}
/**
* 2016-08-20
* @used-by \Dfe\SecurePay\Refund::p()
*/
private function process():void {
$s = $this->s(); /** @var Settings $s */
$tm = df_tm($this->m()); /** @var TM $tm */
$xA = df_xml_g('SecurePayMessage', [
'MessageInfo' => [
'messageID' => df_cdata(df_cc('-', $this->id(), df_uid(4)))
,'messageTimestamp' => $this->timestamp()
,'timeoutValue' => 120
,'apiVersion' => 'xml-4.2'
]
,'MerchantInfo' => ['merchantID' => $s->merchantID(), 'password' => df_cdata($s->password())]
,'RequestType' => 'Payment'
,'Payment' => [
df_xml_node('TxnList', ['count' => 1], [
df_xml_node('Txn', ['ID' => 1], [
'txnType' => 4
,'txnSource' => 23
,'amount' => $this->amountF()
,'purchaseOrderNo' => df_cdata($tm->req('EPS_REFERENCEID'))
,'txnID' => $tm->responseF('txnid')
])
])
]
]); /** @var string $xA */
$c = df_zf_http(dfp_url_api($this, 'https://{stage}.securepay.com.au/xmlapi/payment', ['test', 'api']))
# 2017-06-28
# «Difference between the Accept and Content-Type HTTP headers»
# https://webmasters.stackexchange.com/questions/31212
->setHeaders(array_fill_keys(['accept', 'content-type'], 'text/xml'))
->setRawData($xA)
; /** @var \Zend_Http_Client $c */
$xB = $c->request(\Zend_Http_Client::POST)->getBody(); /** @var string $xB */
$xAL = df_xml_prettify(str_replace($s->password(), '*****', $xA)); /** @var string $xAL */
$xBL = df_xml_prettify($xB); /** @var string $xBL */
$this->m()->iiaSetTRR($xAL, $xBL);
$xxB = df_xml_parse($xB); /** @var X $xxB */
$status = $xxB->{'Status'}; /** @var X $status */
$code = df_leaf_sne($status->{'statusCode'}); /** @var string $code */
$errorMessage = null; /** @var $errorMessage */
if ('000' !== $code) {
$errorMessage = df_leaf_sne($status->{'statusDescription'});
}
else {
# 2016-09-01
# При повторной попытке возврата SecurePay всё равно возвращает:
# <Status>
# <statusCode>000</statusCode>
# <statusDescription>Normal</statusDescription>
# </Status>
#
# Поэтому допольнительно смотрим другой кусок ответа: Payment/TxnList/Txn
# В случае успеха там:
# <approved>Yes</approved>
# <responseCode>00</responseCode>
# <responseText>Approved</responseText>
# <thinlinkResponseCode>100</thinlinkResponseCode>
# <thinlinkResponseText>000</thinlinkResponseText>
# <thinlinkEventStatusCode>000</thinlinkEventStatusCode>
# <thinlinkEventStatusText>Normal</thinlinkEventStatusText>
# В случае сбоя там:
# <approved>No</approved>
# <responseCode>134</responseCode>
# <responseText>Transaction already fully refunded</responseText>
# <thinlinkResponseCode>300</thinlinkResponseCode>
# <thinlinkResponseText>000</thinlinkResponseText>
# <thinlinkEventStatusCode>999</thinlinkEventStatusCode>
# <thinlinkEventStatusText>Error - Transaction Already Fully Refunded/Only $x.xx Available for Refund</thinlinkEventStatusText>
$txn = $xxB->{'Payment'}->{'TxnList'}->{'Txn'};/** @var X $txn */
if ('Yes' !== df_leaf_sne($txn->{'approved'})) {
$errorMessage = df_leaf_sne($txn->{'thinlinkEventStatusText'});
}
}
if ($errorMessage) {
# 2016-09-01
# Из-за бага в ядре исключительная ситуация при refund не только не логируется,
# а и вообще теряется. Поэтому мы и логируем её сами.
dfp_report($this, $xAL, 'request');
dfp_report($this, $xBL, 'response');
df_error($errorMessage);
}
}
/**
* 2016-08-31
* API requires the timezone offset in minutes
* https://github.com/thephpleague/omnipay-securepay/blob/a7b1b5/src/Message/SecureXMLAbstractRequest.php#L124-L138
*/
private function timestamp():string {/** @var \DateTime $d */ $d = new \DateTime; return $d->format(sprintf(
'YmdHis000%+04d', $d->format('Z') / 60
));}
/**
* 2016-08-27
* @used-by \Dfe\SecurePay\Method::_refund()
*/
static function p(Method $m):string {
$i = new self(new SCreditmemo($m)); /** @var self $i */
$i->process();
return $i->id();
}
}