人人商城

bfb_sdk.php 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. <?php
  2. /**
  3. * [WeEngine System] Copyright (c) 2014 WE7.CC
  4. * WeEngine is NOT a free software, it under the license terms, visited http://www.we7.cc/ for more details.
  5. */
  6. if (!defined("BFB_SDK_ROOT"))
  7. {
  8. define("BFB_SDK_ROOT", dirname(__FILE__) . DIRECTORY_SEPARATOR);
  9. }
  10. require_once(BFB_SDK_ROOT . 'bfb_pay.cfg.php');
  11. if (!function_exists('curl_init')) {
  12. exit('您的PHP没有安装 配置cURL扩展,请先安装配置cURL,具体方法可以上网查。');
  13. }
  14. if (!function_exists('json_decode')) {
  15. exit('您的PHP不支持JSON,请升级您的PHP版本。');
  16. }
  17. class bfb_sdk{
  18. public $err_msg;
  19. public $order_no;
  20. function __construct() {
  21. }
  22. function create_baifubao_pay_order_url($params, $url) {
  23. if (empty($params ['service_code']) || empty($params ['sp_no']) ||
  24. empty($params ['order_create_time']) ||
  25. empty($params ['order_no']) ||
  26. empty($params ['goods_name']) ||
  27. empty($params ['total_amount']) ||
  28. empty($params ['currency']) ||
  29. empty($params ['return_url']) ||
  30. empty($params ['pay_type']) ||
  31. empty($params ['input_charset']) ||
  32. empty($params ['version']) ||
  33. empty($params ['sign_method'])) {
  34. $this->log(sprintf('invalid params, params:[%s]', print_r($params, true)));
  35. return false;
  36. }
  37. if (!in_array($url,
  38. array (
  39. sp_conf::BFB_PAY_DIRECT_LOGIN_URL,
  40. sp_conf::BFB_PAY_DIRECT_NO_LOGIN_URL,
  41. sp_conf::BFB_PAY_WAP_DIRECT_URL
  42. ))) {
  43. $this->log(
  44. sprintf('invalid url[%s], bfb just provide three kind of pay url',
  45. $url));
  46. return false;
  47. }
  48. $pay_url = $url;
  49. if (false === ($sign = $this->make_sign($params))) {
  50. return false;
  51. }
  52. $this->order_no = $params ['order_no'];
  53. $params ['sign'] = $sign;
  54. $params_str = http_build_query($params);
  55. $this->log(
  56. sprintf('the params that create baifubao pay order is [%s]',
  57. $params_str));
  58. return $pay_url . '?' . $params_str;
  59. }
  60. function check_bfb_pay_result_notify() {
  61. if (empty($_GET) || !isset($_GET ['sp_no']) || !isset(
  62. $_GET ['order_no']) || !isset($_GET ['bfb_order_no']) ||
  63. !isset($_GET ['bfb_order_create_time']) ||
  64. !isset($_GET ['pay_time']) || !isset($_GET ['pay_type']) ||
  65. !isset($_GET ['total_amount']) || !isset($_GET ['fee_amount']) ||
  66. !isset($_GET ['currency']) || !isset($_GET ['pay_result']) ||
  67. !isset($_GET ['input_charset']) || !isset($_GET ['version']) ||
  68. !isset($_GET ['sign']) || !isset($_GET ['sign_method'])) {
  69. $this->err_msg = 'return_url页面的请求的必选参数不足';
  70. $this->log(
  71. sprintf('missing the params of return_url page, params[%s]',
  72. print_r($_GET)));
  73. }
  74. $arr_params = $_GET;
  75. $this->order_no = $arr_params ['order_no'];
  76. if (sp_conf::$SP_NO != $arr_params ['sp_no']) {
  77. $this->err_msg = '百付宝的支付结果通知中商户ID无效,该通知无效';
  78. $this->log(
  79. 'the id in baifubao notify is wrong, this notify is invaild');
  80. return false;
  81. }
  82. if (sp_conf::BFB_PAY_RESULT_SUCCESS != $arr_params ['pay_result']) {
  83. $this->err_msg = '百付宝的支付结果通知中商户支付结果异常,该通知无效';
  84. $this->log(
  85. 'the pay result in baifubao notify is wrong, this notify is invaild');
  86. return false;
  87. }
  88. if (false === $this->check_sign($arr_params)) {
  89. $this->err_msg = '百付宝后台通知签名校验失败';
  90. $this->log('baifubao notify sign failed');
  91. return false;
  92. }
  93. $this->log('baifubao notify sign success');
  94. $order_no = $arr_params ['order_no'];
  95. $order_state = $this->query_order_state($order_no);
  96. $this->log(sprintf('order state in sp server is [%s]', $order_state));
  97. if (sp_conf::SP_PAY_RESULT_WAITING == $order_state) {
  98. $this->log('the order state is right, the order is waiting for pay');
  99. return true;
  100. } elseif (sp_conf::SP_PAY_RESULT_SUCCESS == $order_state) {
  101. $this->log('the order state is wrong, this order has been paid');
  102. $this->err_msg = '订单[%s]已经处理,此百付宝后台支付通知为重复通知';
  103. return false;
  104. } else {
  105. $this->log(
  106. sprintf('the order state is wrong, it is [%s]',
  107. $order_state));
  108. $this->err_msg = '订单[%s]状态异常';
  109. return false;
  110. }
  111. return false;
  112. }
  113. function notify_bfb() {
  114. $rep_str = "<html><head>" . sp_conf::BFB_NOTIFY_META .
  115. "</head><body><h1>这是一个return_url页面</h1></body></html>";
  116. echo "$rep_str";
  117. }
  118. private function query_order_state($order_no) {
  119. return sp_conf::SP_PAY_RESULT_WAITING;
  120. }
  121. function query_baifubao_pay_result_by_order_no($order_no) {
  122. $params = array (
  123. 'service_code' => sp_conf::BFB_QUERY_INTERFACE_SERVICE_ID, 'sp_no' => sp_conf::$SP_NO,
  124. 'order_no' => $order_no,
  125. 'output_type' => sp_conf::BFB_INTERFACE_OUTPUT_FORMAT, 'output_charset' => sp_conf::BFB_INTERFACE_ENCODING, 'version' => sp_conf::BFB_INTERFACE_VERSION,
  126. 'sign_method' => sp_conf::SIGN_METHOD_MD5
  127. );
  128. if (false === ($sign = $this->make_sign($params))) {
  129. $this->log(
  130. 'make sign for query baifubao pay result interface failed');
  131. return false;
  132. }
  133. $params ['sign'] = $sign;
  134. $params_str = http_build_query($params);
  135. $query_url = sp_conf::BFB_QUERY_ORDER_URL . '?' . $params_str;
  136. $this->log(
  137. sprintf('the url of query baifubao pay result is [%s]',
  138. $query_url));
  139. $content = $this->request($query_url);
  140. $retry = 0;
  141. while (empty($content) && $retry < sp_conf::BFB_QUERY_RETRY_TIME) {
  142. $content = $this->request($query_url);
  143. $retry++;
  144. }
  145. if (empty($content)) {
  146. $this->err_msg = '调用百付宝订单号查询接口失败';
  147. return false;
  148. }
  149. $this->log(
  150. sprintf('the result from baifubao query pay result is [%s]',
  151. $content));
  152. $response_arr = json_decode(json_encode(isimplexml_load_string($content)), true);
  153. foreach ($response_arr as &$value) {
  154. if (empty($value) && is_array($value)) {
  155. $value = '';
  156. }
  157. }
  158. unset($value);
  159. if (empty($response_arr) || !isset($response_arr ['query_status']) ||
  160. !isset($response_arr ['sp_no']) ||
  161. !isset($response_arr ['order_no']) ||
  162. !isset($response_arr ['bfb_order_no']) ||
  163. !isset($response_arr ['bfb_order_create_time']) ||
  164. !isset($response_arr ['pay_time']) ||
  165. !isset($response_arr ['pay_type']) ||
  166. !isset($response_arr ['goods_name']) ||
  167. !isset($response_arr ['total_amount']) ||
  168. !isset($response_arr ['fee_amount']) ||
  169. !isset($response_arr ['currency']) ||
  170. !isset($response_arr ['pay_result']) ||
  171. !isset($response_arr ['sign']) ||
  172. !isset($response_arr ['sign_method'])) {
  173. $this->err_msg = sprintf('百付宝的订单查询接口查询失败,返回数据为[%s]',
  174. print_r($response_arr, true));
  175. return false;
  176. }
  177. if (0 != $response_arr ['query_status']) {
  178. $this->log(
  179. sprintf(
  180. 'query the baifubao pay result interface faild, the query_status is [%s]',
  181. $response_arr ['query_status']));
  182. $this->err_msg = sprintf('百付宝的订单查询接口查询失败,查询状态为[%s]',
  183. $response_arr ['query_status']);
  184. return false;
  185. }
  186. if (sp_conf::$SP_NO != $response_arr ['sp_no']) {
  187. $this->log(
  188. 'the sp_no returned from baifubao pay result interface is invaild');
  189. $this->err_msg = '百付宝的订单查询接口的响应数据中商户ID无效,该通知无效';
  190. return false;
  191. }
  192. if (sp_conf::BFB_PAY_RESULT_SUCCESS != $response_arr ['pay_result']) {
  193. $this->log(
  194. sprintf(
  195. 'the pay result returned from baifubao pay result interface is invalid, is [%s]',
  196. $response_arr ['pay_result']));
  197. $this->err_msg = '百付宝的订单查询接口的响应数据中商户支付结果异常,该通知无效';
  198. return false;
  199. }
  200. $response_arr ['goods_name'] = iconv("UTF-8", "GBK",
  201. $response_arr ['goods_name']);
  202. if (isset($response_arr ['buyer_sp_username'])) {
  203. $response_arr ['buyer_sp_username'] = iconv("UTF-8", "GBK",
  204. $response_arr ['buyer_sp_username']);
  205. }
  206. if (false === $this->check_sign($response_arr)) {
  207. $this->log(
  208. 'sign the result returned from baifubao pay result interface failed');
  209. $this->err_msg = '百付宝订单查询接口响应数据签名校验失败';
  210. return false;
  211. }
  212. return print_r($response_arr, true);
  213. }
  214. private function make_sign($params) {
  215. if (is_array($params)) {
  216. if (ksort($params)) {
  217. if(false === ($params ['key'] = $this->get_sp_key())){
  218. return false;
  219. }
  220. $arr_temp = array ();
  221. foreach ($params as $key => $val) {
  222. $arr_temp [] = $key . '=' . $val;
  223. }
  224. $sign_str = implode('&', $arr_temp);
  225. if ($params ['sign_method'] == sp_conf::SIGN_METHOD_MD5) {
  226. return md5($sign_str);
  227. } else if ($params ['sign_method'] == sp_conf::SIGN_METHOD_SHA1) {
  228. return sha1($sign_str);
  229. } else{
  230. $this->log('unsupported sign method');
  231. $this->err_msg = '签名方法不支持';
  232. return false;
  233. }
  234. } else {
  235. $this->log('ksort failed');
  236. $this->err_msg = '表单参数数组排序失败';
  237. return false;
  238. }
  239. } else {
  240. $this->log('the params of making sign should be a array');
  241. $this->err_msg = '生成签名的参数必须是一个数组';
  242. return false;
  243. }
  244. }
  245. private function check_sign($params) {
  246. $sign = $params ['sign'];
  247. unset($params ['sign']);
  248. foreach ($params as &$value) {
  249. $value = urldecode($value); }
  250. unset($value);
  251. if (false !== ($my_sign = $this->make_sign($params))) {
  252. if (0 !== strcmp($my_sign, $sign)) {
  253. return false;
  254. }
  255. return true;
  256. } else {
  257. return false;
  258. }
  259. }
  260. private function get_sp_key() {
  261. return sp_conf::$SP_KEY_FILE;
  262. }
  263. function request($url) {
  264. $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url);
  265. curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 3); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  266. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  267. $res = curl_exec($curl); $err = curl_error($curl);
  268. if (false === $res || !empty($err)) {
  269. $info = curl_getinfo($curl);
  270. curl_close($curl);
  271. $this->log(
  272. sprintf(
  273. 'curl the baifubao pay result interface failed, err_msg [%s]',
  274. $info));
  275. $this->err_msg = $info;
  276. return false;
  277. }
  278. curl_close($curl); return $res;
  279. }
  280. function log($msg) {
  281. if(defined(sp_conf::$LOG_FILE)) {
  282. error_log(
  283. sprintf("[%s] [order_no: %s] : %s\n", date("Y-m-d H:i:s"),
  284. $this->order_no, $msg));
  285. }
  286. else {
  287. error_log(
  288. sprintf("[%s] [order_no: %s] : %s\n", date("Y-m-d H:i:s"),
  289. $this->order_no, $msg), 3, sp_conf::$LOG_FILE);
  290. }
  291. }
  292. }
  293. ?>