WebhookTestingGateway.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  1. <?php
  2. namespace Braintree;
  3. class WebhookTestingGateway
  4. {
  5. public function __construct($gateway)
  6. {
  7. $this->config = $gateway->config;
  8. $this->config->assertHasAccessTokenOrKeys();
  9. }
  10. public function sampleNotification($kind, $id, $sourceMerchantId = null)
  11. {
  12. $xml = self::_sampleXml($kind, $id, $sourceMerchantId);
  13. $payload = base64_encode($xml) . "\n";
  14. $signature = $this->config->getPublicKey() . "|" . Digest::hexDigestSha1($this->config->getPrivateKey(), $payload);
  15. return [
  16. 'bt_signature' => $signature,
  17. 'bt_payload' => $payload
  18. ];
  19. }
  20. private static function _sampleXml($kind, $id, $sourceMerchantId)
  21. {
  22. switch ($kind) {
  23. case WebhookNotification::SUB_MERCHANT_ACCOUNT_APPROVED:
  24. $subjectXml = self::_merchantAccountApprovedSampleXml($id);
  25. break;
  26. case WebhookNotification::SUB_MERCHANT_ACCOUNT_DECLINED:
  27. $subjectXml = self::_merchantAccountDeclinedSampleXml($id);
  28. break;
  29. case WebhookNotification::TRANSACTION_DISBURSED:
  30. $subjectXml = self::_transactionDisbursedSampleXml($id);
  31. break;
  32. case WebhookNotification::TRANSACTION_SETTLED:
  33. $subjectXml = self::_transactionSettledSampleXml($id);
  34. break;
  35. case WebhookNotification::TRANSACTION_SETTLEMENT_DECLINED:
  36. $subjectXml = self::_transactionSettlementDeclinedSampleXml($id);
  37. break;
  38. case WebhookNotification::DISBURSEMENT_EXCEPTION:
  39. $subjectXml = self::_disbursementExceptionSampleXml($id);
  40. break;
  41. case WebhookNotification::DISBURSEMENT:
  42. $subjectXml = self::_disbursementSampleXml($id);
  43. break;
  44. case WebhookNotification::PARTNER_MERCHANT_CONNECTED:
  45. $subjectXml = self::_partnerMerchantConnectedSampleXml($id);
  46. break;
  47. case WebhookNotification::PARTNER_MERCHANT_DISCONNECTED:
  48. $subjectXml = self::_partnerMerchantDisconnectedSampleXml($id);
  49. break;
  50. case WebhookNotification::PARTNER_MERCHANT_DECLINED:
  51. $subjectXml = self::_partnerMerchantDeclinedSampleXml($id);
  52. break;
  53. case WebhookNotification::OAUTH_ACCESS_REVOKED:
  54. $subjectXml = self::_oauthAccessRevocationSampleXml($id);
  55. break;
  56. case WebhookNotification::CONNECTED_MERCHANT_STATUS_TRANSITIONED:
  57. $subjectXml = self::_connectedMerchantStatusTransitionedSampleXml($id);
  58. break;
  59. case WebhookNotification::CONNECTED_MERCHANT_PAYPAL_STATUS_CHANGED:
  60. $subjectXml = self::_connectedMerchantPayPalStatusChangedSampleXml($id);
  61. break;
  62. case WebhookNotification::DISPUTE_OPENED:
  63. $subjectXml = self::_disputeOpenedSampleXml($id);
  64. break;
  65. case WebhookNotification::DISPUTE_LOST:
  66. $subjectXml = self::_disputeLostSampleXml($id);
  67. break;
  68. case WebhookNotification::DISPUTE_WON:
  69. $subjectXml = self::_disputeWonSampleXml($id);
  70. break;
  71. case WebhookNotification::SUBSCRIPTION_CHARGED_SUCCESSFULLY:
  72. $subjectXml = self::_subscriptionChargedSuccessfullySampleXml($id);
  73. break;
  74. case WebhookNotification::SUBSCRIPTION_CHARGED_UNSUCCESSFULLY:
  75. $subjectXml = self::_subscriptionChargedUnsuccessfullySampleXml($id);
  76. break;
  77. case WebhookNotification::CHECK:
  78. $subjectXml = self::_checkSampleXml();
  79. break;
  80. case WebhookNotification::ACCOUNT_UPDATER_DAILY_REPORT:
  81. $subjectXml = self::_accountUpdaterDailyReportSampleXml($id);
  82. break;
  83. case WebhookNotification::IDEAL_PAYMENT_COMPLETE:
  84. $subjectXml = self::_idealPaymentCompleteSampleXml($id);
  85. break;
  86. case WebhookNotification::IDEAL_PAYMENT_FAILED:
  87. $subjectXml = self::_idealPaymentFailedSampleXml($id);
  88. break;
  89. case WebhookNotification::GRANTED_PAYMENT_INSTRUMENT_UPDATE:
  90. $subjectXml = self::_grantedPaymentInstrumentUpdateSampleXml();
  91. break;
  92. default:
  93. $subjectXml = self::_subscriptionSampleXml($id);
  94. break;
  95. }
  96. $timestamp = self::_timestamp();
  97. $sourceMerchantIdXml = '';
  98. if (!is_null($sourceMerchantId)) {
  99. $sourceMerchantIdXml = "<source-merchant-id>{$sourceMerchantId}</source-merchant-id>";
  100. }
  101. return "
  102. <notification>
  103. <timestamp type=\"datetime\">{$timestamp}</timestamp>
  104. <kind>{$kind}</kind>
  105. {$sourceMerchantIdXml}
  106. <subject>{$subjectXml}</subject>
  107. </notification>
  108. ";
  109. }
  110. private static function _merchantAccountApprovedSampleXml($id)
  111. {
  112. return "
  113. <merchant_account>
  114. <id>{$id}</id>
  115. <master_merchant_account>
  116. <id>master_ma_for_{$id}</id>
  117. <status>active</status>
  118. </master_merchant_account>
  119. <status>active</status>
  120. </merchant_account>
  121. ";
  122. }
  123. private static function _merchantAccountDeclinedSampleXml($id)
  124. {
  125. return "
  126. <api-error-response>
  127. <message>Credit score is too low</message>
  128. <errors>
  129. <errors type=\"array\"/>
  130. <merchant-account>
  131. <errors type=\"array\">
  132. <error>
  133. <code>82621</code>
  134. <message>Credit score is too low</message>
  135. <attribute type=\"symbol\">base</attribute>
  136. </error>
  137. </errors>
  138. </merchant-account>
  139. </errors>
  140. <merchant-account>
  141. <id>{$id}</id>
  142. <status>suspended</status>
  143. <master-merchant-account>
  144. <id>master_ma_for_{$id}</id>
  145. <status>suspended</status>
  146. </master-merchant-account>
  147. </merchant-account>
  148. </api-error-response>
  149. ";
  150. }
  151. private static function _transactionDisbursedSampleXml($id)
  152. {
  153. return "
  154. <transaction>
  155. <id>${id}</id>
  156. <amount>100</amount>
  157. <disbursement-details>
  158. <disbursement-date type=\"date\">2013-07-09</disbursement-date>
  159. </disbursement-details>
  160. </transaction>
  161. ";
  162. }
  163. private static function _transactionSettledSampleXml($id)
  164. {
  165. return "
  166. <transaction>
  167. <id>${id}</id>
  168. <status>settled</status>
  169. <type>sale</type>
  170. <currency-iso-code>USD</currency-iso-code>
  171. <amount>100.00</amount>
  172. <merchant-account-id>ogaotkivejpfayqfeaimuktty</merchant-account-id>
  173. <payment-instrument-type>us_bank_account</payment-instrument-type>
  174. <us-bank-account>
  175. <routing-number>123456789</routing-number>
  176. <last-4>1234</last-4>
  177. <account-type>checking</account-type>
  178. <account-holder-name>Dan Schulman</account-holder-name>
  179. </us-bank-account>
  180. </transaction>
  181. ";
  182. }
  183. private static function _transactionSettlementDeclinedSampleXml($id)
  184. {
  185. return "
  186. <transaction>
  187. <id>${id}</id>
  188. <status>settlement_declined</status>
  189. <type>sale</type>
  190. <currency-iso-code>USD</currency-iso-code>
  191. <amount>100.00</amount>
  192. <merchant-account-id>ogaotkivejpfayqfeaimuktty</merchant-account-id>
  193. <payment-instrument-type>us_bank_account</payment-instrument-type>
  194. <us-bank-account>
  195. <routing-number>123456789</routing-number>
  196. <last-4>1234</last-4>
  197. <account-type>checking</account-type>
  198. <account-holder-name>Dan Schulman</account-holder-name>
  199. </us-bank-account>
  200. </transaction>
  201. ";
  202. }
  203. private static function _disbursementExceptionSampleXml($id)
  204. {
  205. return "
  206. <disbursement>
  207. <id>${id}</id>
  208. <transaction-ids type=\"array\">
  209. <item>asdfg</item>
  210. <item>qwert</item>
  211. </transaction-ids>
  212. <success type=\"boolean\">false</success>
  213. <retry type=\"boolean\">false</retry>
  214. <merchant-account>
  215. <id>merchant_account_token</id>
  216. <currency-iso-code>USD</currency-iso-code>
  217. <sub-merchant-account type=\"boolean\">false</sub-merchant-account>
  218. <status>active</status>
  219. </merchant-account>
  220. <amount>100.00</amount>
  221. <disbursement-date type=\"date\">2014-02-10</disbursement-date>
  222. <exception-message>bank_rejected</exception-message>
  223. <follow-up-action>update_funding_information</follow-up-action>
  224. </disbursement>
  225. ";
  226. }
  227. private static function _disbursementSampleXml($id)
  228. {
  229. return "
  230. <disbursement>
  231. <id>${id}</id>
  232. <transaction-ids type=\"array\">
  233. <item>asdfg</item>
  234. <item>qwert</item>
  235. </transaction-ids>
  236. <success type=\"boolean\">true</success>
  237. <retry type=\"boolean\">false</retry>
  238. <merchant-account>
  239. <id>merchant_account_token</id>
  240. <currency-iso-code>USD</currency-iso-code>
  241. <sub-merchant-account type=\"boolean\">false</sub-merchant-account>
  242. <status>active</status>
  243. </merchant-account>
  244. <amount>100.00</amount>
  245. <disbursement-date type=\"date\">2014-02-10</disbursement-date>
  246. <exception-message nil=\"true\"/>
  247. <follow-up-action nil=\"true\"/>
  248. </disbursement>
  249. ";
  250. }
  251. private static function _disputeOpenedSampleXml($id)
  252. {
  253. return "
  254. <dispute>
  255. <amount>250.00</amount>
  256. <amount-disputed>250.0</amount-disputed>
  257. <amount-won>245.00</amount-won>
  258. <currency-iso-code>USD</currency-iso-code>
  259. <received-date type=\"date\">2014-03-01</received-date>
  260. <reply-by-date type=\"date\">2014-03-21</reply-by-date>
  261. <kind>chargeback</kind>
  262. <status>open</status>
  263. <reason>fraud</reason>
  264. <id>${id}</id>
  265. <transaction>
  266. <id>${id}</id>
  267. <amount>250.00</amount>
  268. </transaction>
  269. <date-opened type=\"date\">2014-03-21</date-opened>
  270. </dispute>
  271. ";
  272. }
  273. private static function _disputeLostSampleXml($id)
  274. {
  275. return "
  276. <dispute>
  277. <amount>250.00</amount>
  278. <amount-disputed>250.0</amount-disputed>
  279. <amount-won>245.00</amount-won>
  280. <currency-iso-code>USD</currency-iso-code>
  281. <received-date type=\"date\">2014-03-01</received-date>
  282. <reply-by-date type=\"date\">2014-03-21</reply-by-date>
  283. <kind>chargeback</kind>
  284. <status>lost</status>
  285. <reason>fraud</reason>
  286. <id>${id}</id>
  287. <transaction>
  288. <id>${id}</id>
  289. <amount>250.00</amount>
  290. <next_billing-date type=\"date\">2020-02-10</next_billing-date>
  291. </transaction>
  292. <date-opened type=\"date\">2014-03-21</date-opened>
  293. </dispute>
  294. ";
  295. }
  296. private static function _disputeWonSampleXml($id)
  297. {
  298. return "
  299. <dispute>
  300. <amount>250.00</amount>
  301. <amount-disputed>250.0</amount-disputed>
  302. <amount-won>245.00</amount-won>
  303. <currency-iso-code>USD</currency-iso-code>
  304. <received-date type=\"date\">2014-03-01</received-date>
  305. <reply-by-date type=\"date\">2014-03-21</reply-by-date>
  306. <kind>chargeback</kind>
  307. <status>won</status>
  308. <reason>fraud</reason>
  309. <id>${id}</id>
  310. <transaction>
  311. <id>${id}</id>
  312. <amount>250.00</amount>
  313. </transaction>
  314. <date-opened type=\"date\">2014-03-21</date-opened>
  315. <date-won type=\"date\">2014-03-22</date-won>
  316. </dispute>
  317. ";
  318. }
  319. private static function _subscriptionSampleXml($id)
  320. {
  321. return "
  322. <subscription>
  323. <id>{$id}</id>
  324. <transactions type=\"array\">
  325. </transactions>
  326. <add_ons type=\"array\">
  327. </add_ons>
  328. <discounts type=\"array\">
  329. </discounts>
  330. </subscription>
  331. ";
  332. }
  333. private static function _subscriptionChargedSuccessfullySampleXml($id)
  334. {
  335. return "
  336. <subscription>
  337. <id>{$id}</id>
  338. <billing-period-start-date type=\"date\">2016-03-21</billing-period-start-date>
  339. <billing-period-end-date type=\"date\">2017-03-31</billing-period-end-date>
  340. <transactions type=\"array\">
  341. <transaction>
  342. <id>{$id}</id>
  343. <status>submitted_for_settlement</status>
  344. <amount>49.99</amount>
  345. </transaction>
  346. </transactions>
  347. <add_ons type=\"array\">
  348. </add_ons>
  349. <discounts type=\"array\">
  350. </discounts>
  351. </subscription>
  352. ";
  353. }
  354. private static function _subscriptionChargedUnsuccessfullySampleXml($id)
  355. {
  356. return "
  357. <subscription>
  358. <id>{$id}</id>
  359. <billing-period-start-date type=\"date\">2016-03-21</billing-period-start-date>
  360. <billing-period-end-date type=\"date\">2017-03-31</billing-period-end-date>
  361. <transactions type=\"array\">
  362. <transaction>
  363. <id>{$id}</id>
  364. <status>failed</status>
  365. <amount>49.99</amount>
  366. </transaction>
  367. </transactions>
  368. <add_ons type=\"array\">
  369. </add_ons>
  370. <discounts type=\"array\">
  371. </discounts>
  372. </subscription>
  373. ";
  374. }
  375. private static function _checkSampleXml()
  376. {
  377. return "
  378. <check type=\"boolean\">true</check>
  379. ";
  380. }
  381. private static function _partnerMerchantConnectedSampleXml($id)
  382. {
  383. return "
  384. <partner-merchant>
  385. <merchant-public-id>public_id</merchant-public-id>
  386. <public-key>public_key</public-key>
  387. <private-key>private_key</private-key>
  388. <partner-merchant-id>abc123</partner-merchant-id>
  389. <client-side-encryption-key>cse_key</client-side-encryption-key>
  390. </partner-merchant>
  391. ";
  392. }
  393. private static function _partnerMerchantDisconnectedSampleXml($id)
  394. {
  395. return "
  396. <partner-merchant>
  397. <partner-merchant-id>abc123</partner-merchant-id>
  398. </partner-merchant>
  399. ";
  400. }
  401. private static function _partnerMerchantDeclinedSampleXml($id)
  402. {
  403. return "
  404. <partner-merchant>
  405. <partner-merchant-id>abc123</partner-merchant-id>
  406. </partner-merchant>
  407. ";
  408. }
  409. private static function _oauthAccessRevocationSampleXml($id)
  410. {
  411. return "
  412. <oauth-application-revocation>
  413. <merchant-id>{$id}</merchant-id>
  414. <oauth-application-client-id>oauth_application_client_id</oauth-application-client-id>
  415. </oauth-application-revocation>
  416. ";
  417. }
  418. private static function _accountUpdaterDailyReportSampleXml($id)
  419. {
  420. return "
  421. <account-updater-daily-report>
  422. <report-date type=\"date\">2016-01-14</report-date>
  423. <report-url>link-to-csv-report</report-url>
  424. </account-updater-daily-report>
  425. ";
  426. }
  427. private static function _connectedMerchantStatusTransitionedSampleXml($id)
  428. {
  429. return "
  430. <connected-merchant-status-transitioned>
  431. <merchant-public-id>{$id}</merchant-public-id>
  432. <status>new_status</status>
  433. <oauth-application-client-id>oauth_application_client_id</oauth-application-client-id>
  434. </connected-merchant-status-transitioned>
  435. ";
  436. }
  437. private static function _connectedMerchantPayPalStatusChangedSampleXml($id)
  438. {
  439. return "
  440. <connected-merchant-paypal-status-changed>
  441. <merchant-public-id>{$id}</merchant-public-id>
  442. <action>link</action>
  443. <oauth-application-client-id>oauth_application_client_id</oauth-application-client-id>
  444. </connected-merchant-paypal-status-changed>
  445. ";
  446. }
  447. private static function _idealPaymentCompleteSampleXml($id)
  448. {
  449. return "
  450. <ideal-payment>
  451. <id>{$id}</id>
  452. <status>COMPLETE</status>
  453. <issuer>ABCISSUER</issuer>
  454. <order-id>ORDERABC</order-id>
  455. <currency>EUR</currency>
  456. <amount>10.00</amount>
  457. <created-at>2016-11-29T23:27:34.547Z</created-at>
  458. <approval-url>https://example.com</approval-url>
  459. <ideal-transaction-id>1234567890</ideal-transaction-id>
  460. </ideal-payment>
  461. ";
  462. }
  463. private static function _idealPaymentFailedSampleXml($id)
  464. {
  465. return "
  466. <ideal-payment>
  467. <id>{$id}</id>
  468. <status>FAILED</status>
  469. <issuer>ABCISSUER</issuer>
  470. <order-id>ORDERABC</order-id>
  471. <currency>EUR</currency>
  472. <amount>10.00</amount>
  473. <created-at>2016-11-29T23:27:34.547Z</created-at>
  474. <approval-url>https://example.com</approval-url>
  475. <ideal-transaction-id>1234567890</ideal-transaction-id>
  476. </ideal-payment>
  477. ";
  478. }
  479. private static function _grantedPaymentInstrumentUpdateSampleXml()
  480. {
  481. return "
  482. <granted-payment-instrument-update>
  483. <grant-owner-merchant-id>vczo7jqrpwrsi2px</grant-owner-merchant-id>
  484. <grant-recipient-merchant-id>cf0i8wgarszuy6hc</grant-recipient-merchant-id>
  485. <payment-method-nonce>
  486. <nonce>ee257d98-de40-47e8-96b3-a6954ea7a9a4</nonce>
  487. <consumed type='boolean'>false</consumed>
  488. <locked type='boolean'>false</locked>
  489. </payment-method-nonce>
  490. <token>abc123z</token>
  491. <updated-fields type='array'>
  492. <item>expiration-month</item>
  493. <item>expiration-year</item>
  494. </updated-fields>
  495. </granted-payment-instrument-update>
  496. ";
  497. }
  498. private static function _timestamp()
  499. {
  500. $originalZone = date_default_timezone_get();
  501. date_default_timezone_set('UTC');
  502. $timestamp = strftime('%Y-%m-%dT%TZ');
  503. date_default_timezone_set($originalZone);
  504. return $timestamp;
  505. }
  506. }
  507. class_alias('Braintree\WebhookTestingGateway', 'Braintree_WebhookTestingGateway');