VM暫存
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1558 lines
64KB

  1. <?php
  2. /**
  3. * 付款方式。
  4. */
  5. abstract class PaymentMethod {
  6. /**
  7. * 不指定付款方式。
  8. */
  9. const ALL = 'ALL';
  10. /**
  11. * 信用卡付費。
  12. */
  13. const Credit = 'Credit';
  14. /**
  15. * 網路 ATM。
  16. */
  17. const WebATM = 'WebATM';
  18. /**
  19. * 自動櫃員機。
  20. */
  21. const ATM = 'ATM';
  22. /**
  23. * 超商代碼。
  24. */
  25. const CVS = 'CVS';
  26. /**
  27. * 超商條碼。
  28. */
  29. const BARCODE = 'BARCODE';
  30. /**
  31. * 支付寶。
  32. */
  33. const Alipay = 'Alipay';
  34. /**
  35. * 財付通。
  36. */
  37. const Tenpay = 'Tenpay';
  38. /**
  39. * 儲值消費。
  40. */
  41. const TopUpUsed = 'TopUpUsed';
  42. }
  43. /**
  44. * 付款方式子項目。
  45. */
  46. abstract class PaymentMethodItem {
  47. /**
  48. * 不指定。
  49. */
  50. const None = '';
  51. // WebATM 類(001~100)
  52. /**
  53. * 台新銀行。
  54. */
  55. const WebATM_TAISHIN = 'TAISHIN';
  56. /**
  57. * 玉山銀行。
  58. */
  59. const WebATM_ESUN = 'ESUN';
  60. /**
  61. * 華南銀行。
  62. */
  63. const WebATM_HUANAN = 'HUANAN';
  64. /**
  65. * 台灣銀行。
  66. */
  67. const WebATM_BOT = 'BOT';
  68. /**
  69. * 台北富邦。
  70. */
  71. const WebATM_FUBON = 'FUBON';
  72. /**
  73. * 中國信託。
  74. */
  75. const WebATM_CHINATRUST = 'CHINATRUST';
  76. /**
  77. * 第一銀行。
  78. */
  79. const WebATM_FIRST = 'FIRST';
  80. /**
  81. * 國泰世華。
  82. */
  83. const WebATM_CATHAY = 'CATHAY';
  84. /**
  85. * 兆豐銀行。
  86. */
  87. const WebATM_MEGA = 'MEGA';
  88. /**
  89. * 元大銀行。
  90. */
  91. const WebATM_YUANTA = 'YUANTA';
  92. /**
  93. * 土地銀行。
  94. */
  95. const WebATM_LAND = 'LAND';
  96. // ATM 類(101~200)
  97. /**
  98. * 台新銀行。
  99. */
  100. const ATM_TAISHIN = 'TAISHIN';
  101. /**
  102. * 玉山銀行。
  103. */
  104. const ATM_ESUN = 'ESUN';
  105. /**
  106. * 華南銀行。
  107. */
  108. const ATM_HUANAN = 'HUANAN';
  109. /**
  110. * 台灣銀行。
  111. */
  112. const ATM_BOT = 'BOT';
  113. /**
  114. * 台北富邦。
  115. */
  116. const ATM_FUBON = 'FUBON';
  117. /**
  118. * 中國信託。
  119. */
  120. const ATM_CHINATRUST = 'CHINATRUST';
  121. /**
  122. * 第一銀行。
  123. */
  124. const ATM_FIRST = 'FIRST';
  125. // 超商類(201~300)
  126. /**
  127. * 超商代碼繳款。
  128. */
  129. const CVS = 'CVS';
  130. /**
  131. * OK超商代碼繳款。
  132. */
  133. const CVS_OK = 'OK';
  134. /**
  135. * 全家超商代碼繳款。
  136. */
  137. const CVS_FAMILY = 'FAMILY';
  138. /**
  139. * 萊爾富超商代碼繳款。
  140. */
  141. const CVS_HILIFE = 'HILIFE';
  142. /**
  143. * 7-11 ibon代碼繳款。
  144. */
  145. const CVS_IBON = 'IBON';
  146. // 其他第三方支付類(301~400)
  147. /**
  148. * 支付寶。
  149. */
  150. const Alipay = 'Alipay';
  151. /**
  152. * 財付通。
  153. */
  154. const Tenpay = 'Tenpay';
  155. // 儲值/餘額消費類(401~500)
  156. /**
  157. * 儲值/餘額消費(歐付寶)
  158. */
  159. const TopUpUsed_AllPay = 'AllPay';
  160. /**
  161. * 儲值/餘額消費(玉山)
  162. */
  163. const TopUpUsed_ESUN = 'ESUN';
  164. // 其他類(901~999)
  165. /**
  166. * 超商條碼繳款。
  167. */
  168. const BARCODE = 'BARCODE';
  169. /**
  170. * 信用卡(MasterCard/JCB/VISA)。
  171. */
  172. const Credit = 'Credit';
  173. /**
  174. * 貨到付款。
  175. */
  176. const COD = 'COD';
  177. }
  178. /**
  179. * 額外付款資訊。
  180. */
  181. abstract class ExtraPaymentInfo {
  182. /**
  183. * 需要額外付款資訊。
  184. */
  185. const Yes = 'Y';
  186. /**
  187. * 不需要額外付款資訊。
  188. */
  189. const No = 'N';
  190. }
  191. /**
  192. * 額外付款資訊。
  193. */
  194. abstract class DeviceType {
  195. /**
  196. * 桌機版付費頁面。
  197. */
  198. const PC = 'P';
  199. /**
  200. * 行動裝置版付費頁面。
  201. */
  202. const Mobile = 'M';
  203. }
  204. /**
  205. * 信用卡訂單處理動作資訊。
  206. */
  207. abstract class ActionType {
  208. /**
  209. * 關帳
  210. */
  211. const C = 'C';
  212. /**
  213. * 退刷
  214. */
  215. const R = 'R';
  216. /**
  217. * 取消
  218. */
  219. const E = 'E';
  220. /**
  221. * 放棄
  222. */
  223. const N = 'N';
  224. }
  225. /**
  226. * 定期定額的週期種類。
  227. */
  228. abstract class PeriodType {
  229. /**
  230. * 無
  231. */
  232. const None = '';
  233. /**
  234. * 年
  235. */
  236. const Year = 'Y';
  237. /**
  238. * 月
  239. */
  240. const Month = 'M';
  241. /**
  242. * 日
  243. */
  244. const Day = 'D';
  245. }
  246. /**
  247. * 電子發票開立註記。
  248. */
  249. abstract class InvoiceState {
  250. /**
  251. * 需要開立電子發票。
  252. */
  253. const Yes = 'Y';
  254. /**
  255. * 不需要開立電子發票。
  256. */
  257. const No = '';
  258. }
  259. /**
  260. * 電子發票載具類別
  261. */
  262. abstract class CarruerType {
  263. // 無載具
  264. const None = '';
  265. // 會員載具
  266. const Member = '1';
  267. // 買受人自然人憑證
  268. const Citizen = '2';
  269. // 買受人手機條碼
  270. const Cellphone = '3';
  271. }
  272. /**
  273. * 電子發票列印註記
  274. */
  275. abstract class PrintMark {
  276. // 不列印
  277. const No = '0';
  278. // 列印
  279. const Yes = '1';
  280. }
  281. /**
  282. * 電子發票捐贈註記
  283. */
  284. abstract class Donation {
  285. // 捐贈
  286. const Yes = '1';
  287. // 不捐贈
  288. const No = '2';
  289. }
  290. /**
  291. * 通關方式
  292. */
  293. abstract class ClearanceMark {
  294. // 經海關出口
  295. const Yes = '1';
  296. // 非經海關出口
  297. const No = '2';
  298. }
  299. /**
  300. * 課稅類別
  301. */
  302. abstract class TaxType {
  303. // 應稅
  304. const Dutiable = '1';
  305. // 零稅率
  306. const Zero = '2';
  307. // 免稅
  308. const Free = '3';
  309. // 應稅與免稅混合(限收銀機發票無法分辦時使用,且需通過申請核可)
  310. const Mix = '9';
  311. }
  312. /**
  313. * 字軌類別
  314. */
  315. abstract class InvType {
  316. // 一般稅額
  317. const General = '07';
  318. // 特種稅額
  319. const Special = '08';
  320. }
  321. abstract class EncryptType {
  322. // MD5(預設)
  323. const ENC_MD5 = 0;
  324. // SHA256
  325. const ENC_SHA256 = 1;
  326. }
  327. /**
  328. * AllInOne short summary.
  329. *
  330. * AllInOne description.
  331. *
  332. * @version 1.0
  333. * @author andy.chao
  334. */
  335. class AllInOne {
  336. public $ServiceURL = 'ServiceURL';
  337. public $ServiceMethod = 'ServiceMethod';
  338. public $HashKey = 'HashKey';
  339. public $HashIV = 'HashIV';
  340. public $MerchantID = 'MerchantID';
  341. public $PaymentType = 'PaymentType';
  342. public $Send = 'Send';
  343. public $SendExtend = 'SendExtend';
  344. public $Query = 'Query';
  345. public $Action = 'Action';
  346. public $ChargeBack = 'ChargeBack';
  347. public $EncryptType = EncryptType::ENC_MD5;
  348. function __construct() {
  349. $this->AllInOne();
  350. $this->PaymentType = 'aio';
  351. $this->Send = array(
  352. "ReturnURL" => '',
  353. "ClientBackURL" => '',
  354. "OrderResultURL" => '',
  355. "MerchantTradeNo" => '',
  356. "MerchantTradeDate" => '',
  357. "PaymentType" => 'aio',
  358. "TotalAmount" => '',
  359. "TradeDesc" => '',
  360. "ChoosePayment" => PaymentMethod::ALL,
  361. "Remark" => '',
  362. "ChooseSubPayment" => PaymentMethodItem::None,
  363. "NeedExtraPaidInfo" => ExtraPaymentInfo::No,
  364. "DeviceSource" => DeviceType::PC,
  365. "IgnorePayment" => '',
  366. "PlatformID" => '',
  367. "InvoiceMark" => InvoiceState::No,
  368. "Items" => array(),
  369. "EncryptType" => EncryptType::ENC_MD5
  370. );
  371. $this->SendExtend = array(
  372. // ATM 延伸參數。
  373. "ExpireDate" => 3,
  374. // CVS, BARCODE 延伸參數。
  375. "Desc_1" => '', "Desc_2" => '', "Desc_3" => '', "Desc_4" => '',
  376. // ATM, CVS, BARCODE 延伸參數。
  377. "ClientRedirectURL" => '',
  378. // Alipay 延伸參數。
  379. "Email" => '', "PhoneNo" => '', "UserName" => '',
  380. // Tenpay 延伸參數。
  381. "ExpireTime" => '',
  382. // Credit 分期延伸參數。
  383. "CreditInstallment" => 0, "InstallmentAmount" => 0, "Redeem" => FALSE, "UnionPay" => FALSE,
  384. // Credit 定期定額延伸參數。
  385. "PeriodAmount" => '', "PeriodType" => '', "Frequency" => '', "ExecTimes" => '',
  386. // 回傳網址的延伸參數。
  387. "PaymentInfoURL" => '', "PeriodReturnURL" => '',
  388. // 電子發票延伸參數。
  389. "CustomerIdentifier" => '',
  390. "CarruerType" => CarruerType::None,
  391. "CustomerID" => '',
  392. "Donation" => Donation::No,
  393. "Print" => PrintMark::No,
  394. "CustomerName" => '',
  395. "CustomerAddr" => '',
  396. "CustomerPhone" => '',
  397. "CustomerEmail" => '',
  398. "ClearanceMark" => '',
  399. "CarruerNum" => '',
  400. "LoveCode" => '',
  401. "InvoiceRemark" => '',
  402. "DelayDay" => 0,
  403. );
  404. $this->Query = array(
  405. 'MerchantTradeNo' => '', 'TimeStamp' => ''
  406. );
  407. $this->Action = Array(
  408. 'MerchantTradeNo' => '', 'TradeNo' => '', 'Action' => ActionType::C, 'TotalAmount' => 0
  409. );
  410. $this->ChargeBack = Array(
  411. 'MerchantTradeNo' => '', 'TradeNo' => '', 'ChargeBackTotalAmount' => 0, 'Remark' => ''
  412. );
  413. }
  414. function AllInOne() {
  415. }
  416. function CheckOut($target = "_self") {
  417. $szHtml = $this->CheckOutString(null, $target);
  418. print $szHtml;
  419. exit();
  420. die();
  421. flush();
  422. return;
  423. }
  424. function CheckOutString($paymentButton, $target = "_self") {
  425. // 變數宣告。
  426. $arErrors = array();
  427. $szHtml = '';
  428. $arParameters = null;
  429. $szItemName = '';
  430. $szAlipayItemName = '';
  431. $szAlipayItemCounts = '';
  432. $szAlipayItemPrice = '';
  433. $szInvoiceItemName = '';
  434. $szInvoiceItemCount = '';
  435. $szInvoiceItemWord = '';
  436. $szInvoiceItemPrice = '';
  437. $szInvoiceItemTaxType = '';
  438. $InvSptr = '|';
  439. // 檢查資料。
  440. if (strlen($this->ServiceURL) == 0) {
  441. array_push($arErrors, 'ServiceURL is required.');
  442. }
  443. if (strlen($this->ServiceURL) > 200) {
  444. array_push($arErrors, 'ServiceURL max langth as 200.');
  445. }
  446. if (strlen($this->HashKey) == 0) {
  447. array_push($arErrors, 'HashKey is required.');
  448. }
  449. if (strlen($this->HashIV) == 0) {
  450. array_push($arErrors, 'HashIV is required.');
  451. }
  452. if (strlen($this->MerchantID) == 0) {
  453. array_push($arErrors, 'MerchantID is required.');
  454. }
  455. if (strlen($this->MerchantID) > 10) {
  456. array_push($arErrors, 'MerchantID max langth as 10.');
  457. }
  458. if (strlen($this->Send['ReturnURL']) == 0) {
  459. array_push($arErrors, 'ReturnURL is required.');
  460. }
  461. if (strlen($this->Send['ClientBackURL']) > 200) {
  462. array_push($arErrors, 'ClientBackURL max langth as 10.');
  463. }
  464. if (strlen($this->Send['OrderResultURL']) > 200) {
  465. array_push($arErrors, 'OrderResultURL max langth as 10.');
  466. }
  467. if (strlen($this->Send['MerchantTradeNo']) == 0) {
  468. array_push($arErrors, 'MerchantTradeNo is required.');
  469. }
  470. if (strlen($this->Send['MerchantTradeNo']) > 20) {
  471. array_push($arErrors, 'MerchantTradeNo max langth as 20.');
  472. }
  473. if (strlen($this->Send['MerchantTradeDate']) == 0) {
  474. array_push($arErrors, 'MerchantTradeDate is required.');
  475. }
  476. if (strlen($this->Send['TotalAmount']) == 0) {
  477. array_push($arErrors, 'TotalAmount is required.');
  478. }
  479. if (strlen($this->Send['TradeDesc']) == 0) {
  480. array_push($arErrors, 'TradeDesc is required.');
  481. }
  482. if (strlen($this->Send['TradeDesc']) > 200) {
  483. array_push($arErrors, 'TradeDesc max langth as 200.');
  484. }
  485. if (strlen($this->Send['ChoosePayment']) == 0) {
  486. array_push($arErrors, 'ChoosePayment is required.');
  487. }
  488. if (strlen($this->Send['NeedExtraPaidInfo']) == 0) {
  489. array_push($arErrors, 'NeedExtraPaidInfo is required.');
  490. }
  491. if (strlen($this->Send['DeviceSource']) == 0) {
  492. array_push($arErrors, 'DeviceSource is required.');
  493. }
  494. if (sizeof($this->Send['Items']) == 0) {
  495. array_push($arErrors, 'Items is required.');
  496. }
  497. // 檢查 Alipay 條件。
  498. if ($this->Send['ChoosePayment'] == PaymentMethod::Alipay) {
  499. if (strlen($this->SendExtend['Email']) == 0) {
  500. array_push($arErrors, "Email is required.");
  501. }
  502. if (strlen($this->SendExtend['Email']) > 200) {
  503. array_push($arErrors, "Email max langth as 200.");
  504. }
  505. if (strlen($this->SendExtend['PhoneNo']) == 0) {
  506. array_push($arErrors, "PhoneNo is required.");
  507. }
  508. if (strlen($this->SendExtend['PhoneNo']) > 20) {
  509. array_push($arErrors, "PhoneNo max langth as 20.");
  510. }
  511. if (strlen($this->SendExtend['UserName']) == 0) {
  512. array_push($arErrors, "UserName is required.");
  513. }
  514. if (strlen($this->SendExtend['UserName']) > 20) {
  515. array_push($arErrors, "UserName max langth as 20.");
  516. }
  517. }
  518. // 檢查產品名稱。
  519. if (sizeof($this->Send['Items']) > 0) {
  520. foreach ($this->Send['Items'] as $keys => $value) {
  521. $szItemName .= vsprintf('#%s %d %s x %u', $this->Send['Items'][$keys]);
  522. $szAlipayItemName .= sprintf('#%s', $this->Send['Items'][$keys]['Name']);
  523. $szAlipayItemCounts .= sprintf('#%u', $this->Send['Items'][$keys]['Quantity']);
  524. $szAlipayItemPrice .= sprintf('#%d', $this->Send['Items'][$keys]['Price']);
  525. if (!array_key_exists('ItemURL', $this->Send)) {
  526. $this->Send['ItemURL'] = $this->Send['Items'][$keys]['URL'];
  527. }
  528. }
  529. if (strlen($szItemName) > 0) {
  530. $szItemName = mb_substr($szItemName, 1, 200);
  531. }
  532. if (strlen($szAlipayItemName) > 0) {
  533. $szAlipayItemName = mb_substr($szAlipayItemName, 1, 200);
  534. }
  535. if (strlen($szAlipayItemCounts) > 0) {
  536. $szAlipayItemCounts = mb_substr($szAlipayItemCounts, 1, 100);
  537. }
  538. if (strlen($szAlipayItemPrice) > 0) {
  539. $szAlipayItemPrice = mb_substr($szAlipayItemPrice, 1, 20);
  540. }
  541. } else {
  542. array_push($arErrors, "Goods information not found.");
  543. }
  544. // 檢查電子發票參數
  545. if (strlen($this->Send['InvoiceMark']) > 1) {
  546. array_push($arErrors, "InvoiceMark max length as 1.");
  547. } else {
  548. if ($this->Send['InvoiceMark'] == InvoiceState::Yes) {
  549. // RelateNumber(不可為空)
  550. if (strlen($this->SendExtend['RelateNumber']) == 0) {
  551. array_push($arErrors, "RelateNumber is required.");
  552. } else {
  553. if (strlen($this->SendExtend['RelateNumber']) > 30) {
  554. array_push($arErrors, "RelateNumber max length as 30.");
  555. }
  556. }
  557. // CustomerIdentifier(預設為空字串)
  558. if (strlen($this->SendExtend['CustomerIdentifier']) > 0) {
  559. if (strlen($this->SendExtend['CustomerIdentifier']) != 8) {
  560. array_push($arErrors, "CustomerIdentifier length should be 8.");
  561. }
  562. }
  563. // CarruerType(預設為None)
  564. if (strlen($this->SendExtend['CarruerType']) > 1) {
  565. array_push($arErrors, "CarruerType max length as 1.");
  566. } else {
  567. // 統一編號不為空字串時,載具類別請設定空字串
  568. if (strlen($this->SendExtend['CustomerIdentifier']) > 0) {
  569. if ($this->SendExtend['CarruerType'] != CarruerType::None) {
  570. array_push($arErrors, "CarruerType should be None.");
  571. }
  572. }
  573. }
  574. // CustomerID(預設為空字串)
  575. if (strlen($this->SendExtend['CustomerID']) > 20) {
  576. array_push($arErrors, "CustomerID max length as 20.");
  577. } else {
  578. // 當載具類別為會員載具(Member)時,此參數不可為空字串
  579. if ($this->SendExtend['CarruerType'] == CarruerType::Member) {
  580. if (strlen($this->SendExtend['CustomerID']) == 0) {
  581. array_push($arErrors, "CustomerID is required.");
  582. }
  583. }
  584. }
  585. // Donation(預設為No)
  586. if (strlen($this->SendExtend['Donation']) > 1) {
  587. array_push($arErrors, "Donation max length as 1.");
  588. } else {
  589. // 統一編號不為空字串時,請設定不捐贈(No)
  590. if (strlen($this->SendExtend['CustomerIdentifier']) > 0) {
  591. if ($this->SendExtend['Donation'] != Donation::No) {
  592. array_push($arErrors, "Donation should be No.");
  593. }
  594. } else {
  595. if (strlen($this->SendExtend['Donation']) == 0) {
  596. $this->SendExtend['Donation'] = Donation::No;
  597. }
  598. }
  599. }
  600. // Print(預設為No)
  601. if (strlen($this->SendExtend['Print']) > 1) {
  602. array_push($arErrors, "Print max length as 1.");
  603. } else {
  604. // 捐贈註記為捐贈(Yes)時,請設定不列印(No)
  605. if ($this->SendExtend['Donation'] == Donation::Yes) {
  606. if ($this->SendExtend['Print'] != PrintMark::No) {
  607. array_push($arErrors, "Print should be No.");
  608. }
  609. } else {
  610. // 統一編號不為空字串時,請設定列印(Yes)
  611. if (strlen($this->SendExtend['CustomerIdentifier']) > 0) {
  612. if ($this->SendExtend['Print'] != PrintMark::Yes) {
  613. array_push($arErrors, "Print should be Yes.");
  614. }
  615. } else {
  616. if (strlen($this->SendExtend['Print']) == 0) {
  617. $this->SendExtend['Print'] = PrintMark::No;
  618. }
  619. // 載具類別為會員載具(Member)、買受人自然人憑證(Citizen)、買受人手機條碼(Cellphone)時,請設定不列印(No)
  620. $notPrint = array(CarruerType::Member, CarruerType::Citizen, CarruerType::Cellphone);
  621. if (in_array($this->SendExtend['CarruerType'], $notPrint) and $this->SendExtend['Print'] == PrintMark::Yes) {
  622. array_push($arErrors, "Print should be No.");
  623. }
  624. }
  625. }
  626. }
  627. // CustomerName(UrlEncode, 預設為空字串)
  628. if (mb_strlen($this->SendExtend['CustomerName'], 'UTF-8') > 20) {
  629. array_push($arErrors, "CustomerName max length as 20.");
  630. } else {
  631. // 列印註記為列印(Yes)時,此參數不可為空字串
  632. if ($this->SendExtend['Print'] == PrintMark::Yes) {
  633. if (mb_strlen($this->SendExtend['CustomerName'], 'UTF-8') == 0) {
  634. array_push($arErrors, "CustomerName is required.");
  635. }
  636. }
  637. }
  638. // CustomerAddr(UrlEncode, 預設為空字串)
  639. if (mb_strlen($this->SendExtend['CustomerAddr'], 'UTF-8') > 200) {
  640. array_push($arErrors, "CustomerAddr max length as 200.");
  641. } else {
  642. // 列印註記為列印(Yes)時,此參數不可為空字串
  643. if ($this->SendExtend['Print'] == PrintMark::Yes) {
  644. if (mb_strlen($this->SendExtend['CustomerAddr'], 'UTF-8') == 0) {
  645. array_push($arErrors, "CustomerAddr is required.");
  646. }
  647. }
  648. }
  649. // CustomerPhone(與CustomerEmail擇一不可為空)
  650. if (strlen($this->SendExtend['CustomerPhone']) > 20) {
  651. array_push($arErrors, "CustomerPhone max length as 20.");
  652. }
  653. // CustomerEmail(UrlEncode, 預設為空字串, 與CustomerPhone擇一不可為空)
  654. if (strlen($this->SendExtend['CustomerEmail']) > 200) {
  655. array_push($arErrors, "CustomerEmail max length as 200.");
  656. }
  657. if (strlen($this->SendExtend['CustomerPhone']) == 0 and strlen($this->SendExtend['CustomerEmail']) == 0) {
  658. array_push($arErrors, "CustomerPhone or CustomerEmail is required.");
  659. }
  660. // TaxType(不可為空)
  661. if (strlen($this->SendExtend['TaxType']) > 1) {
  662. array_push($arErrors, "TaxType max length as 1.");
  663. } else {
  664. if (strlen($this->SendExtend['TaxType']) == 0) {
  665. array_push($arErrors, "TaxType is required.");
  666. }
  667. }
  668. // ClearanceMark(預設為空字串)
  669. if (strlen($this->SendExtend['ClearanceMark']) > 1) {
  670. array_push($arErrors, "ClearanceMark max length as 1.");
  671. } else {
  672. // 請設定空字串,僅課稅類別為零稅率(Zero)時,此參數不可為空字串
  673. if ($this->SendExtend['TaxType'] == TaxType::Zero) {
  674. if ($this->SendExtend['ClearanceMark'] != ClearanceMark::Yes and $this->SendExtend['ClearanceMark'] != ClearanceMark::No) {
  675. array_push($arErrors, "ClearanceMark is required.");
  676. }
  677. } else {
  678. if (strlen($this->SendExtend['ClearanceMark']) > 0) {
  679. array_push($arErrors, "Please remove ClearanceMark.");
  680. }
  681. }
  682. }
  683. // CarruerNum(預設為空字串)
  684. if (strlen($this->SendExtend['CarruerNum']) > 64) {
  685. array_push($arErrors, "CarruerNum max length as 64.");
  686. } else {
  687. switch ($this->SendExtend['CarruerType']) {
  688. // 載具類別為無載具(None)或會員載具(Member)時,請設定空字串
  689. case CarruerType::None:
  690. case CarruerType::Member:
  691. if (strlen($this->SendExtend['CarruerNum']) > 0) {
  692. array_push($arErrors, "Please remove CarruerNum.");
  693. }
  694. break;
  695. // 載具類別為買受人自然人憑證(Citizen)時,請設定自然人憑證號碼,前2碼為大小寫英文,後14碼為數字
  696. case CarruerType::Citizen:
  697. if (!preg_match('/^[a-zA-Z]{2}\d{14}$/', $this->SendExtend['CarruerNum']))
  698. {
  699. array_push($arErrors, "Invalid CarruerNum.");
  700. }
  701. break;
  702. // 載具類別為買受人手機條碼(Cellphone)時,請設定手機條碼,第1碼為「/」,後7碼為大小寫英文、數字、「+」、「-」或「.」
  703. case CarruerType::Cellphone:
  704. if (!preg_match('/^\/{1}[0-9a-zA-Z+-.]{7}$/', $this->SendExtend['CarruerNum'])) {
  705. array_push($arErrors, "Invalid CarruerNum.");
  706. }
  707. break;
  708. default:
  709. array_push($arErrors, "Please remove CarruerNum.");
  710. }
  711. }
  712. // LoveCode(預設為空字串)
  713. // 捐贈註記為捐贈(Yes)時,參數長度固定3~7碼,請設定全數字或第1碼大小寫「X」,後2~6碼全數字
  714. if ($this->SendExtend['Donation'] == Donation::Yes) {
  715. if (!preg_match('/^([xX]{1}[0-9]{2,6}|[0-9]{3,7})$/', $this->SendExtend['LoveCode'])) {
  716. array_push($arErrors, "Invalid LoveCode.");
  717. }
  718. } else {
  719. if (strlen($this->SendExtend['LoveCode']) > 0) {
  720. array_push($arErrors, "Please remove LoveCode.");
  721. }
  722. }
  723. // InvoiceItemName(UrlEncode, 不可為空)
  724. // InvoiceItemCount(不可為空)
  725. // InvoiceItemWord(UrlEncode, 不可為空)
  726. // InvoiceItemPrice(不可為空)
  727. // InvoiceItemTaxType(不可為空)
  728. if (sizeof($this->SendExtend['InvoiceItems']) > 0) {
  729. $tmpItemName = array();
  730. $tmpItemCount = array();
  731. $tmpItemWord = array();
  732. $tmpItemPrice = array();
  733. $tmpItemTaxType = array();
  734. foreach ($this->SendExtend['InvoiceItems'] as $tmpItemInfo) {
  735. if (mb_strlen($tmpItemInfo['Name'], 'UTF-8') > 0) {
  736. array_push($tmpItemName, $tmpItemInfo['Name']);
  737. }
  738. if (strlen($tmpItemInfo['Count']) > 0) {
  739. array_push($tmpItemCount, $tmpItemInfo['Count']);
  740. }
  741. if (mb_strlen($tmpItemInfo['Word'], 'UTF-8') > 0) {
  742. array_push($tmpItemWord, $tmpItemInfo['Word']);
  743. }
  744. if (strlen($tmpItemInfo['Price']) > 0) {
  745. array_push($tmpItemPrice, $tmpItemInfo['Price']);
  746. }
  747. if (strlen($tmpItemInfo['TaxType']) > 0) {
  748. array_push($tmpItemTaxType, $tmpItemInfo['TaxType']);
  749. }
  750. }
  751. if ($this->SendExtend['TaxType'] == TaxType::Mix) {
  752. if (in_array(TaxType::Dutiable, $tmpItemTaxType) and in_array(TaxType::Free, $tmpItemTaxType)) {
  753. // Do nothing
  754. } else {
  755. $tmpItemTaxType = array();
  756. }
  757. }
  758. if ((count($tmpItemName) + count($tmpItemCount) + count($tmpItemWord) + count($tmpItemPrice) + count($tmpItemTaxType)) == (count($tmpItemName) * 5)) {
  759. $szInvoiceItemName = implode($InvSptr, $tmpItemName);
  760. $szInvoiceItemCount = implode($InvSptr, $tmpItemCount);
  761. $szInvoiceItemWord = implode($InvSptr, $tmpItemWord);
  762. $szInvoiceItemPrice = implode($InvSptr, $tmpItemPrice);
  763. $szInvoiceItemTaxType = implode($InvSptr, $tmpItemTaxType);
  764. } else {
  765. array_push($arErrors, "Invalid Invoice Goods information.");
  766. }
  767. } else {
  768. array_push($arErrors, "Invoice Goods information not found.");
  769. }
  770. // InvoiceRemark(UrlEncode, 預設為空字串)
  771. // DelayDay(不可為空, 預設為0)
  772. // 延遲天數,範圍0~15,設定為0時,付款完成後立即開立發票
  773. $this->SendExtend['DelayDay'] = (int)$this->SendExtend['DelayDay'];
  774. if ($this->SendExtend['DelayDay'] < 0 or $this->SendExtend['DelayDay'] > 15) {
  775. array_push($arErrors, "DelayDay should be 0 ~ 15.");
  776. } else {
  777. if (strlen($this->SendExtend['DelayDay']) == 0) {
  778. $this->SendExtend['DelayDay'] = 0;
  779. }
  780. }
  781. // InvType(不可為空)
  782. if (strlen($this->SendExtend['InvType']) == 0) {
  783. array_push($arErrors, "InvType is required.");
  784. }
  785. }
  786. }
  787. // 檢查CheckMacValue加密方式
  788. if (strlen($this->Send['EncryptType']) > 1) {
  789. array_push($arErrors, 'EncryptType max langth as 1.');
  790. }
  791. // 輸出表單字串。
  792. if (sizeof($arErrors) == 0) {
  793. // 信用卡特殊邏輯判斷(行動裝置畫面的信用卡分期處理,不支援定期定額)
  794. if ($this->Send['ChoosePayment'] == PaymentMethod::Credit && $this->Send['DeviceSource'] == DeviceType::Mobile && !$this->SendExtend['PeriodAmount']) {
  795. $this->Send['ChoosePayment'] = PaymentMethod::ALL;
  796. $this->Send['IgnorePayment'] = 'WebATM#ATM#CVS#BARCODE#Alipay#Tenpay#TopUpUsed#APPBARCODE#AccountLink';
  797. }
  798. // 產生畫面控制項與傳遞參數。
  799. $arParameters = array(
  800. 'MerchantID' => $this->MerchantID,
  801. 'PaymentType' => $this->PaymentType,
  802. 'ItemName' => $szItemName,
  803. 'ItemURL' => $this->Send['ItemURL'],
  804. 'InvoiceItemName' => $szInvoiceItemName,
  805. 'InvoiceItemCount' => $szInvoiceItemCount,
  806. 'InvoiceItemWord' => $szInvoiceItemWord,
  807. 'InvoiceItemPrice' => $szInvoiceItemPrice,
  808. 'InvoiceItemTaxType' => $szInvoiceItemTaxType,
  809. );
  810. $arParameters = array_merge($arParameters, $this->Send);
  811. $arParameters = array_merge($arParameters, $this->SendExtend);
  812. // 處理延伸參數
  813. if (!$this->Send['PlatformID']) { unset($arParameters['PlatformID']); }
  814. // 整理全功能參數。
  815. if ($this->Send['ChoosePayment'] == PaymentMethod::ALL) {
  816. unset($arParameters['ExecTimes']);
  817. unset($arParameters['Frequency']);
  818. unset($arParameters['PeriodAmount']);
  819. unset($arParameters['PeriodReturnURL']);
  820. unset($arParameters['PeriodType']);
  821. $arParameters = array_merge($arParameters, array(
  822. 'AlipayItemName' => $szAlipayItemName,
  823. 'AlipayItemCounts' => $szAlipayItemCounts,
  824. 'AlipayItemPrice' => $szAlipayItemPrice
  825. ));
  826. if (!$arParameters['CreditInstallment']) { unset($arParameters['CreditInstallment']); }
  827. if (!$arParameters['InstallmentAmount']) { unset($arParameters['InstallmentAmount']); }
  828. if (!$arParameters['Redeem']) { unset($arParameters['Redeem']); }
  829. if (!$arParameters['UnionPay']) { unset($arParameters['UnionPay']); }
  830. if (!$this->Send['IgnorePayment']) { unset($arParameters['IgnorePayment']); }
  831. if (!$this->SendExtend['ClientRedirectURL']) { unset($arParameters['ClientRedirectURL']); }
  832. }
  833. // 整理 Alipay 參數。
  834. if ($this->Send['ChoosePayment'] == PaymentMethod::Alipay) {
  835. $arParameters = array_merge($arParameters, array(
  836. 'AlipayItemName' => $szAlipayItemName,
  837. 'AlipayItemCounts' => $szAlipayItemCounts,
  838. 'AlipayItemPrice' => $szAlipayItemPrice
  839. ));
  840. unset($arParameters['CreditInstallment']);
  841. unset($arParameters['Desc_1']);
  842. unset($arParameters['Desc_2']);
  843. unset($arParameters['Desc_3']);
  844. unset($arParameters['Desc_4']);
  845. unset($arParameters['ExecTimes']);
  846. unset($arParameters['ExpireDate']);
  847. unset($arParameters['ExpireTime']);
  848. unset($arParameters['Frequency']);
  849. unset($arParameters['InstallmentAmount']);
  850. unset($arParameters['PaymentInfoURL']);
  851. unset($arParameters['PeriodAmount']);
  852. unset($arParameters['PeriodReturnURL']);
  853. unset($arParameters['PeriodType']);
  854. unset($arParameters['Redeem']);
  855. unset($arParameters['UnionPay']);
  856. unset($arParameters['IgnorePayment']);
  857. unset($arParameters['ClientRedirectURL']);
  858. }
  859. // 整理 Tenpay 參數。
  860. if ($this->Send['ChoosePayment'] == PaymentMethod::Tenpay) {
  861. unset($arParameters['CreditInstallment']);
  862. unset($arParameters['Desc_1']);
  863. unset($arParameters['Desc_2']);
  864. unset($arParameters['Desc_3']);
  865. unset($arParameters['Desc_4']);
  866. unset($arParameters['Email']);
  867. unset($arParameters['ExecTimes']);
  868. unset($arParameters['ExpireDate']);
  869. unset($arParameters['Frequency']);
  870. unset($arParameters['InstallmentAmount']);
  871. unset($arParameters['PaymentInfoURL']);
  872. unset($arParameters['PeriodAmount']);
  873. unset($arParameters['PeriodReturnURL']);
  874. unset($arParameters['PeriodType']);
  875. unset($arParameters['PhoneNo']);
  876. unset($arParameters['Redeem']);
  877. unset($arParameters['UnionPay']);
  878. unset($arParameters['UserName']);
  879. unset($arParameters['IgnorePayment']);
  880. unset($arParameters['ClientRedirectURL']);
  881. }
  882. // 整理 ATM 參數。
  883. if ($this->Send['ChoosePayment'] == PaymentMethod::ATM) {
  884. unset($arParameters['CreditInstallment']);
  885. unset($arParameters['Desc_1']);
  886. unset($arParameters['Desc_2']);
  887. unset($arParameters['Desc_3']);
  888. unset($arParameters['Desc_4']);
  889. unset($arParameters['Email']);
  890. unset($arParameters['ExecTimes']);
  891. unset($arParameters['ExpireTime']);
  892. unset($arParameters['Frequency']);
  893. unset($arParameters['InstallmentAmount']);
  894. unset($arParameters['PeriodAmount']);
  895. unset($arParameters['PeriodReturnURL']);
  896. unset($arParameters['PeriodType']);
  897. unset($arParameters['PhoneNo']);
  898. unset($arParameters['Redeem']);
  899. unset($arParameters['UnionPay']);
  900. unset($arParameters['UserName']);
  901. unset($arParameters['IgnorePayment']);
  902. if (!$this->SendExtend['ClientRedirectURL']) { unset($arParameters['ClientRedirectURL']); }
  903. }
  904. // 整理 BARCODE OR CVS 參數。
  905. if ($this->Send['ChoosePayment'] == PaymentMethod::BARCODE || $this->Send['ChoosePayment'] == PaymentMethod::CVS) {
  906. unset($arParameters['CreditInstallment']);
  907. unset($arParameters['Email']);
  908. unset($arParameters['ExecTimes']);
  909. unset($arParameters['ExpireDate']);
  910. unset($arParameters['ExpireTime']);
  911. unset($arParameters['Frequency']);
  912. unset($arParameters['InstallmentAmount']);
  913. unset($arParameters['PeriodAmount']);
  914. unset($arParameters['PeriodReturnURL']);
  915. unset($arParameters['PeriodType']);
  916. unset($arParameters['PhoneNo']);
  917. unset($arParameters['Redeem']);
  918. unset($arParameters['UnionPay']);
  919. unset($arParameters['UserName']);
  920. unset($arParameters['IgnorePayment']);
  921. if (!$this->SendExtend['ClientRedirectURL']) { unset($arParameters['ClientRedirectURL']); }
  922. }
  923. // 整理全功能、WebATM OR TopUpUsed 參數。
  924. if ($this->Send['ChoosePayment'] == PaymentMethod::WebATM || $this->Send['ChoosePayment'] == PaymentMethod::TopUpUsed) {
  925. unset($arParameters['CreditInstallment']);
  926. unset($arParameters['Desc_1']);
  927. unset($arParameters['Desc_2']);
  928. unset($arParameters['Desc_3']);
  929. unset($arParameters['Desc_4']);
  930. unset($arParameters['Email']);
  931. unset($arParameters['ExecTimes']);
  932. unset($arParameters['ExpireDate']);
  933. unset($arParameters['ExpireTime']);
  934. unset($arParameters['Frequency']);
  935. unset($arParameters['InstallmentAmount']);
  936. unset($arParameters['PaymentInfoURL']);
  937. unset($arParameters['PeriodAmount']);
  938. unset($arParameters['PeriodReturnURL']);
  939. unset($arParameters['PeriodType']);
  940. unset($arParameters['PhoneNo']);
  941. unset($arParameters['Redeem']);
  942. unset($arParameters['UnionPay']);
  943. unset($arParameters['UserName']);
  944. unset($arParameters['IgnorePayment']);
  945. unset($arParameters['ClientRedirectURL']);
  946. }
  947. // 整理 Credit 參數。
  948. if ($this->Send['ChoosePayment'] == PaymentMethod::Credit) {
  949. // Credit 分期。
  950. $arParameters['Redeem'] = ($arParameters['Redeem'] ? 'Y' : '');
  951. $arParameters['UnionPay'] = ($arParameters['UnionPay'] ? 1 : 0);
  952. unset($arParameters['Desc_1']);
  953. unset($arParameters['Desc_2']);
  954. unset($arParameters['Desc_3']);
  955. unset($arParameters['Desc_4']);
  956. unset($arParameters['Email']);
  957. unset($arParameters['ExpireDate']);
  958. unset($arParameters['ExpireTime']);
  959. unset($arParameters['PaymentInfoURL']);
  960. unset($arParameters['PhoneNo']);
  961. unset($arParameters['UserName']);
  962. unset($arParameters['IgnorePayment']);
  963. unset($arParameters['ClientRedirectURL']);
  964. }
  965. unset($arParameters['Items']);
  966. // 處理電子發票參數
  967. unset($arParameters['InvoiceItems']);
  968. if ($this->Send['InvoiceMark'] == InvoiceState::Yes) {
  969. $encode_fields = array(
  970. 'CustomerName',
  971. 'CustomerAddr',
  972. 'CustomerEmail',
  973. 'InvoiceItemName',
  974. 'InvoiceItemWord',
  975. 'InvoiceRemark'
  976. );
  977. foreach ($encode_fields as $tmp_field) {
  978. $arParameters[$tmp_field] = urlencode($arParameters[$tmp_field]);
  979. }
  980. } else {
  981. unset($arParameters['InvoiceMark']);
  982. unset($arParameters['RelateNumber']);
  983. unset($arParameters['CustomerIdentifier']);
  984. unset($arParameters['CarruerType']);
  985. unset($arParameters['CustomerID']);
  986. unset($arParameters['Donation']);
  987. unset($arParameters['Print']);
  988. unset($arParameters['CustomerName']);
  989. unset($arParameters['CustomerAddr']);
  990. unset($arParameters['CustomerPhone']);
  991. unset($arParameters['CustomerEmail']);
  992. unset($arParameters['TaxType']);
  993. unset($arParameters['ClearanceMark']);
  994. unset($arParameters['CarruerNum']);
  995. unset($arParameters['LoveCode']);
  996. unset($arParameters['InvoiceItemName']);
  997. unset($arParameters['InvoiceItemCount']);
  998. unset($arParameters['InvoiceItemWord']);
  999. unset($arParameters['InvoiceItemPrice']);
  1000. unset($arParameters['InvoiceItemTaxType']);
  1001. unset($arParameters['InvoiceRemark']);
  1002. unset($arParameters['DelayDay']);
  1003. unset($arParameters['InvType']);
  1004. }
  1005. // 資料排序
  1006. // php 5.3以下不支援
  1007. // ksort($arParameters, SORT_NATURAL | SORT_FLAG_CASE);
  1008. uksort($arParameters, array('AllInOne','merchantSort'));
  1009. $szCheckMacValue = "HashKey=$this->HashKey";
  1010. foreach ($arParameters as $key => $value) {
  1011. $szCheckMacValue .= "&$key=$value";
  1012. }
  1013. $szCheckMacValue .= "&HashIV=$this->HashIV";
  1014. $szCheckMacValue = strtolower(urlencode($szCheckMacValue));
  1015. // 取代為與 dotNet 相符的字元
  1016. $szCheckMacValue = str_replace('%2d', '-', $szCheckMacValue);
  1017. $szCheckMacValue = str_replace('%5f', '_', $szCheckMacValue);
  1018. $szCheckMacValue = str_replace('%2e', '.', $szCheckMacValue);
  1019. $szCheckMacValue = str_replace('%21', '!', $szCheckMacValue);
  1020. $szCheckMacValue = str_replace('%2a', '*', $szCheckMacValue);
  1021. $szCheckMacValue = str_replace('%28', '(', $szCheckMacValue);
  1022. $szCheckMacValue = str_replace('%29', ')', $szCheckMacValue);
  1023. // Customize for Magento
  1024. $szCheckMacValue = str_replace('%3f___sid%3d' . session_id(), '', $szCheckMacValue);
  1025. $szCheckMacValue = str_replace('%3f___sid%3du', '', $szCheckMacValue);
  1026. $szCheckMacValue = str_replace('%3f___sid%3ds', '', $szCheckMacValue);
  1027. // CheckMacValue 壓碼
  1028. $szCheckMacValue = $this->EncCheckMacValue($szCheckMacValue, $this->Send['EncryptType']);
  1029. $szHtml = '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
  1030. $szHtml .= '<div style="text-align:center;" ><form id="__allpayForm" method="post" target="' . $target . '" action="' . $this->ServiceURL . '">';
  1031. foreach ($arParameters as $keys => $value) {
  1032. $szHtml .="<input type='hidden' name='$keys' value='$value' />";
  1033. }
  1034. $szHtml .= '<input type="hidden" name="CheckMacValue" value="' . $szCheckMacValue . '" />';
  1035. // 手動或自動送出表單。
  1036. if (!isset($paymentButton)) {
  1037. $szHtml .= '<script type="text/javascript">document.getElementById("__allpayForm").submit();</script>';
  1038. } else {
  1039. $szHtml .= '<input type="submit" id="__paymentButton" value="' . $paymentButton . '" />';
  1040. }
  1041. $szHtml .= '</form></div>';
  1042. }
  1043. if (sizeof($arErrors) > 0) {
  1044. throw new Exception(join('- ', $arErrors));
  1045. }
  1046. return $szHtml;
  1047. }
  1048. function CheckOutFeedback() {
  1049. // 變數宣告。
  1050. $arErrors = array();
  1051. $arParameters = array();
  1052. $arFeedback = array();
  1053. $szCheckMacValue = '';
  1054. // 重新整理回傳參數。
  1055. foreach ($_POST as $keys => $value) {
  1056. if ($keys != 'CheckMacValue') {
  1057. if ($keys == 'PaymentType') {
  1058. $value = str_replace('_CVS', '', $value);
  1059. $value = str_replace('_BARCODE', '', $value);
  1060. $value = str_replace('_Alipay', '', $value);
  1061. $value = str_replace('_Tenpay', '', $value);
  1062. $value = str_replace('_CreditCard', '', $value);
  1063. }
  1064. if ($keys == 'PeriodType') {
  1065. $value = str_replace('Y', 'Year', $value);
  1066. $value = str_replace('M', 'Month', $value);
  1067. $value = str_replace('D', 'Day', $value);
  1068. }
  1069. $arFeedback[$keys] = $value;
  1070. } else {
  1071. $szCheckMacValue = $value;
  1072. }
  1073. }
  1074. // 回傳參數鍵值轉小寫。
  1075. foreach ($_POST as $keys => $value) {
  1076. if ($keys == 'view' || $keys == 'hikashop_front_end_main') {
  1077. // Customize to Skip Parameters for HikaShop
  1078. } else if ($keys == 'mijoshop_store_id' || $keys == 'language') {
  1079. // Customize to Skip Parameters for MijoShop
  1080. } else {
  1081. $arParameters[strtolower($keys)] = $value;
  1082. }
  1083. }
  1084. unset($arParameters['checkmacvalue']);
  1085. ksort($arParameters);
  1086. // 驗證檢查碼。
  1087. if (sizeof($arFeedback) > 0) {
  1088. $szConfirmMacValue = "HashKey=$this->HashKey";
  1089. foreach ($arParameters as $key => $value) {
  1090. $szConfirmMacValue .= "&$key=$value";
  1091. }
  1092. $szConfirmMacValue .= "&HashIV=$this->HashIV";
  1093. $szConfirmMacValue = strtolower(urlencode($szConfirmMacValue));
  1094. // 取代為與 dotNet 相符的字元
  1095. $szConfirmMacValue = str_replace('%2d', '-', $szConfirmMacValue);
  1096. $szConfirmMacValue = str_replace('%5f', '_', $szConfirmMacValue);
  1097. $szConfirmMacValue = str_replace('%2e', '.', $szConfirmMacValue);
  1098. $szConfirmMacValue = str_replace('%21', '!', $szConfirmMacValue);
  1099. $szConfirmMacValue = str_replace('%2a', '*', $szConfirmMacValue);
  1100. $szConfirmMacValue = str_replace('%28', '(', $szConfirmMacValue);
  1101. $szConfirmMacValue = str_replace('%29', ')', $szConfirmMacValue);
  1102. // 檢查CheckMacValue加密方式
  1103. if (strlen($this->EncryptType) > 1) {
  1104. array_push($arErrors, 'EncryptType max langth as 1.');
  1105. }
  1106. // CheckMacValue 壓碼
  1107. $szConfirmMacValue = $this->EncCheckMacValue($szConfirmMacValue, $this->EncryptType);
  1108. if ($szCheckMacValue != strtoupper($szConfirmMacValue)) {
  1109. array_push($arErrors, 'CheckMacValue verify fail. [checkMac]: '.$szCheckMacValue.', [confirm]: '.strtoupper($szConfirmMacValue)); // 2016/02/15 add memo
  1110. //array_push($arErrors, 'CheckMacValue verify fail.');
  1111. }
  1112. }
  1113. if (sizeof($arErrors) > 0) {
  1114. throw new Exception(join('- ', $arErrors));
  1115. }
  1116. return $arFeedback;
  1117. }
  1118. function QueryTradeInfo() {
  1119. // 變數宣告。
  1120. $arErrors = array();
  1121. $this->Query['TimeStamp'] = time();
  1122. $arFeedback = array();
  1123. $arConfirmArgs = array();
  1124. // 檢查資料。
  1125. if (strlen($this->ServiceURL) == 0) {
  1126. array_push($arErrors, 'ServiceURL is required.');
  1127. }
  1128. if (strlen($this->ServiceURL) > 200) {
  1129. array_push($arErrors, 'ServiceURL max langth as 200.');
  1130. }
  1131. if (strlen($this->HashKey) == 0) {
  1132. array_push($arErrors, 'HashKey is required.');
  1133. }
  1134. if (strlen($this->HashIV) == 0) {
  1135. array_push($arErrors, 'HashIV is required.');
  1136. }
  1137. if (strlen($this->MerchantID) == 0) {
  1138. array_push($arErrors, 'MerchantID is required.');
  1139. }
  1140. if (strlen($this->MerchantID) > 10) {
  1141. array_push($arErrors, 'MerchantID max langth as 10.');
  1142. }
  1143. if (strlen($this->Query['MerchantTradeNo']) == 0) {
  1144. array_push($arErrors, 'MerchantTradeNo is required.');
  1145. }
  1146. if (strlen($this->Query['MerchantTradeNo']) > 20) {
  1147. array_push($arErrors, 'MerchantTradeNo max langth as 20.');
  1148. }
  1149. if (strlen($this->Query['TimeStamp']) == 0) {
  1150. array_push($arErrors, 'TimeStamp is required.');
  1151. }
  1152. // 呼叫查詢。
  1153. if (sizeof($arErrors) == 0) {
  1154. $arParameters = array("MerchantID" => $this->MerchantID);
  1155. $arParameters = array_merge($arParameters, $this->Query);
  1156. // 資料排序。
  1157. ksort($arParameters);
  1158. // 產生檢查碼。
  1159. $szCheckMacValue = "HashKey=$this->HashKey";
  1160. foreach ($arParameters as $key => $value) {
  1161. $szCheckMacValue .= "&$key=$value";
  1162. }
  1163. $szCheckMacValue .= "&HashIV=$this->HashIV";
  1164. $szCheckMacValue = strtolower(urlencode($szCheckMacValue));
  1165. // 取代為與 dotNet 相符的字元
  1166. $szCheckMacValue = str_replace('%2d', '-', $szCheckMacValue);
  1167. $szCheckMacValue = str_replace('%5f', '_', $szCheckMacValue);
  1168. $szCheckMacValue = str_replace('%2e', '.', $szCheckMacValue);
  1169. $szCheckMacValue = str_replace('%21', '!', $szCheckMacValue);
  1170. $szCheckMacValue = str_replace('%2a', '*', $szCheckMacValue);
  1171. $szCheckMacValue = str_replace('%28', '(', $szCheckMacValue);
  1172. $szCheckMacValue = str_replace('%29', ')', $szCheckMacValue);
  1173. // Customize for Magento
  1174. $szCheckMacValue = str_replace('%3f___sid%3d' . session_id(), '', $szCheckMacValue);
  1175. $szCheckMacValue = str_replace('%3f___sid%3du', '', $szCheckMacValue);
  1176. $szCheckMacValue = str_replace('%3f___sid%3ds', '', $szCheckMacValue);
  1177. // MD5 編碼
  1178. $szCheckMacValue = md5($szCheckMacValue);
  1179. $arParameters["CheckMacValue"] = $szCheckMacValue;
  1180. // 送出查詢並取回結果。
  1181. $szResult = $this->ServerPost($arParameters);
  1182. $szResult = str_replace(' ', '%20', $szResult);
  1183. $szResult = str_replace('+', '%2B', $szResult);
  1184. //$szResult = str_replace('/', '%2F', $szResult);
  1185. //$szResult = str_replace('?', '%3F', $szResult);
  1186. //$szResult = str_replace('%', '%25', $szResult);
  1187. //$szResult = str_replace('#', '%23', $szResult);
  1188. //$szResult = str_replace('&', '%26', $szResult);
  1189. //$szResult = str_replace('=', '%3D', $szResult);
  1190. // 轉結果為陣列。
  1191. parse_str($szResult, $arParameters);
  1192. // 重新整理回傳參數。
  1193. foreach ($arParameters as $keys => $value) {
  1194. if ($keys == 'CheckMacValue') {
  1195. $szCheckMacValue = $value;
  1196. } else {
  1197. $arFeedback[$keys] = $value;
  1198. $arConfirmArgs[strtolower($keys)] = $value;
  1199. }
  1200. }
  1201. ksort($arConfirmArgs);
  1202. // 驗證檢查碼。
  1203. if (sizeof($arFeedback) > 0) {
  1204. $szConfirmMacValue = "HashKey=$this->HashKey";
  1205. foreach ($arConfirmArgs as $key => $value) {
  1206. $szConfirmMacValue .= "&$key=$value";
  1207. }
  1208. $szConfirmMacValue .= "&HashIV=$this->HashIV";
  1209. $szConfirmMacValue = strtolower(urlencode($szConfirmMacValue));
  1210. // 取代為與 dotNet 相符的字元
  1211. $szConfirmMacValue = str_replace('%2d', '-', $szConfirmMacValue);
  1212. $szConfirmMacValue = str_replace('%5f', '_', $szConfirmMacValue);
  1213. $szConfirmMacValue = str_replace('%2e', '.', $szConfirmMacValue);
  1214. $szConfirmMacValue = str_replace('%21', '!', $szConfirmMacValue);
  1215. $szConfirmMacValue = str_replace('%2a', '*', $szConfirmMacValue);
  1216. $szConfirmMacValue = str_replace('%28', '(', $szConfirmMacValue);
  1217. $szConfirmMacValue = str_replace('%29', ')', $szConfirmMacValue);
  1218. // MD5 編碼
  1219. $szConfirmMacValue = md5($szConfirmMacValue);
  1220. if ($szCheckMacValue != strtoupper($szConfirmMacValue)) {
  1221. array_push($arErrors, 'CheckMacValue verify fail.');
  1222. }
  1223. }
  1224. }
  1225. if (sizeof($arErrors) > 0) {
  1226. throw new Exception(join('- ', $arErrors));
  1227. }
  1228. return $arFeedback;
  1229. }
  1230. function QueryPeriodCreditCardTradeInfo() {
  1231. // 變數宣告。
  1232. $arErrors = array();
  1233. $this->Query['TimeStamp'] = time();
  1234. $arFeedback = array();
  1235. // 檢查資料。
  1236. if (strlen($this->ServiceURL) == 0) {
  1237. array_push($arErrors, 'ServiceURL is required.');
  1238. }
  1239. if (strlen($this->ServiceURL) > 200) {
  1240. array_push($arErrors, 'ServiceURL max langth as 200.');
  1241. }
  1242. if (strlen($this->HashKey) == 0) {
  1243. array_push($arErrors, 'HashKey is required.');
  1244. }
  1245. if (strlen($this->HashIV) == 0) {
  1246. array_push($arErrors, 'HashIV is required.');
  1247. }
  1248. if (strlen($this->MerchantID) == 0) {
  1249. array_push($arErrors, 'MerchantID is required.');
  1250. }
  1251. if (strlen($this->MerchantID) > 10) {
  1252. array_push($arErrors, 'MerchantID max langth as 10.');
  1253. }
  1254. if (strlen($this->Query['MerchantTradeNo']) == 0) {
  1255. array_push($arErrors, 'MerchantTradeNo is required.');
  1256. }
  1257. if (strlen($this->Query['MerchantTradeNo']) > 20) {
  1258. array_push($arErrors, 'MerchantTradeNo max langth as 20.');
  1259. }
  1260. if (strlen($this->Query['TimeStamp']) == 0) {
  1261. array_push($arErrors, 'TimeStamp is required.');
  1262. }
  1263. // 呼叫查詢。
  1264. if (sizeof($arErrors) == 0) {
  1265. $arParameters = array("MerchantID" => $this->MerchantID);
  1266. $arParameters = array_merge($arParameters, $this->Query);
  1267. // 資料排序。
  1268. ksort($arParameters);
  1269. // 產生檢查碼。
  1270. $szCheckMacValue = "HashKey=$this->HashKey";
  1271. foreach ($arParameters as $key => $value) {
  1272. $szCheckMacValue .= "&$key=$value";
  1273. }
  1274. $szCheckMacValue .= "&HashIV=$this->HashIV";
  1275. $szCheckMacValue = strtolower(urlencode($szCheckMacValue));
  1276. // 取代為與 dotNet 相符的字元
  1277. $szCheckMacValue = str_replace('%2d', '-', $szCheckMacValue);
  1278. $szCheckMacValue = str_replace('%5f', '_', $szCheckMacValue);
  1279. $szCheckMacValue = str_replace('%2e', '.', $szCheckMacValue);
  1280. $szCheckMacValue = str_replace('%21', '!', $szCheckMacValue);
  1281. $szCheckMacValue = str_replace('%2a', '*', $szCheckMacValue);
  1282. $szCheckMacValue = str_replace('%28', '(', $szCheckMacValue);
  1283. $szCheckMacValue = str_replace('%29', ')', $szCheckMacValue);
  1284. // Customize for Magento
  1285. $szCheckMacValue = str_replace('%3f___sid%3d' . session_id(), '', $szCheckMacValue);
  1286. $szCheckMacValue = str_replace('%3f___sid%3du', '', $szCheckMacValue);
  1287. $szCheckMacValue = str_replace('%3f___sid%3ds', '', $szCheckMacValue);
  1288. // MD5 編碼
  1289. $szCheckMacValue = md5($szCheckMacValue);
  1290. $arParameters["CheckMacValue"] = $szCheckMacValue;
  1291. // 送出查詢並取回結果。
  1292. $szResult = $this->ServerPost($arParameters);
  1293. $szResult = str_replace(' ', '%20', $szResult);
  1294. $szResult = str_replace('+', '%2B', $szResult);
  1295. //$szResult = str_replace('/', '%2F', $szResult);
  1296. //$szResult = str_replace('?', '%3F', $szResult);
  1297. //$szResult = str_replace('%', '%25', $szResult);
  1298. //$szResult = str_replace('#', '%23', $szResult);
  1299. //$szResult = str_replace('&', '%26', $szResult);
  1300. //$szResult = str_replace('=', '%3D', $szResult);
  1301. // 轉結果為陣列。
  1302. parse_str($szResult, $arFeedback);
  1303. }
  1304. if (sizeof($arErrors) > 0) {
  1305. throw new Exception(join('- ', $arErrors));
  1306. }
  1307. return $arFeedback;
  1308. }
  1309. function DoAction() {
  1310. // 變數宣告。
  1311. $arErrors = array();
  1312. $arFeedback = array();
  1313. // 檢查資料。
  1314. if (strlen($this->ServiceURL) == 0) {
  1315. array_push($arErrors, 'ServiceURL is required.');
  1316. }
  1317. if (strlen($this->ServiceURL) > 200) {
  1318. array_push($arErrors, 'ServiceURL max langth as 200.');
  1319. }
  1320. if (strlen($this->HashKey) == 0) {
  1321. array_push($arErrors, 'HashKey is required.');
  1322. }
  1323. if (strlen($this->HashIV) == 0) {
  1324. array_push($arErrors, 'HashIV is required.');
  1325. }
  1326. if (strlen($this->MerchantID) == 0) {
  1327. array_push($arErrors, 'MerchantID is required.');
  1328. }
  1329. if (strlen($this->MerchantID) > 10) {
  1330. array_push($arErrors, 'MerchantID max langth as 10.');
  1331. }
  1332. if (strlen($this->Action['MerchantTradeNo']) == 0) {
  1333. array_push($arErrors, 'MerchantTradeNo is required.');
  1334. }
  1335. if (strlen($this->Action['MerchantTradeNo']) > 20) {
  1336. array_push($arErrors, 'MerchantTradeNo max langth as 20.');
  1337. }
  1338. if (strlen($this->Action['TradeNo']) == 0) {
  1339. array_push($arErrors, 'TradeNo is required.');
  1340. }
  1341. if (strlen($this->Action['TradeNo']) > 20) {
  1342. array_push($arErrors, 'TradeNo max langth as 20.');
  1343. }
  1344. if (strlen($this->Action['Action']) == 0) {
  1345. array_push($arErrors, 'Action is required.');
  1346. }
  1347. if (strlen($this->Action['Action']) > 1) {
  1348. array_push($arErrors, 'Action max length as 1.');
  1349. }
  1350. if (strlen($this->Action['TotalAmount']) == 0) {
  1351. array_push($arErrors, 'TotalAmount is required.');
  1352. }
  1353. // 呼叫信用卡訂單處理。
  1354. if (sizeof($arErrors) == 0) {
  1355. $arParameters = array("MerchantID" => $this->MerchantID);
  1356. $arParameters = array_merge($arParameters, $this->Action);
  1357. // 資料排序。
  1358. ksort($arParameters);
  1359. // 產生檢查碼。
  1360. $szCheckMacValue = "HashKey=$this->HashKey";
  1361. foreach ($arParameters as $key => $value) {
  1362. $szCheckMacValue .= "&$key=$value";
  1363. }
  1364. $szCheckMacValue .= "&HashIV=$this->HashIV";
  1365. $szCheckMacValue = strtolower(urlencode($szCheckMacValue));
  1366. // 取代為與 dotNet 相符的字元
  1367. $szCheckMacValue = str_replace('%2d', '-', $szCheckMacValue);
  1368. $szCheckMacValue = str_replace('%5f', '_', $szCheckMacValue);
  1369. $szCheckMacValue = str_replace('%2e', '.', $szCheckMacValue);
  1370. $szCheckMacValue = str_replace('%21', '!', $szCheckMacValue);
  1371. $szCheckMacValue = str_replace('%2a', '*', $szCheckMacValue);
  1372. $szCheckMacValue = str_replace('%28', '(', $szCheckMacValue);
  1373. $szCheckMacValue = str_replace('%29', ')', $szCheckMacValue);
  1374. // Customize for Magento
  1375. $szCheckMacValue = str_replace('%3f___sid%3d' . session_id(), '', $szCheckMacValue);
  1376. $szCheckMacValue = str_replace('%3f___sid%3du', '', $szCheckMacValue);
  1377. $szCheckMacValue = str_replace('%3f___sid%3ds', '', $szCheckMacValue);
  1378. // MD5 編碼
  1379. $szCheckMacValue = md5($szCheckMacValue);
  1380. $arParameters["CheckMacValue"] = $szCheckMacValue;
  1381. // 送出查詢並取回結果。
  1382. $szResult = $this->ServerPost($arParameters);
  1383. // 轉結果為陣列。
  1384. parse_str($szResult, $arParameters);
  1385. // 重新整理回傳參數。
  1386. foreach ($arParameters as $keys => $value) {
  1387. if ($keys == 'CheckMacValue') {
  1388. $szCheckMacValue = $value;
  1389. } else {
  1390. $arFeedback[$keys] = $value;
  1391. }
  1392. }
  1393. if (array_key_exists('RtnCode', $arFeedback) && $arFeedback['RtnCode'] != '1') {
  1394. array_push($arErrors, vsprintf('#%s: %s', array($arFeedback['RtnCode'], $arFeedback['RtnMsg'])));
  1395. }
  1396. }
  1397. if (sizeof($arErrors) > 0) {
  1398. throw new Exception(join('- ', $arErrors));
  1399. }
  1400. return $arFeedback;
  1401. }
  1402. function AioChargeback() {
  1403. // 變數宣告。
  1404. $arErrors = array();
  1405. $arParameters = array("MerchantID" => $this->MerchantID);
  1406. $arParameters = array_merge($arParameters, $this->ChargeBack);
  1407. $arFeedback = array();
  1408. // 檢查資料。
  1409. if (strlen($this->ServiceURL) == 0) {
  1410. array_push($arErrors, 'ServiceURL is required.');
  1411. }
  1412. if (strlen($this->ServiceURL) > 200) {
  1413. array_push($arErrors, 'ServiceURL max langth as 200.');
  1414. }
  1415. if (strlen($this->HashKey) == 0) {
  1416. array_push($arErrors, 'HashKey is required.');
  1417. }
  1418. if (strlen($this->HashIV) == 0) {
  1419. array_push($arErrors, 'HashIV is required.');
  1420. }
  1421. if (strlen($this->MerchantID) == 0) {
  1422. array_push($arErrors, 'MerchantID is required.');
  1423. }
  1424. if (strlen($this->MerchantID) > 10) {
  1425. array_push($arErrors, 'MerchantID max langth as 10.');
  1426. }
  1427. if (strlen($this->ChargeBack['MerchantTradeNo']) == 0) {
  1428. array_push($arErrors, 'MerchantTradeNo is required.');
  1429. }
  1430. if (strlen($this->ChargeBack['MerchantTradeNo']) > 20) {
  1431. array_push($arErrors, 'MerchantTradeNo max langth as 20.');
  1432. }
  1433. if (strlen($this->ChargeBack['TradeNo']) == 0) {
  1434. array_push($arErrors, 'TradeNo is required.');
  1435. }
  1436. if (strlen($this->ChargeBack['TradeNo']) > 20) {
  1437. array_push($arErrors, 'TradeNo max langth as 20.');
  1438. }
  1439. if (strlen($this->ChargeBack['ChargeBackTotalAmount']) == 0) {
  1440. array_push($arErrors, 'ChargeBackTotalAmount is required.');
  1441. }
  1442. if (strlen($this->ChargeBack['Remark']) > 200) {
  1443. array_push($arErrors, 'Remark max length as 200.');
  1444. }
  1445. // 資料排序。
  1446. ksort($arParameters);
  1447. // 產生檢查碼。
  1448. $szCheckMacValue = "HashKey=$this->HashKey";
  1449. foreach ($arParameters as $key => $value) {
  1450. $szCheckMacValue .= "&$key=$value";
  1451. }
  1452. $szCheckMacValue .= "&HashIV=$this->HashIV";
  1453. $szCheckMacValue = strtolower(urlencode($szCheckMacValue));
  1454. // 取代為與 dotNet 相符的字元
  1455. $szCheckMacValue = str_replace('%2d', '-', $szCheckMacValue);
  1456. $szCheckMacValue = str_replace('%5f', '_', $szCheckMacValue);
  1457. $szCheckMacValue = str_replace('%2e', '.', $szCheckMacValue);
  1458. $szCheckMacValue = str_replace('%21', '!', $szCheckMacValue);
  1459. $szCheckMacValue = str_replace('%2a', '*', $szCheckMacValue);
  1460. $szCheckMacValue = str_replace('%28', '(', $szCheckMacValue);
  1461. $szCheckMacValue = str_replace('%29', ')', $szCheckMacValue);
  1462. // Customize for Magento
  1463. $szCheckMacValue = str_replace('%3f___sid%3d' . session_id(), '', $szCheckMacValue);
  1464. $szCheckMacValue = str_replace('%3f___sid%3du', '', $szCheckMacValue);
  1465. $szCheckMacValue = str_replace('%3f___sid%3ds', '', $szCheckMacValue);
  1466. // MD5 編碼
  1467. $szCheckMacValue = md5($szCheckMacValue);
  1468. $arParameters["CheckMacValue"] = $szCheckMacValue;
  1469. // 送出查詢並取回結果。
  1470. $szResult = $this->ServerPost($arParameters);
  1471. // 檢查結果資料。
  1472. if ($szResult == '1|OK') {
  1473. $arFeedback['RtnCode'] = '1';
  1474. $arFeedback['RtnMsg'] = 'OK';
  1475. } else {
  1476. array_push($arErrors, str_replace('-', ': ', $szResult));
  1477. }
  1478. if (sizeof($arErrors) > 0) {
  1479. throw new Exception(join('- ', $arErrors));
  1480. }
  1481. return $arFeedback;
  1482. }
  1483. private function ServerPost($parameters) {
  1484. $ch = curl_init();
  1485. curl_setopt($ch, CURLOPT_URL, $this->ServiceURL);
  1486. curl_setopt($ch, CURLOPT_HEADER, FALSE);
  1487. curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
  1488. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  1489. curl_setopt($ch, CURLOPT_POST, TRUE);
  1490. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parameters));
  1491. $rs = curl_exec($ch);
  1492. curl_close($ch);
  1493. return $rs;
  1494. }
  1495. /**
  1496. * 自訂排序使用
  1497. */
  1498. private static function merchantSort($a,$b)
  1499. {
  1500. return strcasecmp($a, $b);
  1501. }
  1502. private function EncCheckMacValue($checkMacValue, $encType = EncryptType::ENC_MD5) {
  1503. $szCheckMacValue = $checkMacValue;
  1504. switch ($encType) {
  1505. case EncryptType::ENC_SHA256:
  1506. // SHA256 編碼
  1507. $szCheckMacValue = hash('sha256', $szCheckMacValue);
  1508. break;
  1509. case EncryptType::ENC_MD5:
  1510. default:
  1511. // MD5 編碼
  1512. $szCheckMacValue = md5($szCheckMacValue);
  1513. }
  1514. return $szCheckMacValue;
  1515. }
  1516. }