Bridge.php 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. <?php
  2. namespace rbridge\gy;
  3. require_once(BASE_HELPER_PATH . '/rbridge/gy/config.php');
  4. use rbridge\IBridge;
  5. use rbridge\IBridgeEx;
  6. use rbridge\BridgeTrait;
  7. use refill;
  8. use Log;
  9. use SimpleXMLElement;
  10. use member_info;
  11. class Bridge implements IBridge, IBridgeEx
  12. {
  13. use BridgeTrait;
  14. public function add($params)
  15. {
  16. $input_names = ['userid', 'request_id', 'telephone', 'money', 'callbackurl'];
  17. $out_names = ['order_id', 'request_id', 'telephone', 'money', 'result'];
  18. $mchid = config::mchid($params);
  19. if ($mchid === false) {
  20. $params['result'] = 4; //请求参数不完整或不合法
  21. return [false, $this->result_format($params, $out_names, '')];
  22. }
  23. $mchinfo = Model('merchant')->getMerchantInfo(['mchid' => $mchid]);
  24. if (empty($mchinfo)) {
  25. $params['result'] = 6; //代理商不存在
  26. return [false, $this->result_format($params, $out_names, '')];
  27. }
  28. $secure_key = $mchinfo['secure_key'];
  29. [$succ, $result] = $this->check($mchinfo, $params, $input_names);
  30. if (!$succ) {
  31. $params['result'] = $result;
  32. return [false, $this->result_format($params, $out_names, $secure_key)];
  33. }
  34. Model('merchant_query')->add_info($mchid, $params['request_id'], json_encode($params));
  35. $order_time = time();
  36. $mch_order = $params['request_id'];
  37. $card_no = $params['telephone'];
  38. $input = ['mchid' => $mchid,
  39. 'buyer_id' => intval($mchinfo['admin_id']),
  40. 'amount' => $params['money'],
  41. 'card_no' => $card_no,
  42. 'mch_order' => $mch_order,
  43. 'notify_url' => config::MCH_NOTIFY_URL,
  44. 'order_time' => $order_time
  45. ];
  46. refill\util::push_queue_order($mchid, $mch_order, ORDER_STATE_QUEUE);
  47. $detail_id = Model('refill_order')->add_detail($mchid, $mch_order, $order_time, $params, ORDER_STATE_QUEUE);
  48. $state = refill\util::push_add($input);
  49. if ($state === true) {
  50. Log::record("gy::Bridge refill::util::push_add success mchid=$mchid mch_order=$mch_order state=true", Log::DEBUG);
  51. $params['order_id'] = $detail_id;
  52. $params['result'] = 2; //提交成功,正在充值(适用于异步接口)
  53. return [true, $this->result_format($params, $out_names, $secure_key)];
  54. } else {
  55. refill\util::del_queue_order($mchid, $mch_order);
  56. Model('refill_order')->del_detail($mchid, $mch_order);
  57. Log::record("gy::Bridge refill::util::push_add error mchid=$mchid mch_order=$mch_order state=$state", Log::DEBUG);
  58. $params['result'] = 12; //未知错误
  59. return [true, $this->result_format($params, $out_names, $secure_key)];
  60. }
  61. }
  62. private function result_format($input, $names, $secure_key)
  63. {
  64. $result = $this->sign($input, $names, $secure_key);
  65. $xml = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><root></root>');
  66. config::arrayToXml($xml,$result);
  67. return $xml->asXML();
  68. }
  69. private function sign($input, $names, $secure_key)
  70. {
  71. $result = [];
  72. $body = '';
  73. foreach ($names as $name) {
  74. $val = $input[$name] ?? '';
  75. $body .= $val;
  76. $result[$name] = $val;
  77. }
  78. $body .= $secure_key;
  79. $sign = strtoupper(md5($body));
  80. $result['sign'] = $sign;
  81. return $result;
  82. }
  83. private function check($mchinfo, $input, $names): array
  84. {
  85. if ($mchinfo['merchant_state'] != 1) {
  86. return [false, 6]; //代理商不存在
  87. }
  88. $ips = unserialize($mchinfo['ip_white_list']);
  89. if(!empty($ips))
  90. {
  91. $addr = $_SERVER['REMOTE_ADDR'];
  92. if(!in_array($addr,$ips)) {
  93. Log::record("request ip:$addr", Log::DEBUG);
  94. return [false, 12]; //未知错误
  95. }
  96. }
  97. $usekey = intval($mchinfo['use_key']);
  98. $key = $mchinfo['secure_key'];
  99. if ($usekey) {
  100. $ret = $this->verify($input, $names, $key);
  101. if (!$ret) {
  102. return [false, 5]; //签名错误
  103. }
  104. }
  105. return [true, ''];
  106. }
  107. private function verify($params, $names, $key)
  108. {
  109. $body = '';
  110. foreach ($names as $name) {
  111. $val = $params[$name] ?? '';
  112. $body .= $val;
  113. }
  114. $body .= $key;
  115. $sign = strtoupper(md5($body));
  116. return $params['sign'] == $sign;
  117. }
  118. public function query($params)
  119. {
  120. $input_names = ['userid', 'request_id'];
  121. $out_names = ['order_id', 'request_id', 'telephone', 'money', 'result'];
  122. $mchid = config::mchid($params);
  123. $mch_order = $params['request_id'];
  124. if ($mchid === false or empty($mch_order)) {
  125. $params['result'] = 4; //请求参数不完整或不合法
  126. return [false, $this->result_format($params, $out_names, '')];
  127. }
  128. $mchinfo = Model('merchant')->getMerchantInfo(['mchid' => $mchid]);
  129. if (empty($mchinfo)) {
  130. $params['result'] = 6; //代理商不存在
  131. return [false, $this->result_format($params, $out_names, '')];
  132. }
  133. $secure_key = $mchinfo['secure_key'];
  134. [$succ, $result] = $this->check($mchinfo, $params, $input_names);
  135. if(!$succ) {
  136. $params['result'] = $result;
  137. return [$succ, $this->result_format($params, $out_names, $secure_key)];
  138. }
  139. [$detail_id,$info] = $this->detail($mchid, $mch_order);
  140. [$code, $order] = $this->order_query($mchid, $mch_order);
  141. if ($code == 200) {
  142. $info['order_id'] = $detail_id;
  143. $order_state = $order['order_state'];
  144. } else {
  145. $order_state = ORDER_STATE_NOEXIST;
  146. }
  147. if (in_array($order_state, [ORDER_STATE_QUEUE, ORDER_STATE_NEW, ORDER_STATE_PAY, ORDER_STATE_SEND])) {
  148. $info['result'] = 2;
  149. } elseif ($order_state == ORDER_STATE_SUCCESS) {
  150. $info['result'] = 0;
  151. } elseif ($order_state == ORDER_STATE_CANCEL) {
  152. $info['result'] = 1;
  153. } else {
  154. $info['result'] = 3;
  155. }
  156. return [true, $this->result_format($info, $out_names, $secure_key)];
  157. }
  158. private function detail($mchid, $mch_order)
  159. {
  160. $mod_refill = Model('refill_order');
  161. $detail = $mod_refill->get_detail($mchid,$mch_order);
  162. if(empty($detail)) {
  163. return [false, []];
  164. }
  165. else {
  166. return [intval($detail['detail_id']), json_decode($detail['params'], true)];
  167. }
  168. }
  169. public function balance($params)
  170. {
  171. $input_names = ['userid'];
  172. $out_names = ['userid', 'money'];
  173. $mchid = config::mchid($params);
  174. if ($mchid === false) {
  175. $params['result'] = 4; //请求参数不完整或不合法
  176. return [false, $this->result_format($params, $out_names, '')];
  177. }
  178. $mchinfo = Model('merchant')->getMerchantInfo(['mchid' => $mchid]);
  179. if (empty($mchinfo)) {
  180. $params['result'] = 6; //代理商不存在
  181. return [false, $this->result_format($params, $out_names, '')];
  182. }
  183. $secure_key = $mchinfo['secure_key'];
  184. [$succ, $result] = $this->check($mchinfo, $params, $input_names);
  185. if(!$succ) {
  186. $params['result'] = $result;
  187. return [$succ, $this->result_format($params, $out_names, $secure_key)];
  188. }
  189. $uid = intval($mchinfo['admin_id']);
  190. $minfo = new member_info($uid);
  191. $available = $minfo->available_predeposit();
  192. $money = ncPriceFormat($available - $mchinfo['credit_bonus']);
  193. $params['money'] = $money;
  194. return [true, $this->result_format($params, $out_names, $secure_key)];
  195. }
  196. public function notify($params)
  197. {
  198. $out_names = ['order_id', 'request_id', 'telephone', 'money', 'result'];
  199. $mchid = $params['mchid'];
  200. $mch_order = $params['order_sn'];
  201. [$detail_id,$input] = $this->detail($mchid, $mch_order);
  202. $mchid = $params['mchid'];
  203. $mchinfo = Model('merchant')->getMerchantInfo(['mchid' => $mchid]);
  204. $secure_key = $mchinfo['secure_key'];
  205. $body = $this->notify_body($detail_id,$input,$params['state']);
  206. $body = $this->sign($body,$out_names,$secure_key);
  207. $resp = http_request($input['callbackurl'], $body, 'GET');
  208. if (empty($resp)) {
  209. Log::record("回调下游,请求超时 mchid = $mchid mch_order = $mch_order", Log::ERR);
  210. return false;
  211. } elseif (in_array($resp, ['success'])) {
  212. return true;
  213. } else {
  214. return false;
  215. }
  216. }
  217. private function notify_body($detail_id, $input, $order_state)
  218. {
  219. $input['order_id'] = $detail_id;
  220. if($order_state == 'SUCCESS') {
  221. $input['result'] = 0;
  222. } else {
  223. $input['result'] = 1;
  224. }
  225. return $input;
  226. }
  227. }