最近帮朋友做一个微信商城,需要用到微信支付,以前一直以为很简单,做的时候发现也是很多坑的,废话不多说。
1、微信支付有多种,我这用的是微信公众号支付(首先要满足是认证的服务号才有此功能)
2、配置
a、在微信公众平台->公众号设置->功能设置 设置授权回调地址
b、记录公众号的appid和appsecret 待会支付的时候配置时用得到
c、登入微信商户平台 产品中心->开发配置 配置支付授权目录,还得记下商户号
注意:扫码支付就配置扫码支付的,微信支付就配置微信支付的;目录不能带参数,,比如:http://www.xxx.com/home/pay/run 其中run是action,我们只配置到pay的目录,所以正确配置是http://www.xxx.com/home/pay/ 不需要run 这是一个坑。如果是单独申请的微信商户支付,则还需自己去产品中心添加APPID授权管理
d、在https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1下载demo到本地 解压
e、在https://pay.weixin.qq.com/index.php/account/api_cert下载证书,证书有效期是1年,把证书放入稍后的demo文件的cert文件夹里,覆盖
3、上代码
把demo的这几个文件和 WxPay.JsApiPay.php放在一个文件夹中,如图:
在demo中修改代码 打开lib文件夹下的WxPay.Api.php文件,在537行有一段curl网络请求配置代码:
curl_setopt($ch,CURLOPT_URL, $url);
//curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);//注释掉
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);//改成这个
打开lib文件夹下的WxPay.Config.php文件,第25行开始,根据自己的账号完成基本信息设置;
const APPID = '公众账号APPID';
const MCHID = '商户号';
const KEY = '商户支付密钥';
const APPSECRET = '公众帐号secert';
打开lib文件夹下的WxPay.Notify.php文件,第79行的代码:
if($needSign == true &&
$this->GetReturn_code($return_code) == "SUCCESS")
{
$this->SetSign();
}
改成
if($needSign == true &&
$this->GetReturn_code() == "SUCCESS")
{
$this->SetSign();
}
参考:https://blog.csdn.net/sinat_35861727/article/details/72765676
新建一个控制器
require_once INIT_PATH . "vendor/wxpay/lib/WxPay.Api.php";
require_once INIT_PATH . "vendor/wxpay/WxPay.JsApiPay.php";
require_once INIT_PATH . "vendor/wxpay/log.php";
class payController extends homeController
{
public $initphp_list = [
'run',
'notify'
];
public function __construct()
{
parent::__construct();
$config = InitPHP::getConfig();
$this->renderArray['url'] = 'http://' . $config['url'];
}
/**
* 支付主页
* */
public function run()
{
$id = $this->controller->get_gp('id');
if (empty($id)) {
$this->error('非法请求');
}
$info = $this->getMemberCardDao()->getOne($id);
if (empty($info['id'])) {
$this->error('无该会员卡,非法请求');
}
$price = preg_replace('/^0*/', '', $info['price']);
//生成订单
$order_id = (int)'1'.$info['id'].date("YmdHis").mt_rand(1000,9999);//,类型(1会员卡)+id+时间+4位随机
//$cardTime = $this->getMemberCardOrderDao()->getCardType($info['type']);
$orderInfo = [
'order_id' => $order_id,
'card_id' => $info['id'],
'uid' => $this->uid,
'card_type' => $info['type'],
'created_at' => time()
];
//初始化日志
//$logHandler= new CLogFileHandler("/www/logs/wxpay/".date('Y-m-d').'.log');
//$log = Log::Init($logHandler, 15);
//轮播图
//①、获取用户openid
$tools = new JsApiPay();
$openId = $tools->GetOpenid();
//②、统一下单
$input = new WxPayUnifiedOrder();
$input->SetBody($info['name']);//商品名称
$input->SetAttach($info['id']);//附加参数
//$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
$input->SetOut_trade_no($order_id);//订单号
$input->SetTotal_fee($price);//金额,分
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag($info['name']);
//$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");//支付验证链接,可以写其他地址,当然要在支付授权域名之下,支付成功之后就会自动回调到该链接指定的方法里边,可以在里边进行判断和数据库操作.
$input->SetNotify_url("http://www.xxxxx.com/home/notify/run/");//支付验证链接,可以写其他地址,支付成功之后就会自动回调到该链接指定的方法里边,可以在里边进行判断和数据库操作.
$input->SetTrade_type("JSAPI");
$input->SetOpenid($openId);
$order = WxPayApi::unifiedOrder($input);
//echo '<font color="#f00"><b>统一下单支付单信息</b></font><br/>';
//$this->printf_info($order);
$jsApiParameters = $tools->GetJsApiParameters($order);
//echo '<font color="#f00"><b>jsapi付单信息</b></font><br/>';
//$this->printf_info(json_decode($jsApiParameters,true));
//获取共享收货地址js函数参数
//$editAddress = $tools->GetEditAddressParameters();
$info['price'] = FormatMoney($info['price'], 2);
$this->getMemberCardOrderDao()->add($orderInfo);
$this->viewAssign();
$this->view->set_tpl('homeHeader', 'F');
$this->view->assign('title', '支付页面');
$this->view->assign('jsApiParameters', json_decode($jsApiParameters,true));
$this->view->assign('info', $info);
//$this->view->assign('jsApiParameters', $jsApiParameters);
//$this->view->assign('editAddress', json_decode($editAddress,true));
$this->view->set_tpl($this->renderArray['md'] . '/pay/index');
$this->view->display();
}
//打印输出数组信息
private function printf_info($data)
{
foreach($data as $key=>$value){
echo "<font color='#00ff55;'>$key</font> : $value <br/>";
}
}
/**
* @return memberCardOrderDao
*
* */
private function getMemberCardOrderDao()
{
return InitPHP::getDao('memberCardOrder');
}
/**
* @return memberCardDao
* */
private function getMemberCardDao()
{
return InitPHP::getDao('memberCard');
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<!--{ includeCss(array('/static/home/pay/css/reset.css','/static/home/pay/css/listcommen.css','/static/home/pay/css/waitpay.css')); }-->
<title>等待付款</title>
<style type="text/css">
.alert_qr img {
width: 5rem;
height: 5rem;
}
.alert_qr p {
width: 80%;
height: 0.8rem;
line-height: 0.8rem;
margin: 0 auto;
background: #f33;
color: #fff;
border-radius: 0.04rem;
text-align: center;
}
@keyframes loader {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@-webkit-keyframes loader {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
.carditemss p {
width: 100%;
height: .88rem;
line-height: .88rem;
overflow: hidden;
}
select {
background-color:transparent;
border-color:transparent;
-webkit-appearance: none;
font-size: 0.26rem;
text-indent: 1em;
}
</style>
</head>
<body>
<div class="wrap">
<div class="header bg_red1 clearfix">
<strong class="iconfont header_btn1" οnclick="linkBack();"></strong>
<div class="top_tab clearfix">等待付款</div>
<strong class="iconfont header_btn3" οnclick="linkHome();"></strong>
</div>
<div class="wraper">
<div class="shop_content">
<ul class="shop">
<li class="shop_list clearfix">
<div class="img_box2" style="width: 100%;">
<img style="width: 100%;height: auto" src="<!--{$info['image_url']}-->">
</div>
</li>
</ul>
</div>
<div class="cardmsg">
<div class="carditems" v-show="mydata.is_vip != 0 &&buydata.vip_price>0">
<p>
<!--{$info['name']}-->
</p>
<p class="cardcontent red"><!--{$info['desc']}--></p>
</div>
<div class="carditems">
<p>需付款</p>
<p class="cardcontent red">¥<!--{$info['price']}--></p>
</div>
</div>
<p class="cardtit">支付方式</p>
<div class="cardmsg cardpay">
<div class="carditems ">
<p><i class="iconfont" style="color: #0AB70E;margin-right: 0.1rem;vertical-align: middle;"></i>微信支付</p>
<p class="cardcontent">
<input type="radio" name="pay" checked class="weui-check" id="wx">
</p>
</div>
</div>
<p class="topaybtn" οnclick="callpay()">立即支付</p>
</div>
</div>
<script type="text/javascript">
//调用微信JS api 支付
function jsApiCall()
{
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
{
'appId':'<?php echo $jsApiParameters["appId"]; ?>',
'nonceStr':'<?php echo $jsApiParameters["nonceStr"]; ?>',
'package':'<?php echo $jsApiParameters["package"]; ?>',
'signType':'<?php echo $jsApiParameters["signType"]; ?>',
'timeStamp':'<?php echo $jsApiParameters["timeStamp"]; ?>',
'paySign':'<?php echo $jsApiParameters["paySign"]; ?>'
},
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(res.err_code+res.err_desc+res.err_msg);
window.location.href="http://www.17quxun.com/home/center/run";
}else{
//返回跳转到订单详情页面
//alert('支付失败');
//window.location.href="http://www.17quxun.com/";
}
}
);
}
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();
}
}
var url = "<!--{$url}-->";
//返回首页
function linkHome() {
window.location = url + '/home/shop/run';
}
//返回上一级
function linkBack() {
if (document.referrer == '') {
window.location = url + '/home/coupons/run';
} else {
window.location = document.referrer;
}
}
</script>
</body>
</html>
至此,公众号支付完成