php thinkphp 抖音支付,订单同步接口分享

1. 抖音支付

需要获取抖音小程序的AppID,AppSecret,需要配置回调地址,Token获取SALT

官方地址:支付订单同步

以下干货仅针对于有一定开发基础的精英,0基础的止步。

php 复制代码
  public function DouyinPay($openId='',$id='',$body = '抖音担保支付'){

        $order=db('order')->where(['id'=>$id,'status'=>1])->find();//获取订单信息

        $outOrderNo = $order['orderno'];//开发者侧的订单号
        $totalAmount = $order['price'];//支付价格; 接口中参数支付金额单位为[分]
        $subject = "订单号:".$order['orderno']; //商品描述也就是标题
        $body = $body;
        $validTimestamp = 60 * 60;//订单过期时间(秒);
        $notifyUrl = "https://***/notify"; //这里可以忽略,走字节跳动小程序 -支付 -担保配置-设置回调地址
        //创建订单
        $response = $this->createOrder($outOrderNo, $totalAmount, $subject, $body, $validTimestamp, $notifyUrl);

        $this->success('成功',$response);
    }
        /**
     *	创建订单
     */
    public function CreateOrder($outOrderNo, $totalAmount, $subject, $body, $validTimestamp, $notifyUrl)
    {
        $params = [
            'app_id'       => '******',//小程序appid
            'out_order_no' => $outOrderNo,
            'total_amount' => $totalAmount * 100,
            'subject'      => $subject,
            'body'         => $body,
            'valid_time'   => $validTimestamp,
           'notify_url'   => $notifyUrl,
      
        ];

        $params = array_filter($params);
        $params['sign'] = $this->sign($params);

        $res = $this->posts(
            'https://developer.toutiao.com/api/apps/ecpay/v1/create_order',
            $params
        );
        return $res;
    }
    /**
     *	获取签名
     */
    public  function sign($map) {
        $rList = [];
        foreach($map as $k =>$v) {
            if ($k == "other_settle_params" || $k == "app_id" || $k == "sign" || $k == "thirdparty_id")
                continue;

            $value = trim(strval($v));
            if (is_array($v)) {
                $value = $this->arrayToStr($v);
            }

            $len = strlen($value);
            if ($len > 1 && substr($value, 0,1)=="\"" && substr($value, $len-1)=="\"")
                $value = substr($value,1, $len-1);
            $value = trim($value);
            if ($value == "" || $value == "null")
                continue;
            $rList[] = $value;
        }
        $rList[] = "*****";//这里是SALT
        sort($rList, SORT_STRING);
        return md5(implode('&', $rList));
    }
    // **************** 以下方法 是字节小程序支付 签名处理方式

    public function callbackSign($data) {
		//***这里的是配置salt的时候填写的Token令牌
        $array = array(

            '***',(string)$data['timestamp'],(string)$data['nonce'],		(string)htmlspecialchars_decode($data['msg'])

        );

        sort($array,SORT_STRING);

        $join_str = implode('',$array);

        return sha1($join_str);

    }


    public function arrayToStr($map) {
        $isMap =  $this->isArrMap($map);

        $result = "";
        if ($isMap){
            $result = "map[";
        }

        $keyArr = array_keys($map);
        if ($isMap) {
            sort($keyArr);
        }

        $paramsArr = array();
        foreach($keyArr as  $k) {
            $v = $map[$k];
            if ($isMap) {
                if (is_array($v)) {
                    $paramsArr[] = sprintf("%s:%s", $k, arrayToStr($v));
                } else  {
                    $paramsArr[] = sprintf("%s:%s", $k, trim(strval($v)));
                }
            } else {
                if (is_array($v)) {
                    $paramsArr[] = arrayToStr($v);
                } else  {
                    $paramsArr[] = trim(strval($v));
                }
            }
        }

        $result = sprintf("%s%s", $result, join(" ", $paramsArr));
        if (!$isMap) {
            $result = sprintf("[%s]", $result);
        } else {
            $result = sprintf("%s]", $result);
        }

        return $result;
    }

  public  function isArrMap($map) {
        foreach($map as $k =>$v) {
            if (is_string($k)){
                return true;
            }
        }

        return false;
    }
c 复制代码
    // **************** 以下方法 是回调


    public function notify()
    {
        $notify = \request()->param();
    //  验签
        if ($notify['msg_signature'] !== $this->callbackSign($notify)) {
           return false;

        } else {
            //获取订单信息
            $order=(string)htmlspecialchars_decode($notify['msg']);
            $order = json_decode($order, true);
            //处理订单,获取订单号
       
            $sn =  $order['cp_orderno'];
            $do2='订单的处理';
            if($do2){
              
                $data = ['err_no' => '0', 'err_tips' => 'success'];
                return json($data);
            }else{
                db()->rollback();
                return false;
            }
           // Log::info('抖音担保支付效验成功');
        }

    }
      public function posts(string $url, array $params = [], array $headers = [])
    {
        $headers[] = 'Content-type: application/json';

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $output = curl_exec($ch);
        curl_close($ch);

        return json_decode($output, true);
    }

不要单纯以为只要支付完成就OK了,下面还需要订单同步到抖音,下场如下

2.订单同步

这里不需要申请额外的参数,大致分为三步(1.获取token,2.组装商品,3.组装订单)

代码如下:

php 复制代码
     /**
     * 订单推送到抖音
     * @param $data array 订单数据
     * @note order_status 与 status须保持一致,但类型不同
     * @return array
     */
    public  function pushOrder($id=''){
        $data=[];//获取订单信息
        $api = "https://developer.toutiao.com/api/apps/order/v2/push";
        $openid ='';//获取下单用户openid
  		//组装商品
        $item_list = [['item_code' => '购买会员卡','img'=>'https://***/logo.jpg',
            'title'=>'会员服务','amount'=>1,'price'=>(int)($data['price']*100)]];//参数对应请查看官方文档,注意字段类型
           // 组装订单
        $detail = [
            'order_id'=>$data['orderno'],'create_time'=>strtotime($data['add_time'])*1000,'status'=>"已支付",'amount'=>1,
            'total_price'=>(int)($data['price']*100),'detail_url'=>"pages/me/vip/vip",'item_list'=>$item_list];
              dump($detail);
              
        $param = ['access_token'=>$this->getAccessTokens(),'app_name'=>"douyin",
            'open_id'=>$openid,'update_time'=>$this->getMillisecond(),'order_detail'=>json_encode($detail),'order_type'=>0,'order_status'=>1,'payment_order_no'=>$data['orderno']];
     
        $result =$this->posts($api,$param);//请求
      
    }
     /**
     * 获取AccessToken
     */
    public  function getAccessTokens(){
        $api = "https://developer.toutiao.com/api/apps/v2/token";
			  $param = ['appid'=>'***','secret'=>'***','grant_type'=>"client_credential"];
        $access_token = Cache::get('dy_accessToken');
        if(empty($access_token)){
            $data = $this->posts($api,$param);
         //   dump($result);die;
         //   $data = json_decode($result,true);
            if($data['err_no'] == 0){
                $access_token = $data['data']['access_token'];
                Cache::set('dy_accessToken',$access_token,$data['data']['expires_in']);
            }
        }
        return $access_token;
    }
       public  function getMillisecond() {
        list($t1, $t2) = explode(' ', microtime());
        return (float)sprintf('%.0f',(floatval($t1)+floatval($t2))*1000);
    }
相关推荐
两个人的幸福9 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo11 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack11 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820712 天前
PHP 扩展——从入门到理解
php
鹏仔先生13 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下13 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip13 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
酉鬼女又兒13 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog25013 天前
不要再继续优化 TCP
网络协议·tcp/ip·php
Channing Lewis13 天前
PHP 解析 Excel 的那些坑:一次“行号错位”引发的数据丢失
开发语言·php·excel