先分清几个概念:微信公众平台、微信开放平台、微信商户平台
1.微信公众平台、微信开放平台、微信商户平台是三个不同的平台
2.微信公众平台:用于公众号、小程序等等的设置平台,包括APPID、APPSECRET(注:每个公众号、每个小程序的APPID都是独立的、不一样的,所以如果是要用某个小程序支付,那就要用那个小程序的APPID、APPSECRET,不能混淆)。也就是用于微信这个APP本身的设置
3.微信开放平台:用于微信APP与其他APP的“连接”、“沟通”,为其他APP提供了如微信登录、微信分享、微信支付等功能(比如在使用12306APP买票的时候可以选择用微信支付)
4.微信商户平台:是用于微信商户支付设置,因为支付功能属于一个大的模块,所以微信单独分离出了这个平台,微信商户的账号就是MCHID,进入微信商户平台后,设置的支付的密钥就是KEY,设置支付密钥前要安装操作证书以及设置操作密码等
4.微信支付目前有下面这几种,小程序支付实际调用的是公众号支付
5.微信号可以用来登录微信公众平台和微信商户平台,一个微信号可以申请多个公众号、多个小程序,多个微信商户号,所以在配置支付的时候一定要注意哪个小程序对应的哪个微信商户号,一旦配置错误,经常在程序中校验签名的时候返回“签名错误”(个人觉得微信还可以再提示的详细一些,到底是什么错误,避免N次的Debug)
把生成好的xml及商户key对应填入,即可校验,如果校验失败,说明xml格式不正确或者sign与商户KEY不匹配,xml格式不正确请参阅:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1,商户KEY不匹配请重新比对并设置商户KEY
(特别说明:xml校验通过,只能说明xml的格式以及sign签名与商户KEY是匹配的,并不代表APPID、MCHID、KEY、APPSECRET配置的是正确的,这句话一定好好理解一下)
综上,只要是使用的官方sdk(https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1)开发的,xml校验通过了,并且配置对了APPID、MCHID、KEY、APPSECRET的,绝大多数的“签名错误”都可以解决了。
-----------------------------------------------------------------------------------------------------------------
前端:比较简单,在对应的支付事件上进行网络请求就好:
view_moneysure:function(){
var code = this.data.code;
console.log('code是' +code)
wx.request({
url: 'https://...com/pay.php',//这个链接是后端写的
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: {
code: code,
},
method: 'POST',
success: function (response) {
console.log( response.data);
// 发起支付
wx.requestPayment({
'appId': response.data.appId,
'timeStamp': response.data.timeStamp,
'nonceStr': response.data.nonceStr,
'package': response.data.package,
'signType': 'MD5',
'paySign': response.data.paySign,
'success': function (res) {
wx.showToast({
title: '支付成功'
});
console.log(res);
},
'fail': function (res) {
console.log(res)
}
});
},
fail: function (res) {
console.log(res)
}
})
},
后端代码:
1. pay.php //小程序请求的后端地址
/**
* Created by PhpStorm.
* User: UFO
* Date: 17/7/18
* Time: 下午5:31
*/
require_once ('WxPay.Api.php');
class WXPay {
function index() {
// 初始化值对象
$input = new WxPayUnifiedOrder();
// 文档提及的参数规范:商家名称-销售商品类目
$input->SetBody("testceshi");
// 订单号应该是由小程序端传给服务端的,在用户下单时即生成,demo中取值是一个生成的时间戳
$input->SetOut_trade_no(time().'');
// 费用应该是由小程序端传给服务端的,在用户下单时告知服务端应付金额,demo中取值是1,即1分钱
$input->SetTotal_fee("1");
$input->SetNotify_url("https://...com/notify.php");//需要自己写的notify.php
$input->SetTrade_type("JSAPI");
// 由小程序端传给后端或者后端自己获取,写自己获取到的,
$input->SetOpenid('UdhncondJcnkJnjknkcssdcAbckn');
//$input->SetOpenid($this->getSession()->openid);
// 向微信统一下单,并返回order,它是一个array数组
$order = WxPayApi::unifiedOrder($input);
// json化返回给小程序端
header("Content-Type: application/json");
echo $this->getJsApiParameters($order);
}
private function getJsApiParameters($UnifiedOrderResult)
{ //判断是否统一下单返回了prepay_id
if(!array_key_exists("appid", $UnifiedOrderResult)
|| !array_key_exists("prepay_id", $UnifiedOrderResult)
|| $UnifiedOrderResult['prepay_id'] == "")
{
throw new WxPayException("参数错误");
}
$jsapi = new WxPayJsApiPay();
$jsapi->SetAppid($UnifiedOrderResult["appid"]);
$timeStamp = time();
$jsapi->SetTimeStamp("$timeStamp");
$jsapi->SetNonceStr(WxPayApi::getNonceStr());
$jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
$jsapi->SetSignType("MD5");
$jsapi->SetPaySign($jsapi->MakeSign());
$parameters = json_encode($jsapi->GetValues());
return $parameters;
}
//这里是服务器端获取openid的函数
// private function getSession() {
// $code = $this->input->post('code');
// $url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.WxPayConfig::APPID.'&secret='.WxPayConfig::APPSECRET.'&js_code='.$code.'&grant_type=authorization_code';
// $response = json_decode(file_get_contents($url));
// return $response;
// }
}
$WxPay = new WXPay();
$WxPay->index();
解压在lib文件夹下可以看到:
放到服务端可访问的目录下。
在WxPayConfig.php里面配置账号信息:
class WxPayConfig
{
//=======【基本信息设置】=====================================
//
/**
* 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 = 'wx123456789...';//这里填上自己的对应信息
const MCHID = '14151666888';
const KEY = '11223344556677889900';
const APPSECRET = '828bfsdibfsiubfikdbfik';
const NOTIFY_URL='https://...com/notify.php';
注:
期间遇到一个签名错误,一直不好,使用微信支付接口签名校验工具校验也没有错,像网上说的漏写错写参数都查了,就是一直返回
这样的信息,最后解决办法是:重置了KEY (商户支付密钥),重置的和之前的一模一样,但竟然就可以了...
问题主要都是报签名错误,仔细检查就好,比如XML格式不对,MD5加密后的位数,字典排序没排好,缺少参数等...
3.最后附上notify.php
/**
* Created by PhpStorm.
* User: UFO
* Date: 17/7/13
* Time: 下午6:42
*/
require_once ('WxPay.Api.php');
require_once ('WxPay.Notify.php');
class PayNotifyCallBack extends WxPayNotify
{
//查询订单
public function Queryorder($transaction_id)
{
$input = new WxPayOrderQuery();
$input->SetTransaction_id($transaction_id);
$result = WxPayApi::orderQuery($input);
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)
{
$notfiyOutput = array();
if(!array_key_exists("transaction_id", $data)){
$msg = "输入参数不正确";
return false;
}
//查询订单,判断订单真实性
if(!$this->Queryorder($data["transaction_id"])){
$msg = "订单查询失败";
return false;
}
return true;
}
}
$notify = new PayNotifyCallBack();
$notify->Handle(false);