'1002', '农业银行' => '1005', '建设银行' => '1003', '中国银行' => '1026', '交通银行' => '1020', '招商银行' => '1001', '邮储银行' => '1066', '民生银行' => '1006', '平安银行' => '1010', '中信银行' => '1021', '浦发银行' => '1004', '兴业银行' => '1009', '光大银行' => '1022', '广发银行' => '1027', '华夏银行' => '1025', '中原银行' => '4753', '河南省农村信用社' => '4115', '山西省农村信用社' => '4156', '安徽省农村信用社' => '4166', ]; /** * 获得微信支付-付款到零钱/银行卡 API 用到的参数 * * DEPENDENCIES: 数据库读取 */ protected static function getWeixinParams() { // 读取配置 $payment = SystemConfigService::more([ 'pay_routine_appid', 'pay_routine_mchid', 'pay_routine_key', 'pay_routine_client_cert', 'pay_routine_client_key', 'pay_weixin_open', ]); if (!isset($payment['pay_weixin_open']) || !$payment['pay_weixin_open']) { throw new Exception('weixin pay is not enabled.', -1); } $params = new PublicParams(); $params->appID = $payment['pay_routine_appid'] ?? ''; $params->mch_id = $payment['pay_routine_mchid'] ?? ''; $params->key = $payment['pay_routine_key'] ?? ''; $params->keyPath = realpath('.' . $payment['pay_routine_client_key']); $params->certPath = realpath('.' . $payment['pay_routine_client_cert']); return $params; } /** * 付款到微信零钱 * * 文档见 (https://doc.yurunsoft.com/PaySDK/112) * * NOTICE: 本函数只是调用微信 API,并未进行业务逻辑处理。 * * @param int $openid: wechat user openid * @param string $trade_no: 付款订单号,平台自定义 * @param int $amount: 金额,单位为元,内部转换为分 * @param string $desc: 订单描述 * @param string $realname: 收款放真实姓名, 参数 check_name 为 FORCE_CHECK 时使用。 * * @return (bool, int, string) (是否成功,错误代码,错误信息) * * TODO: 微信付款升级为 V3(https://wechatpay-api.gitbook.io/wechatpay-api-v3/wei-xin-zhi-fu-api-v3-jie-kou-gui-fan) * 本功能使用 Yurunsoft/PaySDK 也已支持 V3 (2021/11/28),但申请微信支付时未申请微信 V3 相关 Key。等待升级使用 V3 协议,或再做一个函数 */ public static function toWeixin($openid, $trade_no, $amount, $desc='', $realname='') { try { $caller_ip = Config::get('app.server_ip', '127.0.0.1'); $params = self::getWeixinParams(); $sdk = new SDK($params); $req = new Request(); $req->partner_trade_no = $trade_no; $req->openid = $openid; $req->check_name = 'NO_CHECK'; $req->re_user_name = $realname; $req->amount = intval(bcmul($amount, 100, 0)); $req->desc = $desc; $req->spbill_create_ip = $caller_ip; // 调用接口的机器IP, 这个可能微信用于验证 $res = $sdk->execute($req); if (!$sdk->checkResult($res)) { $err = $sdk->getError($res); errlog("toWeixin(): error=$err openid=$openid amount=$amount"); return [false, $sdk->getErrorCode($res), '微信通道执行失败']; } else { return [true, 0, '']; } } catch (\Exception $e) { $err = $e->getMessage(); errlog("toWeixin(): exception=$err openid=$openid amount=$amount"); return [false, $e->getCode(), '微信通道执行失败']; } } /** * 通过微信支付付款到银行卡 * * @param string $trade_no: 本次交易订单号 * @param float $amount: 金额(元),内部转为分 * @param string $bank_no: 银行卡号 * @param string $true_name: 户名 * @param string $bank_code: 银行名称,内部转为银行代码(微信平台官方定义 https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_4) * @param string $desc: 描述,会通过银行收到 */ public static function toBankByWeixin($trade_no, $amount, $bank_no, $true_name, $bank_name, $desc='') { try { $params = self::getWeixinParams(); $sdk = new SDK($params); $req = new BankRequest(); // TODO: 部署时需要这个文件提前就位,后台暂时没有上传接口 $rsaPublicCertFile = dirname($params->certPath) . DIRECTORY_SEPARATOR . 'wx_rsa_pub_key.pem'; $req->rsaPublicCertFile = $rsaPublicCertFile; $req->partner_trade_no = $trade_no; $req->enc_bank_no = $bank_no; $req->enc_true_name = $true_name; $bank_code = self::BANK_MAP[$bank_name]??''; if (!$bank_code) { return [false, 100403, '不支持的银行']; } $req->bank_code = $bank_code; $req->amount = intval(bcmul($amount, 100, 0)); // 最长为 100 字符,一般不会超过,超过就让失败 if (mb_strlen($desc) > 0) { $req->desc = $desc; } $res = $sdk->execute($req); if (!$sdk->checkResult($res)) { $err = $sdk->getError($res); errlog("error=$err bank_no=$bank_no true_name=$true_name bank_name=$bank_name amount=$amount"); return [false, $sdk->getErrorCode($res), '付款通道执行失败']; } else { return [true, 0, '']; } } catch (\Exception $e) { $err = $e->getMessage(); errlog("exception=$err bank_no=$bank_no true_name=$true_name bank_name=$bank_name amount=$amount"); return [false, $e->getCode(), '付款通道执行失败']; } } /** * 获取微信 RSA PUBLIC KEY * * 调用接口后,保存 pub_key 字段内容为 pem (eg. pub.pem) 文件,手动分为一行一行的格式。 * 然后执行 openssl rsa -RSAPublicKey_in -in rsa_pub_key.pem -out pcs8.pem * pcs8.pem 可用于加密 API */ public static function get_rsa() { try { $params = self::getWeixinParams(); $sdk = new SDK($params); $req = new \Yurun\PaySDK\Weixin\GetPublicKey\Request(); $res = $sdk->execute($req); var_dump($res); } catch(\Exception $e) { var_dump($e->getMessage()); } } /** * 付款到支付宝 */ public static function toAlipay() { } /** * 通过支付宝付款到银行卡 */ public static function toBankByAlipay() { } }