1.需求
微信公众号版产品实现会员自动续费功能。如果有什么问题可以添加微信咨询。
微信号:ycoder--123
第一步,跳转签约页面
```
public function autoPayment(){
$appid = '服务商APPID';
$mchid= '服务商商户号';
$sub_mchid= '您的商户号';
$plan_id=""您的模板ID";
$contract_code = $this->gen_contract_code(); //签约协议号
$request_serial =$this->build_order_no(); //请求序列号
$notify_urls='https://'.$_SERVER['SERVER_NAME'].'/index.php/Home/User/notifyUrl'; //用于接收签约成功消息的回调通知地址
$key="服务商秘钥"; //服务商秘钥
$time=time(); //当前时间
//生成签名
$stringA="appid=".appid ."&contract_code=".$contract_code."&contract_display_account=微信代扣&mch_id=".$mchid."¬ify_url=".$notify_urls."&plan_id=".plan_id."&request_serial=".$request_serial."&sub_mch_id=".plan_id."×tamp=".$time."&version=1.0";
$stringSign=$stringA."&key=".$key;
$sign=strtoupper(md5($stringSign)); //签名
$url="https://api.mch.weixin.qq.com/papay/entrustweb?appid=".$appid."&contract_code=".$contract_code."&contract_display_account=微信代扣&mch_id=".$mchid."&sub_mch_id=".$sub_mchid."¬ify_url=".urlencode($notify_urls)."&plan_id=".plan_id."&request_serial=".$request_serial."×tamp="."$time"."&version=1.0&sign=".$sign; //签约URL拼接
$contract_data=[
"openid"=>"用户ID",
"vip_day"=>30,
"vip_price"=>15.00,
"contract_code"=>$contract_code,
"contract_id"=>$contract_code,
"plan_id"=>$plan_id,
"create_time"=>$time
];
$model=new ContractModel(); //实例化模型
$res=$model>where('openid',$openid)->find();
if(!$res){
$model>save($contract_data);
}else{
$model->where('openid',$openid)->save($contract_data);
}
Header("Location:$url"); //跳转签约页面
}
```
第二部,接受微信通知地址返回的参数
```
public function notifyUrl(){
$contractData=file_get_contents("php://input");
if (!empty($contractData)) {
$obj = simplexml_load_string($contractData, 'SimpleXMLElement', LIBXML_NOCDATA);
$data = json_decode(json_encode($obj), true);
$contract_code= $data["contract_code"];
$plan_id=$data["plan_id"];
$contract_id = $data["contract_id"];
$change_type = $data["change_type"];
$model=new ContractModel(); //实例化模型
if($change_type == "ADD"){ //如果用户签约了
$contract_data=$model>where('contract_code',$contract_code)->find();
if($contract_data){
$model->where('contract_code',$contract_code'")->save(["change_type"=>$change_type,"contract_id"=>$contract_id]);
$appid = '服务商appid';
$mch_id = '服务商商户号';
$key = '服务商Key';
$sub_mch_id = '您的商户号';
$out_trade_no = 'ycoder'.date("YmdHis").mt_rand(1111111111,9999999999);
$body = "微信代扣";
$total_fee = $contractData["vip_price"];
$notify_url='https://'.$_SERVER['SERVER_NAME'].'/index.php/Home/User/notifyTwice';
$autoPay = $this->WeixinAutoPay($appid,$mch_id,$key,$sub_mch_id,$contract_id,$attach,$out_trade_no,$body,$total_fee,$notify_url);
log::write($res);
}
}elseif ($change_type == "DELETE") {
$model>where('contract_code',contract_code)->save(["change_type"=>'DELETE']);
}
$str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
echo $str;
}
$str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[失败]]></return_msg></xml>';
echo $str;
}
```
第三步,扣款
```
private function WeixinAutoPay($appid,$mch_id,$key,$sub_mch_id,$contract_id,$out_trade_no,$body,$total_fee,$notify_url) {
$url = 'https://api.mch.weixin.qq.com/pay/partner/pappayapply';
$datas= array(
'appid' => $appid, //服务商APPID
'mch_id' => $mch_id, //服务商商户号
'sub_mch_id' => $sub_mch_id, //您的商户号
'contract_id' => $contract_id, // 签约协议ID
'nonce_str' => $this->createNoncestr(), //随机字符串
'body' => $body, //商品描述
'out_trade_no'=> $out_trade_no, //商户订单号
'total_fee' => $total_fee, //总金额 单位 分
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'], //终端IP
'notify_url' => $this->notify_url, //通知地址
'trade_type' => 'PAP'//交易类型 (固定值)
);
//统一下单签名
$datas['sign'] = $this->genrateSign($parameters);
$xmlData = $this->arrayToXml($parameters);
$return = $this->xmlToArray($this->postXmlCurl($xmlData, $url, 60));
return $return;
}
```
第四部,扣款完成后修改用户的参数
```
public function notifyTwice(){
$contractData=file_get_contents("php://input");
if (!empty($contractData)) {
$obj = simplexml_load_string($contractData, 'SimpleXMLElement', LIBXML_NOCDATA);
$data = json_decode(json_encode($obj), true);
if($data['return_code']=="SUCCESS"){
$model=new vipOrder(); //实例化模型
$contract_id=$data["contract_id"];
$order_num='ycoder'.mt_rand(1111111111,9999999999);
$contract_data=$model>where("contract_id',$contract_id)->find();
$day=$contract_data["vip_day"];
$order_data=[
"openid"=>$contract_data['openid'],
"order_num"=>$order_num,
"vip_id"=>'auto',
'vip_start_time'=>time(),
'vip_end_time'=>time()+$day*24*3600,
];
$info=$model>where('openid',$openid)->find();
if(!$info){
$model->save(order_data);
}else{
$model->where('openid',$openid)->save($order_data);
}
}
log::write($data);
$str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
echo $str;
}
$str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[失败]]></return_msg></xml>';
echo $str;
}
```