微信提现_微信提现手续费测试用例 - CSDN
精华内容
参与话题
  • apiclient_cert.p12证书:在微信商户平台–>账户设置–>API安全–>证书中下载的 。 (自行下载) 二.开发环境、参数准备 SpringBoot...

    一.p12证书下载


    二.开发环境、参数准备

    • SpringBoot2.0框架 (仅限本例,其他框架自行解决,原理相同)
    • APP_ID (公众账号appid)
    • MCH_ID(商户号)
    • API_SECRET(API密钥)

    三.pom相关jar包、插件引入

    1. xml相关jar包引入(微信接口要求以xml格式传参)

    	<dependencies>
    		<!-- xml -->
            <dependency>
                <groupId>net.sf.kxml</groupId>
                <artifactId>kxml2</artifactId>
                <version>2.3.0</version>
            </dependency>
            <dependency>
                <groupId>xmlpull</groupId>
                <artifactId>xmlpull</artifactId>
                <version>1.1.3.1</version>
            </dependency>
    	</dependencies>
    

    2. maven过滤证书插件引入

    	<build>
            <plugins>
            	<plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>2.7</version>
                    <configuration>
                        <encoding>UTF-8</encoding>
                        <!-- 过滤后缀为p12、crt的证书文件 -->
                        <nonFilteredFileExtensions>
                            <nonFilteredFileExtension>p12</nonFilteredFileExtension>
                            <nonFilteredFileExtension>crt</nonFilteredFileExtension>
                        </nonFilteredFileExtensions>
                    </configuration>
                </plugin>
    		</plugins>
        </build>
    

    3. maven证书资源引入注意: 1.将下载好的证书放在src/main/resources下,2.按如下配置pom)

    	<build>
            <resources>
                <resource>
                    <directory>src/main/resources</directory>
                    <includes>
                        <include>**/*.properties</include>
                        <include>**/*.xml</include>
                        <include>**/*.p12</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    

    四.代码实现

    1. TransferController(提现相关接口)

    package com.zero.jimu.controller;
    
    import com.alibaba.fastjson.JSONObject;
    import com.github.pagehelper.util.StringUtil;
    import com.zero.jimu.entity.WithdrawalRecord;
    import com.zero.jimu.service.WithdrawalRecord.WithdrawalRecordService;
    import com.zero.jimu.service.appUser.AppUserService;
    import com.zero.jimu.service.sysUser.SysUserService;
    import com.zero.jimu.utils.CheckParamsUtil;
    import com.zero.jimu.utils.DateUtil;
    import com.zero.jimu.utils.IpAddrUtil;
    import com.zero.jimu.utils.exception.ErrorEnum;
    import com.zero.jimu.utils.exception.Result;
    import com.zero.jimu.utils.exception.ResultUtil;
    import com.zero.jimu.utils.withdrawal.CollectionUtil;
    import com.zero.jimu.utils.withdrawal.HttpUtils;
    import com.zero.jimu.utils.withdrawal.PayUtil;
    import com.zero.jimu.utils.withdrawal.XmlUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.web.bind.annotation.*;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.UUID;
    
    /**
     * 提现相关接口
     */
    @RestController
    @RequestMapping("/transfer")
    public class TransferController {
    
        @Autowired
        SysUserService sysUserService;
        @Autowired
        AppUserService appUserService;
        @Autowired
        WithdrawalRecordService withdrawalRecordService;
    
        private static final Logger logger = LoggerFactory.getLogger(TransferController.class);
    
        private static final String TRANSFERS_PAY = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; // 企业付款API
    
        private static final String TRANSFERS_PAY_QUERY = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo"; // 企业付款查询API
    
        private static final String APP_ID = "wx100000001000"  ;//公众账号appid
    
        private static final String MCH_ID = "14000000000";//商户号
    
        private static final String API_SECRET = "85565656565656565656565";//API密钥
    
        /**
         * 企业向个人支付转账
         * @param request
         * @param params
         */
        @PostMapping(value = "/pay")
        @ResponseBody
        @Transactional
        public Result transferPay(@RequestBody String params,HttpServletRequest request) {
    
            /** =============================================接口参数校验================================================*/
            JSONObject jsonObject = JSONObject.parseObject(params);//解析json
            //校验参数是否为空
            if(CheckParamsUtil.isBlank(jsonObject,"userId","amount","userType")){
                return ResultUtil.fail(ErrorEnum.ERROR_PARAM_ISBLANK);
            }
    
            /**==============================================设置局部变量=================================================*/
            String userId = jsonObject.getString("userId");//用户id
            String openid = "";//用户openid
            Float applyMoney = jsonObject.getFloat("amount");//用户申请提现金额 0.3-5000
            int userType = jsonObject.getInteger("userType");//用户类型
            String amount;//企业付款金额
            Float poundage = 0f;//手续费
            String desc;//企业付款描述信息
            String id = UUID.randomUUID().toString().replaceAll("-", "");//提现记录表id
    
            if(applyMoney<0.3||applyMoney>5000){
                return ResultUtil.fail("00000001","申请提现金额不符:低于最小金额0.30元或高于5000.00元");
            }
    
            /** ======================================业务判断 1.userId是否有收款资格=====================================*/
            if(userType == 1){
                openid = sysUserService.getOpenidBySysUserId(userId);
            }
            if(userType == 2){
                openid = appUserService.getOpenidByAppUserId(userId);
            }
            if(openid==null||openid.equals("")){
                return ResultUtil.fail("00000001","该用户不可提现");
            }
    
            /** ======================================业务判断 2.openid可提现金额校验=====================================*/
            /** userType==1 商家身份*/
            if(userType == 1){
                //校验用户提现金额
                //1.提现金额<=可提现金额 15%的抽成
    
    
    
    
            }
            Float account = 0f;
            /** userType==2 用户身份*/
            if(userType == 2){
                //校验用户提现金额
                //1.提现金额<=可提现金额
                account = appUserService.getAccount(userId);
                if(applyMoney>account){
                    return ResultUtil.fail("00000001","非法操作:申请提现金额大于可提现金额");
                }
            }
    
    
            /** =================================业务判断 3.userId当天提现次数及当天提现金额限制==================================*/
            //当日提现次数 首次免手续费
            List<WithdrawalRecord> withdrawalRecords = withdrawalRecordService.selectWithdrawalRecordOfToday(userId,openid,userType);
            //当日非初次提现
            if(withdrawalRecords.size()>0&&withdrawalRecords.size()<=10){
                poundage = 2f;//当日非初次提现,手续费为2元
                desc = "申请提现金额:"+applyMoney+"元,当天已提现"+withdrawalRecords.size()+"次,需扣除2元手续费";
    
                //此处对用户当天累计提现金额可做限制
    //            Float withdrawalAmountRequested = 0f;//用户今日累计已申请的提现额度
    //            for(int i = 0;i < withdrawalRecords.size();i++){
    //                withdrawalAmountRequested = (withdrawalAmountRequested*1000+withdrawalRecords.get(i).getActualMoney()*1000)/1000;
    //            }
    
    
    
            }else if(withdrawalRecords.size()>10){
                return ResultUtil.fail("00000001","该用户当天提现次数上限:微信企业付款每天最多可向同一个用户付款10次");
            }else{
                desc = "申请提现金额:"+applyMoney+"元,当天首次提现免手续费";
            }
    
            /** =================================业务判断 4.一个商户同一日付款总额限额10万元==================================*/
            Float amountWithdrawn = withdrawalRecordService.selectAllWithdrawalRecordNumOfToday();//商户同一日付款总额
            if(amountWithdrawn>100000){
                return ResultUtil.fail("00000001","今日商户付款总额限额,请明天再试");
            }
    
            /** ========================校验实际提现金额是否在微信企业付款实际允许的提现(0.3-5000)范围内=========================*/
            Float actualMoney = (applyMoney*1000-poundage*1000)/1000;//实际提现金额
            if(actualMoney<0.3||actualMoney>5000){
                return ResultUtil.fail("00000001","扣除手续费后的实际提现金额不符:"+actualMoney+"元:低于最小金额0.30元或高于5000.00元");
            }
            amount = Integer.parseInt((int)((actualMoney)*10)+"")*10+"";//微信企业付款金额 30-500000
    
    
            /** ==================================================================================================================*/
            /** ==================================================封装提现所需参数================================================*/
            /** ==================================================================================================================*/
            Map<String, String> restmap = null;
            try {
                Map<String, String> parm = new HashMap<String, String>();
                parm.put("mch_appid", APP_ID); //公众账号appid
                parm.put("mchid", MCH_ID); //商户号
                parm.put("nonce_str", PayUtil.getNonceStr()); //随机字符串
                parm.put("partner_trade_no", PayUtil.getTransferNo()); //商户订单号
                parm.put("openid", openid); //用户openid oCVr20N2YLH9VQztnkZTaCj2aYYY
                parm.put("check_name", "NO_CHECK"); //校验用户姓名选项 OPTION_CHECK
                //parm.put("re_user_name", "安迪"); //check_name设置为FORCE_CHECK或OPTION_CHECK,则必填
                parm.put("amount",amount); //转账金额
                parm.put("desc", desc); //企业付款描述信息
                parm.put("spbill_create_ip", IpAddrUtil.getIpAddr(request)); //Ip地址
                parm.put("sign", PayUtil.getSign(parm, API_SECRET));
    
                String restxml = HttpUtils.posts(TRANSFERS_PAY, XmlUtil.xmlFormat(parm, false));
                restmap = XmlUtil.xmlParse(restxml);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                return ResultUtil.fail("00000001","转账发生异常");
            }
    
            /** ========================================================提现结果处理===================================================*/
    
            /** ===================================================生成提现及流水记录,改变余额==================================================*/
            if (CollectionUtil.isNotEmpty(restmap) && "SUCCESS".equals(restmap.get("result_code"))) {
                logger.info("转账成功");
                Map<String, String> transferMap = new HashMap<>();
                transferMap.put("partnerTradeNo", restmap.get("partner_trade_no"));//商户转账订单号
                transferMap.put("paymentNo", restmap.get("payment_no")); //微信订单号
                transferMap.put("paymentTime", restmap.get("payment_time")); //微信支付成功时间
    
                //生成提现记录
                withdrawalRecordService.insert(new WithdrawalRecord(id,userType,userId,applyMoney,poundage,actualMoney,1,restmap.get("partner_trade_no"),restmap.get("payment_no"),
                        restmap.get("payment_time")==null?null:DateUtil.strToDate(restmap.get("payment_time"),"yyyy-MM-dd HH:mm:ss"),openid,desc,restmap.get("spbill_create_ip"),"0"));
                //生成流水表
                String waterId = UUID.randomUUID().toString().replaceAll("-", "");
                Map<String,Object> map = new HashMap<>();
                map.put("id",waterId);//编号
                map.put("userId",userId);//用户id
                map.put("title","提现");//该流水的标题
                map.put("waterType",2);//商家流水类型1.场地收入 2.提现    用户流水类型1.分销收入 2.提现 3.预订场地
                map.put("incomeExpense",1);//收入还是支出 0.收入 1.支出
                map.put("applyMoney",applyMoney);//申请提现金额
                map.put("poundage",poundage);//手续费
                map.put("actualMoney",actualMoney);//实际金额
                map.put("whetherToAccount",1);//是否到账0.未到账1.已到账
                if(userType==1){
                    sysUserService.insertUserWater(map);
                    //改变用户可提现余额
    
    
                }
                if(userType==2){
                    appUserService.insertUserWater1(map);
                    //改变用户可提现余额
                    appUserService.updateUserAccount(userId,(account*1000-applyMoney*1000)/1000);//float精度问题
                }
                return ResultUtil.success(transferMap);
            }
    
            /** =================================================3.转账失败========================================================*/
            else {
                if (CollectionUtil.isNotEmpty(restmap)) {
                    logger.info("转账失败:" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
                }
                return ResultUtil.fail("00000001","转账失败"+restmap.get("err_code_des"));
            }
    
        }
    
    
        /**
         * 企业向个人转账查询
         * @param request
         * @param response
         * @param tradeno 商户转账订单号
         * @param callback
         */
        @PostMapping(value = "/pay/query")
        public Result orderPayQuery(HttpServletRequest request, HttpServletResponse response, String tradeno,
                                  String callback) {
            if (StringUtil.isEmpty(tradeno)) {
                return ResultUtil.fail("00000001","转账订单号不能为空");
            }
    
            Map<String, String> restmap = null;
            try {
                Map<String, String> parm = new HashMap<String, String>();
                parm.put("appid", APP_ID);
                parm.put("mch_id", MCH_ID);
                parm.put("partner_trade_no", tradeno);
                parm.put("nonce_str", PayUtil.getNonceStr());
                parm.put("sign", PayUtil.getSign(parm, API_SECRET));
    
                String restxml = HttpUtils.posts(TRANSFERS_PAY_QUERY, XmlUtil.xmlFormat(parm, true));
                restmap = XmlUtil.xmlParse(restxml);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
    
            if (CollectionUtil.isNotEmpty(restmap) && "SUCCESS".equals(restmap.get("result_code"))) {
                // 订单查询成功 处理业务逻辑
                logger.info("订单查询:订单" + restmap.get("partner_trade_no") + "支付成功");
                Map<String, String> transferMap = new HashMap<>();
                transferMap.put("partnerTradeNo", restmap.get("partner_trade_no"));//商户转账订单号
                transferMap.put("openid", restmap.get("openid")); //收款微信号
                transferMap.put("paymentAmount", restmap.get("payment_amount")); //转账金额
                transferMap.put("transferTime", restmap.get("transfer_time")); //转账时间
                transferMap.put("desc", restmap.get("desc")); //转账描述
                return ResultUtil.success(transferMap);
            }else {
                if (CollectionUtil.isNotEmpty(restmap)) {
                    logger.info("订单转账失败:" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
                }
                return ResultUtil.fail("00000001","订单转账失败");
            }
        }
    
    
    
    }
    
    

    2. HttpUtils(企业付款http请求工具)

    package com.zero.jimu.utils.withdrawal;
    
    import org.apache.http.NameValuePair;
    import org.apache.http.client.config.RequestConfig;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.ssl.SSLContexts;
    import org.apache.http.util.EntityUtils;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.core.io.Resource;
    
    import javax.net.ssl.SSLContext;
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.security.KeyStore;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import java.util.Map.Entry;
    
    /**
     * 企业付款http请求工具
     */
    public class HttpUtils {
    
    	private static final String DEFAULT_CHARSET = "UTF-8";
    	
    	private static final int CONNECT_TIME_OUT = 5000; //链接超时时间3秒
    	
    	private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom().setConnectTimeout(CONNECT_TIME_OUT).build();
    	
    	private static SSLContext wx_ssl_context = null; //微信支付ssl证书
    
        private static final String MCH_ID  = "1000000000";//证书密码默认是商户号
    
    	static{
    		Resource resource = new ClassPathResource("apiclient_cert.p12");//该证书名字最好改为别人猜不到的
    		try {
    			KeyStore keystore = KeyStore.getInstance("PKCS12");
    			char[] keyPassword = MCH_ID.toCharArray(); //证书密码
    			keystore.load(resource.getInputStream(), keyPassword);
    			wx_ssl_context = SSLContexts.custom().loadKeyMaterial(keystore, keyPassword).build();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * @description 功能描述: get 请求
    	 * @param url 请求地址
    	 * @param params 参数
    	 * @param headers headers参数
    	 * @return 请求失败返回null
    	 */
    	public static String get(String url, Map<String, String> params, Map<String, String> headers) {
    
    		CloseableHttpClient httpClient = null;
    		if (params != null && !params.isEmpty()) {
    			StringBuffer param = new StringBuffer();
    			boolean flag = true; // 是否开始
    			for (Entry<String, String> entry : params.entrySet()) {
    				if (flag) {
    					param.append("?");
    					flag = false;
    				} else {
    					param.append("&");
    				}
    				param.append(entry.getKey()).append("=");
    				
    				try {
    					param.append(URLEncoder.encode(entry.getValue(), DEFAULT_CHARSET));
    				} catch (UnsupportedEncodingException e) {
    					//编码失败
    				}
    			}
    			url += param.toString();
    		}
    
    		String body = null;
    		CloseableHttpResponse response = null;
    		try {
    			httpClient = HttpClients.custom().setDefaultRequestConfig(REQUEST_CONFIG).build();
    			HttpGet httpGet = new HttpGet(url);
    			response = httpClient.execute(httpGet);
    			body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (response != null) {
    				try {
    					response.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    
    			if (httpClient != null) {
    				try {
    					httpClient.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		return body;
    	}
    
    	/**
    	 * @description 功能描述: get 请求
    	 * @param url 请求地址
    	 * @return 请求失败返回null
    	 */
    	public static String get(String url) {
    		return get(url, null);
    	}
    
    	/**
    	 * @description 功能描述: get 请求
    	 * @param url 请求地址
    	 * @param params 参数
    	 * @return 请求失败返回null
    	 */
    	public static String get(String url, Map<String, String> params) {
    		return get(url, params, null);
    	}
    
    	/**
    	 * @description 功能描述: post 请求
    	 * @param url 请求地址
    	 * @param params 参数
    	 * @return 请求失败返回null
    	 */
    	public static String post(String url, Map<String, String> params) {
    		CloseableHttpClient httpClient = null;
    		HttpPost httpPost = new HttpPost(url);
    		List<NameValuePair> nameValuePairs = new ArrayList<>();
    		if (params != null && !params.isEmpty()) {
    			for (Entry<String, String> entry : params.entrySet()) {
    				nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
    			}
    		}
    
    		String body = null;
    		CloseableHttpResponse response = null;
    		try {
    			httpClient = HttpClients.custom().setDefaultRequestConfig(REQUEST_CONFIG).build();
    			httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET));
    			response = httpClient.execute(httpPost);
    			body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (response != null) {
    				try {
    					response.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    
    			if (httpClient != null) {
    				try {
    					httpClient.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		return body;
    	}
    
    	/**
    	 * @description 功能描述: post 请求
    	 * @param url 请求地址
    	 * @param s 参数xml
    	 * @return 请求失败返回null
    	 */
    	public static String post(String url, String s) {
    		CloseableHttpClient httpClient = null;
    		HttpPost httpPost = new HttpPost(url);
    		String body = null;
    		CloseableHttpResponse response = null;
    		try {
    			httpClient = HttpClients.custom().setDefaultRequestConfig(REQUEST_CONFIG).build();
    			httpPost.setEntity(new StringEntity(s, DEFAULT_CHARSET));
    			response = httpClient.execute(httpPost);
    			body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (response != null) {
    				try {
    					response.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    
    			if (httpClient != null) {
    				try {
    					httpClient.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		return body;
    	}
    
    	/**
    	 * @description 功能描述: post https请求,服务器双向证书验证
    	 * @param url 请求地址
    	 * @param params 参数
    	 * @return 请求失败返回null
    	 */
    	 public static String posts(String url, Map<String, String> params) {
    		CloseableHttpClient httpClient = null;
    		HttpPost httpPost = new HttpPost(url);
    		List<NameValuePair> nameValuePairs = new ArrayList<>();
    		if (params != null && !params.isEmpty()) {
    			for (Entry<String, String> entry : params.entrySet()) {
    				nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
    			}
    		}
    
    		String body = null;
    		CloseableHttpResponse response = null;
    		try {
    			httpClient = HttpClients.custom().setDefaultRequestConfig(REQUEST_CONFIG).setSSLSocketFactory(getSSLConnectionSocket()).build();
    			httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET));
    			response = httpClient.execute(httpPost);
    			body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (response != null) {
    				try {
    					response.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    
    			if (httpClient != null) {
    				try {
    					httpClient.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		return body;
    	}
    	
    	/**
    	 * @description 功能描述: post https请求,服务器双向证书验证
    	 * @param url 请求地址
    	 * @param s 参数xml
    	 * @return 请求失败返回null
    	 */
    	public static String posts(String url, String s) {
    		CloseableHttpClient httpClient = null;
    		HttpPost httpPost = new HttpPost(url);
    		String body = null;
    		CloseableHttpResponse response = null;
    		try {
    			httpClient = HttpClients.custom().setDefaultRequestConfig(REQUEST_CONFIG).setSSLSocketFactory(getSSLConnectionSocket()).build();
    			httpPost.setEntity(new StringEntity(s, DEFAULT_CHARSET));
    			response = httpClient.execute(httpPost);
    			body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			if (response != null) {
    				try {
    					response.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    
    			if (httpClient != null) {
    				try {
    					httpClient.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    		}
    		return body;
    	}
    
    	//获取ssl connection链接
    	private static SSLConnectionSocketFactory getSSLConnectionSocket() {
    		return new SSLConnectionSocketFactory(wx_ssl_context, new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
    	}
    }
    

    3. XmlUtil (xml、map转换工具)

    package com.zero.jimu.utils.withdrawal;
    
    import com.github.pagehelper.util.StringUtil;
    import org.xmlpull.v1.XmlPullParser;
    import org.xmlpull.v1.XmlPullParserException;
    import org.xmlpull.v1.XmlPullParserFactory;
    
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    
    /**
     * xml、map转换工具
     */
    public class XmlUtil {
    
    	private static final String PREFIX_XML = "<xml>";
    
    	private static final String SUFFIX_XML = "</xml>";
    
    	private static final String PREFIX_CDATA = "<![CDATA[";
    
    	private static final String SUFFIX_CDATA = "]]>";
    
    	/**
    	 * 转化成xml, 单层无嵌套
    	 * 
    	 * @param parm
    	 * @param isAddCDATA
    	 * @return
    	 */
    	public static String xmlFormat(Map<String, String> parm, boolean isAddCDATA) {
    
    		StringBuffer strbuff = new StringBuffer(PREFIX_XML);
    		if (CollectionUtil.isNotEmpty(parm)) {
    			for (Entry<String, String> entry : parm.entrySet()) {
    				strbuff.append("<").append(entry.getKey()).append(">");
    				if (isAddCDATA) {
    					strbuff.append(PREFIX_CDATA);
    					if (StringUtil.isNotEmpty(entry.getValue())) {
    						strbuff.append(entry.getValue());
    					}
    					strbuff.append(SUFFIX_CDATA);
    				} else {
    					if (StringUtil.isNotEmpty(entry.getValue())) {
    						strbuff.append(entry.getValue());
    					}
    				}
    				strbuff.append("</").append(entry.getKey()).append(">");
    			}
    		}
    		return strbuff.append(SUFFIX_XML).toString();
    	}
    
    	/**
    	 * 解析xml
    	 * 
    	 * @param xml
    	 * @return
    	 * @throws XmlPullParserException
    	 * @throws IOException
    	 */
    	public static Map<String, String> xmlParse(String xml) throws XmlPullParserException, IOException {
    		Map<String, String> map = null;
    		if (StringUtil.isNotEmpty(xml)) {
    			InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
    			XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser();
    			pullParser.setInput(inputStream, "UTF-8"); // 为xml设置要解析的xml数据
    			int eventType = pullParser.getEventType();
    
    			while (eventType != XmlPullParser.END_DOCUMENT) {
    				switch (eventType) {
    				case XmlPullParser.START_DOCUMENT:
    					map = new HashMap<String, String>();
    					break;
    				case XmlPullParser.START_TAG:
    					String key = pullParser.getName();
    					if (key.equals("xml"))
    						break;
    					String value = pullParser.nextText().trim();
    					map.put(key, value);
    					break;
    				case XmlPullParser.END_TAG:
    					break;
    				}
    				eventType = pullParser.next();
    			}
    		}
    		return map;
    	}
    }
    
    

    4. PayUtil

    package com.zero.jimu.utils.withdrawal;
    
    import com.github.pagehelper.util.StringUtil;
    import com.zero.jimu.utils.ChineseCharToEnUtil;
    import com.zero.jimu.utils.DateUtil;
    import com.zero.jimu.utils.Encrypt;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.util.Arrays;
    import java.util.Date;
    import java.util.Map;
    import java.util.Set;
    
    public class PayUtil {
    
    	/**
    	 * 生成订单号
    	 * 
    	 * @return
    	 */
    	public static String getTradeNo() {
    		// 自增8位数 00000001
    		return "TNO" + DateUtil.formatDate(new Date(), DateUtil.TIME_STAMP_PATTERN) + "00000001";
    	}
    
    	/**
    	 * 退款单号
    	 * 
    	 * @return
    	 */
    	public static String getRefundNo() {
    		// 自增8位数 00000001
    		return "RNO" + DateUtil.formatDate(new Date(), DateUtil.TIME_STAMP_PATTERN) + "00000001";
    	}
    
    	/**
    	 * 退款单号
    	 * 
    	 * @return
    	 */
    	public static String getTransferNo() {
    		// 自增8位数 00000001
    		return "TNO" + DateUtil.formatDate(new Date(), DateUtil.TIME_STAMP_PATTERN) + "00000001";
    	}
    
    	/**
    	 * 返回客户端ip
    	 * 
    	 * @param request
    	 * @return
    	 */
    	public static String getRemoteAddrIp(HttpServletRequest request) {
    		String ip = request.getHeader("X-Forwarded-For");
    		if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
    			// 多次反向代理后会有多个ip值,第一个ip才是真实ip
    			int index = ip.indexOf(",");
    			if (index != -1) {
    				return ip.substring(0, index);
    			} else {
    				return ip;
    			}
    		}
    		ip = request.getHeader("X-Real-IP");
    		if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
    			return ip;
    		}
    		return request.getRemoteAddr();
    	}
    
    	/**
    	 * 获取服务器的ip地址
    	 * 
    	 * @param request
    	 * @return
    	 */
    	public static String getLocalIp(HttpServletRequest request) {
    		return request.getLocalAddr();
    	}
    
    	public static String getSign(Map<String, String> params, String paternerKey) throws UnsupportedEncodingException {
    		return Encrypt.getMD5(createSign(params, false) + "&key=" + paternerKey).toUpperCase();
    	}
    
    	/**
    	 * 构造签名
    	 * 
    	 * @param params
    	 * @param encode
    	 * @return
    	 * @throws UnsupportedEncodingException
    	 */
    	public static String createSign(Map<String, String> params, boolean encode) throws UnsupportedEncodingException {
    		Set<String> keysSet = params.keySet();
    		Object[] keys = keysSet.toArray();
    		Arrays.sort(keys);
    		StringBuffer temp = new StringBuffer();
    		boolean first = true;
    		for (Object key : keys) {
    			if (key == null || StringUtil.isEmpty(params.get(key))) // 参数为空不参与签名
    				continue;
    			if (first) {
    				first = false;
    			} else {
    				temp.append("&");
    			}
    			temp.append(key).append("=");
    			Object value = params.get(key);
    			String valueStr = "";
    			if (null != value) {
    				valueStr = value.toString();
    			}
    			if (encode) {
    				temp.append(URLEncoder.encode(valueStr, "UTF-8"));
    			} else {
    				temp.append(valueStr);
    			}
    		}
    		return temp.toString();
    	}
    
    	/**
    	 * 创建支付随机字符串
    	 * @return
    	 */
    	public static String getNonceStr(){
    		return ChineseCharToEnUtil.randomString(ChineseCharToEnUtil.LETTER_NUMBER_CHAR, 32);
    	}
    	
    	/**
    	 * 支付时间戳
    	 * @return
    	 */
    	public static String payTimestamp() {
    		return Long.toString(System.currentTimeMillis() / 1000);
    	}
    }
    
    

    5. CollectionUtil

    package com.zero.jimu.utils.withdrawal;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.List;
    import java.util.Map;
    
    /**
     * 集合类工具
     */
    public class CollectionUtil {
    
    	private CollectionUtil() {
    		super();
    	}
    
    	// 判断一个集合是否为空
    	public static <T> boolean isEmpty(Collection<T> col) {
    		if (col == null || col.isEmpty()) {
    			return true;
    		}
    
    		return false;
    	}
    
    	// 判断一个集合是否不为空
    	public static <T> boolean isNotEmpty(Collection<T> col) {
    		return !isEmpty(col);
    	}
    
    	// 判断Map是否为空
    	public static <K, V> boolean isEmpty(Map<K, V> map) {
    		if (map == null || map.isEmpty()) {
    			return true;
    		}
    
    		return false;
    	}
    
    	// 判断Map是否不为空为空
    	public static <K, V> boolean isNotEmpty(Map<K, V> map) {
    		return !isEmpty(map);
    	}
    
    	// 去除list中的重复数据
    	public static <T> List<T> removeRepeat(List<T> list) {
    		if (isEmpty(list)) {
    			return list;
    		}
    
    		List<T> result = new ArrayList<T>();
    		for (T e : list) {
    			if (!result.contains(e)) {
    				result.add(e);
    			}
    		}
    
    		return result;
    	}
    
    	// 将集合转换为String数组
    	public static <T> String[] toArray(List<T> list) {
    		if (isEmpty(list)) {
    			return null;
    		}
    
    		String[] result = new String[list.size()];
    		for (int i = 0; i < list.size(); i++) {
    			result[i] = String.valueOf(list.get(i));
    		}
    
    		return result;
    	}
    
    }
    
    

    展开全文
  • 1.基本配置 //公众账号appid $data["mch_appid"] = 'appid'; //商户号 $data["mchid"] = ''; //随机字符串 $data["nonce_str"] = 'suiji'.mt_rand...]=date('YmdHis').mt_ra...

    1.基本配置

    //公众账号appid  
    $data["mch_appid"] = 'appid'; 
    //商户号   
    $data["mchid"] = ''; 
    //随机字符串  
    $data["nonce_str"] = 'suiji'.mt_rand(100,999); 
    //商户订单号   
    $data["partner_trade_no"]=date('YmdHis').mt_rand(1000,9999); 
    //金额 用户输入的提现金额需要乘以100  
    $data["amount"] = $money;  
    //企业付款描述  
    $data["desc"] = '企业付款到个人零钱';  
    //用户openid     
    $data["openid"] = $openid;  
    //不检验用户姓名 
    $data["check_name"] = 'NO_CHECK';  
    //获取IP    
    $data['spbill_create_ip']=$_SERVER['SERVER_ADDR'];  
    //商户密钥   
    $data['key']=''; 
    //商户证书 商户平台的API安全证书下载 
     $data['apiclient_cert.pem']
     $data['apiclient_key.pem'] 

    2.PHP代码

    
    	/**
    **开始支付
    /
     public function userpay(){
     $money = ‘用户输入提现金额';
     $info['money'] = ‘用户余额';
     if ($this->openid && $money){
      if ($money>$info['money'] ){
      echo json_encode([
       'status' => 1,
       'message' => '余额不足,不能提现!',
       'code'=>'余额不足,不能提现!'   ]);
      }elseif ($money<1){
      echo json_encode([
       'status' => 2,
       'message' => '提现金额不能小于1元',
       'code'=>'提现金额太低'   ]);
      }else{
     $openid = $this->openid;
     $trade_no = date('YmdHis').mt_rand(1000,9999);
     $res = $this->pay($openid,$trade_no,$money*100,'微信提现');
    
     //结果打印
     if($res['result_code']=="SUCCESS"){
    
       echo json_encode([
       'status' => 3,
       'message' => '提现成功!',
       ]);
      }elseif ($res['err_code']=="SENDNUM_LIMIT"){
       echo json_encode([
       'status' => 4,
       'message' => '提现失败!',
       'code'=>'每日仅能提现一次',
       ]);
      }else{
       echo json_encode([
       'status' => 5,
       'message' => '提现失败!',
       'code'=>$res['err_code'],
       ]);
      }
      }
     }else{
      echo json_encode([
      'status' => 5,
      'message' => '未检测到您当前微信账号~',
    
      ]);
     }
     } 

    支付方法

    	/**
    *支付方法
    /
    public function pay($openid,$trade_no,$money,$desc){
     $params["mch_appid"]=''; 
     $params["mchid"] = ''; 
     $params["nonce_str"]= 'suiji'.mt_rand(100,999); 
     $params["partner_trade_no"] = $trade_no;  
     $params["amount"]= $money;  
     $params["desc"]= $desc;  
     $params["openid"]= $openid;  
     $params["check_name"]= 'NO_CHECK'; 
     $params['spbill_create_ip'] = $_SERVER['SERVER_ADDR']; 
    
     //生成签名
     $str = 'amount='.$params["amount"].'&check_name='.$params["check_name"].'&desc='.$params["desc"].'&mch_appid='.$params["mch_appid"].'&mchid='.$params["mchid"].'&nonce_str='.$params["nonce_str"].'&openid='.$params["openid"].'&partner_trade_no='.$params["partner_trade_no"].'&spbill_create_ip='.$params['spbill_create_ip'].'&key=商户密钥';
    
     //md5加密 转换成大写
     $sign = strtoupper(md5($str));
     //生成签名
     $params['sign'] = $sign;
    
     //构造XML数据
     $xmldata = $this->array_to_xml($params); //数组转XML
     $url='https://api.mch.weixin.qq.com/mmpaymkttransfers/prom otion/transfers';
    
     //发送post请求
     $res = $this->curl_post_ssl($url, $xmldata); //curl请求 
     if(!$res){
     return array('status'=>1, 
       'msg'=>"服务器连接失败" );
     }
    
     //付款结果分析
     $content = $this->xml_to_array($res); //xml转数组
     return $content;
     } 
    
    	/**
    * curl请求
    /
    public function curl_post_ssl($url, $xmldata,  $second=30,$aHeader=array()){
     $ch = curl_init();
     //超时时间
     curl_setopt($ch,CURLOPT_TIMEOUT,$second);
     curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);
     //这里设置代理,如果有的话
     //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');
     //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);
     curl_setopt($ch,CURLOPT_URL,$url);
     curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
     curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
    
     //默认格式为PEM,可以注释
     curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
    //绝对地址可使用 dirname(__DIR__)打印,如果不是绝对地址会报 58 错误
     curl_setopt($ch,CURLOPT_SSLCERT,' 绝对地址/apiclient_cert.pem');
     curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
     curl_setopt($ch,CURLOPT_SSLKEY,'绝对地址/apiclient_key.pem');
     if( count($aHeader) >= 1 ){
      curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
     }
     curl_setopt($ch,CURLOPT_POST, 1);
     curl_setopt($ch,CURLOPT_POSTFIELDS,$xmldata);
     $data = curl_exec($ch);
     if($data){
     curl_close($ch);
     return $data;
     }
     else {
     $error = curl_errno($ch);
     echo "call faild, errorCode:$error\n";
     die();
     curl_close($ch);
     return false;
     }
     } 

    生成签名

    
    	/**
     * array 转 xml
     * 用于生成签名
    */ public function array_to_xml($arr){
     $xml = "<xml>";
     foreach ($arr as $key => $val) {
     if (is_numeric($val)) {
     $xml .= "<" .$key.">".$val."</".$key.">";
     } else  $xml .= "<".$key."><![CDATA[".$val."]]></".$key.">";
     }
     $xml .= "</xml>";
     return $xml;
     } 
    	/**
    * xml 转化为array
    */ public function xml_to_array($xml){
     //禁止引用外部xml实体  libxml_disable_entity_loader(true);
     $values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
     return $values;
     }

     

    展开全文
  • 微信提现

    2019-07-11 19:52:15
    微信商户平台:微信提现文档https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1
    展开全文
  • 微信支付对接提现功能(php)

    千次阅读 2019-06-16 22:37:57
    参考:... ... 首先要登录微信支付商户平台下载证书 注意点:最好使用QQ浏览器(兼容模式),在下载安全控件时,使用其他浏览器可能会失败。 获取API证书需要商户号的超级管理员才能操作,详细步骤...

    参考:https://blog.51cto.com/14210437/2353576?source=dra

    http://kf.qq.com/faq/161222NneAJf161222U7fARv.html

     首先要登录微信支付商户平台下载证书

    注意点:最好使用QQ浏览器(兼容模式),在下载安全控件时,使用其他浏览器可能会失败。

    获取API证书需要商户号的超级管理员才能操作,详细步骤如下:

    登录微信支付商户平台,进入【账户中心】->【账户设置】->【API安全】

     1、若页面效果如下图,表示你的证书类型为“微信支付颁发的API证书”,可点击“下载证书”按钮,并按页面指引操作即可。

     2、若页面效果如下图,表示你的证书类型为“权威CA颁发的API证书”,请点击“申请证书”按钮,并按以下指引完成证书申请。

     2.1在【商户平台】打开【生成API证书】弹窗,点击“允许访问”,同意网页访问剪切板;

     

    2.2 ①在【商户平台】-“提交请求串”环节,点击“下载证书工具”按钮;

    ② 下载并打开文件“WXCertUtil.exe”后;

    ③ 在【证书工具】,点击“申请证书”按钮,如下图:

     2.3在【证书工具】-“填写商户信息”环节,填写商户号和商户名称后,点击“下一步”按钮,可在【商户平台】查看商户号和商户名称;

    2.6 在【证书工具】-“生成证书”环节,已完成申请证书流程,点击“查看证书文件夹”,查看已生成的证书文件。

     2.7 请将生成的证书文件转交给技术人员,由技术人员将证书部署到服务器上。

    下载API证书

    运营账户充值

    保证运营账户有一定的余额,才能够提现成功。

     

    封装提现脚本

    将证书文件(3个)放在需要运行脚本的位置。代码如下

    class Cash{
        public function wxcash($openId,$money)   {
            $pub = ['app_id'=>'######','mch_id'=>'######','key'=>'######'];//config('keys.payConfig');
            $appid = $pub['app_id'];//商户账号appid
            $mch_id = $pub['mch_id'];//商户号
            $key = $pub['key'];
            $openid = $openId;//授权用户openid
    
            $arr = array();
            $arr['mch_appid'] = $appid;
            $arr['mchid'] = $mch_id;
            $arr['nonce_str'] = md5(uniqid(microtime(true),true));//随机字符串,不长于32位
            $arr['partner_trade_no'] = '123456789' . date("Ymd") . rand(10000, 90000) . rand(10000, 90000);//商户订单号
            $arr['openid'] = $openid;
            $arr['check_name'] = 'NO_CHECK';//是否验证用户真实姓名,这里不验证
            $arr['amount'] = $money * 100;//付款金额,单位为分
            $arr['desc'] = "零钱提现";//描述信息
            $arr['spbill_create_ip'] = 'xx.xx.xx.xx';//获取服务器的ip
            //封装的关于签名的算法
            $arr['sign'] = $this->makeSign($arr,$key);//签名
            $var = $this->arrayToXml($arr);
            // dump($arr['sign'] );exit;
            $xml = $this->curl_post_ssl('https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers',$var,30, array(), 1);
            libxml_disable_entity_loader(true);
    		//echo $xml; die;
    		$obj1=simplexml_load_string($xml,'SimpleXMLElement');
    //var_dump($obj1); die;
            $rdata = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)),true);
            var_dump('cash_xmldata',$rdata);//eblog('cash_xmldata',$rdata);
            // dump($rdata);exit;
            $return_code = trim(strtoupper($rdata['return_code']));
            $result_code = trim(strtoupper($rdata['result_code']));
            if ($return_code == 'SUCCESS' && $result_code == 'SUCCESS') {
                $isrr = array(
                    'status'=>1,
                    'msg' => '',
                );
            } else {
                // $returnmsg = $rdata['return_msg'];
                $err_code_des = $rdata['err_code_des'];
                $isrr = array(
                    'status' => 0,
                    'msg' => $err_code_des,
                );
            }
            return $isrr;
        }
    
        protected function makesign($data,$key)
        {
            //获取微信支付秘钥
            $data = array_filter($data);
            //签名步骤一:按字典序排序参数
            ksort($data);
            $string_a = http_build_query($data);
            $string_a = urldecode($string_a);
            //签名步骤二:在string后加入KEY
            //$config=$this->config;
            $string_sign_temp = $string_a."&key=".$key;
            //签名步骤三:MD5加密
            $sign = md5($string_sign_temp);
            // 签名步骤四:所有字符转为大写
            $result = strtoupper($sign);
            // $result = strtoupper(hash_hmac("sha256",$string_sign_temp,$key));
            return $result;
        }
    
        protected function arraytoxml($data){
            $str='<xml>';
            foreach($data as $k=>$v) {
                $str.='<'.$k.'>'.$v.'</'.$k.'>';
            }
            $str.='</xml>';
            return $str;
        }
    
        protected function curl_post_ssl($url, $vars, $second = 30, $aHeader = array())
        {
            $isdir = "cert/";//APP_PATH."/common/library/php_sdk/lib/";//证书位置
            $ch = curl_init();//初始化curl
            curl_setopt($ch, CURLOPT_TIMEOUT, $second);//设置执行最长秒数
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
            curl_setopt($ch, CURLOPT_URL, $url);//抓取指定网页
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// 终止从服务端进行验证
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//
            curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');//证书类型
            curl_setopt($ch, CURLOPT_SSLCERT, $isdir . 'apiclient_cert.pem');//证书位置
            curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');//CURLOPT_SSLKEY中规定的私钥的加密类型
            curl_setopt($ch, CURLOPT_SSLKEY, $isdir . 'apiclient_key.pem');//证书位置
            curl_setopt($ch, CURLOPT_CAINFO, 'PEM');
            curl_setopt($ch, CURLOPT_CAINFO, $isdir . 'rootca.pem');
            if (count($aHeader) >= 1) {
                curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);//设置头部
            }
            curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
            curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);//全部数据使用HTTP协议中的"POST"操作来发送
            $data = curl_exec($ch);//执行回话
            if ($data) {
                curl_close($ch);
                return $data;
            } else {
                $error = curl_errno($ch);
                echo "call faild, errorCode:$error\n";
                curl_close($ch);
                return false;
            }
        }
    
    }
    
    $cash=new Cash();
    $cash->wxcash({openid},0.01);

     

    展开全文
  • * 微信提现 * by wangge * 1018.2.7 */ var https = require('https'); var cryptoMO = require('crypto'); // MD5算法 var request = require("request"); var fs = require("fs");...
  • 微信企业付款到零钱(微信提现)

    千次阅读 2018-07-23 18:28:33
    由于项目中要用到微信提现,参数网上代码和官方文档写了提现的工具类 MD5工具类 package com.kk.wechatextract; import java.security.MessageDigest; public class MD5Utils { private static final char ...
  • [微信]企业付款个人/微信提现

    千次阅读 2018-09-19 10:44:13
    微信提现(企业付款到个人含demo) https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2 企业付款文档 ``` public class Configure { // 商户密钥 public static String key = &amp;amp;...
  • 微信支付(提现

    千次阅读 2018-11-16 11:12:29
    api: https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2 需要用到的工具类:(xml和map相互转换) ... import org.w3c.dom.Document;...import org.w3c.dom.Element;...import or...
  • 微信小程序怎么提现到零钱?有个提现的功能,但是看了下小程序API没有看到关于提现的接口,所以不知道该怎么搞了
  • 流程应该是这样: ... app把这个帐号post到自己的server端 server再验证,再根据用户的额度之类的向用户的支付宝帐户转入相应的金额 ...所以其实在ios app端不会进行具体的转帐操作,app只是收集用户的帐号信息,...
  • 关键字:微信商户号 资金解决方案 自动提现 关闭   说起来真坑爹,有些客户能看到自动提现,有些客户看不到自动提现,找了很久,才找到问题所在。 请看: https://cloud.tencent.com/developer/article/1026997  ...
  • 一、证书出错  一般是因为证书路径问题。... 使用微信的签名检查工具 http://mch.weixin.qq.com/wiki/tools/signverify/,检查签名是否已本地签名一致;  若不一致,检查代码;  2、展示一下我
  • Java- 微信提现支付CA证书出错,请登录微信支付商户平台下载证书** 是由于商户id错误,导致错误。检查一下商户的ID** 有问题请发邮件 jscaiming#163.com
  • 微信公众号支付及提现

    万次阅读 2018-03-27 11:19:15
    微信支付,分为很多种,前端一般情况有两种,公众号支付和H5页面支付(在QQ,浏览器上),这篇文章为公众号支付,H5页面支付请看:...1、微信公众号支付 1. 分钟号I...
  • 微信公众号支付和提现

    万次阅读 2017-09-19 11:29:49
    一、微信公众号支付。 1.XXX/WechatPayController/getAuthorizeUrl?url=http://域名/项目/XXXController/toBuyCard,在controller方法里,获取url,重定向到 ...
  • 支付宝充值弄完了之后,接下来就讲一下支付宝的提现和微信提现的服务端集成的大概逻辑。 一:支付宝提现 首先申请appid,生成应用公私钥并上传支付宝后台就不说了,然后写一个配置信息类将appid,privateKey和alipay...
  • 最近遇到个问题,想实现批量的微信或者支付宝提现功能,就是将账户余额里面的钱提现微信零钱或者支付宝余额里面,php的哟
  • 公共参数图表: 接口 需要参数 通知方式 支付宝APP支付 应用公钥,应用私钥 ... 支付宝APP提现 应用公钥,应用私钥,...
  • 已开通微信应用(服务号或者小程序),主要用到APPID+OPENID 已开通微信商户,并且开通企业付款到零钱,主要用到商户号+商户秘钥+商户证书 B.开发流程 主要就是按规则封装好请求参数调用微信接口,涉及一些签名...
  • 千聊资费说明和提现须知

    万次阅读 2017-06-21 10:51:33
    为谋求用户利益最大化,争取用户使用本工具的成本最小化,千聊直播与腾讯官方再三协调后,确定直播间收益及提现有关费用在提现时,微信收取的手续费从2%下降至0.6%,如下图: (点击图片查看大图) ...
1 2 3 4 5 ... 20
收藏数 6,291
精华内容 2,516
关键字:

微信提现