/** * 提交支付信息的接口. * * @param array 提交信息的数组 * * @return mixed false or null */ public function dopay($params, &$msg) { $appid = trim($this->getConf('appid', __CLASS__)); // 公众号ID $mch_id = trim($this->getConf('mch_id', __CLASS__)); //商户号 $mch_key = trim($this->getConf('mch_key', __CLASS__)); //商户API秘钥 $post_data = array('appid' => $appid, 'mch_id' => $mch_id, 'nonce_str' => $this->getNonceStr(), 'body' => $params['subject'] ? $params['subject'] : '支付订单#' . $params['order_id'], 'out_trade_no' => $params['bill_id'], 'total_fee' => $params['money'] * 100, 'spbill_create_ip' => $params['ip'], 'notify_url' => $this->notify_url, 'trade_type' => 'JSAPI', 'openid' => $params['payer_account']); $is_mobile = base_mobiledetect::is_mobile(); $in_wechat = base_mobiledetect::is_wechat(); if (!$is_mobile || !$in_wechat) { //不在微信内,请求微信支付时,进行二维码展示支付 $post_data['trade_type'] = 'NATIVE'; $post_data['product_id'] = $post_data['out_trade_no']; unset($post_data['openid']); } foreach ($post_data as $key => $value) { $this->add_field($key, $value); } $sign = $this->_get_mac($mch_key); $this->add_field('sign', $sign); $res_arr = $this->unifiedorder(); $render = app::get('wechat')->render(); $render->pagedata['total_fee'] = $params['money']; $render->pagedata['order_id'] = $params['order_id']; $render->pagedata['bill_id'] = $params['bill_id']; $render->pagedata['is_mobile'] = $is_mobile ? 'true' : 'false'; $render->pagedata['in_wechat'] = $in_wechat ? 'true' : 'false'; $controller_ins = vmc::singleton(($is_mobile ? 'mobile' : 'site') . '_controller'); if ($res_arr['return_code'] != 'SUCCESS') { $controller_ins->splash('error', '', '调用微信支付失败!' . $res_arr['return_msg']); } elseif ($res_arr['result_code'] != 'SUCCESS') { $controller_ins->splash('error', '', '调用微信支付失败!' . $res_arr['err_code_des']); } if ($res_arr['trade_type'] == 'JSAPI') { //微信内支付 $jsapi_arr = array('appId' => $appid, 'timeStamp' => (string) time(), 'nonceStr' => $this->getNonceStr(), 'package' => 'prepay_id=' . $res_arr['prepay_id'], 'signType' => 'MD5'); $jsapi_arr['paySign'] = $this->_get_mac($mch_key, $jsapi_arr); $render->pagedata['jsapi_object'] = json_encode($jsapi_arr); echo $render->fetch('wxpay/jsapi.html'); exit; } elseif ($res_arr['trade_type'] == 'NATIVE') { //微信外产生二维付款码 $render->pagedata['code_url'] = $res_arr['code_url']; echo $render->fetch('wxpay/qrcode.html'); exit; } }
public function authorize_url() { $app_id = $this->getConf('app_id', __CLASS__); $app_secret = $this->getConf('app_secret', __CLASS__); $redirect_uri = $this->callback_url; //state=STATE 在前台会被跟踪替换成state=$forward; $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$app_id}&redirect_uri={$redirect_uri}&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect"; //微信里 if (base_mobiledetect::is_wechat()) { return $url; } //手机中,微信外 if (base_mobiledetect::is_mobile()) { return false; } //适合扫码登录 return app::get('site')->router()->gen_url(array('app' => 'wechat', 'ctl' => 'site_wxqrlogin', 'act' => 'index', 'args' => array(utils::encrypt(array('app_id' => $app_id, 'app_secret' => $app_secret))))); }
/** * 准备跳转到支付平台. * * @param mixed $order_id 订单编号 * @param $recursive 递归调用标记 */ public function dopayment($order_id, $recursive = false) { $redirect = $this->gen_url(array('app' => 'b2c', 'ctl' => 'mobile_member', 'act' => 'orders')); $obj_bill = vmc::singleton('ectools_bill'); $mdl_bills = app::get('ectools')->model('bills'); $order = $this->app->model('orders')->dump($order_id); if ($order['pay_status'] == '1' || $order['pay_status'] == '2') { $this->splash('success', $redirect, '已支付'); } if (in_array($order['pay_app'], array('cod', 'offline'))) { $this->splash('error', $redirect, '不是在线支付方式'); } if ($this->app->member_id != $order['member_id']) { $this->splash('error', $redirect, '非法操作'); } //未交互过的账单复用 $bill_sdf = array('order_id' => $order['order_id'], 'bill_type' => 'payment', 'pay_mode' => 'online', 'pay_object' => 'order', 'money' => $order['order_total'] - $order['payed'], 'member_id' => $order['member_id'], 'status' => 'ready', 'pay_app_id' => $order['pay_app'], 'pay_fee' => $order['cost_payment'], 'memo' => $order['memo']); $exist_bill = $mdl_bills->getRow('*', $bill_sdf); //一天内重复利用原支付单据 if ($exist_bill && !empty($exist_bill['bill_id']) && $exist_bill['createtime'] + 86400 > time()) { $bill_sdf = array_merge($exist_bill, $bill_sdf); } else { $bill_sdf['bill_id'] = $mdl_bills->apply_id($bill_sdf); } $bill_sdf['return_url'] = $this->gen_url(array('app' => 'b2c', 'ctl' => 'mobile_checkout', 'act' => 'payresult', 'args' => array($bill_sdf['bill_id']))); //微信内支付时,需要静默授权,以获得用户openid if (base_mobiledetect::is_wechat() && $order['pay_app'] == 'wxpay' && empty($bill_sdf['payer_account'])) { $wxpay_setting = unserialize(app::get('ectools')->getConf('wechat_payment_applications_wxpay')); $wxpay_appid = $wxpay_setting['appid']; $wxpay_appsecret = $wxpay_setting['appsecret']; $auth_code = $_GET['code']; $auth_state = $_GET['state']; if (!$recursive) { $oauth_redirect = $this->gen_url(array('app' => 'b2c', 'ctl' => 'mobile_checkout', 'act' => 'dopayment', 'args' => array($order_id, 'recursive'), 'full' => 1)); $oauth_redirect = urlencode($oauth_redirect); $oauth_action = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$wxpay_appid}&redirect_uri={$oauth_redirect}&response_type=code&scope=snsapi_base&state={$order_id}#wechat_redirect"; logger::debug('微信snsapi_base URL:' . $oauth_action); $this->redirect($oauth_action); //静默授权 } elseif ($recursive && $auth_code && $auth_state == $order_id) { //把微信用户openid 记录到支付单据中 $auth_token = vmc::singleton('base_httpclient')->get("https://api.weixin.qq.com/sns/oauth2/access_token?appid={$wxpay_appid}&secret={$wxpay_appsecret}&code={$auth_code}&grant_type=authorization_code"); $auth_token = json_decode($auth_token, 1); if (!$auth_token['openid']) { logger::warning('微信静默授权失败!' . var_export($auth_token, 1)); $this->splash('error', $redirect, '暂无法进行微信内支付。'); } $bill_sdf['payer_account'] = $auth_token['openid']; } else { logger::warning('微信静默授权失败!order_id:' . $order_id . '|' . var_export($_GET, 1)); } } try { if (!$obj_bill->generate($bill_sdf, $msg)) { $this->splash('error', $redirect, $msg); } } catch (Exception $e) { $this->splash('error', $redirect, $e->getMessage()); } $get_way_params = $bill_sdf; if (!vmc::singleton('ectools_payment_api')->redirect_getway($get_way_params, $msg)) { $this->splash('error', $redirect, $msg); } //here we go to the platform }