微信商户帐户/密码(获取appid等信息)
微信公众号帐户/密码(获取cert证书等信息,不作线上退款不须要证书)php
从商户平台进入的话是如下界面或者直接搜索公众号支付文档java
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1
数据库
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
json
解压文件,打开index.php修改
能够改为绝对路径,即你放的位置(某个域名或者某个域名下某个文件夹下)或者相对路径api
http://'.$_SERVER['HTTP_HOST'].'/WxpayAPI/example/jsapi.php
说明
appId:是你的微信公众平台的appId
appsecret:是你商户平台的appsecret这两个参数可登陆你的微信公众平台查看
mchId:是你的商户Id,这个是你的微信公众号开通微信支付,微信分配给你的一个商户支付ID,可登录商户平台查看,便是你登陆商户平台的帐号
key:是你商户平台的支付秘钥,这个参数很关键,它是一个32位的字符串安全
必定要保证你以上四个参数的正确,否则出现的各类错误皆多是这四个参数不正确形成的,固然前提是你开通微信支付而且配置正确的受权域名和支付目录bash
打开example文件夹下的jsapi.php微信
$input->SetNotify_url("http://www.xxx.com/WxpayAPI/example/notify.php"); //设置接收微信支付异步通知回调地址
改成你本身的地址,能够写死或者相对路径获取该地址网络
Wxpay.api.php中的unifiedOrder下单方法中须要session
//异步通知url未设置,则使用配置文件中的url
if(!$inputObj->IsNotify_urlSet()){ $inputObj->SetNotify_url(WxPayConfig::NOTIFY_URL);//异步通知url }
因此若是你没设置,则须要去WXPay.Config.php中添加一条:
const NOTIFY_URL='https://www.xxx.com/WxpayAPI/example/notify.php';
由于微信支付要获取openId,它是微信支付用户的凭证
好比你的是www.xxx.com/WxpayAPI/example/
那么你就把你整个WxpayAPI文件夹传到你的www.xxx.com域名目录下
预览index.php
支付成功jsapi中的js就能够根据返回的信息跳转到支付成功的页面,这是接收微信同步返回的处理
function jsApiCall() { WeixinJSBridge.invoke( 'getBrandWCPayRequest', <?php echo $jsApiParameters; ?>, //订单参数 function (res) { alert(res.err_msg); WeixinJSBridge.log(res.err_msg); if (res.err_msg == 'get_brand_wcpay_request:ok') { window.location.href = 'http://h.yiwang.com/index.php?r=cart/finishedorder&paymentId='+<?php echo $paymentId;?>+'&orderId='+<?php echo $orderId;?>; }else if (res.err_msg == 'get_brand_wcpay_request:cancel') { alert('cancel'); } else { alert('fail'); alert(res.err_msg); } } ); }
可是最终是否支付成功不能以这个为准,而是notify.php接收到的异步通知为准,这是微信异步返回的结果处理
public function NotifyProcess($data, &$msg) { Log::DEBUG("call back:" . json_encode($data)); $notfiyOutput = array(); if(!array_key_exists("transaction_id", $data)){ $msg = "输入参数不正确"; return false; } //查询订单,判断订单真实性 if(!$this->Queryorder($data["transaction_id"])){ $msg = "订单查询失败"; return false; } $this->UpdateOrderStatus();//自定义更改数据库支付成功状态 return true; }
具体的更改数据库订单状态须要接收到微信异步通知的xml,而后判断是否支付成功,再进行更改
function UpdateOrderStatus() { $string = file_get_contents("php://input");//微信返回的xml支付结果 $arr = (array) simplexml_load_string($string, 'SimpleXMLElement', LIBXML_NOCDATA); if ($arr['result_code'] == 'SUCCESS' && $arr['return_code'] == 'SUCCESS') { //操做数据库处理订单状态等 } }
以上是分析的demo大体流程,接下来我说一下我遇到的坑,望各位注意:
这是我最开始调试SDK的demo时候第一个坑
咱们公司把已经使用是APP的商户Id和key给我,让我用这个,这个后台能够登陆,我看到了商户id没问题,但key看不到,只有重置才能够,由于线上用着,我也无法重置,还觉得代码有问题,各类输出查看。
百度好多人都让重置key,说同一个key从新提交一次也行,有人提交两三次同一个key,说就不报签名无效了。但咱们没有开发环境,我不能任性重置。只能找代码的问题
最终发现仍是第一步的四个配置参数有问题,appId没问题是公众号的id,我没用他们给个人appId,他们的appId应该是App开放平台的appId
商户id和秘钥,给个人是app的商户id和key,其实不是。应该是咱们微信公众号申请微信支付分配的商户id和秘钥。而不是说用APP申请的商户id和秘钥。
虽然文档说的很清楚,我也知道,但领导就说和app共用一个,我也很无奈。由于开始我也不是很清楚,就以为那就是吧,或许是demo有问题(哈哈哈)
微信说是32位之内,可是,若是你传1位,确定会报错,它的提示还很弱,不是说位数不足,具体什么提示我忘了。反正位数太少会出错,我在这里也是摔了个跟头
搜了好多资料,大部分人都只讲解了demo,说支付成功以异步通知为准,微信是通知给你设置的地址了,但问题是我怎么获取他的通知呢?
老是以为没有返回变量,就不知道怎么输出变量,怎么处理。
$string = file_get_contents("php://input");
这就是接收到微信的通知,一个xml,详细代码上边有
缘由:在建立商户订单时,须要获取到用户的openid
//①、获取用户openid $tools = new JsApiPay(); $openId = $tools->GetOpenid();
Wxpay.JsApiPay.php
可是在获取用户openid的过程当中须要请求CODE,CODE请求函数以下:
public function GetOpenid() { //经过code得到openid if (!isset($_GET['code'])){ //触发微信返回code码 $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING']); $url = $this->__CreateOauthUrlForCode($baseUrl); Header("Location: $url"); exit(); } else { //获取code码,以获取openid $code = $_GET['code']; $openid = $this->getOpenidFromMp($code); return $openid; } }
所以,在获取openid商户后台与微信系统进行屡次交互,当再次回到生成商户订单页的时候,咱们以前从h5页面经过$_GET或者$_POST方式获取的参数已经被清空,因此没法生成商户订单。
解决办法:
1.先将用户h5页面提交过来的参数保存到session中,而后再重定向到要生成商户订单的页面,
在生成商户订单的页面中先获取openid,再获取session
中的值(这是我百度到别人采用的方法)
2.个人办法:
在获取openid以前把post或者get的参数取到,而后传给微信(采用和他获取code的机制同样)
//①、获取用户openid $tools = new JsApiPay(); $arr = $tools->GetOpenid($Out_trade_no,$paymentId,$Total_fee);
重写GetOpenid方法,以下:
public function GetOpenid($orderId,$paymentId,$totalFee) { //经过code得到openid if (!isset($_GET['code'])){ //触发微信返回code码 $baseUrl = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].$_SERVER['QUERY_STRING'].'?orderId='.$orderId.'&paymentId='.$paymentId.'&totalFee='.$totalFee); $url = $this->__CreateOauthUrlForCode($baseUrl); Header("Location: $url"); exit(); } else { //获取code码,以获取openid $code = $_GET['code']; $orderId = $_GET['orderId']; $paymentId= $_GET['paymentId']; $totalFee = $_GET['totalFee']; $openid = $this->getOpenidFromMp($code); return $arr; } }
传递的金额,微信是以分为单位,而通常是以元为单位,因此记得金额转换一下,不要传给微信小数点
还有这个金额最好在jsapi这个页面,查询一下数据库该笔订单应支付多少,而不是从提交订单页面传输过来,这样不安全,也别觉得请求接口会安全,都不安全,只要存在网络传输就会出现篡改,最好是本身在本页面查询出来,而后传给微信
咱们的提交订单会生成一个orderId和paymentId存在咱们的两个表中(这两个表),而后由于要给微信传咱们本身的订单id,通常来讲只须要传orderId就行,可是接收到微信异步通知的支付成功之后, 咱们须要根据paymenId去改咱们的支付状态。
问题是从微信返回时咱们没有paymentId。
用orderId去查可能会不惟一(咱们数据库设计如此,会有多订单支付),另外一方面是屡次请求会慢,因此我采起了把订单id和paymentId拼接在一块儿做为传给微信,而后支付成功之后微信返回out_trade_no就是咱们的orderId和paymentId