<?php use app\common\model\WxSubMember; use think\Controller; use WeChatPay\Builder; use WeChatPay\Crypto\Rsa; use WeChatPay\Util\PemUtil; class WechatSub { /** 准备部分 * 1.文档(v3分账) https://pay.weixin.qq.com/docs/merchant/products/profit-sharing/apilist.html * 2.商户号 munch_id * 3.商户私钥--merchantPrivateKey--商户平台开可以下载 * 4.商户证书序列号--merchantCertSerialNo--商户平台可以下载 * 5.微信支付平台证书--自己在本地生成--具体步骤见其他控制器 * 6. sdk-- composer require wechatpay/wechatpay * 7. 支付订单的是否需要传分账标识profit_sharing--true/false */ /** * @return \WeChatPay\BuilderChainable */ public function getInstance(): \WeChatPay\BuilderChainable { $merchantId = '商户号'; // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名 $merchantPrivateKeyFilePath = '商户私钥的文件路径'; $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE); // 「商户API证书」的「证书序列号」 $merchantCertificateSerial = '证书序列号'; // 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名 $platformCertificateFilePath = '自己生成的微信平台证书的路径'; $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC); // 从「微信支付平台证书」中获取「证书序列号」 $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath); // 构造一个 APIv3 客户端实例 $instance = Builder::factory([ 'mchid' => $merchantId, 'serial' => $merchantCertificateSerial, 'privateKey' => $merchantPrivateKeyInstance, 'certs' => [ $platformCertificateSerial => $platformPublicKeyInstance, ], ]); // 加密敏感信息 $encryptor = static function (string $msg) use ($platformPublicKeyInstance): string { return \WeChatPay\Crypto\Rsa::encrypt($msg, $platformPublicKeyInstance); }; return $instance; } /** * 特别注意 * 1.微信分账的订单在下单支付的时候 需要把订单的分账标识打开,在实际业务中可根据自身情况灵活控制 * 2.微信没有查询分账接收方这个接口,需要自己建表把分账接收方存起来 * 3.微信的分账产品开通容易但是提升额度比较困难,最大支持30的比例,30的意思是100元中最多有30元可以分出去,不是每个人最多30,若需要提高比例则要向微信提出书面申请 */ private function getEncrypt($str) { //$str是待加密字符串 $public_key_path = $this->public_path() . 'static/cert/3.pem'; $public_key = file_get_contents($public_key_path); $encrypted = ''; if (openssl_public_encrypt($str, $encrypted, $public_key, OPENSSL_PKCS1_OAEP_PADDING)) { //base64编码 $sign = base64_encode($encrypted); } else { throw new Exception('encrypt failed'); } return $sign; } /** * 添加分账接收方 */ public function addWxMember($user) { // $user数组 $instance = $this->getInstance(); $resp = $instance->chain('v3/profitsharing/receivers/add')->post( [ 'debug' => false, 'json' => [ 'appid' => 'wx7ac5a73893c2c6b8', 'type' => 'PERSONAL_OPENID', 'account' => $user['account'], //'name' => $this->getEncrypt('name'), //如果给商户分账 这个name字段必传 'relation_type' => 'USER' ] ] // 调试模式,https://docs.guzzlephp.org/en/stable/request-options.html#debug ); $response = json_decode($resp->getBody()->getContents(), true); /** * 返回数据示例 * "type" : "MERCHANT_ID", * "account" : "example_account", * "name" : "example_name", * "relation_type" : "SERVICE_PROVIDER", * "custom_relation" : "example_custom_relation" */ if ($response) { // wx没有查询分账接收方这一接口,所以微信分账添加或删除接收方都需要自己存到数据库--(微信分账接收方表) $data = []; $data['account'] = $user['account']; $data['type'] = 'PERSONAL_OPENID'; $data['createtime'] = time(); WxSubMember::create($data); return true; } else { return false; } //halt(json_decode($resp->getBody()->getContents(), true), PHP_EOL); //return $response; } /** * 删除分账接收方 */ public function deleteWxMember($user) { // 商户号 $instance = $this->getInstance(); // 发送请求 auth证书 $resp = $instance->chain('v3/profitsharing/receivers/delete')->post( [ 'debug' => false, 'json' => [ 'appid' => $user['appid'], 'type' => $user['type'], 'account' => $user['openid'], //'name' => $encryptor('a'),//如果是给商户进行分账时会用到这个 ], ] // 调试模式,https://docs.guzzlephp.org/en/stable/request-options.html#debug ); $response = json_decode($resp->getBody()->getContents(), true); if ($response) { WxSubMember::where('id', '=', $user['id'])->delete(); return true; } else { return false; } } /** * 分账 */ public function subWx($orderInfo) { // 商户号 $instance = $this->getInstance(); //组装分账接收方数据 $data = []; //业务逻辑部分,如果是多人请用二维数组 $aa = [ 'type' => 'PERSONAL_OPENID', 'account' => '填写分账接收方的openid', 'amount' => 1,//单位是分 'description' => '完成首单返佣' ]; $data[] = $aa; try { $resp = $instance->chain('v3/profitsharing/orders')->post( [ 'debug' => false, 'json' => [ 'appid' => 'wx7ac5a73893c2c6b8', 'transaction_id' => $orderInfo->wx_order_num,//微信订单号(微信官方生成的订单号) 'out_order_no' => '分账请求订单号',//内部分账单号,自己生成,用这个订单号查询分账是否完成 'receivers' => $data, 'unfreeze_unsplit' => true //如果为false,该笔订单剩余未分账的金额不会解冻回分账方商户,可以对该笔订单再次进行分账。 ] ] // 调试模式,https://docs.guzzlephp.org/en/stable/request-options.html#debug ); } catch (\Throwable $e) { halt($e->getMessage()); } $result = json_decode($resp->getBody()->getContents(), true); //halt(json_decode($resp->getBody()->getContents(), true), PHP_EOL); if ($result) { return true; } else { return false; } } /** * 查询分账结果 */ public function getWxSubData($data) { //todo 待测 $instance = $this->getInstance(); $response = $instance->chain('v3/transactions/split/query')->get([ 'transaction_id' => $data['transaction_id'],//支付订单号 ]); $result = json_decode($response->getBody(), true); if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') { // 输出分账结果 echo "分账结果查询成功,分账单号:{$result['split_id']},分账金额:{$result['split_amount']}"; } else { // 输出错误信息 echo "分账结果查询失败,错误代码:{$result['return_code']},错误信息:{$result['return_msg']}"; } } }
最后检测日期:2023/10/09