Home  >  Article  >  Backend Development  >  Following the update trend, the guaranteed payment class of the PHP byte applet has also been updated!

Following the update trend, the guaranteed payment class of the PHP byte applet has also been updated!

藏色散人
藏色散人forward
2021-07-16 15:23:314225browse

The WeChat payment class update is over. I turned around and found that ByteDance has also updated payment. So following the trend, I also updated the ByteDance payment class. The new version uses the latest version of the V1 interface (guarantee Payment introduction), and a new composer installation is added to facilitate the use of the integrated framework (Github address)

can also be copied and used separately:

composer require fengkui/pay

(Note: Due to business needs, only relevant methods are written, not yet tested, for reference only)

First fill in the configuration file completely:

// 支付相关配置
private static $config = array(
	'app_id'        => '', // App ID
	'salt'          => '', // 支付密钥值
	'notify_url'    => '', // 支付回调地址
	'thirdparty_id' => '', // 第三方平台服务商 id,非服务商模式留空
);

Payment class encapsulation related methods:

##queryOrderOrder query notifyOrderOrder callback verificationcreateRefundOrder refundqueryRefundRefund query##settlequerySettleUsage:
method Description
createOrder Place an order and pay
Settle request
Settle query

<?php
require_once(&#39;./vendor/autoload.php&#39;);

$config = []; // 支付配置
$order = [
    &#39;order_sn&#39; => time(), // 订单编号
    &#39;total_amount&#39; => 1, // 订单金额(分)
    &#39;body&#39; => &#39;测试商品&#39;, // 商品名称
];

$wechat = new fengkui\Pay\Bytedance($config);
$re = $wechat->createOrder($order);
die(json_encode($re)); // JSON化直接返回小程序客户端

The following code is a complete encapsulated payment class file (Bytedance.php), You can modify it at will according to your own needs. Detailed usage methods will be documented later:

<?php
/**
 * @Author: [FENG] <1161634940@qq.com>
 * @Date:   2020-05-13 17:02:49
 * @Last Modified by:   [FENG] <1161634940@qq.com>
 * @Last Modified time: 2021-06-15T17:06:18+08:00
 */
namespace fengkui\Pay;

use fengkui\Supports\Http;

/**
 * Bytedance 字节跳动支付
 * 小程序担保支付(V1)
 */
class Bytedance
{
    // 接口版本
    const EDITON = &#39;v1&#39;;

    // 统一下订单管理
    private static $ecpayUrl = &#39;https://developer.toutiao.com/api/apps/ecpay/&#39;;
    // 服务端预下单
    private static $createOrderUrl = &#39;https://developer.toutiao.com/api/apps/ecpay/v1/create_order&#39;;
    // 订单查询
    private static $queryOrderUrl = &#39;https://developer.toutiao.com/api/apps/ecpay/v1/query_order&#39;;
    // 退款
    private static $createRefundUrl = &#39;https://developer.toutiao.com/api/apps/ecpay/v1/create_refund&#39;;
    // 查询退款
    private static $queryRefundUrl = &#39;https://developer.toutiao.com/api/apps/ecpay/v1/query_refund&#39;;
    // 分账请求
    private static $settleUrl = &#39;https://developer.toutiao.com/api/apps/ecpay/v1/settle&#39;;
    // 查询分账
    private static $querySettleUrl = &#39;https://developer.toutiao.com/api/apps/ecpay/v1/query_settle&#39;;
    // 服务商进件
    private static $addMerchantUrl = &#39;https://developer.toutiao.com/api/apps/ecpay/saas/add_merchant&#39;;
    // 分账方进件
    private static $addSubMerchantUrl = &#39;https://developer.toutiao.com/api/apps/ecpay/saas/add_sub_merchant&#39;;

    // 支付相关配置
    private static $config = array(
        &#39;app_id&#39;        => &#39;&#39;, // App ID
        &#39;salt&#39;          => &#39;&#39;, // 支付密钥值
        &#39;notify_url&#39;    => &#39;&#39;, // 支付回调地址
        &#39;thirdparty_id&#39; => &#39;&#39;, // 第三方平台服务商 id,非服务商模式留空
    );

    /**
     * [__construct 构造函数]
     * @param [type] $config [传递支付相关配置]
     */
    public function __construct($config=NULL){
        $config && self::$config = array_merge(self::$config, $config);
    }

    /**
     * [createOrder 下单支付]
     * @param  [type] $order [description]
     * @return [type]        [description]
     * $order = array(
     *      &#39;body&#39;         => &#39;&#39;, // 产品描述
     *      &#39;total_amount&#39; => &#39;&#39;, // 订单金额(分)
     *      &#39;order_sn&#39;     => &#39;&#39;, // 订单编号
     * );
     */
    public static function createOrder($order)
    {
        $config = self::$config;
        $params = [
            &#39;app_id&#39;        => $config[&#39;app_id&#39;], // 是 小程序 AppID
            &#39;out_order_no&#39;  => (string)$order[&#39;order_sn&#39;], // 是 开发者侧的订单号, 同一小程序下不可重复
            &#39;total_amount&#39;  => $order[&#39;total_amount&#39;], // 是 支付价格; 接口中参数支付金额单位为[分]
            &#39;subject&#39;       => $order[&#39;body&#39;], // 是 商品描述; 长度限制 128 字节,不超过 42 个汉字
            &#39;body&#39;          => $order[&#39;body&#39;], // 是 商品详情
            &#39;valid_time&#39;    => 3600 * 2, // 是 订单过期时间(秒); 最小 15 分钟,最大两天
            // &#39;sign&#39;          => &#39;&#39;, // 是 开发者对核心字段签名, 签名方式见文档附录, 防止传输过程中出现意外
            // &#39;cp_extra&#39;      => &#39;&#39;, // 否 开发者自定义字段,回调原样回传
            // &#39;notify_url&#39;    => $config[&#39;notify_url&#39;], // 否 商户自定义回调地址
            // &#39;thirdparty_id&#39; => &#39;&#39;, // 否 第三方平台服务商 id,非服务商模式留空
            &#39;disable_msg&#39;   => 1, // 否 是否屏蔽担保支付的推送消息,1-屏蔽 0-非屏蔽,接入 POI 必传
            // &#39;msg_page&#39;      => &#39;&#39;, // 否 担保支付消息跳转页
            // &#39;store_uid&#39;     => &#39;&#39;, // 否 多门店模式下,门店 uid
        ];
        !empty($order[&#39;cp_extra&#39;]) && $params[&#39;cp_extra&#39;] = $order[&#39;cp_extra&#39;];
        !empty($config[&#39;notify_url&#39;]) && $params[&#39;notify_url&#39;] = $config[&#39;notify_url&#39;];
        !empty($config[&#39;thirdparty_id&#39;]) && $params[&#39;thirdparty_id&#39;] = $config[&#39;thirdparty_id&#39;];
        if (!empty($config[&#39;msg_page&#39;])) {
            $params[&#39;disable_msg&#39;] = 0;
            $params[&#39;msg_page&#39;] = $config[&#39;msg_page&#39;];
        }

        $params[&#39;sign&#39;] = self::makeSign($params);
        // dump($params);die;
        $url = self::$createOrderUrl;
        $response = Http::post($url, json_encode($params));
        $result = json_decode($response, true);
        return $result;
    }

    /**
     * [queryOrder 订单查询]
     * @param  [type] $orderSn [开发者侧的订单号, 不可重复]
     * @return [type]          [description]
     */
    public static function queryOrder($orderSn)
    {
        $config = self::$config;
        $params = [
            &#39;app_id&#39; => $config[&#39;app_id&#39;], // 小程序 AppID
            &#39;out_order_no&#39; => (string)$orderSn, // 开发者侧的订单号, 不可重复
            // &#39;sign&#39; => &#39;&#39;, // 开发者对核心字段签名, 签名方式见文档, 防止传输过程中出现意外
            // &#39;thirdparty_id&#39; => &#39;&#39;, // 服务商模式接入必传	第三方平台服务商 id,非服务商模式留空
        ];

        !empty($config[&#39;thirdparty_id&#39;]) && $params[&#39;thirdparty_id&#39;] = $config[&#39;thirdparty_id&#39;];
        $params[&#39;sign&#39;] = self::makeSign($params);

        $url = self::$queryOrderUrl;
        $response = Http::post($url, json_encode($params));
        $result = json_decode($response, true);
        return $result;
    }

    /**
     * [notifyOrder 订单回调验证]
     * @return [array] [返回数组格式的notify数据]
     */
    public static function notifyOrder()
    {
        $data = $_POST; // 获取回调数据
        $config = self::$config;
        if (!$data || empty($data[&#39;msg&#39;]))
            die(&#39;暂无回调信息&#39;);

        $result = json_decode($data[&#39;msg&#39;], true); // 进行签名验证
        // 判断签名是否正确  判断支付状态
        if ($result && $data[&#39;type&#39;]==&#39;payment&#39;) {
            return $data;
        } else {
            return false;
        }
    }

    /**
     * [createRefund 订单退款]
     * @param  [type] $order [订单相关信息]
     * @return [type]        [description]
     * $order = array(
     *      &#39;order_sn&#39;     => &#39;&#39;, // 订单编号
     *      &#39;refund_sn&#39;    => &#39;&#39;, // 退款编号
     *      &#39;total_amount&#39; => &#39;&#39;, // 订单金额(分)
     *      &#39;body&#39;         => &#39;&#39;, // 退款原因
     * );
     */
    public static function createRefund($order)
    {
        $config = self::$config;
        $params = [
            &#39;app_id&#39;        => $config[&#39;app_id&#39;], // 是	小程序 id
            &#39;out_order_no&#39;  => (string)$order[&#39;order_sn&#39;], // 是	商户分配订单号,标识进行退款的订单
            &#39;out_refund_no&#39; => (string)$order[&#39;refund_sn&#39;], // 是	商户分配退款号
            &#39;refund_amount&#39; => $order[&#39;total_amount&#39;], // 是	退款金额,单位[分]
            &#39;reason&#39;        => $order[&#39;body&#39;] ?? &#39;用户申请退款&#39;, // 是	退款理由,长度上限 100
            // &#39;cp_extra&#39;      => &#39;&#39;, // 否	开发者自定义字段,回调原样回传
            // &#39;notify_url&#39;    => &#39;&#39;, // 否	商户自定义回调地址
            // &#39;sign&#39;          => &#39;&#39;, // 是	开发者对核心字段签名, 签名方式见文档, 防止传输过程中出现意外
            // &#39;thirdparty_id&#39; => &#39;&#39;, // 否,服务商模式接入必传	第三方平台服务商 id,非服务商模式留空
            &#39;disable_msg&#39;   => 1, // 否	是否屏蔽担保支付消息,1-屏蔽
            // &#39;msg_page&#39;      => &#39;&#39;, // 否	担保支付消息跳转页
            // &#39;all_settle&#39;    => &#39;&#39;, // 否	是否为分账后退款,1-分账后退款;0-分账前退款。分账后退款会扣减可提现金额,请保证余额充足
        ];

        !empty($order[&#39;cp_extra&#39;]) && $params[&#39;cp_extra&#39;] = $order[&#39;cp_extra&#39;];
        !empty($order[&#39;all_settle&#39;]) && $params[&#39;all_settle&#39;] = $order[&#39;all_settle&#39;];
        !empty($config[&#39;thirdparty_id&#39;]) && $params[&#39;thirdparty_id&#39;] = $config[&#39;thirdparty_id&#39;];
        if (!empty($config[&#39;msg_page&#39;])) {
            $params[&#39;disable_msg&#39;] = 0;
            $params[&#39;msg_page&#39;] = $config[&#39;msg_page&#39;];
        }

        $params[&#39;sign&#39;] = self::makeSign($params);

        $url = self::$queryOrderUrl;
        $response = Http::post($url, json_encode($params));
        $result = json_decode($response, true);
        return $result;
    }

    /**
     * [queryRefund 退款查询]
     * @param  [type] $refundSn [开发者侧的订单号, 不可重复]
     * @return [type]           [description]
     */
    public static function queryRefund($refundSn)
    {
        $config = self::$config;
        $params = [
            &#39;app_id&#39; => $config[&#39;app_id&#39;], // 小程序 AppID
            &#39;out_refund_no&#39; => $refundSn, // 开发者侧的退款号
            // &#39;sign&#39; => &#39;&#39;, // 开发者对核心字段签名, 签名方式见文档, 防止传输过程中出现意外
            // &#39;thirdparty_id&#39; => &#39;&#39;, // 服务商模式接入必传	第三方平台服务商 id,非服务商模式留空
        ];

        !empty($config[&#39;thirdparty_id&#39;]) && $params[&#39;thirdparty_id&#39;] = $config[&#39;thirdparty_id&#39;];
        $params[&#39;sign&#39;] = self::makeSign($params);

        $url = self::$queryRefundUrl;
        $response = Http::post($url, json_encode($params));
        $result = json_decode($response, true);
        return $result;
    }

    /**
     * [notifyRefund 退款回调验证]
     * @return [array] [返回数组格式的notify数据]
     */
    public static function notifyRefund()
    {
        $data = $_POST; // 获取回调数据
        $config = self::$config;
        if (!$data || empty($data[&#39;status&#39;]))
            die(&#39;暂无回调信息&#39;);

        $result = json_decode($data[&#39;msg&#39;], true); // 进行签名验证
        // 判断签名是否正确  判断支付状态
        if ($result && $data[&#39;status&#39;]!=&#39;FAIL&#39;) {
            return $data;
        } else {
            return false;
        }
    }

    /**
     * [settle 分账请求]
     * @param  [type] $order [分账信息]
     * @return [type]        [description]
     * $order = array(
     *      &#39;body&#39;         => &#39;&#39;, // 产品描述
     *      &#39;total_amount&#39; => &#39;&#39;, // 订单金额(分)
     *      &#39;order_sn&#39;     => &#39;&#39;, // 订单编号
     * );
     */
    public static function settle($order)
    {
        $config = self::$config;
        $params = [
            &#39;app_id&#39;        => $config[&#39;app_id&#39;], // 是 小程序 AppID
            &#39;out_order_no&#39;  => (string)$order[&#39;order_sn&#39;], // 是 商户分配订单号,标识进行结算的订单
            &#39;out_settle_no&#39; => (string)$order[&#39;settle_sn&#39;], // 是 开发者侧的结算号, 不可重复
            &#39;settle_desc&#39;   => $order[&#39;body&#39;], // 是	结算描述,长度限制 80 个字符
            // &#39;cp_extra&#39;      => &#39;&#39;, // 否	开发者自定义字段,回调原样回传
            // &#39;notify_url&#39;    => &#39;&#39;, // 否	商户自定义回调地址
            // &#39;sign&#39;          => &#39;&#39;, // 是	开发者对核心字段签名, 签名方式见文档, 防止传输过程中出现意外
            // &#39;thirdparty_id&#39; => &#39;&#39;, // 否,服务商模式接入必传	第三方平台服务商 id,非服务商模式留空
            // &#39;settle_params&#39; => &#39;&#39;, // 否,其他分账方信息,分账分配参数 SettleParameter 数组序列化后生成的 json 格式字符串
        ];

        !empty($order[&#39;cp_extra&#39;]) && $params[&#39;cp_extra&#39;] = $order[&#39;cp_extra&#39;];
        !empty($order[&#39;settle_params&#39;]) && $params[&#39;settle_params&#39;] = $order[&#39;settle_params&#39;];
        !empty($config[&#39;thirdparty_id&#39;]) && $params[&#39;thirdparty_id&#39;] = $config[&#39;thirdparty_id&#39;];
        $params[&#39;sign&#39;] = self::makeSign($params);

        $url = self::$settleUrl;
        $response = Http::post($url, json_encode($params));
        $result = json_decode($response, true);
        return $result;
    }

    /**
     * [querySettle 分账查询]
     * @param  [type] $settleSn [开发者侧的订单号, 不可重复]
     * @return [type]          [description]
     */
    public static function querySettle($settleSn)
    {
        $config = self::$config;
        $params = [
            &#39;app_id&#39; => $config[&#39;app_id&#39;], // 小程序 AppID
            &#39;out_settle_no&#39; => $settleSn, // 开发者侧的分账号
            // &#39;sign&#39; => &#39;&#39;, // 开发者对核心字段签名, 签名方式见文档, 防止传输过程中出现意外
            // &#39;thirdparty_id&#39; => &#39;&#39;, // 服务商模式接入必传	第三方平台服务商 id,非服务商模式留空
        ];

        !empty($config[&#39;thirdparty_id&#39;]) && $params[&#39;thirdparty_id&#39;] = $config[&#39;thirdparty_id&#39;];
        $params[&#39;sign&#39;] = self::makeSign($params);

        $url = self::$querySettleUrl;
        $response = Http::post($url, json_encode($params));
        $result = json_decode($response, true);
        return $result;
    }

    /**
     * [notifySettle 分账回调验证]
     * @return [array] [返回数组格式的notify数据]
     */
    public static function notifySettle()
    {
        $data = $_POST; // 获取回调数据
        $config = self::$config;
        if (!$data || empty($data[&#39;status&#39;]))
            die(&#39;暂无回调信息&#39;);

        $result = json_decode($data[&#39;msg&#39;], true); // 进行签名验证
        // 判断签名是否正确  判断支付状态
        if ($result && $data[&#39;status&#39;]!=&#39;FAIL&#39;) {
            return $data;
        } else {
            return false;
        }
    }

    /**
     * [addMerchant 服务商进件]
     * @param [type]  $accessToken [授权码兑换接口调用凭证]
     * @param [type]  $componentId [小程序第三方平台应用]
     * @param integer $urlType     [链接类型:1-进件页面 2-账户余额页]
     */
    public static function addMerchant($accessToken, $componentId, $urlType=1)
    {
        $params = [
            &#39;component_access_token&#39; => $accessToken, // 是	授权码兑换接口调用凭证
            &#39;thirdparty_component_id&#39; => $componentId, // 是	小程序第三方平台应用 id
            &#39;url_type&#39; => $urlType, // 是	链接类型:1-进件页面 2-账户余额页
        ];

        $url = self::$addMerchantUrl;
        $response = Http::post($url, json_encode($params));
        $result = json_decode($response, true);
        return $result;
    }

    /**
     * [addSubMerchant 分账方进件]
     * @param [type]  $thirdpartyId [小程序第三方平台应用]
     * @param [type]  $merchantId   [商户 id,用于接入方自行标识并管理进件方。由服务商自行分配管理]
     * @param integer $urlType      [链接类型:1-进件页面 2-账户余额页]
     */
    public static function addSubMerchant($thirdpartyId, $merchantId, $urlType=1)
    {
        $params = [
            &#39;thirdparty_id&#39; => $thirdpartyId, // 是	小程序第三方平台应用 id
            &#39;sub_merchant_id&#39; => $merchantId, // 是	商户 id,用于接入方自行标识并管理进件方。由服务商自行分配管理
            &#39;url_type&#39; => $urlType, // 是	链接类型:1-进件页面 2-账户余额页
            // &#39;sign&#39; => &#39;&#39;, // 开发者对核心字段签名, 签名方式见文档, 防止传输过程中出现意外
        ];

        $params[&#39;sign&#39;] = self::makeSign($params);

        $url = self::$addSubMerchantUrl;
        $response = Http::post($url, json_encode($params));
        $result = json_decode($response, true);
        return $result;
    }

    /**
     * [success 通知状态]
     */
    public static function success()
    {
        $array = [&#39;err_no&#39;=>0, &#39;err_tips&#39;=>&#39;success&#39;];
        die(json_encode($array));
    }

    /**
     * [makeSign 生成秘钥]
     * @param  [type] $data [加密数据]
     * @return [type]       [description]
     */
    public static function makeSign($data) {
        $config = self::$config;
        $rList = array();
        foreach($data as $k => $v) {
            if ($k == "other_settle_params" || $k == "app_id" || $k == "sign" || $k == "thirdparty_id")
                continue;
            $value = trim(strval($v));
            $len = strlen($value);
            if ($len > 1 && substr($value, 0,1)=="\"" && substr($value,$len, $len-1)=="\"")
                $value = substr($value,1, $len-1);
            $value = trim($value);
            if ($value == "" || $value == "null")
                continue;
            array_push($rList, $value);
        }
        array_push($rList, $config[&#39;salt&#39;]);
        sort($rList, 2);
        return md5(implode(&#39;&&#39;, $rList));
    }

}

Recommended learning: "
PHP Video Tutorial
"

The above is the detailed content of Following the update trend, the guaranteed payment class of the PHP byte applet has also been updated!. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:冯奎博客fengkui.net. If there is any infringement, please contact admin@php.cn delete