小弟是第一次写博客,写的不好多有见谅。最近有一个项目要跟微信做支付对接,之前已经听说微信支付是个大坑,好吧,确实是大坑!这次项目公众号支付和APP支付都有涉及,下面分别介绍。
首先,得从从微信官方下载SDK,我这里的开发语言是用PHP。官方下载地址:http://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=11_1
公众号支付
关于公众号支付,官方给出的demo其实已经很全了,按步骤走就可以,下面基于thinkphp来介绍一下步骤和注意点。
1.配置授权目录
假设项目要调用支付的访问地址是:http://yourdomain.com/weixin.php/Order/wechatPay 这个地址是thinkphp的访问路径,意思是Order控制器下wechatPay方法。那么在微信后台配置的授权目录就是http://yourdomain.com/weixin.php/Order,然后添加测试人员的微信白名单。OK
2.配置微信公众号信息和微信商户信息
本人在model层引入微信SDK,怎么引入自己斟酌了。要配置好几个文件的路径(有好几个require_once)。正确引入微信的sdk包之后,修改配置文件的APPID,MCHID,KEY,APPSECRET,商户证书路径等。MCHID,KEY要到商户平台去找,并且到商户平台下载两个证书,替换掉原demo的证书,注意路径不能错。(其实证书在支付端貌似还没用到,先配置好)。
3.参考jsapi.php,设置好参数。
//①、获取用户openid
$tools = new JsApiPay();
$openId = $tools->GetOpenid();
//②、统一下单
$input = new WxPayUnifiedOrder();
$input->SetBody("test");
$input->SetAttach("test");
$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
$input->SetTotal_fee("1");
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("test");
$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
$input->SetTrade_type("JSAPI");
$input->SetOpenid($openId);
$order = WxPayApi::unifiedOrder($input);
//获取订单信息
$jsApiParameters = $tools->GetJsApiParameters($order);
//获取共享收货地址js函数参数
$editAddress = $tools->GetEditAddressParameters();
具体参数可以参考官方说明,步骤是先获取用户的openId,调用统一下单Api生成预付单WxPayApi::unifiedOrder($input);,一定要获取到prepay_id!再组装成JS供前台html调用:GetJsApiParameters。前台JS可以参考demo,起初以为要用到微信的JS-SDK,这里是不需要的。
PS:最近微信推出了一个web调试工具,做支付是用不了那玩意,会提示没有SDK,小弟在这里吃了亏,测试还是老老实实拿手机吧。
到这里基本就可以调通了,还有个notify_url的回调,也可以参考官方demo。
移动支付
移动APP支付相比公众号支付坑要多,服务器端代码官方也是没有给出具体的demo(至少我没找到),但是思路基本跟公众号一样,配置好参数,生成预付单,根据预付单调起支付页面。下面具体说说。
这里有个地方要注意一下!移动支付是只能到微信开发平台注册获取AppId、APPSECRET,然后创建移动应用,配置好应用签名,包名等信息。客户端具体配置可以参考:http://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_5,就是说要在APP注册APPID。另外,商户平台跟上面公众号的说的商户平台不能是同一个,也就是说公众号跟APP各有一个商户平台,这也是非常值得吐槽的地方。
配置好开放平台的信息跟商户平台后,就可以开始撸代码了。
1,APP支付的PHP代码还是参考jsapi.php,略有修改。
配置APPID,证书等信息可以参考公众平台,不过都要换成开放平台的APPID等,这里不再累赘说明。
2参考以下代码:
$input = new WxPayUnifiedOrder();
$input->SetBody("test");
$input->SetAttach("test");
$input->SetOut_trade_no(WxPayConfig::MCHID.date("YmdHis"));
$input->SetTotal_fee("1");
$input->SetTime_start(date("YmdHis"));
$input->SetTime_expire(date("YmdHis", time() + 600));
$input->SetGoods_tag("test");
$input->SetNotify_url("http://paysdk.weixin.qq.com/example/notify.php");
$input->SetTrade_type("APP");
$preorder = WxPayApi::unifiedOrder($input);
//重新生成签名
$jsApiParameters = $tools->GetAppApiParameters($preorder);
要注意的地方是$input->SetTrade_type("APP") ,trade_type要改成APP ,调用统一下单接口后生成预付单$preorder(要有prepay_id),后面重新生成签名这里要稍作修改。GetAppApiParameters方法的代码直接奉上
public function GetAppApiParameters($UnifiedOrderResult)
{
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"]);
$jsapi->SetPartnerId($UnifiedOrderResult["mch_id"]);
$time =time();
$timeStamp = "$time";
$jsapi->SetTimeStamp("$timeStamp");
$jsapi->SetNonceStr(WxPayApi::getNonceStr());
$jsapi->SetPackage("Sign=WXPay");
$jsapi->SetPrepayId($UnifiedOrderResult["prepay_id"]);
$jsapi->SetPaySign($jsapi->MakeSign());
$parameters = json_encode($jsapi->GetValues());
return $parameters;
}
微信的官方说明是这样的:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay
行,没问题,按你微信说的办,上面方法就用这几个参数重新生成签名(也可以在客户端生成sign,这里在服务器端生成),所以新增了几个参数(有的参数可以在客户端直接写死)。有个注意的地方就是签名的字段要改成小写,比如appId要改成appid,prepayId改成prepayid。所以上面的set方法要改了(够坑的。。。)
例如SetAppidset方法改成这样(同样把get方法也修改吧,保持严谨性),其他参数一个个修改。(反正我改成小写就OK了)
public function
SetAppid($value)
{
$this->values['appid'] = $value;//把key值改成小写
}
根据上面方法生成sign签名后,返回预付单json给客户端,搞定。
notify通知处理可以参照公众号demo,具体业务自己再写吧。
总结:公众号支付和APP支付原理差不多,首先都要绑定授权地址或授权APP,调用统一下单API生成预付单,再传到前台调用微信支付。上面只列举了一小部分支付功能,其他支付功能可以参考官方文档,配置的东西太多,官方说明太简单。