/**
 * 发起支付
*/
public function pay($user_id, $order_id)
{
    // 查看用户信息
    $user_info = $this -> user_info($user_id);

    // 查看订单信息
    $order_info = $this -> order_info($order_id);

    // 基本信息
    $money = $order_info['order_amount'] * 100;
    $openid = $user_info['mp_unionid']; // 用户openid
    $order_code = $order_id; // 订单号
    $nonce_str = self::getNonceStr(); // 随机字符串
    $notify_url = "https://new.zhyin.net/index.php/mobile/pay/zhifu";
    // 发送数据
    $post_data = [
        'appid'            => "",
        'mch_id'           => "",
        'nonce_str'        => $nonce_str,
        'body'             => '智慧印',
        'out_trade_no'     => $order_code,
        'total_fee'        => $money,
        'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
        'trade_type'       => 'JSAPI',
        'openid'           => $openid,
        'notify_url'       => $notify_url
    ];
    // 生成签名
    $post_data['sign'] = $this->MakeSign($post_data, "");
    // 组合XML数据
    $xmlData = $this->MakeXml($post_data);
    // 发送请求
    $this->we_chat_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    $result = $this->curl_post($this->we_chat_url,$xmlData,true);

    // 解析xml数据
    $payment = $this->FromXml($result);
    // 是否请求成功
    if($payment['return_code'] != 'SUCCESS'){
        $this->jsonError($payment['return_msg']);
    }

    if ($payment['result_code'] == 'SUCCESS'){

        $payment['timestamp'] = time();
        // 创建统一订单信息
        $sign_data = [
            'appId'=>$payment['appid'],
            'nonceStr'=>$payment['nonce_str'],
            'package'=>'prepay_id=' . $payment['prepay_id'],
            'signType'=>'MD5',
            'timeStamp'=>'' . $payment['timestamp'] . '',
        ];
        $sign_data['paySign'] = $this->MakeSign($sign_data , "");

        return $sign_data;
    } else {
        return ['支付失败'];
    }
}
/**
 * 产生随机字符串,不长于32位
 * @param int $length
 * @return string
 */
protected static function getNonceStr($length = 32)
{
    $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
    $str ="";
    for ( $i = 0; $i < $length; $i++ )  {
        $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
    }
    return $str;
}
/**
 * 生成签名 签名,本函数不覆盖sign成员变量,如要设置签名需要调用SetSign方法赋值
 * @param $sign
 * @param string $keys
 * @return string
 */
protected function MakeSign($sign, $keys = '')
{
    ksort($sign); // 数组排序
    $str = '';
    foreach($sign as $key=>$val){
        if($val != ''){
            $str .= $key . "=" . $val . "&";
        }
    }
    $str .= "key=" . $keys;
    $sign = strtoupper(md5($str));
    return $sign;
}
/**
 * 生成XML数据
 * @param $data
 * @return string
 */
protected function MakeXml($data)
{
    $xmlData = "<xml>";
    foreach($data as $key=>$val){
        $xmlData.="<".$key.">".$val."</".$key.">";
    }
    $xmlData.= "</xml>";
    return $xmlData;
}
/**
 * POST请求数据
 * @param $url
 * @param $xmlData
 * @param bool $useCert
 * @return mixed
 */
public function curl_post($url, $xmlData, $useCert = false)
{
    $header[] = "Content-type: text/xml";
    // POST发送数据
    $ch = curl_init(); // 初始化CURL会话
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    if($useCert == true){
        //设置证书
        //使用证书:cert 与 key 分别属于两个.pem文件
        //证书文件请放入服务器的非web目录下
        $sslCertPath = getcwd() . "/wx_cert/apiclient_cert.pem";
        $sslKeyPath = getcwd() . "/wx_cert/apiclient_key.pem";
        curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLCERT, $sslCertPath);
        curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
        curl_setopt($ch,CURLOPT_SSLKEY, $sslKeyPath);
    }
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlData);
    $result = curl_exec($ch); // 获取结果
    curl_close($ch);// 关闭会话
    return $result;
}
/**
 * 将xml转为array
 * @param $xml
 * @return mixed
 */
protected function FromXml($xml)
{
    if(!$xml){
        $this->jsonReturn(0,'','XML解析错误!');
    }
    libxml_disable_entity_loader(true);
    $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $values;
}

回调地址

public function zhifu()
{
    $postXml = file_get_contents('php://input');

    libxml_disable_entity_loader(true);
    $data = json_decode(json_encode(simplexml_load_string($postXml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);


    $order_id  = $data['out_trade_no'];            // 订单单号
    // 查看有没有这个订单

    $order_info_where['order_id'] = $order_id;

    $order_info_where['order_state'] = 10;
    $order_info = Db::name('order') -> where($order_info_where) -> find();
    // 有这个订单则执行操作
    if ($order_info)
    {
        $update['order_state'] = '20';
        $update['payment_time'] = time();

        if (Db::name('order') -> where($order_info_where) -> update($update))
        {
            // 减每个商品的库存
            $order_common = Db::name('order_goods') -> where('order_id', $order_id) -> select();

        foreach($order_common as $v)
            {
                $goods = Db::name('goods') -> where('goods_id', $v['goods_id']) -> field('goods_storage, goods_salenum, goods_id') -> find();

                $update_goods['goods_storage'] = $goods['goods_storage'] - $v['goods_num'];
                $update_goods['goods_salenum'] = $goods['goods_salenum'] + $v['goods_num'];

                Db::name('goods') -> where('goods_id', $v['goods_id']) -> update($update_goods);
            }

            $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        } else {
            $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>';
        }
    }

    return $str;
}
07-05 22:44