getLocaleUrl(true); } /** * 获取门店付款方式列表 * @route({"POST","/querylist"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"market_key","$._POST.market_key"}) 门店key * @param({"paytype","$._POST.paytype"}) 支付类型 * @param({"level","$._POST.level"}) 类型(1: 线上支付; 2: 线下扫码支付; 3: 移动app支付) * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return string|returnObject|mixed */ public function getPayList($appid = '', $devkey = '', $market_key = '', $paytype = 0, $level = 0, $version = null, $sign = null) { /// 验证公共参数是否合法 $this->init($appid, $devkey); $verify_result = $this->verify_admin($market_key); if (is_error_api($verify_result)) { if ($verify_result instanceof returnObject) { return $verify_result; } else { $return = new returnObject(); $return->from_array((array)$verify_result); return $verify_result; } } switch ($version) { case 1: { if (empty($market_key)) { $condition = 'is_enabled = 1'; if (!empty($level)) $condition .= sprintf(' and type_level = %d', intval($level)); if (!empty($paytype)) $condition .= sprintf(' and type_id = %d', intval($paytype)); $data = Sql::Select('type_id, type_key, type_name, image, url, is_third, third_flag, type_level') ->from('syweb_paytype_base') ->where($condition) ->get($this->db); return new returnObject(0, 0, '', $data); } else { $condition = 'a.type_key = b.type_key and a.is_enabled = 1 and b.is_enabled = 1 and b.market_key = ?'; if (!empty($level)) $condition .= sprintf(' and a.type_level = %d', intval($level)); if (!empty($paytype)) $condition .= sprintf(' and a.type_id = %d', intval($paytype)); $data = Sql::Select('a.type_id, a.type_key, a.type_name, a.image, a.url, a.is_third, a.third_flag, a.type_level') ->from('syweb_paytype_base a, syweb_paytype_market b') ->where($condition, $market_key) ->get($this->db); return new returnObject(0, 0, '', $data); } break; } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * 聚合支付-线上 * @route({"POST","/pay/online"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"sid","$._POST.sid"}) sid * @param({"scode","$._POST.scode"}) scode * @param({"orderid","$._POST.orderid"}) 订单编号 * @param({"fee","$._POST.fee"}) 支付总价 * @param({"title","$._POST.title"}) 支付主题 * * @param({"notice_url","$._POST.notice_url"}) 回调地址(异步) * @param({"return_url","$._POST.return_url"}) 回调地址(同步) * * @param({"paytype","$._POST.paytype"}) 支付类型(1: 微信支付; 2: 支付宝支付; 3: 威富通聚合支付(微信); 4: 威富通聚合支付(支付宝)) * * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return returnObject */ public function pay_online($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $paytype, $version = null, $sign = null) { switch ($version) { case 1: { /// 支付前校验 $attach = $this->verify_pay_online_v1($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $sign); if ($attach instanceof returnObject) return $attach; switch ($paytype) { case PAYCODE_ONLINE_WECHAT: /// 微信支付 return $this->_pay_online_wechat_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); case PAYCODE_ONLINE_ALIPAY: /// 支付宝支付 return $this->_pay_online_ali_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); case PAYCODE_ONLINE_SWIFTPASS_WECHAT: /// 威富通聚合支付-微信 return $this->_pay_online_swiftpass_wechat_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); case PAYCODE_ONLINE_SWIFTPASS_ALIPAY: /// 威富通聚合支付-支付 return $this->_pay_online_swiftpass_ali_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); case PAYCODE_ONLINE_HEEPAY_WECHAT: /// 汇付宝微信支付(线上网页支付) return $this->_pay_online_heepay_wechat_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); case PAYCODE_ONLINE_HEEPAY_ALIPAY: /// 汇付宝支付宝支付(线上网页支付) return $this->_pay_online_heepay_ali_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); case PAYCODE_ONLINE_WECHATWITHBROWSER: /// /// 微信支付(线上网页支付)(非微信环境) return $this->_pay_online_wechat_with_browser_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); case PAYCODE_ONLINE_HEEPAY_WECHATWITHBROWSER: /// 汇付宝微信支付(线上网页支付)(非微信环境) return $this->_pay_online_heepay_wechat_with_browser_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); default: echo sprintf('未知的支付类型: %d' . PHP_EOL . '支付类型(%d: 微信支付; %d: 支付宝支付; %d: 威富通聚合支付(微信); %d: 威富通聚合支付(支付宝))', $paytype, PAYCODE_ONLINE_WECHAT, PAYCODE_ONLINE_ALIPAY, PAYCODE_ONLINE_SWIFTPASS_WECHAT, PAYCODE_ONLINE_SWIFTPASS_ALIPAY); return -1; } break; } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * 微信支付 * @route({"POST","/pay/online/wechat"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"sid","$._POST.sid"}) sid * @param({"scode","$._POST.scode"}) scode * @param({"orderid","$._POST.orderid"}) 订单编号 * @param({"fee","$._POST.fee"}) 支付总价 * @param({"title","$._POST.title"}) 支付主题 * * @param({"notice_url","$._POST.notice_url"}) 回调地址(异步) * @param({"return_url","$._POST.return_url"}) 回调地址(同步) * * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return returnObject */ public function pay_online_wechat($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $version = null, $sign = null) { switch ($version) { case 1: { $attach = $this->verify_pay_online_v1($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $sign); if ($attach instanceof returnObject) return $attach; return $this->_pay_online_wechat_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * 支付宝支付 * @route({"POST","/pay/online/ali"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"sid","$._POST.sid"}) sid * @param({"scode","$._POST.scode"}) scode * @param({"orderid","$._POST.orderid"}) 订单编号 * @param({"fee","$._POST.fee"}) 支付总价 * @param({"title","$._POST.title"}) 支付主题 * * @param({"notice_url","$._POST.notice_url"}) 回调地址(异步) * @param({"return_url","$._POST.return_url"}) 回调地址(同步) * * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return returnObject */ public function pay_online_ali($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $version = null, $sign = null) { switch ($version) { case 1: { $attach = $this->verify_pay_online_v1($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $sign); if ($attach instanceof returnObject) return $attach; return $this->_pay_online_ali_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * 威富通聚合支付--微信 * @route({"POST","/pay/online/swiftpasswechat"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"sid","$._POST.sid"}) sid * @param({"scode","$._POST.scode"}) scode * @param({"orderid","$._POST.orderid"}) 订单编号 * @param({"fee","$._POST.fee"}) 支付总价 * @param({"title","$._POST.title"}) 支付主题 * * @param({"notice_url","$._POST.notice_url"}) 回调地址(异步) * @param({"return_url","$._POST.return_url"}) 回调地址(同步) * * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return returnObject */ public function pay_online_swiftpass_wechat($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $version = null, $sign = null) { switch ($version) { case 1: { $attach = $this->verify_pay_online_v1($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $sign); if ($attach instanceof returnObject) return $attach; return $this->_pay_online_swiftpass_wechat_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * 威富通聚合支付--支付宝 * @route({"POST","/pay/online/swiftpassali"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"sid","$._POST.sid"}) sid * @param({"scode","$._POST.scode"}) scode * @param({"orderid","$._POST.orderid"}) 订单编号 * @param({"fee","$._POST.fee"}) 支付总价 * @param({"title","$._POST.title"}) 支付主题 * * @param({"notice_url","$._POST.notice_url"}) 回调地址(异步) * @param({"return_url","$._POST.return_url"}) 回调地址(同步) * * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return returnObject */ public function pay_online_swiftpass_ali($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $version = null, $sign = null) { switch ($version) { case 1: { $attach = $this->verify_pay_online_v1($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $sign); if ($attach instanceof returnObject) return $attach; return $this->_pay_online_swiftpass_ali_v1($orderid, $fee, $title, $notice_url, $return_url, $attach); } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * 聚合支付-线下 * @route({"POST","/pay/offline"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"market_key","$._POST.market_key"}) 门店key * @param({"orderid","$._POST.orderid"}) 订单编号 * @param({"fee","$._POST.fee"}) 支付总价 * @param({"title","$._POST.title"}) 支付主题 * * @param({"notice_url","$._POST.notice_url"}) 回调地址(异步) * @param({"paytype","$._POST.paytype"}) 支付类型(1: 微信支付; 2: 支付宝支付; 3: 威富通聚合支付(微信); 4: 威富通聚合支付(支付宝)) * * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return returnObject */ public function pay_offline($appid, $devkey, $market_key, $orderid, $fee, $title, $notice_url, $paytype, $version = null, $sign = null) { switch ($version) { case 1: { /// 支付前校验 $attach = $this->verify_pay_offline_v1($appid, $devkey, $market_key, $orderid, $fee, $title, $notice_url, $sign); if ($attach instanceof returnObject) { return $attach; } switch ($paytype) { case PAYCODE_OFFLINE_WECHAT: /// 微信支付 return $this->_pay_offline_wechat_v1($orderid, $fee, $title, $notice_url, $attach); case PAYCODE_OFFLINE_ALIPAY: /// 支付宝支付 return $this->_pay_offline_ali_v1($orderid, $fee, $title, $notice_url, $attach); case PAYCODE_OFFLINE_SWIFTPASS_WECHAT: /// 威富通聚合支付-微信 return $this->_pay_offline_swiftpass_wechat_v1($orderid, $fee, $title, $notice_url, $attach); case PAYCODE_OFFLINE_SWIFTPASS_ALIPAY: /// 威富通聚合支付-支付宝 return $this->_pay_offline_swiftpass_ali_v1($orderid, $fee, $title, $notice_url, $attach); case PAYCODE_OFFLINE_HEEPAY_WECHAT: /// 汇付宝微信支付(线下扫码支付) return $this->_pay_offline_heepay_wechat_v1($orderid, $fee, $title, $notice_url, $attach); case PAYCODE_OFFLINE_HEEPAY_ALIPAY: /// 汇付宝支付宝支付(线下扫码支付) return $this->_pay_offline_heepay_ali_v1($orderid, $fee, $title, $notice_url, $attach); default: echo sprintf('未知的支付类型: %d' . PHP_EOL . '支付类型(%d: 微信支付; %d: 支付宝支付; %d: 威富通聚合支付(微信); %d: 威富通聚合支付(支付宝)); %d: 汇付宝聚合支付(微信); %d: 汇付宝聚合支付(支付宝));', $paytype, PAYCODE_OFFLINE_WECHAT, PAYCODE_OFFLINE_ALIPAY, PAYCODE_OFFLINE_SWIFTPASS_WECHAT, PAYCODE_OFFLINE_SWIFTPASS_ALIPAY, PAYCODE_OFFLINE_HEEPAY_WECHAT, PAYCODE_OFFLINE_HEEPAY_ALIPAY); return -1; } } default: { return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } } /** * 聚合支付-移动端 * @route({"POST","/pay/mobile"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"sid","$._POST.sid"}) sid * @param({"scode","$._POST.scode"}) scode * @param({"market_key","$._POST.market_key"}) 门店key * @param({"from_user","$._POST.from_user"}) 要支付的用户标志(openid或userid) * @param({"orderid","$._POST.orderid"}) 订单编号 * @param({"fee","$._POST.fee"}) 支付总价 * @param({"title","$._POST.title"}) 支付主题 * * @param({"notice_url","$._POST.notice_url"}) 回调地址(异步) * @param({"paytype","$._POST.paytype"}) 支付类型(1: 微信支付; 2: 支付宝支付; 3: 威富通聚合支付(微信); 4: 威富通聚合支付(支付宝)) * * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return returnObject */ public function pay_mobile($appid, $devkey, $sid, $scode, $market_key, $from_user, $orderid, $fee, $title, $notice_url, $paytype, $version, $sign) { switch ($version) { case 1: { /// 支付前校验 $attach = $this->verify_pay_mobile_v1($appid, $devkey, $market_key, $from_user, $orderid, $fee, $title, $notice_url, $sign); if ($attach instanceof returnObject) return $attach; switch ($paytype) { case PAYCODE_MOBILE_WECHAT: /// 微信支付 return $this->_pay_mobile_wechat_v1($orderid, $fee, $title, $notice_url, $attach); case PAYCODE_MOBILE_ALIPAY: /// 支付宝支付 return $this->_pay_mobile_ali_v1($orderid, $fee, $title, $notice_url, $attach); case PAYCODE_MOBILE_SWIFTPASS_WECHAT: /// 威富通聚合支付-微信 return $this->_pay_mobile_swiftpass_wechat_v1($orderid, $fee, $title, $notice_url, $attach); case PAYCODE_MOBILE_SWIFTPASS_ALIPAY: /// 威富通聚合支付-支付宝 return $this->_pay_mobile_swiftpass_ali_v1($orderid, $fee, $title, $notice_url, $attach); default: echo sprintf('未知的支付类型: %d' . PHP_EOL . '支付类型(%d: 微信支付; %d: 支付宝支付; %d: 威富通聚合支付(微信); %d: 威富通聚合支付(支付宝))', $paytype, PAYCODE_MOBILE_WECHAT, PAYCODE_MOBILE_ALIPAY, PAYCODE_MOBILE_SWIFTPASS_WECHAT, PAYCODE_MOBILE_SWIFTPASS_ALIPAY); return -1; } } default: { return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } } /** * 退款(错误码:13000-13050) * @route({"POST","/refund"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"sid","$._POST.sid"}) sid * @param({"scode","$._POST.scode"}) scode * @param({"transaction_id","$._POST.transaction_id"}) 微信订单号 * @param({"out_trade_no","$._POST.out_trade_no"}) 商户单号 * @param({"refund_fee","$._POST.refund_fee"}) 退款金额(单位分) * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return returnObject */ public function refund($appid, $devkey, $sid, $scode, $transaction_id, $out_trade_no, $refund_fee, $version, $sign) { switch ($version) { case 1: { /// 腿款前校验 $attach = $this->verify_refund_v1($appid, $devkey, $sid, $scode, $transaction_id, $out_trade_no, $refund_fee, $sign); if ($attach instanceof returnObject) return $attach; if (!empty($out_trade_no) && !empty($transaction_id)) { $pay_log = Sql::Select('*') ->from('syweb_core_paylog a') ->where('out_trade_no = ? and transaction_id = ? and app_key = ? and market_key = ?', $out_trade_no, $transaction_id, $this->appid, $this->market_key) ->get($this->db, null); } elseif (!empty($out_trade_no)) { $pay_log = Sql::Select('*') ->from('syweb_core_paylog a') ->where('out_trade_no = ? and app_key = ? and market_key = ?', $out_trade_no, $this->appid, $this->market_key) ->get($this->db, null); } elseif (!empty($transaction_id)) { $pay_log = Sql::Select('*') ->from('syweb_core_paylog a') ->where('transaction_id = ? and app_key = ? and market_key = ?', $transaction_id, $this->appid, $this->market_key) ->get($this->db, null); } else $pay_log = null; if (!empty($pay_log) && count($pay_log) > 0) { $pay_log = $pay_log[0]; switch ($pay_log['status']) { case PAYSTATUS_NORMAL: return new returnObject(500, 1, '该订单尚未付款, 申请退款失败!'); case PAYSTATUS_REFUND: case PAYSTATUS_PAY: $total_fee = intval($pay_log['pay_fee']) - intval($pay_log['refund_fee']); if ($refund_fee > $total_fee) return new returnObject(500, 2, '超过订单最大可退金额!'); break; default: return new returnObject(500, 3, sprintf('未知的订单状态 %d, 申请退款失败!', $pay_log['status'])); } } else return new returnObject(500, 4, '找不到对应的支付记录,请核实后再试!'); switch ($pay_log['type']) { case PAYTYPE_ONLINE_WECHAT: /// 微信在线支付 return $this->_refund_online_wechat_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_ONLINE_ALIPAY: /// 支付宝在线支付 return $this->_refund_online_ali_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_ONLINE_SWIFTPASS_WECHAT: /// 威富通微信在线支付 return $this->_refund_online_swiftpass_wechat_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_ONLINE_SWIFTPASS_ALIPAY: /// 威富通支付宝在线支付 return $this->_refund_online_swiftpass_ali_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_ONLINE_HEEPAY_WECHAT: /// 汇付宝微信支付(线上网页支付) return $this->_refund_online_heepay_wechat_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_ONLINE_HEEPAY_ALIPAY: /// 汇付宝支付宝支付(线上网页支付) return $this->_refund_online_heepay_ali_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_ONLINE_WECHATWITHBROWSER: /// 微信支付(线上网页支付)(非微信环境) return $this->_refund_online_wechat_with_browser_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_ONLINE_HEEPAY_WECHATWITHBROWSER: /// 汇付宝微信支付(线上网页支付)(非微信环境) return $this->_refund_online_heepay_wechat_with_browser_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_OFFLINE_WECHAT: /// 微信扫码支付 return $this->_refund_offline_wechat_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_OFFLINE_ALIPAY: /// 支付宝扫码支付 return $this->_refund_offline_ali_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_OFFLINE_SWIFTPASS_WECHAT: /// 威富通微信扫码支付 return $this->_refund_offline_swiftpass_wechat_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_OFFLINE_SWIFTPASS_ALIPAY: /// 威富通支付宝扫码支付 return $this->_refund_offline_swiftpass_ali_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_OFFLINE_HEEPAY_WECHAT: /// 汇付宝微信支付(线下扫码支付) return $this->_refund_offline_heepay_wechat_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_OFFLINE_HEEPAY_ALIPAY: /// 汇付宝支付宝支付(线下扫码支付) return $this->_refund_offline_heepay_ali_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_MOBILE_WECHAT: /// 微信支付(移动平台支付) return $this->_refund_mobile_wechat_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_MOBILE_ALIPAY: /// 支付宝支付(移动平台支付) return $this->_refund_mobile_ali_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_MOBILE_SWIFTPASS_WECHAT: /// 威富通微信支付(移动平台支付) return $this->_refund_mobile_swiftpass_wechat_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); case PAYTYPE_MOBILE_SWIFTPASS_ALIPAY: /// 威富通支付宝支付(移动平台支付) return $this->_refund_mobile_swiftpass_ali_v1($pay_log['transaction_id'], $pay_log['out_trade_no'], $pay_log['order_id'], $pay_log['pay_fee'], $refund_fee, $attach); default: return new returnObject(500, -1, '不正确的支付信息, 请联系管理员!!'); } } default: { return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } } /** * 检测支付是否成功(错误代码:12000-12050) * @route({"POST","/querystatus"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"sid","$._POST.sid"}) sid * @param({"scode","$._POST.scode"}) scode * @param({"transaction_id","$._POST.transaction_id"}) 微信订单号 * @param({"out_trade_no","$._POST.out_trade_no"}) 商户单号 * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return string|returnObject|mixed */ public function query_pay_status($appid, $devkey, $sid, $scode, $transaction_id, $out_trade_no, $version, $sign) { switch ($version) { case 1: { /// 验证公共参数是否合法 parent::init($appid, $devkey, $sid, $scode); $verify_result = parent::verify(); if (is_error_api($verify_result)) return json_encode($verify_result, JSON_UNESCAPED_UNICODE); if (empty($orderid)) return new returnObject(1, 12001, '请指定订单编号'); /// 根据order_id查询指定支付纪录的状态 if (!empty($out_trade_no) && !empty($transaction_id)) { $payLog = Sql::Select('*') ->from('syweb_core_paylog a') ->where('out_trade_no = ? and transaction_id = ? and app_key = ? and market_key = ?', $out_trade_no, $transaction_id, $this->appInfo['id'], $this->market_key) ->get($this->db, null); } elseif (!empty($out_trade_no)) { $payLog = Sql::Select('*') ->from('syweb_core_paylog a') ->where('out_trade_no = ? and app_key = ? and market_key = ?', $out_trade_no, $this->appInfo['id'], $this->market_key) ->get($this->db, null); } elseif (!empty($transaction_id)) { $payLog = Sql::Select('*') ->from('syweb_core_paylog a') ->where('transaction_id = ? and app_key = ? and market_key = ?', $transaction_id, $this->appInfo['id'], $this->market_key) ->get($this->db, null); } else { $payLog = null; } if (!empty($payLog) && count($payLog) > 0) $payLog['tag'] = json_decode($payLog['tag']); return new returnObject(0, 0, '', $payLog); } default: { return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } } /** * @note 通知微信订单状态. * @param string $app_id appid * @param string $market_key 门店id * @param string $out_trade_no 订单号 * @param string $transaction_id 微信订单号 * @param string $from_user 来源用户(用户openid) * @param int $pay_fee 支付金额 * @param int $refund_fee 退款金额(单位分) * @param string $sign_key 签名key * @param int $status 通知订单状态(0: 正常; 1: 已付款; -1: 已退款) * @return bool */ private function _notify_wechat_order_status_v1($app_id, $market_key, $out_trade_no, $transaction_id, $from_user, $pay_fee, $refund_fee, $status, $sign_key) { switch ($status) { case PAYSTATUS_NORMAL: /// 普通状态 break; case PAYSTATUS_PAY: /// 已支付 { $log = Sql::select('syweb_core_paylog.*') ->from('syweb_core_paylog') ->where('`app_key` = ? and `market_key` = ? and `out_trade_no` = ?', $app_id, $market_key, $out_trade_no) ->get($this->db, null); if (!empty($log) && count($log) > 0) { $log = $log[0]; } if (!empty($log) && !empty($log['plid']) && is_numeric($log['status']) && $log['status'] != '0') { ///exit('订单已经付款'); return true; } $log['tag'] = json_decode($log['tag']); $log['tag']->transaction_id = $transaction_id; $log['tag']->total_fee = $pay_fee; /// 提前设置为已经支付成功状态 $recordTemp = array( 'status' => PAYSTATUS_PAY, 'transaction_id' => $transaction_id, ///'openid' => $open_id, 'tag' => json_encode($log['tag'], JSON_UNESCAPED_UNICODE), ); try { $db = $this->db; $db->beginTransaction(); Sql::update('syweb_core_paylog')->setArgs($recordTemp)->where('plid = ?', $log['plid'])->exec($db); $db->commit(); } catch (PDOException $e) { var_dump($e); } $notice_url = $log['tag']->notice_url; /// 回调地址 //$param_mask = $log['tag']->param_mask; /// 回调参数格式 /// 验证客户端逻辑处理 if (!empty($notice_url)) { // if (!empty($param_mask)) // { // $callback_data = str_replace("%orderNo%", $log['order_id'], $param_mask); // $callback_data = str_replace("%money%", $log["fee"], $callback_data); // // $callback_data = str_replace("%outtradeNo%", $log['out_trade_no'], $callback_data); // $callback_data = str_replace("%transactionid%", $log['tag']->transaction_id, $callback_data); // $callback_data = str_replace("%signkey%", $sign_key, $callback_data); // // $callback_response = ihttp_request($notice_url . "?" . $callback_data, "", false); // $callback_response = mb_convert_encoding($callback_response, "UTF-8"); // // $begin_position = strstr($callback_response, "\r\n"); // if ($begin_position >= 0) // { // $callback_response = substr($callback_response, $begin_position + 17); // } // else // { // $callback_response = ""; // } // // if (!empty($callback_response) && !is_null(json_decode($callback_response))) // { // $callback_result = @json_decode($callback_response, true); // if ($callback_result['error'] != '0') // { // /// 假如客户端返回非0,则表示逻辑处理失败,则将再次发起 // //$msg = "订单处理出错。"; // return false; // } // } // else // { // /// 假如客户端返回非0,则表示支付失败 // //$msg = "订单处理出错。"; // return false; // } // } // else { /// 获取附带的参数 $attach = $log['tag']->attach; if (is_string($attach)) $attach = json_decode($attach); $callback_data = (array)$attach; $callback_data['order_no'] = $log['order_id']; /// 订单号 $callback_data['out_trade_no'] = $log['out_trade_no']; /// 商家订单号 $callback_data['transaction_id'] = $transaction_id; /// 微信订单号 $callback_data['total_fee'] = $log['tag']->total_fee; /// 支付金额(单位分) $callback_data['version'] = 1; /// 版本号 $callback_data['sign'] = SignParameter($callback_data, $sign_key); /// 生成签名 //$callback_data = json_encode($callback_data, JSON_UNESCAPED_UNICODE); //$callback_response = ihttp_request($notice_url, $callback_data, false); try { /// 发送post请求 $callback_response = @SendPost($notice_url, $callback_data); /// 返回success表示成功, 否则表示失败. return strcasecmp(NOTIFYSTATUS_SUCCESS, $callback_response) == 0; } catch (Exception $e) { return false; } } } } break; case PAYSTATUS_REFUND: /// 已退款 { try { $db = $this->db; if (!empty($transaction_id)) { $pay_log = Sql::Select('*') ->from('syweb_core_paylog') ->where('`app_key` = ? and `market_key` = ? and `transaction_id` = ?', $app_id, $market_key, $transaction_id) ->get($db); $refund_fee += intval((empty($pay_log) || count($pay_log) == 0) ? 0 : $pay_log[0]['refund_fee']); $recordTemp = array( 'status' => PAYSTATUS_REFUND, 'refund_fee' => $refund_fee, ); $db->beginTransaction(); Sql::update('syweb_core_paylog') ->setArgs($recordTemp) ->where('`app_key` = ? and `market_key` = ? and `transaction_id` = ?', $app_id, $market_key, $transaction_id) ->exec($db); $db->commit(); } elseif (!empty($out_trade_no)) { $pay_log = Sql::Select('*') ->from('syweb_core_paylog') ->where('`app_key` = ? and `market_key` = ? and `out_trade_no` = ?', $app_id, $market_key, $out_trade_no) ->get($db); $refund_fee += intval((empty($pay_log) || count($pay_log) == 0) ? 0 : $pay_log[0]['refund_fee']); $recordTemp = array( 'status' => PAYSTATUS_REFUND, 'refund_fee' => $refund_fee, ); $db->beginTransaction(); Sql::update('syweb_core_paylog') ->setArgs($recordTemp) ->where('`app_key` = ? and `market_key` = ? and `out_trade_no` = ?', $app_id, $market_key, $out_trade_no) ->exec($db); $db->commit(); return true; } else return false; } catch (PDOException $e) { //var_dump($e); return false; } } break; } return true; } /** * @note 通知支付宝订单状态. * @param string $app_id appid * @param string $market_key 门店id * @param string $out_trade_no 订单号 * @param string $trade_no 支付宝交易订单号 * @param string $from_user 来源用户(用户openid) * @param int $pay_fee 支付金额 * @param int $refund_fee 退款金额(单位分) * @param string $sign_key 签名key * @param int $status 通知订单状态(0: 正常; 1: 已付款; -1: 已退款) * @return bool */ private function _notify_alipay_order_status_v1($app_id = '', $market_key = '', $out_trade_no = '', $trade_no = '', $from_user = '', $pay_fee = 0, $refund_fee = 0, $status = PAYSTATUS_REFUND, $sign_key = '') { switch ($status) { case PAYSTATUS_NORMAL: /// 普通状态 break; case PAYSTATUS_PAY: /// 已支付 { $log = Sql::select('syweb_core_paylog.*') ->from('syweb_core_paylog') ->where('`app_key` = ? and `market_key` = ? and `out_trade_no` = ?', $app_id, $market_key, $out_trade_no) ->get($this->db, null); if (!empty($log) && count($log) > 0) $log = $log[0]; if (!empty($log) && !empty($log['plid']) && is_numeric($log['status']) && $log['status'] != '0') return true; $log['tag'] = json_decode($log['tag']); $log['tag']->transaction_id = $trade_no; $log['tag']->total_fee = $pay_fee; /// 提前设置为已经支付成功状态 $recordTemp = array( 'status' => PAYSTATUS_PAY, 'transaction_id' => $trade_no, ///'openid' => $open_id, 'tag' => json_encode($log['tag'], JSON_UNESCAPED_UNICODE), ); try { $db = $this->db; $db->beginTransaction(); Sql::update('syweb_core_paylog')->setArgs($recordTemp)->where('plid = ?', $log['plid'])->exec($db); $db->commit(); } catch (PDOException $e) { var_dump($e); } $notice_url = $log['tag']->notice_url; /// 回调地址 //$param_mask = $log['tag']->param_mask; /// 回调参数格式 /// 验证客户端逻辑处理 if (!empty($notice_url)) { /// 获取附带的参数 $attach = $log['tag']->attach; if (is_string($attach)) $attach = json_decode($attach); $callback_data = (array)$attach; $callback_data['order_no'] = $log['order_id']; /// 订单号(用户) $callback_data['out_trade_no'] = $log['out_trade_no']; /// 商户订单号(平台) $callback_data['transaction_id'] = $trade_no; /// 支付宝交易订单号 $callback_data['total_fee'] = $log['tag']->total_fee; /// 支付金额(单位分) $callback_data['version'] = 1; /// 版本号 $callback_data['sign'] = SignParameter($callback_data, $sign_key); /// 生成签名 //$callback_data = json_encode($callback_data, JSON_UNESCAPED_UNICODE); //$callback_response = ihttp_request($notice_url, $callback_data, false); try { /// 发送post请求 $callback_response = @SendPost($notice_url, $callback_data); /// 返回success表示成功, 否则表示失败. return strcasecmp(NOTIFYSTATUS_SUCCESS, $callback_response) == 0; } catch (Exception $e) { return false; } } break; } case PAYSTATUS_REFUND: /// 已退款 { try { $db = $this->db; $pay_log = Sql::Select('*') ->from('syweb_core_paylog') ->where('`app_key` = ? and `market_key` = ? and `out_trade_no` = ?', $app_id, $market_key, $out_trade_no) ->get($db); $refund_fee += intval((empty($pay_log) || count($pay_log) == 0) ? 0 : $pay_log[0]['refund_fee']); $recordTemp = array( 'status' => PAYSTATUS_REFUND, 'refund_fee' => $refund_fee, ); $db->beginTransaction(); Sql::update('syweb_core_paylog') ->setArgs($recordTemp) ->where('`app_key` = ? and `market_key` = ? and `out_trade_no` = ?', $app_id, $market_key, $out_trade_no) ->exec($db); $db->commit(); return true; } catch (PDOException $e) { var_dump($e); return false; } break; } } return true; } /** * 支付完成回调到客户端(同步回调页面) * @route({"GET","/callback/v1"}) * @param({"plid","$._GET.plid"}) 订单编号 * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return null */ public function online_callback_v1($plid) { $log = Sql::select('a.*, b.signkey') ->from('syweb_core_paylog a') ->leftJoin('syweb_market b') ->on('a.market_key = b.market_key') ->where('a.plid = ?', $plid) ->get($this->db, null); if (!empty($log)) { $log = $log[0]; /// 判断支付订单号(内部) $log['tag'] = json_decode($log['tag']); $returnUrl = $log['tag']->return_url; /// 客户端回调地址 $attach = (array)json_decode($log['tag']->attach); /// 客户端传回的参数 $order_no = $log['order_id']; /// 订单号 $out_trade_no = $log['out_trade_no']; /// 商家订单号 $transaction_id = $log['transaction_id']; /// 微信订单号 //$total_fee = $log['tag']->total_fee; /// 支付金额(单位分) /// tag中的支付金额为实际回调的支付金额,这里需要判断一下是因为有可能在执行同步回调的时候,异步回调还没有通知,所以这里需要做一个判断 $total_fee = empty($log['tag']->total_fee) ? $log['pay_fee'] : $log['tag']->total_fee; /// 支付金额(单位分) $signkey = $log['signkey']; /// 签名key /// 这里生成参数的签名 $param = $attach; $param['order_no'] = $order_no; /// 订单号 $param['out_trade_no'] = $out_trade_no; /// 商家订单号 $param['transaction_id'] = $transaction_id; /// 微信订单号 $param['total_fee'] = $total_fee; /// 支付金额(单位分) $sign = SignParameter($param, $signkey); $param = ''; foreach ($attach as $k => $v) { $param .= "&{$k}={$v}"; } if (!empty($returnUrl)) { $p = strstr($returnUrl, '?'); if (empty($p)) $returnUrl .= "?order_no={$order_no}&out_trade_no={$out_trade_no}&transaction_id={$transaction_id}&total_fee={$total_fee}{$param}&sign={$sign}"; elseif ('?' == $p) $returnUrl .= "order_no={$order_no}&out_trade_no={$out_trade_no}&transaction_id={$transaction_id}&total_fee={$total_fee}{$param}&sign={$sign}"; else $returnUrl .= "&order_no={$order_no}&out_trade_no={$out_trade_no}&transaction_id={$transaction_id}&total_fee={$total_fee}{$param}&sign={$sign}"; header('location: ' . $returnUrl); } else header('location: ' . $this->getLocaleUrl()); } else echo '无效的支付信息!'; } /** * 支付完成回调到客户端(同步回调页面) * @route({"GET","/callback"}) * @param({"plid","$._GET.plid"}) 订单编号 * @param({"version","$._GET.version"}) 版本号 * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return null */ public function online_callback($plid = 0, $version = 1) { switch ($version) { case 1: $this->online_callback_v1($plid); break; default: echo JsonObjectToJsonString('不正确的支付信息, 请联系管理员!!'); } } /** * 微信支付 异步回调用页面 * @route({"POST","/notify/online/wechatpay"}) * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return string|returnObject */ public function online_wechat_notify() { $content = file_get_contents('php://input'); $resultObj = new WxPayResults(); $resultObj->FromXml($content, 2); if (!array_key_exists('attach', $resultObj->GetValues())) return new returnObject(1, 10001, '回调参数缺少attach参数。'); $attach = json_decode($resultObj->GetValues()['attach']); if (empty($attach)) return new returnObject(1, 10002, '回调参数attach不能为空。'); $app_id = $attach->app_id; $market_key = $attach->market_key; $version = $attach->version; switch ($version) { case 1: { $marketList = Sql::select('a.*') ->from('syweb_market a') ->where('a.market_key = ?', $market_key) ->get($this->db, null); if (empty($marketList) || count($marketList) <= 0) return new returnObject(1, 10004, '找不到的商户信息。'); $wechatInfo["appid"] = $marketList[0]['weixin_appid']; $wechatInfo["secret"] = $marketList[0]['weixin_secret_appid']; $wechatInfo["mchid"] = $marketList[0]['weixin_mchid']; $wechatInfo["signkey"] = $marketList[0]['weixin_paykey']; $sign_key = $marketList[0]['signkey']; /// 签名key $resultObj->CheckSign($wechatInfo); $values = $resultObj->GetValues(); /// 订单号 $tradeno = $values['out_trade_no']; /// 支付订单号(微信) $out_transaction_id = $values['transaction_id']; /// 支付金额(单位分) $total_fee = $values['total_fee']; /// 用户openid $open_id = $values['openid']; /// 此处可以在添加相关处理业务,校验通知参数中的商户订单号out_trade_no和金额total_fee是否和商户业务系统的单号和金额是否一致,一致后方可更新数据库表中的记录。 /// 更改订单状态 if ($this->_notify_wechat_order_status_v1($app_id, $market_key, $tradeno, $out_transaction_id, $open_id, $total_fee, 0, PAYSTATUS_PAY, $sign_key)) echo NOTIFYSTATUS_SUCCESS; else echo NOTIFYSTATUS_ERROR; exit; } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * 支付宝支付 异步回调用页面 * @route({"POST","/notify/online/alipay"}) * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return string|returnObject */ public function online_alipay_notify() { //$content = (array)JsonStringToJsonObject(rawurldecode(file_get_contents('php://input'))); $content = $_POST; if (!array_key_exists('passback_params', $content)) //return new returnObject(1, 10001, '回调参数缺少passback_params参数。'); die(NOTIFYSTATUS_FAIL); if (is_string($content['passback_params'])) $attach = (array)json_decode($content['passback_params']); else $attach = (array)$content['passback_params']; if (empty($attach)) //return new returnObject(1, 10002, '回调参数passback_params不能为空。'); die(NOTIFYSTATUS_FAIL); $app_id = $attach['app_id']; $market_key = $attach['market_key']; $version = $attach['version']; switch ($version) { case 1: { $marketList = Sql::select('a.*') ->from('syweb_market a') ->where('a.market_key = ?', $market_key) ->get($this->db, null); if (empty($marketList) || count($marketList) <= 0) return new returnObject(1, 10004, '找不到的商户信息。'); $alipay_appid = $marketList[0]['alipay_appid']; /// 支付宝appid $sign_key = $marketList[0]['signkey']; /// 签名key //============== $aop = new AopClient(); $aop->alipayPublicKey = dirname(dirname(__DIR__)) . '/payment/alipay/key/' . $alipay_appid . '/alipay_rsa_public_key.pem'; $result = $aop->rsaCheckV1($content, $aop->alipayPublicKey, 'RSA2'); if (!$result) { file_put_contents('d:/signerror.txt', JsonObjectToJsonString($content)); die(NOTIFYSTATUS_FAIL); } //============== // 验证成功 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //$seller_id = isset($content['seller_id']) ? $content['seller_id'] : ''; /// seller_id卖家支付宝用户号 $out_trade_no = $content['out_trade_no']; /// 商户订单号 $trade_no = $content['trade_no']; /// 支付宝交易号 $trade_status = $content['trade_status']; /// 交易状态 $buyer_id = isset($content['buyer_id']) ? $content['buyer_id'] : ''; /// 买家支付宝账号对应的支付宝唯一用户号。以2088开头的纯16位数字 //$buyer_logon_id = isset($content['buyer_logon_id']) ? $content['buyer_logon_id'] : ''; /// 买家支付宝账号 //$total_amount = intval(isset($content['total_amount']) ? floatval($content['total_amount']) * 100 : 0); /// 订单金额 $receipt_amount = intval(isset($content['receipt_amount']) ? floatval($content['receipt_amount']) * 100 : 0); /// 实收金额 //$invoice_amount = intval(isset($content['invoice_amount']) ? floatval($content['invoice_amount']) * 100 : 0); /// 开票金额 //$buyer_pay_amount = intval(isset($content['buyer_pay_amount']) ? floatval($content['buyer_pay_amount']) * 100 : 0); /// 用户在交易中支付的金额 //$point_amount = intval(isset($content['point_amount']) ? floatval($content['point_amount']) : 0); /// 使用集分宝支付的金额 //$refund_fee = intval(isset($content['refund_fee']) ? floatval($content['refund_fee']) : 0); /// 退款通知中,返回总退款金额,单位为元,支持两位小数 if ('TRADE_FINISHED' == $trade_status) { // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 // 如果有做过处理,不执行商户的业务程序 // 注意: // 退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 // 调试用,写文本函数记录程序运行情况是否正常 // logResult("这里写入想要调试的代码变量值,或其他运行的结果记录"); } elseif ('TRADE_SUCCESS' == $trade_status) { // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 // 如果有做过处理,不执行商户的业务程序 // 注意: // 付款完成后,支付宝系统发送该交易状态通知 // 调试用,写文本函数记录程序运行情况是否正常 // logResult("这里写入想要调试的代码变量值,或其他运行的结果记录"); } /// 更改订单状态 if ($this->_notify_alipay_order_status_v1($app_id, $market_key, $out_trade_no, $trade_no, $buyer_id, $receipt_amount, 0, PAYSTATUS_PAY, $sign_key)) die(NOTIFYSTATUS_SUCCESS); else die(NOTIFYSTATUS_FAIL); } default: //return new returnObject(500, -1, "不支持的接口版本:{$version}!"); die(NOTIFYSTATUS_FAIL); } } /** * 威富通聚合支付-微信支付 异步回调用页面 * @route({"POST","/notify/online/swiftpasswechatpay"}) * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return string|returnObject */ public function online_swiftpass_wechat_notify() { $xml = file_get_contents('php://input'); $resHandler = new ClientResponseHandler(); $resHandler->setContent($xml); $attach = $resHandler->getParameter('attach'); /// {"app_id":"14936872341446","market_key":"0000"} $attach = json_decode($attach); if (!is_object($attach)) return new returnObject(1, 10002, '回调参数attach不能为空。'); $app_id = $attach->app_id; $market_key = $attach->market_key; $version = $attach->version; switch($version) { case 1: { $marketList = Sql::select('a.*') ->from('syweb_market a') ->where('a.market_key = ?', $market_key) ->get($this->db, null); if (empty($marketList) || count($marketList) <= 0) return new returnObject(1, 10003, '找不到的商户信息。'); $mchid = $marketList[0]['swiftpass_mchid']; /// 商户号 $secret_key = $marketList[0]['swiftpass_paykey']; /// 签名key $sign_key = $marketList[0]['signkey']; /// 签名key $resHandler->setKey($secret_key); if (!$resHandler->isTenpaySign()) /// 验签 return new returnObject(1, 10004, 'bad signature.'); if ($resHandler->getParameter('status') == 0 && $resHandler->getParameter('result_code') == 0) { /// 订单号 $tradeno = $resHandler->getParameter('out_trade_no'); /// 支付订单号(威富通平台) $transaction_id = $resHandler->getParameter('transaction_id'); /// 支付订单号(微信) $out_transaction_id = $resHandler->getParameter('out_transaction_id'); /// 支付金额(单位分) $total_fee = $resHandler->getParameter('total_fee'); /// 用户openid $open_id = $resHandler->getParameter('sub_openid'); /// 此处可以在添加相关处理业务,校验通知参数中的商户订单号out_trade_no和金额total_fee是否和商户业务系统的单号和金额是否一致,一致后方可更新数据库表中的记录。 /// 更改订单状态 if ($this->_notify_wechat_order_status_v1($app_id, $market_key, $tradeno, $out_transaction_id, $open_id, $total_fee, 0, PAYSTATUS_PAY, $sign_key)) echo NOTIFYSTATUS_SUCCESS; else echo NOTIFYSTATUS_ERROR; exit; } elseif (0 != $resHandler->getParameter('status')) return new returnObject(500, $resHandler->getParameter('status'), $resHandler->getParameter('message'), null); elseif (0 != $resHandler->getParameter('result_code')) return new returnObject(500, $resHandler->getParameter('result_code'), $resHandler->getParameter('err_msg'), null); else return new returnObject(500, -1, $resHandler->getAllParameters()); break; } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * 汇付宝聚合支付-微信支付 异步回调用页面 * @route({"GET","/notify/online/heepaywechatpay"}) * @route({"POST","/notify/online/heepaywechatpay"}) * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return string|returnObject */ public function online_heepay_wechat_notify() { $result = $_REQUEST['result']; /// 必填 支付结果,1=成功 其它为未知 $pay_message = $_REQUEST['pay_message']; /// 选填 支付结果信息,支付成功时为空 $agent_id = $_REQUEST['agent_id']; /// 必填 商户编号 如1234567 $jnet_bill_no = $_REQUEST['jnet_bill_no']; /// 必填 汇付宝交易号(订单号) $agent_bill_id = $_REQUEST['agent_bill_id']; /// 必填 商户系统内部的订单号 $pay_type = $_REQUEST['pay_type']; /// 必填 支付类型 $pay_amt = $_REQUEST['pay_amt']; /// 必填 订单实际支付金额(注意:此金额是用户的实付金额) $remark = $_REQUEST['remark']; /// 必填 商家数据包,原样返回 $return_sign = $_REQUEST['sign']; /// 必填 MD5签名结果 $remark = iconv("GB2312","UTF-8//IGNORE", urldecode($remark)); /// 签名验证中的中文采用UTF-8编码; /* $attach = json_decode($remark); if (!is_object($attach)) return new returnObject(1, 10002, '回调参数attach不能为空。'); $id = $attach->id; $version = $attach->ver; */ $record = Sql::select('a.plid, a.app_key, a.market_key, b.heepay_paykey, b.signkey, a.version') ->from('syweb_core_paylog a, syweb_market b') ->where('a.market_key = b.market_key and a.out_trade_no = ?', $agent_bill_id) ->get($this->db, null); if (empty($record) || count($record) <= 0) return new returnObject(1, 10003, '找不到对应的支付信息。'); $version = $record[0]['version']; /// 版本号 switch($version) { case 1: { /* $record = Sql::select('a.plid, a.app_key, a.market_key, b.heepay_paykey, b.signkey, a.version') ->from('syweb_core_paylog a, syweb_market b') ->where('a.market_key = b.market_key and a.plid = ?', $id) ->get($this->db, null); if (empty($record) || count($record) <= 0) return new returnObject(1, 10003, '找不到对应的支付信息。'); */ $key = $record[0]['heepay_paykey']; /// 商户签名密钥 $Params = "result={$result}&agent_id={$agent_id}&jnet_bill_no={$jnet_bill_no}&agent_bill_id={$agent_bill_id}&pay_type={$pay_type}&pay_amt={$pay_amt}&remark={$remark}&key={$key}"; $Sign = md5($Params); if($Sign == $return_sign) { /// 比较签名密钥结果是否一致,一致则保证了数据的一致性 /// 商户自行处理自己的业务逻辑 /// 订单号 $tradeno = $agent_bill_id; /// 支付订单号(汇付宝平台) $transaction_id = $jnet_bill_no; /// 支付订单号(微信) //$out_transaction_id = ''; /// 支付金额(单位分) $total_fee = intval($pay_amt * 100); /// 用户openid $open_id = ''; /// 此处可以在添加相关处理业务,校验通知参数中的商户订单号out_trade_no和金额total_fee是否和商户业务系统的单号和金额是否一致,一致后方可更新数据库表中的记录。 /// 更改订单状态 if ($this->_notify_wechat_order_status_v1($record[0]['app_key'], $record[0]['market_key'], $tradeno, $transaction_id, $open_id, $total_fee, 0, PAYSTATUS_PAY, $record[0]['signkey'])) //echo NOTIFYSTATUS_SUCCESS; echo 'ok'; else echo NOTIFYSTATUS_ERROR; exit; } else { //echo NOTIFYSTATUS_ERROR; echo 'error'; /// 商户自行处理,可通过查询接口更新订单状态,也可以通过商户后台自行补发通知,或者反馈运营人工补发 return new returnObject(1, 10004, 'bad signature.'); } break; } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * 微信支付 异步回调用页面 * @route({"POST","/notify/offline/wechatpay"}) * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 */ public function offline_wechat_notify() { return $this->online_wechat_notify(); } /** * 支付宝支付 异步回调用页面 * @route({"POST","/notify/offline/alipay"}) * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 */ public function offline_alipay_notify() { $content = $_POST; if (!array_key_exists('body', $content)) //return new returnObject(1, 10001, '回调参数缺少body参数。'); die(NOTIFYSTATUS_FAIL); if (is_string($content['body'])) $attach = (array)json_decode($content['body']); else $attach = (array)$content['body']; if (empty($attach)) //return new returnObject(1, 10002, '回调参数body不能为空。'); die(NOTIFYSTATUS_FAIL); $app_id = $attach['app_id']; $market_key = $attach['market_key']; $version = $attach['version']; switch ($version) { case 1: { $marketList = Sql::select('a.*') ->from('syweb_market a') ->where('a.market_key = ?', $market_key) ->get($this->db, null); if (empty($marketList) || count($marketList) <= 0) return new returnObject(1, 10004, '找不到的商户信息。'); $alipay_appid = $marketList[0]['alipay_appid']; /// 支付宝appid $sign_key = $marketList[0]['signkey']; /// 签名key //============== $aop = new AopClient(); $aop->alipayPublicKey = dirname(dirname(__DIR__)) . '/payment/alipay/key/' . $alipay_appid . '/alipay_rsa_public_key.pem'; $result = $aop->rsaCheckV1($content, $aop->alipayPublicKey, 'RSA2'); if (!$result) { file_put_contents('d:/signerror.txt', JsonObjectToJsonString($content)); die(NOTIFYSTATUS_FAIL); } //============== // 验证成功 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //$seller_id = isset($content['seller_id']) ? $content['seller_id'] : ''; /// seller_id卖家支付宝用户号 $out_trade_no = $content['out_trade_no']; /// 商户订单号 $trade_no = $content['trade_no']; /// 支付宝交易号 $trade_status = $content['trade_status']; /// 交易状态 $buyer_id = isset($content['buyer_id']) ? $content['buyer_id'] : ''; /// 买家支付宝账号对应的支付宝唯一用户号。以2088开头的纯16位数字 //$buyer_logon_id = isset($content['buyer_logon_id']) ? $content['buyer_logon_id'] : ''; /// 买家支付宝账号 //$total_amount = intval(isset($content['total_amount']) ? floatval($content['total_amount']) * 100 : 0); /// 订单金额 $receipt_amount = intval(isset($content['receipt_amount']) ? floatval($content['receipt_amount']) * 100 : 0); /// 实收金额 //$invoice_amount = intval(isset($content['invoice_amount']) ? floatval($content['invoice_amount']) * 100 : 0); /// 开票金额 //$buyer_pay_amount = intval(isset($content['buyer_pay_amount']) ? floatval($content['buyer_pay_amount']) * 100 : 0); /// 用户在交易中支付的金额 //$point_amount = intval(isset($content['point_amount']) ? floatval($content['point_amount']) : 0); /// 使用集分宝支付的金额 //$refund_fee = intval(isset($content['refund_fee']) ? floatval($content['refund_fee']) : 0); /// 退款通知中,返回总退款金额,单位为元,支持两位小数 if ('TRADE_FINISHED' == $trade_status) { // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 // 如果有做过处理,不执行商户的业务程序 // 注意: // 退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 // 调试用,写文本函数记录程序运行情况是否正常 // logResult("这里写入想要调试的代码变量值,或其他运行的结果记录"); } elseif ('TRADE_SUCCESS' == $trade_status) { // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的 // 如果有做过处理,不执行商户的业务程序 // 注意: // 付款完成后,支付宝系统发送该交易状态通知 // 调试用,写文本函数记录程序运行情况是否正常 // logResult("这里写入想要调试的代码变量值,或其他运行的结果记录"); } /// 更改订单状态 if ($this->_notify_alipay_order_status_v1($app_id, $market_key, $out_trade_no, $trade_no, $buyer_id, $receipt_amount, 0, PAYSTATUS_PAY, $sign_key)) die(NOTIFYSTATUS_SUCCESS); else die(NOTIFYSTATUS_FAIL); } default: //return new returnObject(500, -1, "不支持的接口版本:{$version}!"); die(NOTIFYSTATUS_FAIL); } } /** * 威富通聚合支付-微信支付 异步回调用页面 * @route({"POST","/notify/offline/swiftpasswechatpay"}) * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 */ public function offline_swiftpass_wechat_notify() { return $this->online_swiftpass_wechat_notify(); } /** * 汇付宝聚合支付-微信支付 异步回调用页面 * @route({"POST","/notify/offline/heepaywechatpay"}) * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 */ public function offline_heepay_wechat_notify() { return $this->offline_heepay_wechat_notify(); } /** * 微信支付 异步回调用页面 * @route({"POST","/notify/mobile/wechatpay"}) * @return returnObject|string */ public function mobile_wechat_notify() { return $this->online_wechat_notify(); } /** * 威富通聚合支付-微信支付 异步回调用页面 * @route({"POST","/notify/mobile/swiftpasswechatpay"}) * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 */ public function mobile_swiftpass_wechat_notify() { return $this->online_swiftpass_wechat_notify(); } /** * 发红包 * @route({"GET","/sendredpack"}) * @route({"POST","/sendredpack"}) * @param({"appid","$._POST.appid"}) 应用appid * @param({"devkey","$._POST.devkey"}) 开发者key * @param({"sid","$._POST.sid"}) sid * @param({"scode","$._POST.scode"}) scode * @param({"orderid","$._POST.orderid"}) 订单编号 * @param({"fee","$._POST.fee"}) 红包金额(单位分) * @param({"wishing","$._POST.wishing"}) 红包祝福语 * @param({"act_name","$._POST.act_name"}) 活动名称 * @param({"remark","$._POST.remark"}) 备注 * * @param({"send_type","$._POST.send_type"}) 支付类型(1: 微信支付; 2: 支付宝支付) * * @param({"version","$._POST.version"}) 版本号 * @param({"sign","$._POST.sign"}) 签名 * * @throws({"phprs\util\exceptions\Forbidden","res", "403 Forbidden",{"error":"Forbidden"}}) cookie不可用 * @return returnObject */ public function send_red_pack($appid, $devkey, $sid, $scode, $orderid, $fee, $wishing, $act_name, $remark, $send_type = 1, $version = 1, $sign = '') { switch ($version) { case 1: { /// 发送前校验 $attach = $this->verify_send_red_pack_v1($appid, $devkey, $sid, $scode, $orderid, $fee, $wishing, $act_name, $remark, $sign); if ($attach instanceof returnObject) return $attach; switch ($send_type) { case PAYCODE_ONLINE_WECHAT: /// 微信红包 return $this->_send_red_pack_wechat_v1($orderid, $fee, $wishing, $act_name, $remark, $attach); case PAYCODE_ONLINE_ALIPAY: /// 支付宝红包 return $this->_send_red_pack_ali_v1($orderid, $fee, $wishing, $act_name, $remark, $attach); default: echo sprintf('未知的红包类型: %d' . PHP_EOL . '支付类型(%d: 微信红包; %d: 支付宝红包; %d)', $send_type, PAYCODE_ONLINE_WECHAT, PAYCODE_ONLINE_ALIPAY); return -1; } break; } default: return new returnObject(500, -1, "不支持的接口版本:{$version}!"); } } /** * @note 在线支付前校验 * @param string $appid 应用id * @param string $devkey 开发者key * @param string $sid sid * @param string $scode scode * @param string $orderid 订单号 * @param int $fee 支付金额(分) * @param string $title 支付标题 * @param string $notice_url 异步通知地址 * @param string $return_url 同步通知地址 * @param string $sign 签名 * @return array|returnObject */ private function verify_pay_online_v1($appid, $devkey, $sid, $scode, $orderid, $fee, $title, $notice_url, $return_url, $sign) { /// 验证公共参数是否合法 parent::init($appid, $devkey, $sid, $scode); $verify_result = parent::verify(); if (!is_error_api($verify_result)) { if (false) { /// 校验签名 $param = $_REQUEST; $sign_str = ''; if (isset($param['sign'])) { unset($param['sign']); $sign_str = SignParameter($param, $this->marketInfo['signkey']); } if ($sign_str != $sign) return new returnObject(500, -1, '签名错误', null); } if (empty($orderid)) return new returnObject(500, 500, '请指定订单编号!', null); if (!is_numeric($fee)) return new returnObject(500, 500, '请正确指定订单价格!', null); if (empty($title)) return new returnObject(500, 500, '请指定title!', null); if (empty($notice_url) && empty($return_url)) return new returnObject(500, 500, '请至少指定一个支付回调通知页面!', null); /// 获取附加的参数 $attach = GetAttachParameters(array('appid', 'devkey', 'sid', 'scode', 'orderid', 'fee', 'title', 'notice_url', 'return_url', 'paytype', 'version', 'sign',)); $attach['paytime'] = time(); return $attach; } elseif ($verify_result instanceof returnObject) { return $verify_result; } else { $return = new returnObject(); $return->from_array((array)$verify_result); return $verify_result; } } /** * @note 扫码支付前校验 * @param string $appid 应用id * @param string $devkey 开发者key * @param string $market_key 门店key * @param string $orderid 订单号 * @param int $fee 支付金额(分) * @param string $title 支付标题 * @param string $notice_url 异步通知地址 * @param string $sign 签名 * @return array|returnObject */ private function verify_pay_offline_v1($appid, $devkey, $market_key, $orderid, $fee, $title, $notice_url, $sign) { /// 验证公共参数是否合法 parent::init($appid, $devkey, '', ''); $verify_result = parent::verify_admin($market_key); if (!is_error_api($verify_result)) { if (false) { /// 校验签名 $param = $_REQUEST; $sign_str = ''; if (isset($param['sign'])) { unset($param['sign']); $sign_str = SignParameter($param, $this->marketInfo['signkey']); } if ($sign_str != $sign) return new returnObject(500, -1, '签名错误', null); } if (empty($orderid)) return new returnObject(500, 500, '请指定订单编号!', null); if (!is_numeric($fee)) return new returnObject(500, 500, '请正确指定订单价格!', null); if (empty($title)) return new returnObject(500, 500, '请指定title!', null); if (empty($notice_url)) return new returnObject(500, 500, '请指定一个支付回调通知页面!', null); /// 获取附加的参数 $attach = GetAttachParameters(array('appid', 'devkey', 'market_key', 'orderid', 'fee', 'title', 'notice_url', 'paytype', 'version', 'sign',)); $attach['paytime'] = time(); return $attach; } elseif ($verify_result instanceof returnObject) { return $verify_result; } else { $return = new returnObject(); $return->from_array((array)$verify_result); return $verify_result; } } /** * @param string $appid 应用id * @param string $devkey 开发者id * @param string $market_key 门店key * @param string $from_user 支付用户 * @param string $orderid 订单号 * @param int $fee 支付总价 * @param string $title 支付主题 * @param string $notice_url 回调地址(异步) * @param string $sign 签名 * @return array|null|returnObject */ private function verify_pay_mobile_v1($appid, $devkey, $market_key, $from_user, $orderid, $fee, $title, $notice_url, $sign) { /// 验证公共参数是否合法 parent::init($appid, $devkey, '', ''); $verify_result = parent::verify_admin($market_key); if (!is_error_api($verify_result)) { if (false) { /// 校验签名 $param = $_REQUEST; $sign_str = ''; if (isset($param['sign'])) { unset($param['sign']); $sign_str = SignParameter($param, $this->marketInfo['signkey']); } if ($sign_str != $sign) return new returnObject(500, -1, '签名错误', null); } if (empty($orderid)) return new returnObject(500, 500, '请指定订单编号!', null); if (!is_numeric($fee)) return new returnObject(500, 500, '请正确指定订单价格!', null); if (empty($title)) return new returnObject(500, 500, '请指定title!', null); if (empty($notice_url)) return new returnObject(500, 500, '请指定一个支付回调通知页面!', null); /// 获取附加的参数 $attach = GetAttachParameters(array('appid', 'devkey', 'sid', 'scode', 'market_key', 'from_user', 'orderid', 'fee', 'title', 'notice_url', 'paytype', 'version', 'sign',)); $attach['paytime'] = time(); return $attach; } elseif ($verify_result instanceof returnObject) { return $verify_result; } else { $return = new returnObject(); $return->from_array((array)$verify_result); return $verify_result; } } /** * @note 退款校验 * @param string $appid 应用id * @param string $devkey 开发者key * @param string $sid sid * @param string $scode scode * @param string $transaction_id 三方订单号(微信等) * @param string $out_trade_no 平台订单号 * @param int $refund_fee 退款金额 * @param string $sign 签名 * @return array|returnObject */ private function verify_refund_v1($appid, $devkey, $sid, $scode, $transaction_id, $out_trade_no, $refund_fee, $sign) { /// 验证公共参数是否合法 parent::init($appid, $devkey, $sid, $scode); $verify_result = parent::verify(); if (!is_error_api($verify_result)) { /// 校验签名 $param = $_REQUEST; $sign_str = ''; if (isset($param['sign'])) { unset($param['sign']); $sign_str = SignParameter($param, $this->marketInfo['signkey']); } if ($sign_str != $sign) return new returnObject(500, -1, '签名错误', null); if (!isset($transaction_id) && !isset($out_trade_no)) return new returnObject(500, 13001, 'transaction_id和out_trade_no参数必须至少传入一个。', null); if (empty($transaction_id) && empty($out_trade_no)) return new returnObject(500, 13002, 'transaction_id和out_trade_no参数必须有一个不为空。', null); if (empty($refund_fee) || (!is_numeric($refund_fee) && !is_float($refund_fee))) return new returnObject(500, 13004, 'refund_fee不能为空,并且需要为数字。', null); $refererUrl = $_SERVER['HTTP_REFERER']; /// 当前调用退款的域名 $localUrl = $this->getLocaleUrl(); /// 本地域名 /// 退款安全域名 $refund_safe_domain = json_decode($this->marketInfo['refund_safe_domain']); $refund_safe_domain1 = $refund_safe_domain->refund_safe_domain1; $refund_safe_domain2 = $refund_safe_domain->refund_safe_domain2; $refund_safe_domain3 = $refund_safe_domain->refund_safe_domain3; $referer_paths = parse_url($refererUrl); $local_paths = parse_url($localUrl); if (!empty($referer_paths) && count($referer_paths) > 0) { $referer_domain = $referer_paths['host']; $local_domain = $local_paths['host']; if ($refund_safe_domain1 != $referer_domain && $refund_safe_domain2 != $referer_domain && $refund_safe_domain3 != $referer_domain && $local_domain != $referer_domain) return new returnObject(500, 13006, '不是安全的域名。', $referer_domain); } $attach = GetAttachParameters(array('appid', 'devkey', 'sid', 'scode', 'transaction_id', 'out_trade_no', 'total_fee', 'refund_fee', 'version', 'sign',)); return $attach; } else { $return = new returnObject(); $return->from_array((array)$verify_result); return $return; } } /** * @note 保存支付信息 * @param string $app_id 支付应用(int) * @param string $market_key 门店key * @param string $fromUser 支付用户 * @param string $orderid 订单ID * @param integer $fee 支付价格 * @param string $title 支付主题 * @param string $notice_url 支付成功回调地址 * @param string $return_url 支付回调地址 * @param array $attach 支付附加参数 // * @param string $param_mask 自定义的参数格式(回调通知时使用) * @param string $type 支付方式 * @return mixed **/ private function saved_payinfo_v1($app_id, $market_key, $fromUser, $orderid, $fee, $title, $notice_url, $return_url, $attach, $type) { $log = Sql::select('syweb_core_paylog.*') ->from('syweb_core_paylog') ->where('app_key = ? and market_key = ? and `order_id` = ?', $app_id, $market_key, $orderid) ->get($this->db, null); if (!empty($log) && count($log) > 0) $log = $log[0]; if (!empty($log) && !empty($log['plid']) && is_numeric($log['status'])) { switch ($log['status']) { case PAYSTATUS_PAY: echo '订单已经付款'; return false; case PAYSTATUS_REFUND: echo '订单已经退款'; return false; case PAYSTATUS_NORMAL: break; default: break; } } /// 重置支付记录 if (!empty($log)) $log = null; if (empty($log)) { $tag = array(); $tag['return_url'] = $return_url; /// 支付完成页面跳转地址 $tag['notice_url'] = $notice_url; /// 支付回调页面请求地址 //$tag['param_mask'] = $param_mask; /// 支付回复参数格式 $tag['total_fee'] = $fee; /// 支付金额 $tag['attach'] = json_encode($attach, JSON_UNESCAPED_UNICODE); $tag = json_encode($tag, JSON_UNESCAPED_UNICODE); $record = array(); $record['type'] = $type; /// 支付方式 $record['app_key'] = $app_id; /// 支付应用(int) $record['market_key'] = $market_key; /// 支付商家(int) $record['openid'] = $fromUser; /// 支付来源用户 $record['order_id'] = $orderid; /// 订单编号 $record['pay_fee'] = $fee; /// 支付金额 $record['refund_fee'] = 0; /// 退款金额 $record['tag'] = $tag; /// 其他附加内容 $record['title'] = $title; /// 支付主题 $record['status'] = PAYSTATUS_NORMAL; /// 支付状态 $record['encrypt_code'] = ''; /// 编码 $record['createtime'] = TIMESTAMP; /// 支付创建时间戳 $record['out_trade_no'] = md5(date('YmdHis') . '_' . $app_id . '_' . $market_key . '_' . random(8, 1)); /// 支付唯一ID $record['version'] = 1; /// 版本号 $pdo = $this->db; try { $pdo->beginTransaction(); /// 插入一条支付记录 $plid = Sql::insertInto('syweb_core_paylog')->values($record)->exec($pdo)->lastInsertId(); $pdo->commit(); $record['plid'] = $plid; return $record; } catch(Exception $e) { $pdo->rollBack(); echo $e->getMessage(); return false; } } return true; } /** * 微信支付-线上 * @param string $orderid 订单号 * @param integer $fee 支付金额(单位分) * @param string $title 支付标题 * @param string $notice_url 回调地址(异步) * @param string $return_url 回调地址(同步) //* @param string $param_mask * @param array|mixed $attach 附带的其他参数 * @return returnObject */ private function _pay_online_wechat_v1($orderid, $fee, $title, $notice_url, $return_url, $attach) { /// 验证用户登陆方式 if (AUTHTYPE_WECHAT != $this->userInfo['auth_type']) return new returnObject(500, 500, '请使用微信登录再进行支付!', null); /// 保存支付记录 $pay_log = $this->saved_payinfo_v1($this->appid, $this->market_key, $this->userInfo['openid'], $orderid, $fee, $title, $notice_url, $return_url, $attach, PAYTYPE_ONLINE_WECHAT); if (!$pay_log) return new returnObject(500, 500, '写入支付信息失败, 请联系管理员或稍候再试!', null); $notify_url = $this->getFullUrl('/api/newpay/notify/online/wechatpay'); /// 异步通知地址 $callback_url = $this->getFullUrl('/api/newpay/callback/v1?plid=' . $pay_log['plid']); /// 同步通知地址 load()->model('payment'); $wechat = array(); $wechat['appid'] = $this->marketInfo['weixin_appid']; /// 微信公众号APPID $wechat['secret'] = $this->marketInfo['weixin_secret_appid']; $wechat['mchid'] = $this->marketInfo['weixin_mchid']; /// 微信公众号商户号 $wechat['signkey'] = $this->marketInfo['weixin_paykey']; /// 支付秘钥 //$openid = $this->userInfo['openid']; $attach = json_encode(array('app_id' => $this->appid, 'market_key' => $this->market_key, 'version' => 1,), JSON_UNESCAPED_UNICODE); $tools = new JsApiPay(); /// ②、实例化统一下单对象 $input = new WxPayUnifiedOrder(); $input->SetAppid($wechat['appid']); /// 公众号APPID $input->SetMch_id($wechat['mchid']); /// 公众号商户ID //$input->SetPayKey($wechat['signkey']); /// 公众号APPID //$input->SetSecretId($wechat['secret']); /// 公众号商户ID $input->SetBody($title); /// 本次支付主题 $input->SetAttach($attach); /// 支付回传的值 $input->SetOut_trade_no($pay_log['out_trade_no']); $input->SetTotal_fee($fee); /// 微信支付单位为分 $input->SetTime_start(date("YmdHis")); /// 支付发起时间戳 $input->SetTime_expire(date("YmdHis", time() + 600));/// 支付有效期 $input->SetGoods_tag(""); $input->SetNotify_url($notify_url); $input->SetTrade_type("JSAPI"); $input->SetOpenid($pay_log['openid']); try { $order = WxPayApi::unifiedOrder($input, 6, $wechat); /// 提交统一订单 } catch (Exception $e) { if (isset($order['return_msg'])) echo $order['return_msg'], '
'; exit($e->getMessage()); } /// $wOpt = wechat_build($params, $wechat); $jsApiParameters = $tools->GetJsApiParameters($order, $wechat); if (is_error($jsApiParameters)) { /* if ($jsApiParameters['message'] == 'invalid out_trade_no' || $jsApiParameters['message'] == 'OUT_TRADE_NO_USED') { $id = date('YmdH'); pdo_update('syweb_core_paylog', array('plid' => $id), array('plid' => $log['plid'])); pdo_query("ALTER TABLE " . tablename('syweb_core_paylog') . " auto_increment = " . ($id + 1) . ";"); exit('抱歉,发起支付失败,系统已经修复此问题,请重新尝试支付。'); } */ exit("抱歉,发起支付失败,具体原因为:“{$jsApiParameters['errno']}:{$jsApiParameters['message']}”。请及时联系站点管理员。"); } $htmlContent = << function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', {$jsApiParameters}, function(res) { if ('get_brand_wcpay_request:ok' == res.err_msg) { /// 支付成功 window.location.href="{$callback_url}"; } else if ('get_brand_wcpay_request:cancel' == res.err_msg) { /// 用户取消 //alert('启动微信支付失败, 请检查你的支付参数. 详细错误为: ' + res.err_msg); history.go(-1); } else { /// 其他错误 //alert('启动微信支付失败, 请检查你的支付参数. 详细错误为: ' + res.err_msg); history.go(-1); } } ); } if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } } else { jsApiCall(); } EOF; exit($htmlContent); } /** * 支付宝支付-线上 * @param string $orderid 订单号 * @param integer $fee 支付金额(单位分) * @param string $title 支付标题 * @param string $notice_url 回调地址(异步) * @param string $return_url 回调地址(同步) * @param array|mixed $attach 附带的其他参数 * @return boolean */ private function _pay_online_ali_v1($orderid, $fee, $title, $notice_url, $return_url, $attach) { /// 保存支付记录 $pay_log = $this->saved_payinfo_v1($this->appid, $this->market_key, @$this->userInfo['openid'], $orderid, $fee, $title, $notice_url, $return_url, $attach, PAYTYPE_ONLINE_ALIPAY); if (!$pay_log) return new returnObject(500, 500, '写入支付信息失败, 请联系管理员或稍候再试!', null); $alipay_appid = $this->marketInfo['alipay_appid']; $attach = json_encode(array('app_id' => $this->appid, 'market_key' => $this->market_key, 'version' => 1,), JSON_UNESCAPED_UNICODE); $notify_url = $this->getFullUrl('/api/newpay/notify/online/alipay'); /// 异步通知地址 $callback_url = $this->getFullUrl('/api/newpay/callback/v1?plid=' . $pay_log['plid']); /// 同步通知地址 $payRequestBuilder = new AlipayTradeWapPayContentBuilder(); $payRequestBuilder->setBody($title); /// 商品描述,可空 $payRequestBuilder->setSubject($title); /// 订单名称,必填 $payRequestBuilder->setOutTradeNo($pay_log['out_trade_no']); /// 商户订单号,商户网站订单系统中唯一订单号,必填 $payRequestBuilder->setTotalAmount($fee / 100); /// 付款金额,必填 $payRequestBuilder->setTimeExpress('1m'); $payRequestBuilder->setPassbackParams($attach); /// 回传参数 $config = array ( 'app_id' => $alipay_appid, /// 应用id //'merchant_private_key' => '', /// 商户私钥,您的原始格式RSA私钥 'merchant_private_key_filepath' => dirname(dirname(__DIR__)) . '/payment/alipay/key/' . $alipay_appid . '/rsa_private_key.pem', /// 商户私钥文件名 'notify_url' => $notify_url, /// 异步通知地址 'return_url' => $callback_url, /// 同步通知地址 'charset' => 'utf-8', /// 编码格式 'sign_type' => 'RSA2', /// 签名方式 'gatewayUrl' => 'https://openapi.alipay.com/gateway.do', /// 支付宝网关 //'alipay_public_key' => '', /// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 'alipay_public_key_filepath' => dirname(dirname(__DIR__)) . '/payment/alipay/key/' . $alipay_appid . '/alipay_rsa_public_key.pem', /// 支付宝公钥文件名 ); $payResponse = new AlipayTradeService_wappay($config); $result = $payResponse->wapPay($payRequestBuilder, $config['return_url'], $config['notify_url']); exit($result); } /** * 威富通聚合支付--微信-线上 * @param string $orderid 订单号 * @param integer $fee 支付金额(单位分) * @param string $title 支付标题 * @param string $notice_url 回调地址(异步) * @param string $return_url 回调地址(同步) * @param array|mixed $attach 附带的其他参数 * @return returnObject */ private function _pay_online_swiftpass_wechat_v1($orderid, $fee, $title, $notice_url, $return_url, $attach) { if (AUTHTYPE_WECHAT != $this->userInfo['auth_type']) { return new returnObject(500, 500, '请使用微信登录再进行支付!', null); } $pay_log = $this->saved_payinfo_v1($this->appid, $this->market_key, $this->userInfo['openid'], $orderid, $fee, $title, $notice_url, $return_url, $attach, PAYTYPE_ONLINE_SWIFTPASS_WECHAT); if (!$pay_log) { return new returnObject(500, 500, '写入支付信息失败, 请联系管理员或稍候再试!', null); } $openid = $this->userInfo['openid']; $mch_id = $this->marketInfo['swiftpass_mchid']; $secret_key = $this->marketInfo['swiftpass_paykey']; $attach = json_encode(array('app_id' => $this->appid, 'market_key' => $this->market_key, 'version' => 1), JSON_UNESCAPED_UNICODE); $resHandler = new ClientResponseHandler(); $reqHandler = new RequestHandler(); $pay = new PayHttpClient(); $reqHandler->setGateUrl('https://pay.swiftpass.cn/pay/gateway'); $reqHandler->setKey($secret_key); $notify_url = $this->getFullUrl('/api/newpay/notify/online/swiftpasswechatpay', true); /// 异步通知地址 $callback_url = $this->getFullUrl('/api/newpay/callback/v1?plid=' . $pay_log['plid']); /// 同步通知地址 /* service 是 String(32) 接口类型:pay.weixin.jspay version 否 String(8) 版本号,version默认值是2.0 charset 否 String(8) 可选值 UTF-8 ,默认为 UTF-8 sign_type 否 String(8) 签名类型,取值:MD5默认:MD5 mch_id 是 String(32) 商户号,由平台分配 is_raw 否 String(1) 是否原生态 值为1:是;值为0:否;不传默认是0 is_minipg 否 String(1) 值为1,表示小程序支付;不传或值不为1,表示公众账号内支付 out_trade_no 是 String(32) 商户系统内部的订单号 ,32个字符内、 可包含字母,确保在商户系统唯一 device_info 否 String(32) 终端设备号 body 是 String(127) 商品描述 sub_openid 是 String(128) 微信用户关注商家公众号的openid(注:使用测试号时此参数置空,即不要传这个参数,使用正式商户号时才传入,参数名是sub_openid,具体请看文档最后注意事项第7点) sub_appid 否 String(32) 微信公众平台基本配置中的AppID(应用ID) attach 否 String(128) 商户附加信息,可做扩展参数,255字符内 total_fee 是 Int 总金额,以分为单位,不允许包含任何字、符号 mch_create_ip 是 String(16) 订单生成的机器 IP notify_url 是 String(255) 接收平台通知的URL,需给绝对路径,255字符内格式如:http://wap.tenpay.com/tenpay.asp,确保平台能通过互联网访问该地址 callback_url 否 String(255) 交易完成后跳转的URL,需给绝对路径,255字符内格式如:http://wap.tenpay.com/callback.asp注:该地址只作为前端页面的一个跳转,需使用notify_url通知结果作为支付最终结果。 time_start 否 String(14) 订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。时区为GMT+8 beijing。该时间取自商户服务器 time_expire 否 String(14) 订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。时区为GMT+8 beijing。该时间取自商户服务器 goods_tag 否 String(32) 商品标记,微信平台配置的商品标记,用于优惠券或者满减使用 nonce_str 是 String(32) 随机字符串,不长于 32 位 limit_credit_pay 否 String(32) 限定用户使用微信支付时能否使用信用卡,值为1,禁用信用卡;值为0或者不传此参数则不禁用 sign 是 String(32) MD5签名结果,详见“安全规范” */ //$reqHandler->setReqParams($_POST, array('method')); $reqHandler->setParameter('service', 'pay.weixin.jspay'); /// 接口类型 $reqHandler->setParameter('mch_id', $mch_id); /// 商户号,由平台分配 $reqHandler->setParameter('version', '2.0'); /// 版本号,version默认值是2.0 $reqHandler->setParameter('is_raw', '1'); /// 是否原生态 值为1:是;值为0:否;不传默认是0 $reqHandler->setParameter('out_trade_no', $pay_log['out_trade_no']); /// 商户系统内部的订单号 ,32个字符内、 可包含字母,确保在商户系统唯一 $reqHandler->setParameter('body', $title); /// 商品描述 $reqHandler->setParameter('sub_openid', $openid); /// 微信用户关注商家公众号的openid(注:使用测试号时此参数置空,即不要传这个参数,使用正式商户号时才传入,参数名是sub_openid,具体请看文档最后注意事项第7点) $reqHandler->setParameter('attach', $attach); /// 商户附加信息,可做扩展参数,255字符内 $reqHandler->setParameter('total_fee', $fee); /// 总金额,以分为单位,不允许包含任何字、符号 $reqHandler->setParameter('mch_create_ip', $_SERVER['REMOTE_ADDR']); /// 订单生成的机器 IP $reqHandler->setParameter('notify_url', $notify_url); /// 异步通知地址 $reqHandler->setParameter('callback_url', $callback_url); /// 同步通知地址 $reqHandler->setParameter('nonce_str', mt_rand(time(), time() + rand())); /// 随机字符串,必填项,不长于 32 位 $reqHandler->createSign(); /// 创建签名 $data = Utils::toXml($reqHandler->getAllParameters()); //var_dump($data); //var_dump($pay->getResContent()); $pay->setReqContent($reqHandler->getGateURL(), $data); if ($pay->call()) { $resHandler->setContent($pay->getResContent()); $resHandler->setKey($reqHandler->getKey()); //var_dump($resHandler->getAllParameters()); if ($resHandler->isTenpaySign()) { //var_dump($resHandler->getAllParameters()); /// 当返回状态与业务结果都为0时才返回,其它结果请查看接口文档 $status_code = $resHandler->getParameter('status'); $result_code = $resHandler->getParameter('result_code'); if (0 == $status_code && 0 == $result_code) { /* $payInfo = json_decode($resHandler->getParameter('pay_info')); $htmlContent = << function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', { "appId": "{$payInfo->appId}", /// 公众号名称,由商户传入 "timeStamp": "{$payInfo->timeStamp}", /// 时间戳,自1970 年以来的秒数 "nonceStr": "{$payInfo->nonceStr}", /// 随机串 "package": "{$payInfo->package}", "signType": "{$payInfo->signType}", /// 微信签名方式: "paySign": "{$payInfo->paySign}" /// 微信签名, }, function (res) { if (res.err_msg == "get_brand_wcpay_request:ok") { /// 此处可以使用此方式判断前端返回,微信团队郑重提示:res.err_msg 将在用户支付成功后返回ok,但并不保证它绝对可靠。 window.location.href="{$callback_url}"; } else { //alert('启动微信支付失败, 请检查你的支付参数. 详细错误为: ' + res.err_msg); history.go(-1); } } ); } if (typeof WeixinJSBridge == "undefined") { if( document.addEventListener ){ document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); }else if (document.attachEvent){ document.attachEvent('WeixinJSBridgeReady', jsApiCall); document.attachEvent('onWeixinJSBridgeReady', jsApiCall); } }else{ jsApiCall(); } EOF; */ $htmlContent = << window.location.href="https://pay.swiftpass.cn/pay/jspay?token_id={$resHandler->getParameter('token_id')}&showwxtitle=1"; EOF; die($htmlContent); //return new returnObject(0, 0, '', array('token_id' => $resHandler->getParameter('token_id'), 'pay_info' => $resHandler->getParameter('pay_info'),)); } elseif (0 != $status_code) return new returnObject(500, $status_code, $resHandler->getParameter('message'), null); elseif (0 != $result_code) return new returnObject(500, $result_code, $resHandler->getParameter('err_msg'), null); else return new returnObject(500, 500, '未知错误!'); } else { if (0 != $resHandler->getParameter('status')) return new returnObject(502, $resHandler->getParameter('status'), $resHandler->getParameter('message'), null); elseif (0 != $resHandler->getParameter('result_code')) return new returnObject(502, $resHandler->getParameter('result_code'), $resHandler->getParameter('err_msg'), null); else return new returnObject(502, 502, '签名错误'); } } else return new returnObject(501, $pay->getResponseCode(), $pay->getErrInfo(), null); } /** * 威富通聚合支付--支付宝-线上 * @param string $orderid 订单号 * @param integer $fee 支付金额(单位分) * @param string $title 支付标题 * @param string $notice_url 回调地址(异步) * @param string $return_url 回调地址(同步) * @param array|mixed $attach 附带的其他参数 * @return returnObject */ private function _pay_online_swiftpass_ali_v1($orderid, $fee, $title, $notice_url, $return_url, $attach) { return new returnObject(500, 500, '还没有实现该支付功能, 请关注平台后续更新!', null); } /** * 汇付宝聚合支付--微信-线上 * @param string $orderid 订单号 * @param integer $fee 支付金额(单位分) * @param string $title 支付标题 * @param string $notice_url 回调地址(异步) * @param string $return_url 回调地址(同步) * @param array|mixed $attach 附带的其他参数 * @return returnObject */ private function _pay_online_heepay_wechat_v1($orderid, $fee, $title, $notice_url, $return_url, $attach) { if (AUTHTYPE_WECHAT != $this->userInfo['auth_type']) return new returnObject(500, 500, '请使用微信登录再进行支付!', null); $pay_log = $this->saved_payinfo_v1($this->appid, $this->market_key, $this->userInfo['openid'], $orderid, $fee, $title, $notice_url, $return_url, $attach, PAYTYPE_ONLINE_HEEPAY_WECHAT); if (!$pay_log) return new returnObject(500, 500, '写入支付信息失败, 请联系管理员或稍候再试!', null); //$openid = $this->userInfo['openid']; $mch_id = $this->marketInfo['heepay_mchid']; $secret_key = $this->marketInfo['heepay_paykey']; //$attach = JsonObjectToJsonString(array('app_id' => $this->appid, 'market_key' => $this->market_key, 'version' => 1)); $notify_url = $this->getFullUrl('/api/newpay/notify/online/heepaywechatpay'); /// 异步通知地址 $callback_url = $this->getFullUrl('/api/newpay/callback/v1?plid=' . $pay_log['plid']); /// 同步通知地址 /// 获取用户IP if (isset($_SERVER['HTTP_CLIENT_IP'])) $ClientIP = $_SERVER['HTTP_CLIENT_IP']; elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) $ClientIP = $_SERVER['HTTP_X_FORWARDED_FOR']; elseif (isset($_SERVER['REMOTE_ADDR'])) $ClientIP = $_SERVER['REMOTE_ADDR']; else $ClientIP = null; $version = 1; /// 必填 当前接口版本号1 $is_phone = 1; /// 必填 是否使用手机触屏版,1=是(不参加签名) $is_frame = 1; /// 必填 =0代表在除了微信浏览器之外的浏览器支付(不参加签名) $pay_type = 30; /// 必填 支付类型30,(数据类型:int) $agent_id = $mch_id; /// 必填 商户编号 如1234567(汇付宝商户编号:七位整数数字) $agent_bill_id = $pay_log['out_trade_no']; /// 必填 商户系统内部的订单号(要保证唯一)。长度最长50字符 $pay_amt = $fee / 100; /// 必填 订单总金额 不可为空,取值范围(0.01到10000000.00),单位:元,小数点后保留两位。 //$notify_url = $notify_url; /// 必填 (异步回调)支付后返回的商户处理页面,URL参数是以http://或https://开头的完整URL地址(后台处理) 提交的url地址必须外网能访问到,否则无法通知商户。值可以为空,但不可以为null。 $return_url = $callback_url; /// 必填 (同步回调)支付后返回的商户显示页面,URL参数是以http://或https://开头的完整URL地址(前台显示),原则上该参数与notify_url提交的参数不一致。值可以为空,但不可以为null。 /// 微信支付不涉及同步返回,此处可填写任意URL,没有实际使用 $user_ip = str_ireplace('.', '_', $ClientIP); /// 必填 用户所在客户端的真实ip其中的“.”替换为“_” 。如 127_127_12_12。因为近期我司发现用户在提交数据时,user_ip在网络层被篡改,导致签名错误,所以我们规定使用这种格式。 $agent_bill_time = date('YmdHis', time()); /// 必填 提交单据的时间yyyyMMddHHmmss 如:20100225102000该参数共计14位,当时不满14位时,在后面加0补足14位 $goods_name = rawurlencode($title); /// 必填 商品名称,长度最长50字符,不能为空(不参加签名) $goods_num = 1; /// 选填 产品数量,长度最长20字符(不参加签名) //$remark = rawurlencode($attach); /// 必填 商户自定义 原样返回,长度最长50字符,可以为空。(不参加签名) $remark = empty(@$attach['remark']) ? JsonObjectToJsonString(array('id' => $pay_log['plid'], 'ver' => 1,)) : $attach['remark']; /// $goods_note = ''; /// 选填 支付说明,长度50字符(不参加签名) $meta_option = JsonObjectToJsonString(array('s' => 'WAP', 'n' => $this->marketInfo['market_name'], 'id' => $this->getLocaleUrl(),)); /// 必填 {“s”:”WAP”,”n”:”WAP网站名”,”id”:”WAP网站的首页URL”}(不参加签名) //$timestamp = time(); /// 选填 时间戳,订单在+-1min内有效,超过时间订单不能提交。如果传此参数,此参数也需要参与签名,参数加在key后面 $pay_code = ''; //char型,空字符串 $sign_key = $secret_key; /// 签名密钥,需要商户使用为自己的真实KEY $meta_option = rawurlencode(base64_encode(Characet($meta_option, 'GBK'))); /// /*************创建签名***************/ $sign_str = ''; $sign_str = $sign_str . 'version=' . $version; $sign_str = $sign_str . '&agent_id=' . $agent_id; $sign_str = $sign_str . '&agent_bill_id=' . $agent_bill_id; $sign_str = $sign_str . '&agent_bill_time=' . $agent_bill_time; $sign_str = $sign_str . '&pay_type=' . $pay_type; $sign_str = $sign_str . '&pay_amt=' . $pay_amt; $sign_str = $sign_str . '¬ify_url=' . $notify_url; $sign_str = $sign_str . '&return_url=' . $return_url; $sign_str = $sign_str . '&user_ip=' . $user_ip; $sign_str = $sign_str . '&key=' . $sign_key; $sign = md5($sign_str); /// 签名值 $html = <<