php的微信支付接口
在开发之中经常会使用到支付的功能,现在常用的两种支付方式是支付宝和微信。相对而言,支付宝的文档较为健全,并且配置和调用方式方式比较简单,这里就不过多的描述。
首先去微信官网网站下去下载服务端的demo:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
这里虽然是官网提供的公众号支付的demo,虽然微信支付的预下单等都可以在前端进行实现,不过官方还是建议在服务端进行处理。下载后,将其中的demo引入你的项目就好,注意的是如果是公众号的支付用到的类文件WxPay.JsApiPay.php在文件中example目录下。
接下来我们就可以进行引用了并实现。以thinkphp框架下进行调用为例(以下案例包括移动端以及公众号支付以及公众号获取openid等功能)。以下代码为了能够更容易理解,将一些类中的方法提取了出来,写的有点乱,请见谅。
/* 微信APP下支付预下单 */
public function wxAppOrder(){
//TODO:首先获取订单详情,例如传递过来订单号或订单id,获取订单的详情信息,例如将取出的数据存放入$user_order_info数组,订单中包含的商品在$user_order_product_info之中。
/* 向微信发起请求 */
vendor("WxpayAPI.lib.WxPay","",".Api.php");
vendor("WxpayAPI.lib.WxPay","",".Data.php");//生成数据
//统一下单输入对象
$order_info= new WxPayUnifiedOrder();
$order_info->SetOut_trade_no($user_order_info["orderNo"]);//商品订单号
$body=$user_order_product_info["productName"];
// $body=iconv("UTF-8", "ISO-8859-1", $user_order_product_info["productName"]);
$order_info->SetBody($body);//商品描述
$order_info->SetTrade_type("CNY");//人民币
$order_info->SetTotal_fee(intval($user_order_info["sumPrice"]*100));//总金额,以分为单位
$order_info->SetTrade_type("APP");//交易类型
$order_info->SetAppid(C("wxAPPID"));
$order_info->SetMch_id(C("wxMCHID"));
$order_info->SetNotify_url("你的回调地址");
$order_info->SetSign();
//进行统一支付
$wxpay=new WxPayApi();
$order_result=$wxpay->unifiedOrder($order_info);//统一下单
if ($order_result["return_code"]=="FAIL") {
$arr=array(
"resultCode"=>"99",
"resultDesc"=>$order_result["return_msg"],
"resultObj"=>array(""=>""),
);
echo JSON($arr);
exit();
}
if ($order_result["result_code"]=="SUCCESS") {
//预下单成功后,重新签名返回给移动端
$wxpay_result=new WxPayResults();
$timestamp=time();
$wxpay_result->SetData("appid", $order_result["appid"]);
$wxpay_result->SetData("partnerid", $order_result["mch_id"]);
$wxpay_result->SetData("prepayid", $order_result["prepay_id"]);
$wxpay_result->SetData("timestamp", $timestamp);
$wxpay_result->SetData("noncestr", $order_result["nonce_str"]);
$wxpay_result->SetData("package", "Sign=WXPay");
// $wxpay_result->SetData("key", C("wxKEY"));
//上方注释的代码是再签名中必要的一步,只是这个包含在了微信demo的类中,如果像该项目中既有app支付,又有公众号支付,最好是注释类中代码,并自己写入
$resign_result=$wxpay_result->SetSign();
//处理返回数据
$result=array(
"appid"=>$order_result["appid"],//appid
"partnerid"=>$order_result["mch_id"],//商户号
"prepayid"=>$order_result["prepay_id"],//与支付id
"package"=>"Sign=WXPay",
"noncestr"=>$order_result["nonce_str"],
"timestamp"=>$timestamp,
"sign"=>$resign_result,
);
$arr=array(
"resultCode"=>"00",
"resultDesc"=>"成功",
"resultObj"=>$result,
);
echo JSON($arr);
exit();
}else{
$arr=array(
"resultCode"=>"99",
"resultDesc"=>"失败",
"resultObj"=>$order_result,
);
echo JSON($arr);
exit();
}
}
/* 微信支付回调函数 */
public function wxpayNotify(){
vendor("WxpayAPI.lib.Logwx","",".Log.php");//在回调中最好是引入日志进行记录,在这里因为Log类与thinkphp中的log类重复,需要进行处理
$handle=new CLogFileHandler("./Public/wxlog.txt");
$log=Logwx::Init($handle);
$xml = $GLOBALS["HTTP_RAW_POST_DATA"];//获取数据
vendor("WxpayAPI.lib.WxPay","",".Api.php");
vendor("WxpayAPI.lib.WxPay","",".Data.php");
$wxpay=new WxPayApi();
$notify=new WxPayNotifyReply();
$result=WxPayResults::Init($xml);//获取数据并转换为数组
if ($result["return_code"]=="SUCCESS" && $result["result_code"]=="SUCCESS") {//此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
//TODO:进行数据库操作的业务逻辑处理,假设其成功与否的数据为$res
if ($res) {
$log->INFO("订单:".$result["out_trade_no"]."支付成功");
$notify->SetReturn_code("SUCCESS");
$notify->SetReturn_msg("OK");
$notify->SetSign();
}else{
$log->ERROR("微信支付失败");
$notify->SetReturn_code("FAIL");
$notify->SetReturn_msg("客户服务器错误");
}
}else{
$log->ERROR("微信回调返回错误");
$notify->SetReturn_code("FAIL");
$notify->SetReturn_msg("微信支付失败");
}
//返回微信端
$wxpay->replyNotify($notify->ToXml());
}
/* 微信公众账号下单
* 获取code等信息
* 跳转至获取信息
* */
public function wxPubOrder(){
//此流程中
$orderId=$_GET["orderId"];
//注意:此处如果想要回调成功,需要在微信公众平台设置回调域名
// print_r("Location:https://open.weixin.qq.com/connect/oauth2/authorize?appid=".C("wxAPPID")."&redirect_uri="."http://你的域名/Pay/getOpenid/orderId/".$orderId."&response_type=code&scope=snsapi_base&state=123#wechat_redirect");
// exit();
header("Location:https://open.weixin.qq.com/connect/oauth2/authorize?appid="."*******"."&redirect_uri=".urlencode("http://*****/Pay/getOpenid/orderId/".$orderId)."&response_type=code&scope=snsapi_base&state=123#wechat_redirect");
exit();
}
/* 微信获取openid,跳转到微信同意下单接口 */
public function getOpenid(){
//code
$code=$_GET["code"];
$state=$_GET["state"];
$orderId=$_GET["orderId"];
$appid="******";
$appsecret="******";
//获取openid
$get_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=".$appid."&secret=".$appsecret."&code=".$code."&grant_type=authorization_code";
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$get_token_url);
curl_setopt($ch,CURLOPT_HEADER,0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$res = curl_exec($ch);
curl_close($ch);
$json_obj = json_decode($res,true);
$openId=$json_obj["openid"];
// 跳转到预下单
// echo $openId;exit();
$url="http://******/html5/#/pay/".$orderId."openid=".$openId;
header("Location:".$url);
}
/* 微信公众账号统一下单 */
public function wxOrder(){
$orderId=$_GET["orderId"];
$openId=$_GET["openId"];
if (empty($orderId)||empty($openId)) {
$arr=array(
"resultCode"=>"66",
"resultDesc"=>"缺少参数",
"resultObj"=>array(),
);
echo JSON($arr);
exit();
}
//TODO:获取订单和订单商品信息,分别存储在$user_order_info中和$user_order_good_info中
if (empty($user_order_info)) {
$arr=array(
"resultCode"=>"99",
"resultDesc"=>"不存在该订单",
"resultObj"=>array(),
);
echo JSON($arr);
exit();
}
/* 向微信发起请求 */
vendor("WxpayAPI.lib.WxPay","",".Api.php");
vendor("WxpayAPI.lib.WxPay","",".Data.php");//生成数据
// vendor("WxpayAPI.lib.WxPay","",".JsApiPay.php");
//统一下单输入对象
$order_info= new WxPayUnifiedOrder();
$wxpay=new WxPayApi();
$order_info->SetMch_id("***");//商户号
$order_info->SetAppid("****");//微信号APPID//wx70a40dfa2711c4fe
$order_info->SetOut_trade_no($user_order_info["orderNo"]);//商品订单号
$order_info->SetBody($user_order_good_info["productName"]);//商品描述
$order_info->SetTrade_type("CNY");//人民币
$order_info->SetTotal_fee(intval($user_order_info["sumPrice"]*100));//总金额,以分为单位
$order_info->SetTrade_type("JSAPI");//交易类型
$order_info->SetNonce_str($wxpay->getNonceStr(32));
$order_info->SetSpbill_create_ip("1.1.1.1");
// $order_info->SetOpenid($user_info["openId"]);
$order_info->SetOpenid($openId);
//TODO:
$order_info->SetNotify_url("http://****/Pay/wxpayNotify");
$order_info->SetSign();//设置签名
//进行统一支付
$order_result=$wxpay->unifiedOrder($order_info);//统一下单
//同意下单后再加
if ($order_result["return_code"]=="FAIL") {
$arr=array(
"resultCode"=>"99",
"resultDesc"=>$order_result["return_code"].":".$order_result["return_msg"],
"resultObj"=>array(),
);
echo JSON($arr);
exit();
}
if ($order_result["result_code"]=="SUCCESS") {
$jsapi = new WxPayJsApiPay();
$jsapi->SetAppid($order_result["appid"]);
$timeStamp = time();
$jsapi->SetTimeStamp("$timeStamp");
$jsapi->SetNonceStr(WxPayApi::getNonceStr());
$jsapi->SetPackage("prepay_id=" . $order_result["prepay_id"]);
$jsapi->SetSignType("MD5");
$jsapi->SetPaySign($jsapi->MakeSign());
$order_result = $jsapi->GetValues();
// print_r($order_result);exit();
$arr=array(
"resultCode"=>"00",
"resultDesc"=>"成功",
"resultObj"=>$order_result,
);
echo JSON($arr);
exit();
}else{
$arr=array(
"resultCode"=>"99",
"resultDesc"=>"失败",
"resultObj"=>$order_result,
);
echo JSON($arr);
exit();
}
}
这就是一个支付的流程,在这之中会遇到很多问题,在此给出一个大多数会遇到的问题的解决方法的大概思路:
1、APP统一下单后数据返回给前端,前端调用报签名错误:首先验证自己的秘钥信息是否正确,要注意移动端和公众号的是不同的,而类拿着key又去重新签名,可以将微信官方提供的demo中的直接内部调用配置文件那里注释掉
2、在公众号获取openid的时候,显示跨域:这个解决参考YII2框架中对于yii::$app->response->header,中的remove方法,将报头去掉即可。
3、对于微信支付的配置,包括公众号支付配置白名单、测试目录啥的就不过多说了,请自行搜索资料
过程中肯定还遇到很多问题,这里不一一写了,如果还有问题可以在评论中留言,大家一起讨论学习,共同进步。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: php版本历史
- 下一篇: PHP开发中遇到的小问题(0与字符串比较)-L001