微信小程序服务商模式支付日记

业务需求

公司的需求是,在小程序商城支付的钱不要经过我们公司账上(服务商),用户支付后钱直接转到供应商(特约子商户)。备注:我们的需求是一笔订单只支持单个供应商下单。

申请配置

注册服务号!别的不行,然后就是例行的微信认证。
认证完找到微信支付----》服务商申请
其中:无资金结算功能,商户交易资金直接结算至特约商户的账户;

在这里插入图片描述

1.开通分账功能

开通分账功能,产品中心->我的产品->分账,开通后产品设置,设置分账比例
在这里插入图片描述

2.添加分账接收方

在这里插入图片描述

开发

我们项目使用了 “overtrue/laravel-wechat”: “~4.0”

说明:实现分账只是在普通支付下单接口中新增了一个分账参数profit_sharing,其他与普通支付方式完全相同。目前支持付款码支付、JSAPI支付、Native支付、APP支付、小程序支付、H5支付、委托代扣、车主平台。

发起支付

		$app = \EasyWeChat::payment();
		
        $notifyUrl = env('APP_URL').'/****/notify';

        $param = [
            'body' => '样品购买',
            'out_trade_no' => $orderInfo->order_no,// 系统订单号
            'trade_type' => 'JSAPI',  // 必须为JSAPI
            'sub_openid' => $userInfo["wx_openid"],// 这里的openid为付款人的openid,巨坑
            'total_fee' => $orderInfo->actual_total_fee, // 总价
            'profit_sharing' => 'Y',    // 是否指定服务商分账  Y-是,需要分账/N-否,不分账/字母要求大写,不传默认不分账
            'sub_mch_id' => $supplierInfo->sub_mchid,// 这里对应特约商户号id 付款到对应商户
            'notify_url' => $notifyUrl
        ];
        \Log::info("订单发起微信支付,参数:" . json_encode($param));
        $result = $app->order->unify($param);

        // 如果成功生成统一下单的订单,那么进行二次签名
        if ($result['return_code'] === 'SUCCESS') {
            // 二次签名的参数必须与下面相同
            $params = [
                'appId' => config('wechat.mini_program.default.app_id'),//小程序app_id
                'timeStamp' => time(),
                'nonceStr' => $result['nonce_str'],
                'package' => 'prepay_id=' . $result['prepay_id'],
                'signType' => 'MD5',
            ];

            // config('wechat.payment.default.key')为商户的key
            $params['paySign'] = generate_sign($params, config('wechat.payment.default.key'));
            return $this->responseJsonSuccess('success', $params);
        } else {
            \Log::error("发起微信错误:" . json_encode($result));
            return $this->responseJsonError("800062|发起微信支付失败");
        }

回调

回调就按正常走,具体参考官方文档。我使用的EasyWeChat的包,参考文档详情

分账

在特约商户后台发现金额是冻结状态
在这里插入图片描述

分账的官方文档说明
在这里插入图片描述
因为EasyWeChat4.x还没用微信分账的可调用方法,5.x及以上才有,这边我就自己手写(copy)一个类实现。我是直接调用微信分账的完成分账接口。

	//格式化参数格式化成url参数  生成签名sign
    public function appgetSign($data)
    {
        foreach ($data as $k => $v) {
            $params[$k] = $v;
        }

        //签名步骤一:按字典序排序参数
        ksort($params); // ksort — 对数组按照键名排序

        $string = $this->formatBizQueryParaMap($params, false);
        $string = $string . "&key=" . config("wechat.payment.default.key");
        if ($data["sign_type"] == "HMAC-SHA256") {
            $string = hash_hmac("sha256", $string, config("wechat.payment.default.key"));
        } else {
            //签名步骤三:MD5加密
            $string = md5($string);
        }

        //签名步骤四:所有字符转为大写
        $result = strtoupper($string);
        return $result;
    }

    //按字典序排序参数
    public function formatBizQueryParaMap($paraMap, $urlencode)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if ($urlencode) {
                $v = urlencode($v); //urlencode — 编码 URL 字符串
            }
            //$buff .= strtolower($k) . "=" . $v . "&";
            $buff .= $k . "=" . $v . "&";
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }

    //将数组转换为xml格式
    public function arrayToXml($arr, $bool)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if ($bool) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }

    //发送请求
    public function sendPrePayCurl($xml, $url = '', $options = array())
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        $data = curl_exec($ch);
        curl_close($ch);

        $data_xml_arr = $this->XMLDataParse($data);
        if ($data_xml_arr) {
            return $data_xml_arr;
        } else {
            return false;
        }
    }

    //xml格式数据解析函数
    public function XMLDataParse($data)
    {
        $xml = simplexml_load_string($data, NULL, LIBXML_NOCDATA);
        $array = json_decode(json_encode($xml), true);
        return $array;
    }

    // 完结分账
    public function finishSplit($subMchId,$transactionId)
    {
        header("Content-Type:text/html;charset=utf8");

        $param = [
            "mch_id" => config("wechat.payment.default.mch_id"),
            "sub_mch_id" => $subMchId,
            "appid" => config("wechat.payment.default.app_id"),
            "nonce_str" => $this->createNoncestr(),// 随机字符串
            "sign_type" => "HMAC-SHA256",
            "out_order_no" => rand(1000,9999),
            "transaction_id" => $transactionId,
            "description" => "分账已完成"
        ];

        // 签名
        $param["sign"] = $this->appgetSign($param);
        //把数组转化成xml格式
        $xmlData = $this->arrayToXml($param, true);
        $options = array(
            CURLOPT_SSLCERT => config("wechat.payment.default.cert_path"),// 客户端证书,用于双向认证
            CURLOPT_SSLCERTTYPE => 'PEM',// 证书的类型。支持的格式有"PEM" (默认值), "DER"和"ENG"。
            CURLOPT_SSLKEY => config("wechat.payment.default.key_path"),// 客户端私钥的文件路径
            CURLOPT_SSLKEYTYPE => 'PEM',// 客户端私钥类型,支持的私钥类型为"PEM"(默认值)、"DER"和"ENG"。
            CURLOPT_KEYPASSWD => config("wechat.payment.default.key"),//客户端私钥密码,私钥在创建时可以选择加密。
            //API证书调用或安装需要使用到密码,该密码的值为微信商户号(mch_id)
        );

        $url = "https://api.mch.weixin.qq.com/secapi/pay/profitsharingfinish";

        $result = $this->sendPrePayCurl($xmlData, $url, $options);
        return $result;
     }

总结

服务商模式微信的官方文档还是比较混乱的(至少我是这么认为的)。也是网上找了很多人的文章。个人认为这篇文章还不够完善,多个特约服务商分账还没尝试,后续还会更新。

参考:
https://blog.csdn.net/qq_18881987/article/details/94428628
https://blog.csdn.net/qq_29755359/article/details/104963754

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值