log(sprintf('invalid params, params:[%s]', print_r($params, true)));
return false;
}
if (!in_array($url,
array (
sp_conf::BFB_PAY_DIRECT_LOGIN_URL,
sp_conf::BFB_PAY_DIRECT_NO_LOGIN_URL,
sp_conf::BFB_PAY_WAP_DIRECT_URL
))) {
$this->log(
sprintf('invalid url[%s], bfb just provide three kind of pay url',
$url));
return false;
}
$pay_url = $url;
if (false === ($sign = $this->make_sign($params))) {
return false;
}
$this->order_no = $params ['order_no'];
$params ['sign'] = $sign;
$params_str = http_build_query($params);
$this->log(
sprintf('the params that create baifubao pay order is [%s]',
$params_str));
return $pay_url . '?' . $params_str;
}
function check_bfb_pay_result_notify() {
if (empty($_GET) || !isset($_GET ['sp_no']) || !isset(
$_GET ['order_no']) || !isset($_GET ['bfb_order_no']) ||
!isset($_GET ['bfb_order_create_time']) ||
!isset($_GET ['pay_time']) || !isset($_GET ['pay_type']) ||
!isset($_GET ['total_amount']) || !isset($_GET ['fee_amount']) ||
!isset($_GET ['currency']) || !isset($_GET ['pay_result']) ||
!isset($_GET ['input_charset']) || !isset($_GET ['version']) ||
!isset($_GET ['sign']) || !isset($_GET ['sign_method'])) {
$this->err_msg = 'return_url页面的请求的必选参数不足';
$this->log(
sprintf('missing the params of return_url page, params[%s]',
print_r($_GET)));
}
$arr_params = $_GET;
$this->order_no = $arr_params ['order_no'];
if (sp_conf::$SP_NO != $arr_params ['sp_no']) {
$this->err_msg = '百付宝的支付结果通知中商户ID无效,该通知无效';
$this->log(
'the id in baifubao notify is wrong, this notify is invaild');
return false;
}
if (sp_conf::BFB_PAY_RESULT_SUCCESS != $arr_params ['pay_result']) {
$this->err_msg = '百付宝的支付结果通知中商户支付结果异常,该通知无效';
$this->log(
'the pay result in baifubao notify is wrong, this notify is invaild');
return false;
}
if (false === $this->check_sign($arr_params)) {
$this->err_msg = '百付宝后台通知签名校验失败';
$this->log('baifubao notify sign failed');
return false;
}
$this->log('baifubao notify sign success');
$order_no = $arr_params ['order_no'];
$order_state = $this->query_order_state($order_no);
$this->log(sprintf('order state in sp server is [%s]', $order_state));
if (sp_conf::SP_PAY_RESULT_WAITING == $order_state) {
$this->log('the order state is right, the order is waiting for pay');
return true;
} elseif (sp_conf::SP_PAY_RESULT_SUCCESS == $order_state) {
$this->log('the order state is wrong, this order has been paid');
$this->err_msg = '订单[%s]已经处理,此百付宝后台支付通知为重复通知';
return false;
} else {
$this->log(
sprintf('the order state is wrong, it is [%s]',
$order_state));
$this->err_msg = '订单[%s]状态异常';
return false;
}
return false;
}
function notify_bfb() {
$rep_str = "
" . sp_conf::BFB_NOTIFY_META .
"这是一个return_url页面
";
echo "$rep_str";
}
private function query_order_state($order_no) {
return sp_conf::SP_PAY_RESULT_WAITING;
}
function query_baifubao_pay_result_by_order_no($order_no) {
$params = array (
'service_code' => sp_conf::BFB_QUERY_INTERFACE_SERVICE_ID, 'sp_no' => sp_conf::$SP_NO,
'order_no' => $order_no,
'output_type' => sp_conf::BFB_INTERFACE_OUTPUT_FORMAT, 'output_charset' => sp_conf::BFB_INTERFACE_ENCODING, 'version' => sp_conf::BFB_INTERFACE_VERSION,
'sign_method' => sp_conf::SIGN_METHOD_MD5
);
if (false === ($sign = $this->make_sign($params))) {
$this->log(
'make sign for query baifubao pay result interface failed');
return false;
}
$params ['sign'] = $sign;
$params_str = http_build_query($params);
$query_url = sp_conf::BFB_QUERY_ORDER_URL . '?' . $params_str;
$this->log(
sprintf('the url of query baifubao pay result is [%s]',
$query_url));
$content = $this->request($query_url);
$retry = 0;
while (empty($content) && $retry < sp_conf::BFB_QUERY_RETRY_TIME) {
$content = $this->request($query_url);
$retry++;
}
if (empty($content)) {
$this->err_msg = '调用百付宝订单号查询接口失败';
return false;
}
$this->log(
sprintf('the result from baifubao query pay result is [%s]',
$content));
$response_arr = json_decode(json_encode(isimplexml_load_string($content)), true);
foreach ($response_arr as &$value) {
if (empty($value) && is_array($value)) {
$value = '';
}
}
unset($value);
if (empty($response_arr) || !isset($response_arr ['query_status']) ||
!isset($response_arr ['sp_no']) ||
!isset($response_arr ['order_no']) ||
!isset($response_arr ['bfb_order_no']) ||
!isset($response_arr ['bfb_order_create_time']) ||
!isset($response_arr ['pay_time']) ||
!isset($response_arr ['pay_type']) ||
!isset($response_arr ['goods_name']) ||
!isset($response_arr ['total_amount']) ||
!isset($response_arr ['fee_amount']) ||
!isset($response_arr ['currency']) ||
!isset($response_arr ['pay_result']) ||
!isset($response_arr ['sign']) ||
!isset($response_arr ['sign_method'])) {
$this->err_msg = sprintf('百付宝的订单查询接口查询失败,返回数据为[%s]',
print_r($response_arr, true));
return false;
}
if (0 != $response_arr ['query_status']) {
$this->log(
sprintf(
'query the baifubao pay result interface faild, the query_status is [%s]',
$response_arr ['query_status']));
$this->err_msg = sprintf('百付宝的订单查询接口查询失败,查询状态为[%s]',
$response_arr ['query_status']);
return false;
}
if (sp_conf::$SP_NO != $response_arr ['sp_no']) {
$this->log(
'the sp_no returned from baifubao pay result interface is invaild');
$this->err_msg = '百付宝的订单查询接口的响应数据中商户ID无效,该通知无效';
return false;
}
if (sp_conf::BFB_PAY_RESULT_SUCCESS != $response_arr ['pay_result']) {
$this->log(
sprintf(
'the pay result returned from baifubao pay result interface is invalid, is [%s]',
$response_arr ['pay_result']));
$this->err_msg = '百付宝的订单查询接口的响应数据中商户支付结果异常,该通知无效';
return false;
}
$response_arr ['goods_name'] = iconv("UTF-8", "GBK",
$response_arr ['goods_name']);
if (isset($response_arr ['buyer_sp_username'])) {
$response_arr ['buyer_sp_username'] = iconv("UTF-8", "GBK",
$response_arr ['buyer_sp_username']);
}
if (false === $this->check_sign($response_arr)) {
$this->log(
'sign the result returned from baifubao pay result interface failed');
$this->err_msg = '百付宝订单查询接口响应数据签名校验失败';
return false;
}
return print_r($response_arr, true);
}
private function make_sign($params) {
if (is_array($params)) {
if (ksort($params)) {
if(false === ($params ['key'] = $this->get_sp_key())){
return false;
}
$arr_temp = array ();
foreach ($params as $key => $val) {
$arr_temp [] = $key . '=' . $val;
}
$sign_str = implode('&', $arr_temp);
if ($params ['sign_method'] == sp_conf::SIGN_METHOD_MD5) {
return md5($sign_str);
} else if ($params ['sign_method'] == sp_conf::SIGN_METHOD_SHA1) {
return sha1($sign_str);
} else{
$this->log('unsupported sign method');
$this->err_msg = '签名方法不支持';
return false;
}
} else {
$this->log('ksort failed');
$this->err_msg = '表单参数数组排序失败';
return false;
}
} else {
$this->log('the params of making sign should be a array');
$this->err_msg = '生成签名的参数必须是一个数组';
return false;
}
}
private function check_sign($params) {
$sign = $params ['sign'];
unset($params ['sign']);
foreach ($params as &$value) {
$value = urldecode($value); }
unset($value);
if (false !== ($my_sign = $this->make_sign($params))) {
if (0 !== strcmp($my_sign, $sign)) {
return false;
}
return true;
} else {
return false;
}
}
private function get_sp_key() {
return sp_conf::$SP_KEY_FILE;
}
function request($url) {
$curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url);
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);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
$res = curl_exec($curl); $err = curl_error($curl);
if (false === $res || !empty($err)) {
$info = curl_getinfo($curl);
curl_close($curl);
$this->log(
sprintf(
'curl the baifubao pay result interface failed, err_msg [%s]',
$info));
$this->err_msg = $info;
return false;
}
curl_close($curl); return $res;
}
function log($msg) {
if(defined(sp_conf::$LOG_FILE)) {
error_log(
sprintf("[%s] [order_no: %s] : %s\n", date("Y-m-d H:i:s"),
$this->order_no, $msg));
}
else {
error_log(
sprintf("[%s] [order_no: %s] : %s\n", date("Y-m-d H:i:s"),
$this->order_no, $msg), 3, sp_conf::$LOG_FILE);
}
}
}
?>