上一篇记录了支付宝支付模块,本篇主要记录微信支付的模块。一周一组十几个人就干这两件事了。
微信支付可以大体分为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 {
@Autowired
private 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);
}
// h5
return weChatPayService.h5CreatePayOrder(billNo, getIpAddr(request), isPayEarnest);
} else if (appType == 1) {
// 小程序
return weChatPayService.wxAppCreatePayOrder(code, billNo, isPayEarnest);
} else {
// app
return 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);
//微信支付配置参数
@Autowired
private WeChatPayProperties weChatPayProperties;
private String orderDetail = "XXXX业务:";
//支付业务
@Autowired
private PayService payService;
@Override
public Result wxAppCreatePayOrder(String code, String billNo, int isPayEarnest) {
// 向微信请求获取openId
Map 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 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));
}
@Override
public Result appCreatePayOrder(int appType, String billNo, int isPayEarnest) {
// 判断app类型 获取相应appId
String 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 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 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 returnHashMap = (HashMap) 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) {
// 获取openId
Map 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 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));
}
@Override
public 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 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 returnHashMap = (HashMap) result.getData();
return new Result(Constants.SUCCESS_CODE, "",
WeChatPayOrderStatus.findNameById(returnHashMap.get("trade_state")));
}
private HashMap initH5CreatePayBillReturnParams(String prePayid, String url) {
HashMap signMap = new HashMap();
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 initH5InnerCreatePayBillReturnParams(String prePayid) {
HashMap signMap = new HashMap();
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 initWxAppCreatePayBillReturnParams(String prePayid) {
HashMap signMap = new HashMap();
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 initWxAppCreatePayBillParams(String openId, String body, String billNo,
BigDecimal totalFee) {
// 生成微信下单请求参数
HashMap params = new HashMap();
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 params) {
Result result = sendRequestToWxApi(params, weChatPayProperties.CREATE_PAY_ORDER_URL);
if (result.getCode() == Constants.FAILURE_CODE) {
return result;
}
@SuppressWarnings("unchecked")
HashMap returnHashMap = (HashMap) 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 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 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 initAppCreateOrderParams(String appid, String body, String billNo,
BigDecimal totolFee) {
HashMap params = new HashMap();
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 initH5CreateOrderParams(String sceneInfo, String body, String billNo, String ip,
BigDecimal totolFee) {
HashMap params = new HashMap();
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 initAppCreateOrderRetunParams(String appId, String prepayid) {
HashMap signMap = new HashMap();
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 initWxAppOpenIdParmMap(String code) {
HashMap params = new HashMap();
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 initH5OpenIdParmMap(String code) {
HashMap params = new HashMap();
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 getOpenId(Map params) {
Map 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 getH5OpenId(Map params) {
Map 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 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 stringToHashMap(String retStr) {
ObjectMapper mapper = new ObjectMapper();
HashMap 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 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 initOrderQueryParams(String appid, String wxBillNo, String erpBillNo) {
Map params = new HashMap();
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;
}
// 获取openID
public Map getOpenId(String code) {
Map map = null;
Map params = new HashMap();
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外部浏览器最后是跳转页面,基本都是服务端做好请求参数,客户端返回参数直接就吊起支付。虽然最后代码看起来简单,但这个微信支付捣鼓了我好几天才断断续续做完,我总结了下主要是以下几个原因:
1. 微信公众平台,开放平台,商户平台3者的关系特别凌乱。首先像微信小程序的开发是需要在开放平台处理的;接下来H5的微信内部吊起支付是需要通过绑定公众号才能实现,需要通过公众平台来处理;最令人惊讶的是app支付是通过在开放平台开通权限,然后用申请到的商户号进入商户平台处理。跟支付宝只需要在一个开发者中心处理完所有的业务来说,这是腾讯很坑的一点,需要阅读很多文档,因为没有人有精力去研究这三个平台的关联。
2. 腾讯缺少在线客服。支付宝调试遇到问题可以在线向支付宝的技术客服询问,可以很高效地解决问题,相反像腾讯这种虽然文档齐全,但是只能发邮件来问问题我认为效率太低了。因为经常会遇到一些可能客服解决只需要·半分钟的事情,我们却花了3个小时去查看腾讯的文档,这是十分低效的。
3. 微信支付文档齐全但却缺少代码。微信支付几乎没有代码可以使用,都是开发者通过看他的流程图然后自己写代码。我认为微信支付既然都有那么多商户接入,为什么不做一些比较好的代码demo提高接入接口的效率呢?
在这个开发过程中也遇到一些坑: