上一篇写了关于支付宝支付的相关问题,本篇主要介绍微信支付的模块
微信支付可以大体分为5块:1.网页支付、2.App支付、3.H5外部浏览器支付、4.小程序支付、5.H5微信内部浏览器支付。这篇文章主要讲解 2、3、4、5这4种支付。
整体难度来说:H5微信内部浏览器支付>H5外部浏览器支付>小程序支付>App支付>网页支付。
编程语言为JAVA,采用的框架是SpringBoot+Mybatis.


控制层代码:
1.createPayOrder为三端统一调起的接口 只用appType和code区分出到底是调用哪个方法
2.因为H5外部浏览器支付需要获取用户的Ip地址所以主动去获取了请求的ip地址
3.isPayEarnest只是区分是否定金

@RestController
@RequestMapping("/wechatpay")
public class WeChatPayController {@Autowiredprivate WeChatPayService weChatPayService;/*** 发起统一下单* @param appType 0为H5端 1为小程序 2为app* @param billNo Code是微信通过授权后获取的* @return Result*/@RequestMapping(value = "/createPayOrder", method = RequestMethod.POST)public @ResponseBody Result createAppWeChatPayOrder(HttpServletRequest request, int appType, String billNo,String code, int isPayEarnest) {if (appType == 0) {if (code != null) {return weChatPayService.h5CreateInnerPayOrder(billNo,code,isPayEarnest);}// h5return weChatPayService.h5CreatePayOrder(billNo, getIpAddr(request), isPayEarnest);} else if (appType == 1) {// 小程序return weChatPayService.wxAppCreatePayOrder(code, billNo, isPayEarnest);} else {// appreturn weChatPayService.appCreatePayOrder(appType, billNo, isPayEarnest);}}/*** 获取访问者IP* * 在一般情况下使用Request.getRemoteAddr()即可,但是经过nginx等反向代理软件后,这个方法会失效。* * 本方法先从Header中获取X-Real-IP,如果不存在再从X-Forwarded-For获得第一个IP(用,分割),* 如果还不存在则调用Request .getRemoteAddr()。* * @param request* @return*/public static String getIpAddr(HttpServletRequest request) {String ip = request.getHeader("X-Real-IP");if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {return ip;}ip = request.getHeader("X-Forwarded-For");if (!StringUtils.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {// 多次反向代理后会有多个IP值,第一个为真实IP。int index = ip.indexOf(',');if (index != -1) {return ip.substring(0, index);} else {return ip;}} else {return request.getRemoteAddr();}}/*** 查询订单* @param appType String* @param wxBillNo String* @param erpBillNo String* @return*/@RequestMapping(value = "/orderquery")public @ResponseBody Result orderQuery(WeChatPayOrderQueryRequest request) {return weChatPayService.orderQuery(request);}
}

业务层代码:

```
@Service
public class WeChatPayServiceImpl implements WeChatPayService {private static Logger LOG = Logger.getLogger(WeChatPayServiceImpl.class);//微信支付配置参数@Autowiredprivate WeChatPayProperties weChatPayProperties;private String orderDetail = "XXXX业务:";//支付业务@Autowiredprivate PayService payService;@Overridepublic Result wxAppCreatePayOrder(String code, String billNo, int isPayEarnest) {// 向微信请求获取openIdMap<String, Object> openIdMap = getOpenId(initWxAppOpenIdParmMap(code));if (openIdMap == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.GET_WECHATPAY_OPENID);}String openId = (String) openIdMap.get("openid");if (openId == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.GET_WECHATPAY_OPENID);}// String session_key = (String) openIdMap.get("session_key");// 获取订单信息CarRentOrderPerson dto = payService.findOrder(billNo);//为了能多次吊起支付,调起支付订单号要加上时间戳String newbillNo = payService.createNewOrderNo(billNo);//保存吊起支付请求记录,方便维护(可有可无)payService.savePayRequest(newbillNo, dto, PayTypeEnums.WXAPP.getIndex(), SourceTypeEnums.WXAPP.getIndex());// 初始化微信小程序统一下单参数Map<String, String> params = initWxAppCreatePayBillParams(openId, orderDetail + dto.getModelname(), newbillNo,isPayEarnest == 1 ? dto.getPrepaydeposit().multiply((new BigDecimal(100))): dto.getReceivableamount().multiply((new BigDecimal(100))));// 向微信平台请求Result result = sendCreateOrderRequest(params);if (result.getCode() == Constants.FAILURE_CODE) {return result;}String prePayid = (String) result.getData();// 封装prePayId到返回参数中,直接返回给前端,前端直接拿着这个就可以调起支付return new Result(Constants.SUCCESS_CODE, "", initWxAppCreatePayBillReturnParams(prePayid));}@Overridepublic Result appCreatePayOrder(int appType, String billNo, int isPayEarnest) {// 判断app类型 获取相应appIdString appId = weChatPayProperties.getAppAppid();if (!(appType == 3 || appType == 2)) {return new Result(Constants.FAILURE_CODE, ErrorMsg.NO_SUCH_APP_TYPE);}// 获取预订单CarRentOrderPerson dto = payService.findOrder(billNo);if (dto == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.BILLNO_CANOT_BE_NULL);}String newbillNo = payService.createNewOrderNo(billNo);//3为安卓 2为ios 记录请求if (appType == 3) {payService.savePayRequest(newbillNo, dto, PayTypeEnums.WXAPP.getIndex(),SourceTypeEnums.ANDROID.getIndex());} else {payService.savePayRequest(newbillNo, dto, PayTypeEnums.WXAPP.getIndex(), SourceTypeEnums.IOS.getIndex());}//创建请求信息Map<String, String> params = initAppCreateOrderParams(appId, orderDetail + dto.getModelname(), newbillNo,isPayEarnest == 1 ? dto.getPrepaydeposit().multiply((new BigDecimal(100))): dto.getReceivableamount().multiply(new BigDecimal(100)));// 向微信请求Result result = sendCreateOrderRequest(params);if (result.getCode() == Constants.FAILURE_CODE) {return result;}String prePayid = (String) result.getData();return new Result(Constants.SUCCESS_CODE, "", initAppCreateOrderRetunParams(appId, prePayid));}@Override//H5外部调起支付public Result h5CreatePayOrder(String billNo, String ip, int isPayEarnest) {String sceenInfo = "{\"h5_info\": \"h5_info\" {\"type\": \"api\",  \"wap_url\": \"\",\"wap_name\": \"\"}}";// 获取预订单CarRentOrderPerson dto = payService.findOrder(billNo);if (dto == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.BILLNO_CANOT_BE_NULL);}String newbillNo = payService.createNewOrderNo(billNo);// 保存请求参数payService.savePayRequest(newbillNo, dto, PayTypeEnums.WXAPP.getIndex(), SourceTypeEnums.H5.getIndex());Map<String, String> params = initH5CreateOrderParams(sceenInfo, orderDetail + dto.getModelname(), newbillNo, ip,isPayEarnest == 1 ? dto.getPrepaydeposit().multiply((new BigDecimal(100))): dto.getReceivableamount().multiply(new BigDecimal(100)));Result result = sendRequestToWxApi(params, weChatPayProperties.CREATE_PAY_ORDER_URL);if (result.getCode() == Constants.FAILURE_CODE) {return result;}@SuppressWarnings("unchecked")HashMap<String, String> returnHashMap = (HashMap<String, String>) result.getData();//prePayid为空请求失败String prePayid = returnHashMap.get("prepay_id");if (prePayid == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.WECHATPAY_WXAPP_CREATE_ORDER_FAIL);}String url = returnHashMap.get("mweb_url");if (url == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.WECHATPAY_WXAPP_CREATE_ORDER_FAIL);}return new Result(Constants.SUCCESS_CODE, "", initH5CreatePayBillReturnParams(prePayid, url));}@Override//H5微信内部浏览器调起public Result h5CreateInnerPayOrder(String billNo, String code, int isPayEarnest) {// 获取openIdMap<String, Object> openIdMap = getH5OpenId(initH5OpenIdParmMap(code));if (openIdMap == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.GET_WECHATPAY_OPENID);}String openId = (String) openIdMap.get("openid");if (openId == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.GET_WECHATPAY_OPENID);}// 获取预订单CarRentOrderPerson dto = payService.findOrder(billNo);String newbillNo = payService.createNewOrderNo(billNo);payService.savePayRequest(newbillNo, dto, PayTypeEnums.WXAPP.getIndex(), SourceTypeEnums.H5.getIndex());// 初始化微信统一下单参数Map<String, String> params = initWxAppCreatePayBillParams(openId, orderDetail + dto.getModelname(), newbillNo,isPayEarnest == 1 ? dto.getPrepaydeposit().multiply((new BigDecimal(100))): dto.getReceivableamount().multiply((new BigDecimal(100))));// 向微信平台请求Result result = sendCreateOrderRequest(params);if (result.getCode() == Constants.FAILURE_CODE) {return result;}String prePayid = (String) result.getData();// 封装prePayId到返回参数中return new Result(Constants.SUCCESS_CODE, "", initH5InnerCreatePayBillReturnParams(prePayid));}@Overridepublic Result orderQuery(WeChatPayOrderQueryRequest request) {String appid = "";if (StringUtils.isBlank(request.getErpBillNo()) && StringUtils.isBlank(request.getWxBillNo())) {return new Result(Constants.FAILURE_CODE, ErrorMsg.BILLNO_CANOT_BE_NULL);}if (2 == request.getAppType() || 3 == request.getAppType()) {appid = weChatPayProperties.getAppAppid();} else if (0 == request.getAppType()) {appid = weChatPayProperties.getH5Appid();} else if (1 == request.getAppType()) {appid = weChatPayProperties.getWxAppAppid();} else {return new Result(Constants.FAILURE_CODE, ErrorMsg.NO_SUCH_APP_TYPE);}Map<String, String> params = initOrderQueryParams(appid, request.getWxBillNo(), request.getErpBillNo());// 向微信请求Result result = sendRequestToWxApi(params, weChatPayProperties.ORDERQUERY_URL);if (result.getCode() == Constants.FAILURE_CODE) {return result;}@SuppressWarnings("unchecked")HashMap<String, String> returnHashMap = (HashMap<String, String>) result.getData();return new Result(Constants.SUCCESS_CODE, "",WeChatPayOrderStatus.findNameById(returnHashMap.get("trade_state")));}private HashMap<String, String> initH5CreatePayBillReturnParams(String prePayid, String url) {HashMap<String, String> signMap = new HashMap<String, String>();signMap.put("appId", weChatPayProperties.getH5Appid());signMap.put("nonceStr", RandomUtils.generateString(31));signMap.put("package", "prepay_id=" + prePayid);signMap.put("signType", "MD5");signMap.put("timeStamp", new Date().getTime() + "");signMap.put("mweb_url", url);signMap.put("paySign", createSign(signMap));return signMap;}private HashMap<String, String> initH5InnerCreatePayBillReturnParams(String prePayid) {HashMap<String, String> signMap = new HashMap<String, String>();signMap.put("appId", weChatPayProperties.getH5Appid());signMap.put("nonceStr", RandomUtils.generateString(31));signMap.put("package", "prepay_id=" + prePayid);signMap.put("signType", "MD5");signMap.put("timeStamp", new Date().getTime() + "");signMap.put("paySign", createSign(signMap));return signMap;}/*** 初始化微信小程序统一下单返回参数* @param prePayid 预订单编号* @return*/private HashMap<String, String> initWxAppCreatePayBillReturnParams(String prePayid) {HashMap<String, String> signMap = new HashMap<String, String>();signMap.put("appId", weChatPayProperties.getWxAppAppid());signMap.put("nonceStr", RandomUtils.generateString(31));signMap.put("package", "prepay_id=" + prePayid);signMap.put("signType", "MD5");signMap.put("timeStamp", new Date().getTime() + "");signMap.put("paySign", createSign(signMap));return signMap;}/*** 初始化微信小程序统一下单参数* @param openId 商户openId* @param body 商品信息* @param billNo 订单编号* @param totalFee 总价(单位分)* @return*/private Map<String, String> initWxAppCreatePayBillParams(String openId, String body, String billNo,BigDecimal totalFee) {// 生成微信下单请求参数HashMap<String, String> params = new HashMap<String, String>();Instant now = Instant.now();Date nowDate = Date.from(now);// 支付有限时间为10分钟now = now.plusSeconds(600);Date endDate = Date.from(now);params.put("appid", weChatPayProperties.getWxAppAppid());params.put("mch_id", weChatPayProperties.getWxAppMchId());params.put("notify_url", weChatPayProperties.getNotifyUrl());params.put("time_start", DateUtils.dateToString(nowDate, "yyyyMMddHHmmss"));params.put("time_expire", DateUtils.dateToString(endDate, "yyyyMMddHHmmss"));params.put("nonce_str", RandomUtils.generateString(31));params.put("body", body);/* + DateUtils.dateToString(nowDate, "yyyyMMddHHmm") */params.put("out_trade_no", billNo);params.put("total_fee", String.valueOf(totalFee.intValue()));// params.put("total_fee", String.valueOf(1));// 测试金额// params.put("total_fee", String.valueOf(new BigDecimal(100)));params.put("spbill_create_ip", "0.0.0.1");params.put("trade_type", "JSAPI");params.put("openid", openId);params.put("sign", createSign(params));return params;}/*** 向微信后台发送统一下单请求* * @param 统一下单请求参数 params* @return*/private Result sendCreateOrderRequest(Map<String, String> params) {Result result = sendRequestToWxApi(params, weChatPayProperties.CREATE_PAY_ORDER_URL);if (result.getCode() == Constants.FAILURE_CODE) {return result;}@SuppressWarnings("unchecked")HashMap<String, String> returnHashMap = (HashMap<String, String>) result.getData();String prePayid = returnHashMap.get("prepay_id");if (prePayid == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.WECHATPAY_WXAPP_CREATE_ORDER_FAIL);}return new Result(Constants.SUCCESS_CODE, "", prePayid);}/*** 向微信后台发送请求* @param 参数 params* @param 地址 url* @return*/private Result sendRequestToWxApi(Map<String, String> params, String url) {String sendMsg = XMLUtils.mapToXml(params);if (sendMsg == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.WECHATPAY_REQUEST);}String retString = HttpUtils.postXML(url, sendMsg);if (retString == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.WECHATPAY_REQUEST);}Map<String, String> returnHashMap = XMLUtils.parseMap(retString);if (returnHashMap == null) {return new Result(Constants.FAILURE_CODE, ErrorMsg.WECHATPAY_REQUEST);}if (WeChatPayConstants.RETURN_CODE_FAIL.equals(returnHashMap.get("return_code"))) {return new Result(Constants.FAILURE_CODE, returnHashMap.get("return_msg"));}if (WeChatPayConstants.RETURN_CODE_FAIL.equals(returnHashMap.get("result_code"))) {return new Result(Constants.FAILURE_CODE, returnHashMap.get("err_code_des"));}return new Result(Constants.SUCCESS_CODE, "", returnHashMap);}/*** 初始化App统一下单请求参数* @return*/private Map<String, String> initAppCreateOrderParams(String appid, String body, String billNo,BigDecimal totolFee) {HashMap<String, String> params = new HashMap<String, String>();Instant now = Instant.now();Date nowDate = Date.from(now);now = now.plusSeconds(600);Date endDate = Date.from(now);params.put("appid", appid);params.put("mch_id", weChatPayProperties.getMchId());params.put("notify_url", weChatPayProperties.getNotifyUrl());params.put("time_start", DateUtils.dateToString(nowDate, "yyyyMMddHHmmss"));params.put("time_expire", DateUtils.dateToString(endDate, "yyyyMMddHHmmss"));params.put("nonce_str", RandomUtils.generateString(31));params.put("body", body);params.put("out_trade_no", billNo);params.put("total_fee", String.valueOf(totolFee.intValue()));params.put("spbill_create_ip", "117.28.154.84");params.put("trade_type", "APP");params.put("sign", createSign(params));return params;}/*** 初始化App统一下单请求参数* @return*/private Map<String, String> initH5CreateOrderParams(String sceneInfo, String body, String billNo, String ip,BigDecimal totolFee) {HashMap<String, String> params = new HashMap<String, String>();Instant now = Instant.now();Date nowDate = Date.from(now);now = now.plusSeconds(600);Date endDate = Date.from(now);params.put("appid", weChatPayProperties.getH5Appid());params.put("mch_id", weChatPayProperties.getMchId());params.put("notify_url", weChatPayProperties.getNotifyUrl());params.put("time_start", DateUtils.dateToString(nowDate, "yyyyMMddHHmmss"));params.put("time_expire", DateUtils.dateToString(endDate, "yyyyMMddHHmmss"));params.put("nonce_str", RandomUtils.generateString(31));params.put("body", body);params.put("out_trade_no", billNo);params.put("total_fee", String.valueOf(totolFee.intValue()));params.put("spbill_create_ip", ip);params.put("trade_type", "MWEB");params.put("scene_info", sceneInfo);params.put("sign", createSign(params));return params;}/*** 初始化App统一下单请求参数* @return*/private Map<String, String> initAppCreateOrderRetunParams(String appId, String prepayid) {HashMap<String, String> signMap = new HashMap<String, String>();signMap.put("appid", appId);signMap.put("partnerid", weChatPayProperties.getMchId());signMap.put("prepayid", prepayid);signMap.put("package", "Sign=WXPay");signMap.put("noncestr", RandomUtils.generateString(31));String timestamp = String.valueOf(new Date().getTime());signMap.put("timestamp", timestamp.substring(0, timestamp.length() - 3));signMap.put("sign", createSign(signMap));return signMap;}public Map<String, String> initWxAppOpenIdParmMap(String code) {HashMap<String, String> params = new HashMap<String, String>();params.put("appid", weChatPayProperties.getWxAppAppid());params.put("secret", weChatPayProperties.getWxAppAppsecret());params.put("js_code", code);params.put("grant_type", "authorization_code");return params;}public Map<String, String> initH5OpenIdParmMap(String code) {HashMap<String, String> params = new HashMap<String, String>();params.put("appid", weChatPayProperties.getH5Appid());params.put("secret", weChatPayProperties.getH5Appsecret());params.put("code", code);params.put("grant_type", "authorization_code");return params;}/*** 获取openID* @param params* @return*/public Map<String, Object> getOpenId(Map<String, String> params) {Map<String, Object> map = null;String retStr = HttpUtils.sendPost(weChatPayProperties.GET_OPEN_ID_URL, params);if (retStr == null) {return null;}map = stringToHashMap(retStr);if (map == null || map.get("openid") == null || map.get("session_key") == null) {return null;}return map;}/*** 获取H5openID* @param params* @return*/public Map<String, Object> getH5OpenId(Map<String, String> params) {Map<String, Object> map = null;String retStr = HttpUtils.sendPost(weChatPayProperties.GET_H5_OPEN_ID_URL, params);if (retStr == null) {return null;}map = stringToHashMap(retStr);if (map == null || map.get("openid") == null) {return null;}return map;}private boolean checkSign(Map<String, String> map) {String signFromAPIResponse = map.get("sign").toString();if (signFromAPIResponse == "" || signFromAPIResponse == null) {return false;}// 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名map.remove("sign");// 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较String signForAPIResponse = createSign(map);if (!signForAPIResponse.equals(signFromAPIResponse)) {return false;}return true;}@SuppressWarnings("unchecked")private Map<String, Object> stringToHashMap(String retStr) {ObjectMapper mapper = new ObjectMapper();HashMap<String, Object> map = null;try {map = mapper.readValue(retStr, HashMap.class);} catch (JsonParseException e) {LOG.info(e.toString());return null;} catch (JsonMappingException e) {LOG.info(e.toString());return null;} catch (IOException e) {LOG.info(e.toString());return null;}return map;}// 创建签名private String createSign(Map<String, String> params) {if (params.isEmpty()) {return null;}StringBuilder sb = new StringBuilder();params.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey())).forEachOrdered(e -> {sb.append(e.getKey() + "=" + e.getValue() + "&");});String key = weChatPayProperties.getWxAppAppid().equals(params.get("appid"))|| weChatPayProperties.getWxAppAppid().equals(params.get("appId")) ? weChatPayProperties.getWxAppKey(): weChatPayProperties.getKey();sb.append("key=" + key);String md5 = MD5Helper.getMd5(sb.toString());return md5.toUpperCase();}private Map<String, String> initOrderQueryParams(String appid, String wxBillNo, String erpBillNo) {Map<String, String> params = new HashMap<String, String>();params.put("appid", appid);params.put("mch_id", weChatPayProperties.getWxAppAppid().equals(appid) ? weChatPayProperties.getWxAppMchId(): weChatPayProperties.getMchId());params.put("nonce_str", RandomUtils.generateString(31));if (StringUtils.isNotEmpty(wxBillNo)) {params.put("transaction_id", wxBillNo);} else {// 根据旧单号查询params.put("out_trade_no", payService.getNewOrderNoByOrderNo(erpBillNo));}params.put("sign", createSign(params));return params;}// 获取openIDpublic Map<String, Object> getOpenId(String code) {Map<String, Object> map = null;Map<String, String> params = new HashMap<String, String>();params.put("appid", weChatPayProperties.getWxAppAppid());params.put("secret", weChatPayProperties.getWxAppAppsecret());params.put("js_code", code);params.put("grant_type", "authorization_code");String retStr = HttpUtils.sendPost(weChatPayProperties.GET_OPEN_ID_URL, params);if (retStr == null) {return null;}map = stringToHashMap(retStr);if (map == null || map.get("openid") == null || map.get("session_key") == null) {return null;}return map;}

@Configuration
@PropertySource("classpath:pay.properties")
public class WeChatPayProperties {@Value("${WeChatPay.wxapp.appid}")private String wxAppAppid;@Value("${WeChatPay.wxapp.appsecret}")private String wxAppAppsecret;@Value("${WeChatPay.app.appid}")private String appAppid;@Value("${WeChatPay.app.appsecret}")private String appAppsecret;@Value("${WeChatPay.h5.appid}")private String h5Appid;@Value("${WeChatPay.h5.appsecret}")private String h5Appsecret;@Value("${WeChatPay.mch_id}")private String mchId;@Value("${WeChatPay.key}")private String key;@Value("${WeChatPay.notify_url}")private String notifyUrl;@Value("${WeChatPay.wxappmch_id}")private String wxAppMchId;@Value("${WeChatPay.wxappkey}")private String wxAppKey;public final String CREATE_PAY_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";public final String ORDERQUERY_URL = "https://api.mch.weixin.qq.com/pay/orderquery";public final String GET_OPEN_ID_URL = "https://api.weixin.qq.com/sns/jscode2session";public final String GET_H5_OPEN_ID_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";}

总体来说,微信支付其实整体流程基本差不多,除了h5外部浏览器最后是跳转页面,基本都是服务端做好请求参数,客户端返回参数直接就吊起支付。虽然最后代码看起来简单,但这个微信支付捣鼓了我2个多月才断断续续做完,我总结了下主要是以下几个原因:

 1. 微信公众平台,开放平台,商户平台3者的关系特别凌乱。首先像微信小程序的开发是需要在开放平台处理的;接下来H5的微信内部吊起支付是需要通过绑定公众号才能实现,需要通过公众平台来处理;最令人惊讶的是app支付是通过在开放平台开通权限,然后用申请到的商户号进入商户平台处理。跟支付宝只需要在一个开发者中心处理完所有的业务来说,这是腾讯很坑的一点,需要阅读很多文档,因为没有人有精力去研究这三个平台的关联。2. 腾讯缺少在线客服。支付宝调试遇到问题可以在线向支付宝的技术客服询问,可以很高效地解决问题,相反像腾讯这种虽然文档齐全,但是只能发邮件来问问题我认为效率太低了。因为经常会遇到一些可能客服解决只需要·半分钟的事情,我们却花了3个小时去查看腾讯的文档,这是十分低效的。3. 微信支付文档齐全但却缺少代码。微信支付几乎没有代码可以使用,都是开发者通过看他的流程图然后自己写代码。我认为微信支付既然都有那么多商户接入,为什么不做一些比较好的代码demo提高接入接口的效率呢?

在这个开发过程中也遇到一些坑:

  1. App支付必须要发布到正式环境才能调起。
  2. H5外部客户端调起支付同样也必须发布到正式环境才能调起。
  3. H5外部客户端支付是在商户平台申请开通的,开通后appid是和App支付的appid一致(我的商户号是通过申请App支付才能生成的),商户号也是和app支付一致
  4. 各个客户端调起支付的请求参数是不一样的,需要逐个确认。
  5. app支付的时间戳是10位的,但是其他支付的时间戳长度没有限制。
  6. 调起支付的金额一定记得要处理。

Java服务端支付功能模块--(二)微信支付相关推荐

  1. java版app微信支付服务端代码【手机app微信支付】

    老早就像做支付模块的东西,因为觉得很高大上,很早就开始把微信支付模块的重心签名给做好了,一直就缺个商家的key,现在有幸来电商公司,哈哈,果然一切很顺利,能够很给力地App端提供支持: 个人觉得核心部 ...

  2. JAVA PC端扫码支付(一)微信支付

    微信支付从配置到开发 一.配置 1.开通公众平台支付功能 商户号 微信支付功能先要申请微信(企业)公众平台,然后开通企业公众平台付功能.下图为微信(企业)公众平台页面,可以看到商户号等信息 微信公众号 ...

  3. 微信支付java服务端开发(APP)

    我这边是针对微信商户支付功能开发.其他的未涉及到. 当你所有的准备工作准备好后:微信支付申请成功,api_key 配置好,等等一系列. 那么让我们进入java开发吧. 微信支付demo下载: http ...

  4. 【javaWeb微服务架构项目——乐优商城day15】——会调用订单系统接口,实现订单结算功能,实现微信支付功能

    0.学习目标 会调用订单系统接口 实现订单结算功能 实现微信支付功能 源码笔记及资料: 链接:https://pan.baidu.com/s/1_opfL63P1pzH3rzLnbFiNw 提取码:v ...

  5. java(服务器端)调用支付宝和微信支付功能

    之前发过这篇文章,但没有排版,今天重新整理了一下 最近项目上用到了调用微信和支付宝的第三方支付接口,因为以前没用过,所以这次用到了之后总结一下分享给大家,这里介绍两种支付方式,即app支付和扫码支付方 ...

  6. 支付宝APP支付Java服务端

    支付宝APP支付Java服务端: 公司项目要求对接支付宝进行支付功能,这边做出整理方便以后使用(支付宝的支付对接还是很简单的). 1):去支付宝开放平台,-1.注册账号,2.创建应用 3.配置应用 4 ...

  7. 谷歌支付(Java服务端)

    Google Pay主要支付流程 1.手机端向Java服务端发起支付,生成预订单,给手机端返回生成的订单号 2.手机端向Google发起支付(传入本地服务器生成的订单号) 3.Google服务器将支付 ...

  8. socket java 客户端_Java基于socket实现的客户端和服务端通信功能完整实例

    本文实例讲述了Java基于socket实现的客户端和服务端通信功能.分享给大家供大家参考,具体如下: 以下代码参考马士兵的聊天项目,先运行ChatServer.java实现端口监听,然后再运行Chat ...

  9. 那些年,我们见过的 Java 服务端“问题”

    导读 明代著名的心学集大成者王阳明先生在<传习录>中有云: 道无精粗,人之所见有精粗.如这一间房,人初进来,只见一个大规模如此.处久,便柱壁之类,一一看得明白.再久,如柱上有些文藻,细细都 ...

  10. 手把手安排 --- JavaH5微信支付(移动端浏览器H5拉起微信支付)

    Java项目接入H5微信支付 开发环境 前期准备 申请微信公众平台及微信支付 准备内网穿透域名 微信支付开发配置 开始撸代码 成功案例 总结 公司项目需要接入微信支付,因为主要是在移动端的网页进行支付 ...

最新文章

  1. 机器人日行十万步却无需动力源!究竟如何完美的机械结构让你开始怀疑人身...
  2. js 设计模式—工厂模式
  3. 开源自己写的Library到github,让别人或自己的项目依赖
  4. “盗”亦有道,关于robots协议
  5. 使用Eclipse本地运行SAP UI5时, UI5库文件的js文件是从本地哪里加载的
  6. java选择是否弹窗_java Swing 点击对话框选择是或者否后又再次弹出刚才关闭的对话框...
  7. CDH Yarn资源动态分配 - 指定资源限制 公平调度具体设置
  8. 喜讯 | 国际智慧城市大会巨杉喜获两项大奖
  9. 如何使用Visual Studio无需成本即可实现连续集成
  10. 第一百七十三节,jQuery,Ajax
  11. 人脸对齐(十五)--PIFA with a Single CNN
  12. SQL server 2016数据库 下载安装
  13. STM32入门开发: 介绍IIC总线、读写AT24C02(EEPROM)(采用模拟时序)
  14. 中图杯获奖作品计算机组,地理奥赛网-首页
  15. IOS免越狱安装历史版本APP软件
  16. Acdream 1729 Crime
  17. everedit 格式化json_Bracket 使用指南
  18. CIO Mini MBA 阅读管理书籍
  19. ddos攻击怎么防御,一文了解如何防御DDoS攻击
  20. 怎么分开设置目录和正文的页码

热门文章

  1. RecyclerView的notifyDateSetChanged()等不起作用,必须点击屏幕列表才会刷新的解决方法
  2. python忽略大小写的搜索_【Python 秘籍】字符串忽略大小写的搜索替换 -
  3. C# 遍历TabControl控件里的所有控件
  4. 【STM32串口通信】
  5. 浅析游戏辅助工具的开发
  6. 台式电脑怎么使用iPhone热点进行上网
  7. java 属性 方法_Java类的属性与方法
  8. C语言switch中break的作用,C语言switch中break语句的作用
  9. ubantu系统忘记登陆密码解决方案---简洁版
  10. 什么运动蓝牙耳机好用?专业运动健将教你如何选择运动耳机