您的位置:首页 > 移动开发 > 微信开发

工作日志--微信支付整合到opensns(v2)下之jsapi支付(输入金额无刷新)

2016-08-19 09:45 603 查看
之前完成微博模块的修改后好长一段时间没有写博客了。嘛,重复性的工作感觉没什么可写的就偷懒了。这周领导新任务,需要加入微信支付功能,之前没有接触过花了1天时间用原生PHP实现了支付的功能,但是发现没有整合在框架下要开发扩展功能十分不方便,于是第二天就开始研究将微信支付整合进opensns(v2),又是一天奋战,总算实测完成了,之后按老板要求实现输入金额当前页面无刷新支付,需要用到ajax的时候又碰到一些问题,以下会详细给出。截止目前为止,通知notify还没有写,之后会来补上。嘛废话不说了,以下上干货。

使用的微信支付sdk是WxpayAPI_php_v3版本。下载的话去官方网页就好我这里就不给出了。config的配置指南网上很多我这里也就不再赘述了。

一:准备工作

首先我们需要用到的类库文件,二维码生成文件,cert证书放到一个文件夹下,并且对类库文件文件名处理下方便在框架下用vendor调用。

类库文件:lib里的所有文件;example里的WxPay.JsApiPay.php,WxPay.MicroPay.php,WxPay.NativePay.php,log.php

二维码生成文件:example里的phpqrcode文件夹

cert证书:cert文件夹

以上文件具体用途之后给出,将这些文件拷贝到新建文件夹(我命名为wxpay)中,其中类库文件全部放入lib文件夹,二级目录如图:



接下来对类库文件名处理如图:



其实就是讲中间的点去掉

还有类库文件中引入require_once在opensns中会报错无法打开文件。请同意修改为include_once,并且记得把文件名中间的点去掉哦。

处理完成后,就可以将整个文件夹放到根目录下ThinkPHP/Library/Vendor中

然后我们要选择控制器与视图所在模块,当然可以自己创建一个支付模块以后开发别的支付渠道也可以发放在该模块下,不过由于时间原因,我暂时放在了mob模块下。

在mob模块下我创建了一个PayController.class.php控制器,并创建对于视图文件夹Pay

准备工作的最后一步是去微信公众平台配置支付授权目录。这里需要填写到控制器,并以/结尾,……index.php?s=/mob/pay/ 这样。

以上就是准备工作。接下来我们来编写控制器和视图。这里我直接以输入金额当前页面无刷新支付为实例:

1.在PayController.class.php控制器中继承BaseController:

namespace Mob\Controller;

use Think\Controller;

class PayController extends BaseController


视图显示方法jsapi_show:主要获取openid并分配到视图中用ajax传参到处理方法中。因为处理ajax的方法中无法访问微信服务器获取openid。

public function jsapi_show(){
vendor('wxpay.lib.WxPayConfig');     //引入微信配置类
vendor('wxpay.lib.WxPayJsApiPay');   //引入jsapi支付类库

//①、获取用户openid
$tools = new \JsApiPay();
$openId = $tools->GetOpenid("请求网址/index.php?s=/mob/pay/jsapi_show"); //将请求网址作为参数传入

$this->assign('openid',$openId);
$this->display();
}
这里需要注意的是  JsApiPay类中的GetOpenid方法原来是不需要传请求网址,在方法中以'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING']   形式获取,但是opensns在没有开启伪静态的情况下啊,这样获取地址是错误的。因此需要将请求网址作为参数传入,在WxPayJsApiPay.php的GetOpenid中进行一下修改:

public function GetOpenid($urlin="")
{
//通过code获得openid
if (!isset($_GET['code'])){
//触发微信返回code码
$baseUrl = urlencode($urlin);


OK,视图方法完成后,我们来编写处理ajax请求的方法jsapi_ajax,一下给现给出代码,之后来讲解其中的注意点:

public function jsapi_ajax(){
$fee = I("post.fee","1","float");
$openId = $_POST['openid'];
$body = I("post.body",'default',"op_t");
$attach = I("post.attach",'default',"op_t");
$goods_tag = I("post.goods_tag","default","op_t");

vendor('wxpay.lib.WxPayConfig');     //引入微信配置类
vendor('wxpay.lib.WxPayJsApiPay');   //引入jsapi支付类库

//①、获取用户openid
$tools = new \JsApiPay();

$wxc = new \WxPayConfig;
$wxa = new \WxPayApi;
//②、统一下单
$input = new \WxPayUnifiedOrder();
$input->SetBody($body);         //商品描述
$input->SetAttach($attach);		//附加数据
$input->SetOut_trade_no($wxc::MCHID.date("YmdHis"));
$input->SetTotal_fee($fee*100);   //交易金额
$input->SetTime_start(date("YmdHis")); //交易起始时间
$input->SetTime_expire(date("YmdHis", time() + 600)); //交易结束时间
$input->SetGoods_tag($goods_tag);  //商品标记,代金券或立减优惠的参数
$input->SetNotify_url("http://网站根目录/index.php?s=/mob/pay/notify"); //交易通知url
$input->SetTrade_type("JSAPI");  //交易类型
$input->SetOpenid($openId);

$order = $wxa::unifiedOrder($input);

$jsApiParameters = $tools->GetJsApiParameters($order);
$jsApiParameters = json_decode($jsApiParameters);
$this->ajaxReturn($jsApiParameters);

}


这里除了OpenId我们用$_POST接收,其他参数我们用I()函数接收post值,为空时付给defult初始值,应为Total_fee不能为空,所以初始值付给一个1元,当然前端在输入金额时就应该js判断不能为空。

接下来一点需要注意的是用到的类都需要实例化,无论调用的方法是不是静态。

最后一点当时困扰我好久的是注意这里

$jsApiParameters = $tools->GetJsApiParameters($order);
在GetJsApiParameters方法中已经对数据进行了一次转JSON处理,如果直接ajax返回,会再一次被转JSON处理,数据type就会是string而不是opject,导致报错。所以这里需要对
$jsApiParameters
JSON解码处理然后ajax返回。

接下来就是编辑视图文件了。这里我们将SDK中的jsapi.php复制一份命名为jsapi_show.html   删掉其中所有php部分,html部分继承Base/mob_common

并抱在mob_body块中:

<extend name="Base/mob_common"/>
<block name="mob_body">
</block>


然后将金额部分改为input标签,并对button按钮onclick调用的方法修改为我们自定义的方法jsapi_ajax():

<font color="#9ACD32"><b>该笔订单支付金额为<input type="text" name="fee" id="fee" />元钱</b></font><br/><br/>
<input type="hidden" name="openid" id="openid" value="{$openid}"/>
<br/><br/>
<div align="center">
<button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer;  color:white;  font-size:16px;" type="button" onclick="jsapi_ajax()" >立即支付</button>


下面现给出jsapi_ajax()方法:
<script>
function jsapi_ajax()
{

var fee = $("#fee").val();
var openid = $("#openid").val();

if(fee == ""){
alert("输入money不能为空");

}else{

$.post("网站根目录/index.php?s=/mob/pay/jsapi_ajax",{"fee":fee,'openid':openid,'body':"自定义名称"}, function(data) {

callpay(data);

});
}

}
</script>


这里必传参数是fee金额和openid,其他不传的话就是后台设置的默认值。之后将返回数据传给callpay方法。还是把callpay方法和jsApiCall贴一下吧:

<script type="text/javascript">
//调用微信JS api 支付
function jsApiCall(data)
{

WeixinJSBridge.invoke(
'getBrandWCPayRequest',
data,
function(res){
WeixinJSBridge.log(res.err_msg);
alert(res.err_code+res.err_desc+res.err_msg);   //res.err_msg 为get_brand_wcpay_request:ok 表明前端判断的支付成功   可以根据这个将支付跳转到成功页面。
}
);
}

function callpay(data)
{

if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridg
a822
eReady', jsApiCall, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}else{
jsApiCall(data);
}
}

</script>


到此为止就OK拉。之后完成后台通知方法notify后会补上的。

如果还有什么问题的话,欢迎加企鹅2541497491,交流讨论。那么下次再见啦
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息