Browse Source

支持微信支付提现到银行卡

joe 4 năm trước cách đây
mục cha
commit
c311c47b78

+ 12 - 0
app/admin/controller/Test.php

@@ -20,6 +20,7 @@ use crmeb\services\async\task\WechatNotify;
 use think\facade\Config;
 use RobThree\Auth\TwoFactorAuth;
 use RobThree\Auth\TwoFactorAuthException;
+use tw\redis\TwRedis;
 use tw\redis\UserRds;
 
 class Test
@@ -29,6 +30,11 @@ class Test
 
         $redis = Redis::instance();
         var_dump($redis->get(['CRMEB','TESD']));
+
+        echo '</br>';
+        $twredis = TwRedis::instance();
+        echo '</br>';
+        print_r($twredis::hGetAll('user:1'));
     }
 
     protected function test_board() {
@@ -116,8 +122,14 @@ class Test
         var_dump($ok, $ec, $es);
     }
 
+    protected function get_rsa_key()
+    {
+        MachantPay::get_rsa();
+    }
+
     public function test()
     {
+        // $this->get_rsa_key();
         // $this->test_enterprise_pay();
         // echo $this->test_async_func();
         // $this->test_redis();

+ 79 - 5
crmeb/payment/MachantPay.php

@@ -4,10 +4,10 @@ namespace crmeb\payment;
 
 use \Yurun\PaySDK\Weixin\Params\PublicParams;
 use \Yurun\PaySDK\Weixin\CompanyPay\Weixin\Pay\Request;
+use \Yurun\PaySDK\Weixin\CompanyPay\Bank\Pay\Request as BankRequest;
 use \Yurun\PaySDK\Weixin\SDK; // TODO: update to V3
 use crmeb\services\SystemConfigService;
 use EasyWeChat\Core\Exception;
-use \think\facade\Log;
 use \think\facade\Config;
 /**
  * 企业付款
@@ -16,6 +16,28 @@ use \think\facade\Config;
  */
 class MachantPay {
 
+    const BANK_MAP = [
+        '工商银行'       => '1002',
+        '农业银行'	     => '1005',
+        '建设银行'	     => '1003',
+        '中国银行'	     => '1026',
+        '交通银行'	     => '1020',
+        '招商银行'	     => '1001',
+        '邮储银行'	     => '1066',
+        '民生银行'	     => '1006',
+        '平安银行'	     => '1010',
+        '中信银行'	     => '1021',
+        '浦发银行'	     => '1004',
+        '兴业银行'	     => '1009',
+        '光大银行'	     => '1022',
+        '广发银行'	     => '1027',
+        '华夏银行'	     => '1025',
+        '中原银行'	     => '4753',
+        '河南省农村信用社' => '4115',
+        '山西省农村信用社' => '4156',
+        '安徽省农村信用社' => '4166',
+    ];
+    
     /**
      * 获得微信支付-付款到零钱/银行卡 API 用到的参数
      * 
@@ -43,7 +65,7 @@ class MachantPay {
         $params->key = $payment['pay_routine_key'] ?? '';
         $params->keyPath = realpath('.' . $payment['pay_routine_client_key']);
         $params->certPath = realpath('.' . $payment['pay_routine_client_cert']);
-
+        var_dump($payment['pay_routine_client_key']);
         return $params;
     }
 
@@ -56,7 +78,7 @@ class MachantPay {
      * 
      * @param int $openid: wechat user openid
      * @param string $trade_no: 付款订单号,平台自定义
-     * @param int $amount: 金额,单位为分
+     * @param int $amount: 金额,单位为元,内部转换为
      * @param string $desc: 订单描述
      * @param string $realname: 收款放真实姓名, 参数 check_name 为 FORCE_CHECK 时使用。
      * 
@@ -88,20 +110,72 @@ class MachantPay {
                 $sdk->getError($res),
             ];
         } catch (\Exception $e) {
-            Log::warning('exception:' . $e->getMessage());
+            errlog('exception:' . $e->getMessage());
             return [false, $e->getCode(), $e->getMessage()];
         }
     }
 
     /**
      * 通过微信支付付款到银行卡
+     * 
+     * @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() 
+    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));
+            $req->desc = $desc;
+
+            $res = $sdk->execute($req);
+
+            return [
+                $sdk->checkResult($res),
+                $sdk->getErrorCode($res),
+                $sdk->getError($res),
+            ];
         } catch (\Exception $e) {
+            errlog('exception:' . $e->getMessage());
+            return [false, $e->getCode(), $e->getMessage()];
+        }
+    }
 
+    /**
+     * 获取微信 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());
         }
     }
 

+ 7 - 1
crmeb/services/payment/PaymentService.php

@@ -167,7 +167,13 @@ class PaymentService
                 return MachantPay::toWeixin($openid, $trade_no, $extractInfo['extract_price'], '佣金提现', $extractInfo['real_name']);
             case 'bank':
                 // 记忆银行信息
-                break;
+                $user = new UserRds();
+                $user->sets($extractInfo['uid'], [
+                    'bankCardNo' => $extractInfo['bank_code'],
+                    'bankUser' => $extractInfo['real_name'],
+                    'bankName' => $extractInfo['bank_address'],
+                ]);
+                return MachantPay::toBankByWeixin($trade_no, $extractInfo['extract_price'], $extractInfo['bank_code'], $extractInfo['real_name'], $extractInfo['bank_address']);
             default:
                 // 其他情况不处理,返回失败
                 errlog('unbelievable error: extract_type='. $extractInfo['extract_type']);

+ 6 - 0
tw/redis/traits/HashTrait.php

@@ -34,6 +34,12 @@ trait HashTrait
         return TwRedis::hSet($this->key($word), $attr, $value);
     }
 
+    /**
+     * 设置多个 attr
+     * 
+     * @param array $attrs: ['attr1'=>'value1', 'attr2' => 'value2']
+     * @return bool
+     */
     public function sets($word, array $attrs) : bool
     {
         return TwRedis::hMSet($this->key($word), $attrs);