微信支付主要分为四大部分:
1.html 页面用来展示支付二维码
2.controller 引入微信支付api及支付代码 (微信Native支付SDK与DEMO下载地址)
3.将微信支付api放到thinkphp的Vendor目录下
(将/example目录下WxPay.Config.php文件中的APPID,MCHID,KEY,APPSECRET替换成自己公众平台和商户号的)
4.在微信公众平台和微信商户平台配置相关域名及回调地址
1.html页面部分
<div class="col-sm-4">
//生成二维码类在微信下载的demo中/example/phpqrcode/phpqrcode.php
<img alt="微信扫码支付" src="<?php echo $_SERVER['REQUEST_SCHEME'] ?>://<?php echo $_SERVER['SERVER_NAME'] ?>/index.php/Home/Wxpay/qrcode?data=<?php echo urlencode($url);?>" style="width:220px;text-align: center;"/>
</div>
2.controller部分
<?php
namespace Home\Controller;
use Think\Controller;
class WxpayController extends Controller {
private $ordObj;
public function __construct() {
parent::__construct();
//引入Vendor下面的微信支付类
header("Content-type:text/html;charset=utf-8");
require_once VENDOR_PATH.'/Wxpay/lib/WxPay.Api.php';
require_once VENDOR_PATH.'/Wxpay/lib/WxPay.Notify.php';
require_once VENDOR_PATH.'/Wxpay/lib/WxPay.Data.php';
require_once VENDOR_PATH.'/Wxpay/example/WxPay.Config.php';
require_once VENDOR_PATH.'/Wxpay/example/phpqrcode/phpqrcode.php';
$this->ordObj=D('order');
}
//生成二维码
public function qrcode(){
$url = urldecode($_GET["data"]);
if(substr($url, 0, 6) == "weixin"){
\QRcode::png($url);
}else{
header('HTTP/1.1 404 Not Found');
}
exit();
}
/**
* 调起微信支付
* @param int $id 订单id
* 订单验证成功后调起支付
*/
public function wxpay($id){
layout(false);
$whe = array('id'=>$id,);
$data = $this->ordObj->where($whe)->find();
/**
此处写支付前的逻辑验证代码
*/
$param =array(
'out_trade_no'=>$data['order_id'], //订单号
'price'=>$data['order_money'], //订单金额
'subject'=>C('configs.preliminary_title'), // 商品名称标题
);
//调用微信支付代码
$this->wxpays($param);
}
public function wxpays($param){
$input = new \WxPayUnifiedOrder();
$input->SetBody($param['subject']);
$input->SetAttach("test");
$input->SetOut_trade_no($param['out_trade_no']);
$input->SetTotal_fee($param['price']*100);
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("test");
$input->SetNotify_url($_SERVER['REQUEST_SCHEME']."://".$_SERVER['SERVER_NAME']."/index.php/Home/Wxpay/notify");
$input->SetTrade_type("NATIVE");
$input->SetProduct_id($param['out_trade_no']);
$result = $this->GetPayUrl($input);
if( $result['result_code'] == 'FAIL' ){
redirect(U("Home/Signup/orderlistx") ,3, $result['err_code_des']);
exit();
}
$url = $result["code_url"];
$this -> assign('url',$url);
$this -> assign('out_trade_no',$param['out_trade_no']);
$this -> assign('price',$param['price']);
$this -> assign('preliminary_title',C('configs.preliminary_title'));
$this -> display();
}
/**
* 微信回调接口
* logPays是自己封装记录log的方法
*/
public function notify(){
//获取接口数据,如果$_REQUEST拿不到数据,则使用file_get_contents函数获取
$post = $_REQUEST;
if ( isset($post) || empty($post) ) {
$post = file_get_contents("php://input");
}
libxml_disable_entity_loader(true); //禁止引用外部xml实体
$data = simplexml_load_string($post, 'SimpleXMLElement', LIBXML_NOCDATA);//XML转数组
$data = json_encode($data);
$json = '微信同步回调: '. $data;
logPays($json,'Wxpaylog.json'); // json日志
$data = json_decode($data,true);
//TODO 1、进行参数校验
if(!array_key_exists("return_code", $data) && $data['return_code'] != "SUCCESS") {
//TODO失败,不是支付成功的通知
//如果有需要可以做失败时候的一些清理处理,并且做一些监控
$json = '微信同步回调: 订单状态异常!';
logPays($json,'Wxpaylog.json'); // json日志
redirect(U("Home/Signup/orderlistx") ,3, '订单状态异常...');
exit();
}
if(!array_key_exists("transaction_id", $data)){
$json = '微信同步回调: 订单号异常!';
logPays($json,'Wxpaylog.json'); // json日志
redirect(U("Home/Signup/orderlistx") ,3, '订单号异常...');
exit();
}
// //TODO 2、进行签名验证
$config = new \WxPayConfig();
try {
$WxPayResults = new \WxPayResults();
$setsign = $WxPayResults->SetSign($config);
$checkResult = $WxPayResults->CheckSign($config);
if($checkResult == false){
$json = '微信同步回调: 签名错误!';
logPays($json,'Wxpaylog.json'); // json日志
//签名错误
redirect(U("Home/Signup/orderlistx") ,3, '签名错误...');
exit();
}
} catch(Exception $e) {
redirect(U("Home/Signup/orderlistx") ,3, $e);
exit();
}
// //TODO 3、处理业务逻辑
//查询订单,判断订单真实性
$res = $this->Queryorder($data["transaction_id"]);
if(!$res){
$json = '微信同步回调: 订单查询失败!';
logPays($json,'Wxpaylog.json'); // json日志
redirect(U("Home/Signup/orderlistx") ,3, '订单查询失败...');
exit();
}else{
// 查询成功
$json = '微信同步回调: 查询成功!';
logPays($json,'Wxpaylog.json'); // json日志
$whe = array('order_id'=>$res['out_trade_no'],);
$data1 = $this->ordObj->where($whe)->find();
// 支付成功
if( $res['trade_state'] == 'SUCCESS' && $data1['order_money']*100 == $res['total_fee'] ){
$json = '微信同步回调: 支付成功!';
logPays($json,'Wxpaylog.json'); // json日志
// 交易支付成功,同步回调完成,处理订单
$out_trade_no = $res['out_trade_no']; // 商户订单号
$trade_no = $res['transaction_id']; //微信交易号
$trade_status = $res['trade_state'];//交易状态
$result = $this->ordObj->pay_success($out_trade_no,$trade_no,2);
redirect(U("Home/User/paysuccess"), 1, '支付成功!');
}else{
$json = '微信同步回调: 支付失败或金额错误!';
logPays($json,'Wxpaylog.json'); // json日志
}
}
exit();
}
//查询订单
public function Queryorder($transaction_id)
{
$input = new \WxPayOrderQuery();
$input->SetTransaction_id($transaction_id);
$config = new \WxPayConfig();
$result = \WxPayApi::orderQuery($config, $input);
if( array_key_exists("return_code", $result) && array_key_exists("result_code", $result) && $result["return_code"] == "SUCCESS" && $result["result_code"] == "SUCCESS" )
{
return $result;
}
return false;
}
/**
*
* 生成直接支付url,支付url有效期为2小时,模式二
* @param UnifiedOrderInput $input
*/
public function GetPayUrl($input)
{
if($input->GetTrade_type() == "NATIVE")
{
try{
$config = new \WxPayConfig();
$result = \WxPayApi::unifiedOrder($config, $input);
return $result;
} catch(Exception $e) {
Log::ERROR(json_encode($e));
}
}
return false;
}
/**
*
* 参数数组转换为url参数
* @param array $urlObj
*/
private function ToUrlParams($urlObj)
{
$buff = "";
foreach ($urlObj as $k => $v)
{
$buff .= $k . "=" . $v . "&";
}
$buff = trim($buff, "&");
return $buff;
}
public function getstatus(){
$get = I('get.');
$whe = array('order_id'=>$get['out_trade_no'],);
$data = $this->ordObj->where($whe)->find();
if( $data['order_state'] == 1 ){
echo 1;//已支付
}else{
echo 0;//待支付
}
exit();
}
}