微信小程序内嵌H5页面实现微信支付

在微信H5页面已经实现了微信JSAPI的网页支付,老板要求把整个业务线快速转移到微信小程序中,作为懒惰的程序员来说,直接把页面嵌套到小程序不就行了。说干就干,在小程序中设置好基本信息后,一预览居然成功了,一切看来是那么顺利,可到了系统的支付环节时,小程序是无法调用JSAPI微信支付的,难不成要重构所有页面转成小程序?

小程序打开H5页面后,在需要调用微信支付的页面用js做当前页面环境判断:

var is_weixin_app = window.__wxjs_environment === 'miniprogram';

如果是在小程序中打开,则通过wx.miniProgram.navigateTo 方法跳转到小程序的内置页面:

if(is_weixin_app){
wx.miniProgram.navigateTo({url:'/pages/pay/pay?api_token='+api_token+'&order_id='+order_id+'&amount='+order_amount});
}

在小程序内置页面pay中获取传过来的参数,做业务处理,然后调用小程序的支付接口,获取小程序需要的关键支付参数(该方法可参考微信支付对接文档:小程序支付开发指引):

'timeStamp': mydata.timeStamp,
'nonceStr': mydata.nonceStr,
'package': mydata.package,
'signType': mydata.signType,
'paySign': mydata.paySign,

小程序支付需要的openid参数,这个openid和微信公众号的openid不是相同的,所以小程序内置app.js还需要获取小程序的openid(微信小程序无需授权可直接根据code获取openid,微信公开接口:https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code),并将openid存在全局变量中:

App({
  onLaunch() {
    let that = this;
    wx.login({
      success (res) {
          if (res.code) {
              //发起网络请求
              wx.request({
                  url: 'https://localhost/api/home/wxapp_openid', //接口地址
                  data: {
                    code: res.code
                  },
                  success: function (res){
                    that.globalData.openid = res.data.data.openid;
                  }
              })
          }
      }
  })
  
  },
  globalData: {
    userInfo: null,
    openid:''
  }
})

index是小程序的首页,用来打开H5的链接

---index.js代码:
Page({
  data: {
    bg_url : "https://localhost"
  },
  onLoad() {
  },
})
 
 
---index.wxml代码:
<!--index.wxml-->
<official-account></official-account>
<web-view src="{{bg_url}}"></web-view>

pay是H5链接支付时跳转到的小程序支付页面

---pay.js代码:
let order_id=0,amount=0,quotation_id=0,api_token=0;
var app = getApp();
Page({
  /**
   * 页面的初始数据
   */
  data: {},
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    order_id=options.order_id;
    amount=options.amount;
    quotation_id=options.quotation_id;
    api_token=options.api_token;
    this.submitInfo();
  },
  submitInfo(){
    wx.showLoading({
      title: '微信支付...',
      mask: true
    });
    wx.request({
      url: 'https://localhost/api/order/pay_request', 
      data: {
        type:1,
        pay_mode:3,
        order_id: order_id,
        amount:amount,
        quotation_id:quotation_id,
        api_token:api_token,
        openid:app.globalData.openid
      },
      success: function (res) {
        wx.hideLoading();
        if (res.data.ret == "200") {
          let mydata = res.data.data.data;
          wx.requestPayment(
            {
              'timeStamp': mydata.timeStamp,
              'nonceStr': mydata.nonceStr,
              'package': mydata.package,
              'signType': mydata.signType,
              'paySign': mydata.paySign,
              'success': function (e) { //支付成功
                wx.showToast({
                  title: '支付成功',
                  icon: 'success',
                  duration: 1200,
                  mask: true,
                  success: function ()
                  {
                    setTimeout(function () {
                      wx.navigateBack(); 
                    }, 1500);
                  }
                });
 
              },
              'fail': function (e) { //支付取消或出错
              //  wx.navigateBack();
              }
            })
        }
        else {
          wx.showToast({
            title: '该订单已失效',
            icon: 'success',
            duration: 3000,
            mask: true,
            success: function () {
              setTimeout(function () {
                wx.navigateBack();
              }, 1500);
            }
          })
        }
      }
    });
  }
})
 
---pay.wxml代码
<view class='body'>
<form bindsubmit="submitInfo" report-submit='true'>
<view class='body-view'><text >微信小程序支付</text></view>
<view class="btn-area">
<button type="primary" form-type="submit">确认支付</button>
</view>
</form>
</view>

PHP支付宝手机网页和PC网页支付对接

application/controllers/Alipay.php

<?php
defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' );
require_once(APPPATH."/libraries/alipay/AliPayConfig.php");
require_once(APPPATH."/libraries/alipay/AlipayTradeService.php");
require_once(APPPATH."/libraries/alipay/AlipayTradeWapPayContentBuilder.php");
require_once(APPPATH."/libraries/alipay/AlipayTradePagePayContentBuilder.php");
 
/**
 * Class Alipay
 */
class Alipay extends MY_Controller {
 
	function __construct()
	{
		parent::__construct(false);
        $this->load->model('Pay_log_model');
	}
 
    /**
     * 手机端网页支付
     */
    public function alipay_detail(){
        //$amount = $this->input->get('amount');
        //$phone = $this->input->get('phone');
        $amount = (float)0.01;
        $phone = '13427790490';
        if($amount < 0.01){
            $data['error'] = '请输入有效的支付金额';
            $this->load->view('alipay_detail', $data);
            return;
        }
        //插入支付日志
        $pay_log = array();
        $pay_log['pay_user'] = $phone;
        $pay_log['name'] = '支付宝wap订单支付';
        $pay_log['amount'] = $amount;
        $pay_log['pay_mode'] = 2;
        $pay_log['add_time'] = time();
        $pay_log['add_time_ymd'] = date("Y-m-d H:i:s");
        $this->Pay_log_model->save($pay_log);
        $log_id = $pay_log['log_id'];
        try {
            $data['alipay_data'] = $this->get_alipay_request_data($pay_log['name'], $log_id, $amount);
        } catch (Exception $e) {
            $data['alipay_data'] = '小伙子,出错了';
        }
        $this->load->view('alipay_detail',$data);
    }
 
    /**
     * 支付宝移动端下单信息
     * @param $name
     * @param $log_id
     * @param $amount
     * @return false|mixed|SimpleXMLElement|string|提交表单HTML文本
     * @throws Exception
     */
    private function get_alipay_request_data($name,$log_id,$amount){
        $payRequestBuilder = new AlipayTradeWapPayContentBuilder();
        $payRequestBuilder->setBody($log_id);//订单描述(日志ID)
        $payRequestBuilder->setSubject($name);//订单标题。注意:不可使用特殊字符,如 /,=,& 等。
        $payRequestBuilder->setOutTradeNo(AliPayConfig::app_id.date("YmdHis").$log_id);//商户订单号,商户网站订单系统中唯一订单号,必填
        $payRequestBuilder->setTotalAmount($amount);//订单总金额。单位为元,精确到小数点后两位,取值范围:[0.01,100000000]
        $payRequestBuilder->setTimeExpress('5m');//(推荐使用,相对时间) 支付超时时间,5m 5分钟
        $payResponse = new AlipayTradeService();
        return $payResponse->wapPay($payRequestBuilder,AliPayConfig::return_url,AliPayConfig::notify_url);
    }
 
    /**
     * PC端扫码支付
     */
    public function aliyun_pay(){
        //$amount = $this->input->get('amount');
        //$phone = $this->input->get('phone');
        $amount = (float)0.01;
        $phone = '13427790490';
        if($amount < 0.01){
            $data['error'] = '请输入有效的支付金额';
            $this->load->view('aliyun_pay', $data);
            return;
        }
        //插入支付日志
        $pay_log = array();
        $pay_log['pay_user'] = $phone;
        $pay_log['name'] = '支付宝PC订单支付';
        $pay_log['amount'] = $amount;
        $pay_log['pay_mode'] = 2;
        $pay_log['add_time'] = time();
        $pay_log['add_time_ymd'] = date("Y-m-d H:i:s");
        $this->Pay_log_model->save($pay_log);
        $log_id = $pay_log['log_id'];
        try {
            $data['alipay_data'] = $this->get_pc_alipay_request_data($pay_log['name'], $log_id, $amount);
        } catch (Exception $e) {
            $data['alipay_data'] = '小伙子,出错了';
        }
        $this->load->view('aliyun_pay',$data);
    }
 
    /**
     * 支付宝PC端下单信息
     * @param $name
     * @param $log_id
     * @param $amount
     * @return false|mixed|SimpleXMLElement|string|提交表单HTML文本
     * @throws Exception
     */
    private function get_pc_alipay_request_data($name,$log_id,$amount){
        $payRequestBuilder = new AlipayTradePagePayContentBuilder();
        $payRequestBuilder->setBody($log_id);//订单描述(日志ID)
        $payRequestBuilder->setSubject($name);//订单标题。注意:不可使用特殊字符,如 /,=,& 等。
        $payRequestBuilder->setOutTradeNo(AliPayConfig::app_id.date("YmdHis").$log_id);//商户订单号,商户网站订单系统中唯一订单号,必填
        $payRequestBuilder->setTotalAmount($amount);//订单总金额。单位为元,精确到小数点后两位,取值范围:[0.01,100000000]
        $payRequestBuilder->setTimeExpress('5m');//(推荐使用,相对时间) 支付超时时间,5m 5分钟
        $payResponse = new AlipayTradeService();
        return $payResponse->pagePay($payRequestBuilder,AliPayConfig::return_url,AliPayConfig::notify_url);
    }
 
    /**
     * 支付宝回调异步通知
     */
    public function alipay_recharge_notify()
    {
        //log_message('error', "POST:" . print_r($_POST, true));
        //计算得出通知验证结果
        $alipaySevice = new AlipayTradeService();
        $result = $alipaySevice->check($_POST);
        if($result) {//验证成功
            //逻辑处理
            $log_id = $_POST['body'];
            $out_trade_no = $_POST['out_trade_no'];
            $total_amount = $_POST['total_amount'];
            //交易状态
            $trade_status = $_POST['trade_status'];
            //logResult("mobile callback:res=".$out_trade_no.";login_id=".$_POST['subject'].";total_frme=".$_POST['total_fee'].";trade_status=".$trade_status);
            //只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功
            if($trade_status == 'TRADE_FINISHED' || $trade_status == 'TRADE_SUCCESS')
            {
                //支付成功的后续操作
                $pay_log = $this->Pay_log_model->get_info($log_id);
                if(!empty($pay_log))
                {
                    if($pay_log['amount'] == $total_amount && $pay_log['pay_status'] == 0)
                    {
                        //修改支付状态
                        $log_data = array(
                            'pay_status'=>1,
                            'trade_no'=>$out_trade_no,
                            'pay_user'=>$_POST['buyer_id'],
                            'pay_trans_id'=>$_POST['trade_no'],
                            'pay_code'=>$_POST['trade_status']
                        );
                        $this->Pay_log_model->save($log_data, $log_id);
                        //给支付宝返回成功
                        echo "success";exit;
                    }
                }
            }
        }
        //验证失败
        echo "fail";
    }
}

application/models/Pay_log_model.php(和微信支付使用了同一个model)

<?php
 
/**
 * Class Pay_log_model
 */
class Pay_log_model extends MY_Model {
	
	public $_table = 'pay_log';
	public $primary_key = 'log_id';
	
	function get_info($id, $select=null){
		if(!empty($select)){
			$this->db->select($select);
		}
		return $this->get($id);
	}
	
	function save(&$data, $id = 0) {
		$data['last_time'] = time();
		if ($id > 0) {
			$this->db->set ( $data );
			$this->db->where ( $this->primary_key, $id );
			$this->db->update ( $this->_table );
			$err = $this->db->error();
			$data['db_code'] = $err['code'];
			$data [$this->primary_key] = $id;
			return $this->db->affected_rows ();
		}
	
		$data['add_time'] = time();
		$this->db->insert ( $this->_table, $data );
		$err = $this->db->error();
		$data['db_code'] = $err['code'];
		$data [$this->primary_key] = $this->db->insert_id ();
		return $this->db->affected_rows ();
	}
}
 

application/views/alipay_detail.php

<!DOCTYPE html>
<html>
<head>
    <title>支付宝手机网站支付接口</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 
</head>
<body text=#000000 bgColor="#ffffff" leftMargin=0 topMargin=4>
<header class="am-header">
    <h1>支付宝手机网站支付接口快速通道(接口名:alipay.trade.wap.pay)</h1>
</header>
<div id="main">
    <?php echo $alipay_data?>
    <div id="foot">
        <ul class="foot-ul">
            <li>
                支付宝版权所有 2015-2018 ALIPAY.COM
            </li>
        </ul>
    </div>
</div>
</body>
 
</html>

application/views/aliyun_pay.php

<!DOCTYPE html>
<html>
<head>
    <title>支付宝PC网站支付接口</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 
</head>
<body text=#000000 bgColor="#ffffff" leftMargin=0 topMargin=4>
<header class="am-header">
    <h1>支付宝PC网站支付接口快速通道(接口名:alipay.trade.page.pay)</h1>
</header>
<div id="main">
    <?php echo $alipay_data?>
    <div id="foot">
        <ul class="foot-ul">
            <li>
                支付宝版权所有 2015-2018 ALIPAY.COM
            </li>
        </ul>
    </div>
</div>
</body>
 
</html>

application/libraries/alipay/AliPayConfig.php

<?php
/**
 *    配置账号信息
 */
class AliPayConfig
{
    /**
     * 应用ID,您的APPID
     */
    const app_id = '';
    /**
     * 异步通知地址
     */
    const notify_url = '';
    /**
     * 同步跳转
     */
    const return_url = '';
    /**
     * 编码格式
     */
    const charset = 'UTF-8';
    /**
     * 签名方式
     */
    const sign_type = 'RSA2';
    /**
     * 支付宝网关
     */
    const gatewayUrl = 'https://openapi.alipaydev.com/gateway.do';
    //const gatewayUrl = 'https://openapi.alipay.com/gateway.do';
    /**
     * 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
     */
    const alipay_public_key = '';
    /**
     * 商户私钥,您的原始格式RSA私钥
     */
    const merchant_private_key = '';
}

PHP微信支付JSAPI网页支付Native原生支付

JSAPI网页支付,即日常所说的公众号支付,可在微信公众号、朋友圈、聊天会话中点击页面链接,或者用微信“扫一扫”扫描页面地址二维码在微信中打开商户HTML5页面,在页面内下单完成支付。

Native原生支付,即日常所说的扫码支付,商户根据微信支付协议格式生成的二维码,用户通过微信“扫一扫”扫描二维码后即进入付款确认界面,输入密码即完成支付。

方式一:JSApi支付,即:在微信中打开网页,直接调用微信支付。

方式二:Native支付,即:浏览器访问链接网页,产生微信支付二维码,微信扫码后可完成支付。

1.数据库mysql语句

CREATE TABLE `fanqie_pay_log` (
  `log_id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '支付日志ID',
  `name` varchar(32) DEFAULT NULL COMMENT '支付说明',
  `amount` decimal(10,2) DEFAULT '0.00' COMMENT '付款金额',
  `pay_status` tinyint(2) DEFAULT '0' COMMENT '支付状态 0未支付 1已支付 2已退款 3部分退款',
  `add_time_ymd` datetime DEFAULT NULL COMMENT '产生支付日志的时间',
  `prepay_id` varchar(128) DEFAULT NULL COMMENT '微信支付流水ID(没有用)',
  `trade_no` varchar(32) DEFAULT NULL COMMENT '商户编号',
  `pay_mode` tinyint(1) DEFAULT '1' COMMENT '支付方式:1微信  2支付宝',
  `pay_user` varchar(128) DEFAULT NULL COMMENT '支付的用户(微信openid)',
  `pay_trans_id` varchar(256) DEFAULT NULL COMMENT '支付订单id(微信流ID)',
  `pay_code` varchar(32) DEFAULT NULL COMMENT '支付回调产生的结果代码(微信支付成功SUCCESS)',
  `pay_message` varchar(50) DEFAULT NULL COMMENT '支付回调返回的信息(失败时返回)',
  `refund_amount` decimal(10,2) DEFAULT '0.00' COMMENT '退款金额',
  `add_time` int(10) DEFAULT '0' COMMENT '创建时间戳',
  `last_time` int(10) DEFAULT '0' COMMENT '更新时间戳',
  PRIMARY KEY (`log_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='平台支付日志';

application/controllers/Wxpay.php

<?php
defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' );
 
require_once(APPPATH."/libraries/wxpay/api/WxPay.JsApiPay.php");
require_once(APPPATH."/libraries/wxpay/api/WxPay.NativePay.php");
require_once(APPPATH."/libraries/wxpay/lib/WxPay.Api.php");
require_once(APPPATH."/libraries/wxpay/lib/WxPay.Notify.php");
 
class Wxpay extends MY_Controller {
 
	function __construct()
	{
		parent::__construct(false);
        $this->load->model('Pay_log_model');
	}
 
    /**
     * 微信支付二维码显示页面
     */
    public function wxpay_detail(){
        //$amount = $this->input->get('amount');
        //$phone = $this->input->get('phone');
        $amount = 0.01;
        $phone = '13427790490';
        if($amount < 0.01){
            $data['error'] = '请输入有效的支付金额';
            $this->load->view('wxpay_detail', $data);
            return;
        }
        $pay_log = array();
        $pay_log['pay_user'] = $phone;
        $pay_log['name'] = '订单微信扫码支付';
        $pay_log['amount'] = $amount;
        $pay_log['add_time'] = time();
        $pay_log['add_time_ymd'] = date("Y-m-d H:i:s");
        $this->Pay_log_model->save($pay_log);
        $log_id = $pay_log['log_id'];
        $data = $this->get_wxpay_native_data($log_id,"微信扫码测试商品");
        $this->load->view('wxpay_detail',$data);
    }
 
    /**
     * 微信扫码支付内容
     * @param $log_id 订单日志id
     * @param $name 商品名称
     */
    private function get_wxpay_native_data($log_id,$name){
        $notify = new NativePay();
        $input = new WxPayUnifiedOrder();
        $input->SetBody($name);
        $input->SetAttach($log_id);
        $input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis").$log_id);//商户订单号
        $input->SetTotal_fee(1 );//总金额
        $input->SetTime_start(date("YmdHis"));//交易起始时间
        $input->SetTime_expire(date("YmdHis", time() + 600));//交易结束时间
        $input->SetNotify_url(base_url('/wxpay/wxpay_recharge_notify_url'));//通知地址
        $input->SetTrade_type("NATIVE");
        $input->SetProduct_id("1");//商品ID,可随意定
        return $notify->GetPayUrl($input);
    }
 
    /**
     * 微信网页调用JsApi支付
     * @throws WxPayException
     */
    public function weixin_pay()
    {
        $amount = (float)0.01;
        if($amount < 0.01){
            $data['error'] = '请输入有效的支付金额';
            $this->load->view('weixin_pay', $data);
            return;
        }
        //$openid = $this->get_openid();
        $openid = 'ocJaB1lcjS-xA5V3w-VOKQJjynUU';//对应公众号的openid
        //插入支付日志
        $pay_log = array();
        $pay_log['pay_user'] = $openid;
        $pay_log['name'] = '微信JSAPI订单支付';
        $pay_log['amount'] = $amount;
        $pay_log['add_time'] = time();
        $pay_log['add_time_ymd'] = date("Y-m-d H:i:s");
        $this->Pay_log_model->save($pay_log);
        $log_id = $pay_log['log_id'];
        $request_data = $this->get_wxpay_request_data($openid, $log_id, $amount, $pay_log['name']);
        $data['jsApiParameters'] = $request_data;
        $this->load->view('weixin_pay', $data);
    }
 
    /**
     * 得到微信支付请求数据
     * @param unknown $log_id
     * @param unknown $amount
     * @param unknown $name
     * @return json数据,可直接填入js函数作为参数
     * @throws WxPayException
     */
    private function get_wxpay_request_data($openId, $log_id, $amount, $name)
    {
        $tools = new JsApiPay();
        $input = new WxPayUnifiedOrder();
        $input->SetBody($name);//商品描述
        $input->SetAttach($log_id);//附加数据
        $input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis").$log_id);//商户订单号
        $input->SetTotal_fee($amount * 100);//总金额
        $input->SetTime_start(date("YmdHis"));//交易起始时间
        $input->SetTime_expire(date("YmdHis", time() + 600));//交易结束时间
        $input->SetNotify_url(base_url('/wxpay/wxpay_recharge_notify_url'));//通知地址
        $input->SetTrade_type("JSAPI");//交易类型
        $input->SetOpenid($openId);//用户标识
        $order = WxPayApi::unifiedOrder($input);
        if($order['return_code'] == 'FAIL'){
            echo $order['return_msg'].',请去到后台进行微信支付配置';exit;
        }
        return $tools->GetJsApiParameters($order);
    }
    /**
     * 微信支付异步通知
     */
    public function wxpay_recharge_notify_url()
    {
        //log_message('error', "POST_XML:" . file_get_contents("php://input"));
        $notify = new PayNotifyCallBack();
        $notify->Handle(false);
    }
}
 
    class PayNotifyCallBack extends WxPayNotify
    {
        //查询订单
        public function Queryorder($transaction_id)
        {
            $input = new WxPayOrderQuery();
            $input->SetTransaction_id($transaction_id);
            try {
                $result = WxPayApi::orderQuery($input);
            } catch (WxPayException $e) {
                return false;
            }
            //Log::DEBUG("Queryorder:" . json_encode($result));
            if(array_key_exists("return_code", $result)
                && array_key_exists("result_code", $result)
                && $result["return_code"] == "SUCCESS"
                && $result["result_code"] == "SUCCESS")
            {
                return true;
            }
            return false;
        }
 
        //重写回调处理函数
        public function NotifyProcess($data, &$msg)
        {
            //Log::DEBUG("NotifyProcess:" . json_encode($data));
            if(!array_key_exists("transaction_id", $data)){
                $msg = "输入参数不正确";
                return false;
            }
            //查询订单,判断订单真实性
            if(!$this->Queryorder($data["transaction_id"])){
                $msg = "订单查询失败";
                return false;
            }
            //逻辑处理
            $log_id = $data['attach'];
            $ci_obj = &get_instance();
            $ci_obj->load->model('Pay_log_model');
            $pay_log = $ci_obj->Pay_log_model->get_info($log_id);
            if(!empty($pay_log))
            {
                /* 检查支付的金额是否相符 */
                if($pay_log['amount'] == $data['total_fee']/100 && $pay_log['pay_status'] == 0)
                {
                    //修改支付状态
                    $log_data = array(
                        'pay_status'=>1,
                        'trade_no'=>$data['out_trade_no'],
                        'pay_user'=>$data['openid'],
                        'pay_trans_id'=>$data['transaction_id'],
                        'pay_code'=>$data['result_code'],
                        'pay_message'=>empty($data['return_msg'])?'':$data['return_msg'],
                    );
                    $ci_obj->Pay_log_model->save($log_data, $log_id);
                    //给微信返回成功
                    return true;
                }
            }
        }
    }

application/models/Pay_log_model

<?php
class Pay_log_model extends MY_Model {
	
	public $_table = 'pay_log';
	public $primary_key = 'log_id';
	
	function get_info($id, $select=null){
		if(!empty($select)){
			$this->db->select($select);
		}
		return $this->get($id);
	}
	
	function save(&$data, $id = 0) {
		$data['last_time'] = time();
		if ($id > 0) {
			$this->db->set ( $data );
			$this->db->where ( $this->primary_key, $id );
			$this->db->update ( $this->_table );
			$err = $this->db->error();
			$data['db_code'] = $err['code'];
			$data [$this->primary_key] = $id;
			return $this->db->affected_rows ();
		}
	
		$data['add_time'] = time();
		$this->db->insert ( $this->_table, $data );
		$err = $this->db->error();
		$data['db_code'] = $err['code'];
		$data [$this->primary_key] = $this->db->insert_id ();
		return $this->db->affected_rows ();
	}
}

application/views/weixin_pay.php

<!DOCTYPE html>
<html>
<head>
<title>微信安全支付</title>
<base href="<?php echo base_url()?>" id="base_url">
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
</head>
<body>
	<div class="conainer">
        微信支付
	</div>
	<script>
        	//调用微信JS api 支付
        	function jsApiCall()
        	{
        		WeixinJSBridge.invoke(
        			'getBrandWCPayRequest',
        			<?php echo isset($jsApiParameters) ? $jsApiParameters : 'null'?>,
        			function(res){
        				//WeixinJSBridge.log(res.err_msg);
        				//alert(res.err_code+res.err_desc+res.err_msg);
        				if(res.err_msg == "get_brand_wcpay_request:ok"){
        					alert("支付成功!");
        				}else{
            				alert("取消支付!");
        				}
        				window.history.go(-1);
        			}
        		);
        		WeixinJSBridge.call('hideOptionMenu');
    		    WeixinJSBridge.call('hideToolbar');
        	};
        
        	function callpay()
        	{
        		if (typeof WeixinJSBridge == "undefined"){
        		    if( document.addEventListener ){
        		        document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
        		    }else if (document.attachEvent){
        		        document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
        		        document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
        		    }
        		}else{
        		    jsApiCall();
        		}
        	};
        	
        	callpay();
    </script>
</body>
</html>

application/views/wxpay_detail.php

<html>
<head>
    <meta http-equiv="content-type" content="text/html;charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>微信扫描支付样例</title>
</head>
<body>
<div style="text-align:center;margin-left: 10px;color:#556B2F;font-size:30px;font-weight: bolder;">扫描支付0.01元钱</div>
<br/>
<div style="text-align:center;">
    <img alt="扫码支付" src="<?php echo base_url('/qrcode?data='.urlencode($code_url))?>" style="width:300px;height:300px;"/>
</div>
</body>
</html>

application/libraries/wxpay/lib/WxPay.Config.php

/**
	 * TODO: 修改这里配置为您自己申请的商户信息
	 * 微信公众号信息配置
	 * 
	 * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
	 * 
	 * MCHID:商户号(必须配置,开户邮件中可查看)
	 * 
	 * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置)
	 * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
	 * 
	 * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置),
	 * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
	 * @var string
	 */
	const APPID = 'XXX';
	const MCHID = 'XXX';
	const KEY = 'XXX';
	const APPSECRET = 'XXX';

通过dompdf用codeigniter生成的pdf电子邮件

从Codeigniter中的html视图生成的PDF,现在我想将其发送到我的电子邮件,但是我遇到的麻烦是它显示$pdf中有一个字符串,但是在发送时却为空 我的电子邮件。 这是整个Codeigniter函数。

public function generatePDF()
{
    require_once(APPPATH.'third_party/dompdf/dompdf_config.inc.php');

    $dompdf = new Dompdf();
    $msg = $this->load->view('credit_agreement_view', '', true);
    $html = mb_convert_encoding($msg, 'HTML-ENTITIES', 'UTF-8');
    $dompdf->load_html($html);
    $paper_orientation = 'Potrait';
    $dompdf->set_paper($paper_orientation);

    // Render the HTML as PDF
    $dompdf->render();
    $pdf = $dompdf->output();

    // sending the pdf to email
    $this->load->library('email');
    $config['protocol'] = 'smtp';
    $config['smtp_host'] = 'ssl://smtp.gmail.com';
    $config['smtp_port']    = '465';
    $config['smtp_timeout'] = '7';
    $config['smtp_user']    = 'support@aurorax.co';
    $config['smtp_pass']    = '#######';
    $config['charset']    = 'utf-8';
    $config['newline']    ="\
\
";
    $config['mailtype'] = 'text'; // or html
    $config['validation'] = TRUE; // bool whether to validate email or not    
    $this->email->initialize($config);

    $this->email->from('support@aurorax.co', 'aurora exchange');
    $this->email->to('masnad@aurorax.co');
    $this->email->subject('pdf');
    $this->email->attach($pdf);
    $this->email->message('Hello!');  

    $this->email->send();
}

首先保存,然后附加绝对路径
@ManinderpreetSingh那基本上是保存到我不想要的计算机上,我想直接将其发送到我的电子邮件中,或者稍后将其保存到mysql数据库中
更改您的这一行$ this-> email-> attach($ pdf);到$ this-> email-> string_attach($ pdf,myfile.pdf,application / pdf);
@ManinderpreetSingh我做到了,但出现错误致命错误:在C:\ Apache24 \ htdocs \中调用未定义的方法CI_Email :: string_attach()
@ManinderpreetSingh您阅读了我之前的评论吗?
抱歉,实际上此功能已删除,我打开了旧版本文档..请尝试使用$this->email->attach(myfile.pdf , $yourString,applicationpdf);
成功发送电子邮件后,您可以取消链接已保存的文件。
@Tpojka我真的不想将其保存到计算机或任何地方,所以这是一种将其保存到mysql数据库然后发送电子邮件的方法吗?我必须要找到一种方法,但是找不到
@ManinderpreetSingh我看到了$ pdf,它有一个原始字符串,如果有任何方法可以转换它,那就太好了。
试试这个stackoverflow.com/questions/17022101/
但这是生成的字符串是base64吗?
另外,在这些答案中找到有用的东西。

ThinkPHP5错误解析之variable type error:array

在TP5的post提交方式中,有一个坑爹的bug就是post提交数据不能提交数组。
请注意是不能提交数组形式的数据,而不是单纯的数据。举个例子:注意以下2种格式数据的比较:
第一种:普通的数据提交,这种格式的数据在TP5中用post提交,$request->post(‘参数’);可以接受数据。

{
    'data':123,
    'id':1,
    'name':'user'
}

下面看坑爹的第二种:

{
'data':[1,2,3,4,5],
'id':1,
'name':'user'
}

这种形式的数据同过POST提交数据在TP5框架内通过$request->post(‘参数’);去接收就会报错。
variable type error:array
这是因为tp5不能用post去接收数组‘data’:[1,2,3,4,5]这种数据。在通过request的post方法取获取时,post方法不能分辨它是否是数组。
所以在想不改变post提交方式的情况下,解决办法之一就是用/a。(这里的/a就相当于告诉解析器我要获取一个数组。)
将原来的接收方式参数修改为:

$data = $request->post('data/a');

同时,如果是表单直接提交,也需要把name的值改为数组,也就是加个[]

<select name="sid[]" id="sid" placeholder="必须选择适用产品" data-am-selected="{searchBox: 1}" multiple required>

php 时间如何增加1天

php实现时间增加1天的方法:首先创建一个PHP示例文件;然后通过“date(‘Y-m-d H:i:s’,strtotime(“+1 day +1 hour +1 minute”);”方式实现时间增加1天。

php 当前日期加一天和指定日期加一天

1.给当前时间加一天?一小时?

echo "明天:",date('Y-m-d H:i:s',strtotime('+1 day'));

上一行输出当前时间,下一行输出明天时间

同理加一年,一小时,一分钟 ,一月

echo "明天:",date('Y-m-d H:i:s',strtotime('+1 day'));

echo "明天:",date('Y-m-d H:i:s',strtotime('+1 hour'));

echo "明天:",date('Y-m-d H:i:s',strtotime('+1 minute'));

echo "明天:",date('Y-m-d H:i:s',strtotime('+1 mouth'));

这里+1 day可以修改参数1为任何想需要的数 day也可以改成year(年),month(月),hour(小时)minute(分),second(秒)如:

date('Y-m-d H:i:s',strtotime("+1 day +1 hour +1 minute");

可以随便自由组合,以达到任意输出时间的目的

注:该方法之针对1970年以后试用,也就是时间戳的适用范围。

2.给指定时间加一天?一小时?.。。。。。

echo date("Y-m-d",strtotime("+1 month",strtotime("2012-02-04")));

结果为:2011-03-04

echo date("Y-m-d",strtotime("+1 week",strtotime("2011-02-04")));

结果为:2011-02-11

echo date("Y-m-d",strtotime("+1 day",strtotime("2011-02-04")));

结果为:2011-02-05

EasyUi的DataGrid组件扩展,统计当前页信息

 [代码]使用方法

// 为datagrid开启统计功能
$('#list').datagrid({
    ..... // 此处代码略
    showFooter : true,
    onLoadSuccess : function() {
        $('#list').datagrid('statistics');
    }
});
// 统计某列(参照金额列)
<table id="list">
    <thead>
    <tr>
        <th field="no" width="100">序号</th>
        <th field="data" width="100">日期</th>
        <th field="money" width="100"
                formatter="formatMoney" align="right"
                sum="true" avg="true" min="true" max="true" >金额(元)</th>
        <th field="status" width="60" sortable="true">有效状态</th>
    </tr>
    </thead>
</table>

[图片] 效果演示 

$.extend($.fn.datagrid.methods, {
    statistics: function (jq) {
        var opt=$(jq).datagrid('options').columns;
        var rows = $(jq).datagrid("getRows");
         
        var footer = new Array();
        footer['sum'] = "";
        footer['avg'] = "";
        footer['max'] = "";
        footer['min'] = "";
         
        for(var i=0; i<opt[0].length; i++){
            if(opt[0][i].sum){
                footer['sum'] = footer['sum'] + sum(opt[0][i].field)+ ',';
            }
            if(opt[0][i].avg){
                footer['avg'] = footer['avg'] + avg(opt[0][i].field)+ ',';
            }
            if(opt[0][i].max){
                footer['max'] = footer['max'] + max(opt[0][i].field)+ ',';
            }
            if(opt[0][i].min){
                footer['min'] = footer['min'] + min(opt[0][i].field)+ ',';
            }
        }
 
        var footerObj = new Array();
         
        if(footer['sum'] != ""){
            var tmp = '{' + footer['sum'].substring(0,footer['sum'].length - 1) + "}";
            var obj = eval('(' + tmp + ')');
            if(obj[opt[0][0].field] == undefined){
                footer['sum'] += '"' + opt[0][0].field + '":"<b>当页合计:</b>"';
                obj = eval('({' + footer['sum'] + '})');
            }else{
                obj[opt[0][0].field] = "<b>当页合计:</b>" + obj[opt[0][0].field];
            }
            footerObj.push(obj);
        }
         
        if(footer['avg'] != ""){
            var tmp = '{' + footer['avg'].substring(0,footer['avg'].length - 1) + "}";
            var obj = eval('(' + tmp + ')');
            if(obj[opt[0][0].field] == undefined){
                footer['avg'] += '"' + opt[0][0].field + '":"<b>当页均值:</b>"';
                obj = eval('({' + footer['avg'] + '})');
            }else{
                obj[opt[0][0].field] = "<b>当页均值:</b>" + obj[opt[0][0].field];
            }
            footerObj.push(obj);
        }
         
        if(footer['max'] != ""){
            var tmp = '{' + footer['max'].substring(0,footer['max'].length - 1) + "}";
            var obj = eval('(' + tmp + ')');
             
            if(obj[opt[0][0].field] == undefined){
                footer['max'] += '"' + opt[0][0].field + '":"<b>当页最大值:</b>"';
                obj = eval('({' + footer['max'] + '})');
            }else{
                obj[opt[0][0].field] = "<b>当页最大值:</b>" + obj[opt[0][0].field];
            }
            footerObj.push(obj);
        }
         
        if(footer['min'] != ""){
            var tmp = '{' + footer['min'].substring(0,footer['min'].length - 1) + "}";
            var obj = eval('(' + tmp + ')');
             
            if(obj[opt[0][0].field] == undefined){
                footer['min'] += '"' + opt[0][0].field + '":"<b>当页最小值:</b>"';
                obj = eval('({' + footer['min'] + '})');
            }else{
                obj[opt[0][0].field] = "<b>当页最小值:</b>" + obj[opt[0][0].field];
            }
            footerObj.push(obj);
        }
         
         
         
        if(footerObj.length > 0){
            $(jq).datagrid('reloadFooter',footerObj); 
        }
         
         
        function sum(filed){
            var sumNum = 0;
            for(var i=0;i<rows.length;i++){
                sumNum += Number(rows[i][filed]);
            }
            return '"' + filed + '":"' + sumNum.toFixed(2) +'"';
        };
         
        function avg(filed){
            var sumNum = 0;
            for(var i=0;i<rows.length;i++){
                sumNum += Number(rows[i][filed]);
            }
            return '"' + filed + '":"'+ (sumNum/rows.length).toFixed(2) +'"';
        }
 
        function max(filed){
            var max = 0;
            for(var i=0;i<rows.length;i++){
                if(i==0){
                    max = Number(rows[i][filed]);
                }else{
                    max = Math.max(max,Number(rows[i][filed]));
                }
            }
            return '"' + filed + '":"'+ max +'"';
        }
         
        function min(filed){
            var min = 0;
            for(var i=0;i<rows.length;i++){
                if(i==0){
                    min = Number(rows[i][filed]);
                }else{
                    min = Math.min(min,Number(rows[i][filed]));
                }
            }
            return '"' + filed + '":"'+ min +'"';
        }
    }
});

CI使用phpqrcode生成二维码

PHP QR Code是一个PHP二维码生成类库,利用它可以轻松生成二维码,官网提供了下载和多个演示demo,查看地址:

http://phpqrcode.sourceforge.net/

这个类库就一个文件。打开文件可以发现由多个类组成(我用的是1.1.4)。第一个类名字是 qrstr,文件名是phpqrcode。

下载官网提供的类库后,只需要使用phpqrcode.php就可以生成二维码了,当然您的PHP环境必须开启支持GD2。

CI类命名约定

文件名首字母必须大写,例如:Myclass.php

类名定义首字母必须大写,例如:class Myclass

类名和文件名必须一致

以下是CI使用的流程

A、根据CI命名约定,将第一个类名qrstr改成QRstr,将phpqrcode.php改成Qrcode.php,将该文件放至application/libraries 目录下。

B、CI控制器文件里装载该类 $this->load->library(‘Qrcode’); //二维码生成

C、使用简单例子:echo $this->qrcode->png(“http://www.sina.com”); //显示二维码

phpqrcode.php提供了一个关键的png()方法,其中

参数$text表示生成二位的的信息文本;

参数$outfile表示是否输出二维码图片 文件,默认否;

参数$level表示容错率,也就是有被覆盖的区域还能识别,分别是 L(QR_ECLEVEL_L,7%),M(QR_ECLEVEL_M,15%),Q(QR_ECLEVEL_Q,25%),H(QR_ECLEVEL_H,30%);

参数$size表示生成图片大小,默认是3;参数$margin表示二维码周围边框空白区域间距值;

参数$saveandprint表示是否保存二维码并显示。

. 代码如下:

public static function png($text, $outfile=false, $level=QR_ECLEVEL_L, $size=3, $margin=4, $saveandprint=false)

{

$enc = QRencode::factory($level, $size, $margin);   

return $enc->encodePNG($text, $outfile, $saveandprint=false);   

}

调用PHP QR Code非常简单,如下代码即可生成一张内容为”http://www.cnblogs.com/txw1958/”的二维码.

include ‘phpqrcode.php’;

QRcode::png(‘http://www.cnblogs.com/txw1958/’);

那么实际应用中,我们会在二维码的中间加上自己的LOGO,已增强宣传效果。那如何生成含有logo的二维码呢?其实原理很简单,先使用PHP QR Code生成一张二维码图片,然后再利用php的image相关函数,将事先准备好的logo图片加入到刚生成的原始二维码图片中间,然后重新生成一张新 的二维码图片。

. 代码如下:

include 'phpqrcode.php';    

$value = 'http://www.cnblogs.com/txw1958/'; //二维码内容   

$errorCorrectionLevel = 'L';//容错级别   

$matrixPointSize = 6;//生成图片大小   

//生成二维码图片   

QRcode::png($value, 'qrcode.png', $errorCorrectionLevel, $matrixPointSize, 2);   

$logo = 'logo.png';//准备好的logo图片   

$QR = 'qrcode.png';//已经生成的原始二维码图   



if ($logo !== FALSE) {   

    $QR = imagecreatefromstring(file_get_contents($QR));   

    $logo = imagecreatefromstring(file_get_contents($logo));   

    $QR_width = imagesx($QR);//二维码图片宽度   

    $QR_height = imagesy($QR);//二维码图片高度   

    $logo_width = imagesx($logo);//logo图片宽度   

    $logo_height = imagesy($logo);//logo图片高度   

    $logo_qr_width = $QR_width / 5;   

    $scale = $logo_width/$logo_qr_width;   

    $logo_qr_height = $logo_height/$scale;   

    $from_width = ($QR_width - $logo_qr_width) / 2;   

    //重新组合图片并调整大小   

    imagecopyresampled($QR, $logo, $from_width, $from_width, 0, 0, $logo_qr_width,   

    $logo_qr_height, $logo_width, $logo_height);   

}   

//输出图片   

imagepng($QR, 'helloweixin.png');   

include ‘phpqrcode.php’;

$value = ‘http://www.cnblogs.com/txw1958/’; //二维码内容

$errorCorrectionLevel = ‘L’;//容错级别

$matrixPointSize = 6;//生成图片大小

//生成二维码图片

QRcode::png($value, ‘qrcode.png’, $errorCorrectionLevel, $matrixPointSize, 2);

$logo = ‘logo.png’;//准备好的logo图片

$QR = ‘qrcode.png’;//已经生成的原始二维码图

if ($logo !== FALSE) {

$QR = imagecreatefromstring(file_get_contents($QR));   

$logo = imagecreatefromstring(file_get_contents($logo));   

$QR_width = imagesx($QR);//二维码图片宽度   

$QR_height = imagesy($QR);//二维码图片高度   

$logo_width = imagesx($logo);//logo图片宽度   

$logo_height = imagesy($logo);//logo图片高度   

$logo_qr_width = $QR_width / 5;   

$scale = $logo_width/$logo_qr_width;   

$logo_qr_height = $logo_height/$scale;   

$from_width = ($QR_width - $logo_qr_width) / 2;   

//重新组合图片并调整大小   

imagecopyresampled($QR, $logo, $from_width, $from_width, 0, 0, $logo_qr_width,   

$logo_qr_height, $logo_width, $logo_height);   

}

//输出图片

imagepng($QR, ‘helloweixin.png’);

Nextcloud搭建私有云解决安全及设置警告

在如今的云计算大数据时代,data显得格外的重要,而且从去年开始,各大网盘相继公布关闭,那我们的数据该何去何从呢?买块移动硬盘?貌似有些不方便哦!那我们搭建一个属于自己的私人网盘如何呢?答案是肯定的,至少圈内很多朋友都这样认为。

然后我们看下这类的源码,主流的有owncloud、nextcloud、seafile等几款,这里就不再讲述他们的优劣了,纠结了半天然后我决定使用nextcloud,我这里的环境是tengine2.2.1 + php7.0 + mysql5.6,用的宝塔控制面板,和我们平时搭建网站的方法一样,很简单,这里就不再累述,需要注意的是你的服务器内存尽量要大于512M,建议最低也要使用1G的吧,否则有可能会跑不起来。

登录到后台以后,不出意外的话会有一条警告提示Nextcloud搭建私有云解决安全及设置警告,强迫症是不是又犯了呢?好,重点来了,我们来逐一解决一下。

1. getenv(\”PATH\”)为空,PHP 的设置似乎有问题, 无法获取系统环境变量. 使用 getenv(\”PATH\”) 测试时仅返回空结果

/www/server/php/71/etc/php–fpm.conf,按照路径打开php-fpm.conf文件,后面添加如下内容:

getenv(\”PATH\”)为空,PHP 的设置似乎有问题, 无法获取系统环境变量. 使用 getenv(\”PATH\”) 测试时仅返回空结果PHP

env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp
2. 一些文件没有通过完整性检查. 了解如何解决该问题请查看我们的文档. (无效的文件列表… / 重新扫描…)

点击无效的文件列表,INVALID_HASH 这里表示错误的文件,根据提示的路径查看,多半是你自己上传的和程序无关的文件,移动到其他地方就好。EXTRA_FILE 这里表示多余的文件,需要删除。EXCEPTION 其他错误信息。

3. 模块‘fileinfo’缺失

php扩展安装PATH_INFO和fileinfo

4. 你的数据存储目录可以从互联网上直接访问,.htaccess文件没有生效,请配置你的网页服务器以避免数据存储目录可从外部访问或将数据存储目录转移到网页服务器根目录之外

在你网站的伪静态中加入如下代码(Nginx):

location
~ ^/(data|config|\.ht|db_structure\.xml|README) {
deny all;
}
5 . HTTP 请求头“Strict-Transport-Security”没有配置为至少“15552000”秒,出于增强安全性考虑,我们推荐按照安全提示中的说明启用HSTS

这个问题是你已经启用了https后提示的,确保打开了443端口,然后打开你网站的配置文件添加如下代码:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
6. 内存缓存未配置,如果可用,请配置memcache以增强性能,更多信息请查看我们的文档

php扩展添加redis,然后打开你网站根目录下的config文件夹,打开config.php文件,在最后一个括号前添加如下代码:

'memcache.local' => '\OC\Memcache\Redis',
'redis' => array(
'host' => 'localhost',
'port' => 6379,
),
7.PHP 的组件OPcache没有正确配置,为了提供更好的性能,我们建议在php.ini文件中使用下列设置

php扩展添加opcache,并在php配置文件中找到[Zend Opcache]替换如下代码,效果见图:

opcache.enable=1 opcache.enable_cli=1 opcache.interned_strings_buffer=8 opcache.max_accelerated_files=10000 opcache.memory_consumption=128 opcache.save_comments=1 opcache.revalidate_freq=1