't' const HTTP_PREFIX = 'https://'; public static $errMsg = ''; private static $wxPHPSDK; private static $wxJSSDK; /** * 获取用户公众号数据库配置 */ public static function getMpSetting() { $settings = UserMPSetting::findOne(1); if (false == $settings) { throw new Exception('严重错误: 用户公众号配置不存在!'); } return $settings; } /** * 根据配置获取[微信公众平台PHP-SDK接口实例] * @return bool|WxPHPSDK * @throws \yii\base\Exception */ public static function getWxPHPSDK() { if(self::$wxPHPSDK instanceof WxJSSDK){ return self::$wxPHPSDK; } $settings = self::getMpSetting(); self::$wxPHPSDK = new WxPHPSDK([ 'token' => $settings->token, // 填写你设定的key 'appid' => $settings->appid, // 填写高级调用功能的app id 'appsecret' => $settings->appsecret, // 填写高级调用功能的密钥 ]); return self::$wxPHPSDK; } /** * @return WxJSSDK */ public static function getWxJSSDK() { if(self::$wxJSSDK instanceof WxJSSDK){ return self::$wxJSSDK; } $settings = self::getMpSetting(); self::$wxJSSDK = new WxJSSDK([ 'token' => $settings->token, // 填写你设定的key 'appid' => $settings->appid, // 填写高级调用功能的app id 'appsecret' => $settings->appsecret, // 填写高级调用功能的密钥 ]); return self::$wxJSSDK; } /** * 获取用户公众号域名 * @param $httpPrefix 是否需要http://前缀 * @return bool|string */ public static function getDomain($httpPrefix = false) { $settings = self::getMpSetting(); $url = false; if('dev' == YII_ENV){ $url = '127.0.0.1/jiwork/app-user/web'; } elseif('test' == YII_ENV) { $url = self::TEST_PREFIX . $settings->domain; }elseif('prod' == YII_ENV){ $url = $settings->domain; } return ($httpPrefix) ? (self::HTTP_PREFIX . $url) : $url; } /** * 微信支付结果通知回调地址[app-pay: WxpayController/actionNotify 函数] * @param bool|false $httpPrefix 是否需要http://前缀 * @return bool|string */ public static function getWxpayNotifyUrl($httpPrefix = false) { $settings = self::getMpSetting(); $url = false; if('dev' == YII_ENV){ $url = '127.0.0.1/jiwork/app-user/web/wxpay/notify'; } elseif('test' == YII_ENV) { $url = self::TEST_PREFIX . $settings->pay_domain . '/wxpay/notify'; } elseif('prod' == YII_ENV){ $url = $settings->pay_domain . '/wxpay/notify'; } return ($httpPrefix) ? (self::HTTP_PREFIX . $url) : $url; } /** * 开发者用来接收微信消息和事件的接口URL * @param bool|false $httpPrefix 是否需要http://前缀 * @return bool|string */ public static function getWechatNotifyUrl($httpPrefix = false) { $settings = self::getMpSetting(); $url = false; if('dev' == YII_ENV){ $url = '127.0.0.1/jiwork/app-user/web/wechat/notify'; } elseif('test' == YII_ENV) { $url = self::TEST_PREFIX . $settings->domain . '/wechat/notify'; } elseif('prod' == YII_ENV){ $url = $settings->domain . '/wechat/notify'; } return ($httpPrefix) ? (self::HTTP_PREFIX . $url) : $url; } /** * 支付授权目录-pay * @param bool|false $httpPrefix 是否需要http://前缀 * @return bool|string */ public static function getWxpayAuthRoot() { $settings = self::getMpSetting(); $url = false; if('dev' == YII_ENV){ $url = '127.0.0.1/jiwork/app-user/web/wxpay/notify/'; } elseif('test' == YII_ENV) { $url = self::TEST_PREFIX . $settings->pay_domain . '/wxpay/'; } elseif('prod' == YII_ENV){ $url = $settings->pay_domain . '/wxpay/'; } return $url; } /** * 读取微信支付配置选项 * @return array */ public static function getWxpayOptions() { $settings = self::getMpSetting(); $certRoot = \yii::getAlias('@certs'); $certDir = $certRoot . '/usermp'; if (!file_exists($certDir)) { mkdir($certDir, 0777, true); } $saveCertPath = $certDir . '/' . 'apiclient_cert.pem'; $saveKeyPath = $certDir . '/' . 'apiclient_key.pem'; $saveRootcaPath = $certDir . '/' . 'rootca.pem'; // 数据库上传证书 if (!empty($settings->ssl_cert_content)) { if (!file_exists($saveCertPath)) { // 证书文件不存在, 创建并写入文件 file_put_contents($saveCertPath, $settings->ssl_cert_content); }elseif (file_get_contents($saveCertPath) !== $settings->ssl_cert_content) { // 证书内容不一致, 重新写入文件 file_put_contents($saveCertPath, $settings->ssl_cert_content); } }else { $saveCertPath = ''; // 证书为空 } // 数据库上传了秘钥 if (!empty($settings->ssl_key_content)) { if (!file_exists($saveKeyPath)) { // 秘钥文件不存在, 创建并写入文件 file_put_contents($saveKeyPath, $settings->ssl_key_content); }elseif (file_get_contents($saveKeyPath) !== $settings->ssl_key_content) { // 秘钥内容不一致, 重新写入文件 file_put_contents($saveKeyPath, $settings->ssl_key_content); } }else { $saveKeyPath = ''; // 秘钥为空 } // 数据库上传了CA证书 if (!empty($settings->ssl_rootca_content)) { if (!file_exists($saveRootcaPath)) { // CA证书文件不存在, 创建并写入文件 file_put_contents($saveRootcaPath, $settings->ssl_rootca_content); }elseif (file_get_contents($saveRootcaPath) !== $settings->ssl_rootca_content) { // CA证书内容不一致, 重新写入文件 file_put_contents($saveRootcaPath, $settings->ssl_rootca_content); } }else { $saveRootcaPath = ''; // CA证书为空 } // 初始化配置数组 $options = [ 'appid' => $settings->appid, 'appsecret' => $settings->appsecret, 'mch_id' => $settings->mch_id, 'api_key' => $settings->api_key, 'ssl_cert_path' => $saveCertPath, 'ssl_key_path' => $saveKeyPath, 'ssl_rootca_path' => $saveRootcaPath ]; return $options; } // $size 有0、46、64、96、132数值可选,0代表640*640正方形头像 /** * @param $url * @param int $size * @return bool|string */ public static function exchangeHeadImgSize($url,$size = 0) { if(empty($url)) return false; if($size==''){return $url;} $sizeArr=array(0,46,64,96,132); if(!in_array($size,$sizeArr)) return $url; $headUrlArr=explode('/',$url); $lastElement=array_pop($headUrlArr); if(intval($lastElement)<0){ return $url; } array_push($headUrlArr,$size); $newHeadUrl=implode('/',$headUrlArr); return $newHeadUrl; } /** * 发送红包接口 * @param $openId 接受红包的用户openId(必须是已关注公众号的用户) * @param $amount 红包金额 * @param $wishing 红包祝福语, 如'恭喜发财' * @param $actName 活动名称, 如'码上有钱' * @param $remark 备注信息, 如'每个设备二维码绑定成功均有奖励' * @return array|mixed * @throws \common\exts\wxpay\ErrorException * * * 余额不足返回结果 { "return_code":"SUCCESS", "return_msg":"帐号余额不足,请到商户平台充值后再重试", "result_code":"FAIL", "err_code":"NOTENOUGH", "err_code_des":"帐号余额不足,请到商户平台充值后再重试", "mch_billno":"145088440220170711123739", "mch_id":"1450884402", "wxappid":"wxb7b73e54344a5d95", "re_openid":"oZIQ2wLFmYJQ6YJOIPkM04NU-kDY", "total_amount":"10000" } */ public static function sendRedPack($openId, $amount, $wishing, $actName, $remark,$sendName='') { WxLog::init(); // 初始化微信支付配置数据 $config = WxpayConfig::getInstance(UserMPHelper::getWxpayOptions()); if(empty($sendName)){ $sendName='极办公用户公众号'; } WxLog::init(); WxLog::DEBUG('极办公用户公众号-发红包配置: [' . json_encode($config) . ']'); $input = new RedPack(); $input->SetMch_billno($config->MCHID . date("YmdHis") . QrcodeToken::rand(4)); $input->SetSend_name($sendName); // 红包发送者名称 $input->SetRe_openid($openId); $input->SetTotal_amount($amount * 100); $input->SetTotal_num(1); $input->SetWishing($wishing); // 红包祝福语 $input->SetAct_name($actName); // 活动名称 $input->SetRemark($remark); // 备注信息 $input->SetScene_id("PRODUCT_1"); // 场景ID: 商品促销 $result = WxPayApi::sendRedPack($input); WxLog::DEBUG('极办公用户公众号发红包结果: ' . json_encode($result)); WechatPayWarning::sendManagerMsg('用户公众号', 'sendRedPack', $result); return $result; } /** * 企业付款接口 * @param $openId 转账用户openId(必须是已关注公众号的用户) * @param $amount 转账金额 * @param bool $desc 转账说明 * @return array|mixed * @throws \common\exts\wxpay\ErrorException */ public static function transfersOrder($openId, $amount, $desc = false) { WxLog::init(); // 初始化微信支付配置数据 $config = WxpayConfig::getInstance(UserMPHelper::getWxpayOptions()); $input = new TransfersOrder(); $input->SetPartner_trade_no($config->MCHID . date("YmdHis")); $input->SetDesc($desc ? $desc : '极办公企业付款'); $input->SetOpenid($openId); $input->SetAmount($amount * 100); $input->SetCheck_name('NO_CHECK'); $result = WxPayApi::transfersOrder($input); WxLog::DEBUG('transfersOrder=>企业付款结果: ' . json_encode($result)); //WechatPayWarning::sendManagerMsg('工程师端', 'transfersOrder', $result); return $result; } /** * 获取运营账户余额 * @param $billDate 下载对账单的日期,格式:20140603 * @return float |mixed < 0 读取失败; >= 0 读取成功 * @throws \common\exts\wxpay\ErrorException */ public static function getAccountBalance($billDate) { WxpayLog::init(); // 初始化微信支付配置数据 WxpayConfig::getInstance(self::getWxpayOptions()); $input = new DownloadFundFlow(); $input->SetAccount_type("Operation"); // 账单的资金来源账户: Basic 基本账户 | Operation 运营账户 | Fees 手续费账户 $input->SetBill_date($billDate); $result = WxPayApi::downloadFundFlow($input); if (!empty($result)) { // 第一行为表头; 第二行起,为资金流水数据,各参数以逗号分隔,参数前增加`符号,为标准键盘1左边键的字符,字段顺序与表头一致 $arr = explode("\r\n", $result); $arrSize = count($arr); if (!empty($arr) && $arrSize >= 4) { $dataStr = $arr[$arrSize - 4]; $dataStr = str_replace("`", '', $dataStr); $dataArr = explode(",", $dataStr); $accountBalance = (float)$dataArr[7]; // 第8列是[账户结余] WxpayLog::DEBUG('getAccountBalance=>成功获取[用户公众号]账户余额: ' . $accountBalance); return $accountBalance; } } WxpayLog::DEBUG('getAccountBalance=>获取[用户公众号]账户余额失败: ' . $result); return -1; } /** * 获取商户ID */ public static function getMchId() { $settings = self::getMpSetting(); return $settings->mch_id; } /** * 查询订单接口 * 支付失败字符串 * array(9) { * ["appid"]=> string(18) "wx353a02cfb6fb396e" * ["err_code"]=> string(13) "ORDERNOTEXIST" * ["err_code_des"]=> string(15) "order not exist" * ["mch_id"]=> string(10) "1496776442" * ["nonce_str"]=> string(16) "yLExeHc7glwOChqp" * ["result_code"]=> string(4) "FAIL" * ["return_code"]=> string(7) "SUCCESS" * ["return_msg"]=> string(2) "OK" * ["sign"]=> string(32) "6CF77A6ADC5A619D6497F61AA290A639" * } * * 支付成功字符串 *array(20) { * ["appid"]=> string(18) "wx353a02cfb6fb396e" * ["attach"]=> string(24) "charge201811222114185754" * ["bank_type"]=> string(3) "CFT" * ["cash_fee"]=> string(1) "1" * ["fee_type"]=> string(3) "CNY" * ["is_subscribe"]=> string(1) "Y" * ["mch_id"]=> string(10) "1496776442" * ["nonce_str"]=> string(16) "FAvL6CPLFaxv0Ii0" * ["openid"]=> string(28) "ouTJ71srm1oD7fQiXjTqyPgP2aOU" * ["out_trade_no"]=> string(24) "charge201811222114185754" * ["result_code"]=> string(7) "SUCCESS" * ["return_code"]=> string(7) "SUCCESS" * ["return_msg"]=> string(2) "OK" * ["sign"]=> string(32) "BC19AF28ACA056DEE10BC2E5AFA997A8" * ["time_end"]=> string(14) "20181122211424" * ["total_fee"]=> string(1) "1" * ["trade_state"]=> string(7) "SUCCESS" * ["trade_state_desc"]=> string(12) "支付成功" * ["trade_type"]=> string(5) "JSAPI" * ["transaction_id"]=> string(28) "4200000211201811225568135264" * } * @param $orderNo * @return bool|\common\exts\wxpay\成功时返回,其他抛异常 */ public static function orderQuery($orderNo){ if (empty($orderNo)) { return false; } try { // 初始化微信支付配置数据 WxpayConfig::getInstance(self::getWxpayOptions()); $queryOrderInput = new WxPayOrderQuery(); $queryOrderInput->SetOut_trade_no($orderNo); $result = WxPayApi::orderQuery($queryOrderInput); } catch (Exception $e) { return false; } return !empty($result) ? $result : false; } }