西宁特钢

您当前的位置 :中原视窗 >> 科技

微信支付之扫码、APP、小程序支付接入详解

来源: 2020-08-21 04:46:20 阅读:-

做电商平台的小伙伴都知道,支付服务是必不可少的一部分,今天中证军工 开始就说说支付服务的接入及实现。目前在国内,几乎90%中小广发证券 的支付系统都离不开微信支付和支付宝支付。那么大家要思考了,为什么微信支付和支付宝支付能作为大多数广发证券 接入的首选呢?其实这个问题大多小伙伴应该是很清楚的,说白了就是人家有庞大的用户流量,目前微信在国内的用户已突破10亿,支付宝也接近8亿左右,如此庞大的用户群体,你还会选择其他的第三方支付(微博钱包、财付通、快钱等)吗,作为普通客户,大家都希望能方便快捷,谁会为了在一个平台买点东西下载或开通其他服务呢,除非你给他有诱惑性的好处。今天中证军工 先说说微信支付的接入及实现。

微信支付之扫码、APP、小程序支付接入详解

微信支付接入

西宁特钢首选中证军工 去微信支付的官网,先看看官方提供的开发文档。链接地址:http://pay.weixin.qq.com/wiki/doc/api/index.html。

微信支付之扫码、APP、小程序支付接入详解

中证军工 先看看微信支付目前提供的支付方式(如上图),本次只讲原生支付(扫码支付)、App支付及小程序支付三种。

一,准备工作

在开发前,需要先申请一个商家版的微信公众号或微信小程序(目前微信支付只有商家版公众号可开通),然后开通微信支付功能,并做相应的配置。

微信支付之扫码、APP、小程序支付接入详解

申请开通微信公众号和开通微信支付(商户)需要等待审核,一般都5个工作日左右。开通成功后,需要获取配置信息:

wx.pay.appid=***
wx.pay.mchid=***
wx.pay.key=***
wx.pay.secret=***

注:appid是公众号ID,mchid是支付的商户ID,

其中appid和secret可以在公众平台找着,mchid和key则在商户平台找到,特别是key(即API_KEY)要在商户平台设置好。本项目中这些配置通过properties文件放在***-payment-service工程的resource根路径下。

在编码之前,还需要登录微信商户平台配置支付回调URL,此配置作为支付成功后回调接口的域名。如果配置的URL为:http://www.abc.com/, 你的支付回调路径则可设置为:http://www.abc.com/api/payment/notify。

二,编码阶段

西宁特钢在开始编码前,中证军工 必须先了解清楚微信支付的对接及支付的业务流程。

  • 扫码支付的业务流程:
微信支付之扫码、APP、小程序支付接入详解

西宁特钢App支付的业务流程:

微信支付之扫码、APP、小程序支付接入详解

小程序支付的业务流程:

微信支付之扫码、APP、小程序支付接入详解

从官方提供的业务流程图中证军工 可以大致总结对接流程如下:

1,在发起支付前,先在自己的商户后台下单,生成商户订单信息;

2,根据对应支付方式的参数需求,封装对应所需参数,并调用微信官方提供的统一下单Api接口下单;

3,统一下单成功,微信后台返回对应的响应数据。返回数据类型如下:

西宁特钢 a,扫码支付统一下单后会返回生成二维码图片的链接code_url;

b,app和小程序支付统一下单后会返回预支付id,即:prepay_id;

4,如果扫码支付,你要用code_url生成一个二维码展示在前端页面供客户扫码付款;如果是app和小程序支付,后端只需将prepay_id及需要的参数传给app和小程序端。app会通过调用SDK、小程序会通过调用微信的JS发起支付。

5,客户付款成功后,客户的微信端会展示付款结果信息,同时微信后台会异步调用商户后台的回调接口(回调的api接口在统一下单作为下单参数),更新商户系统的支付单状态。

看到这里,大家会发现这三种方式的基本业务流程都差不多,只是由于不同支付方式调起微信应用支付功能的方式不同,所以统一下单成功后返回的参数有所不同。

Controller接口层:

@RestController
@RequestMapping(value = "/api/payment/")
public class PaymentController {
private static Logger logger = LoggerFactory.getLogger(PaymentController.class);
@Autowired
private PaymentService paymentService;

/**
* App支付接口
* 微信和支付宝统一下单入口
*
* @param request
* @return
* @throws Exception
*/
@ResponseBody
@RequestMapping(value="toPay", method=RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
public JSONObject toPay(HttpServletRequest request) throws Exception {
String requestStr = RequestStr.getRequestStr(request);
if (StringUtils.isEmpty(requestStr)) {
throw new ParamException();
}
JSONObject jsonObj = JSONObject.parseObject(requestStr);
if(StringUtils.isEmpty(jsonObj.getString("orderNo")) || StringUtils.isEmpty(jsonObj.getString("payAmount"))){
throw new ParamException();
}
//验证订单是否存在
String orderNo = jsonObj.getString("orderNo");
double payAmount = jsonObj.getDouble("payAmount");
if(payAmount < 0.01){
return AjaxUtil.renderFailMsg("订单有误,请确认!");
} else {
//微信支付
Map resMap = paymentService.wxAppPayment(orderInfo.getOrderNo(),orderInfo.getPayPrice(),null);
//判断微信统一下单是否成功
if("SUCCESS".equals(resMap.get("returnCode")) && "OK".equals(resMap.get("returnMsg"))){
//统一下单成功
resMap.remove("returnCode");
resMap.remove("returnMsg");
logger.info("【App支付服务】微信支付下单成功!");
return AjaxUtil.renderSuccessMsg(resMap);
}else{
logger.info("【App支付服务】微信支付下单失败!原因:"+resMap.get("returnMsg"));
return AjaxUtil.renderFailMsg(resMap.get("returnMsg"));
}
}
}

PaymentService接口方法:

微信支付之扫码、APP、小程序支付接入详解

西宁特钢PaymentService实现类部分代码(微信App支付):

@Service(value = "paymentService")
public class PaymentServiceImpl implements PaymentService {

private static Logger LOGGER = LoggerFactory.getLogger(PaymentServiceImpl.class);
@Value("${spring.profiles.active}")
private String PROJECT_ENV;
@Value("${hcc.pay.domain}")
private String payDomain;
@Autowired
private PaymentRecordMapper paymentRecordMapper;

@Override
@Transactional(readOnly=false,rollbackFor={Exception.class})
public Map wxAppPayment(String orderId, double money,Long customerId) throws Exception {
LOGGER.info("【微信App支付】 统一下单开始, 订单编号="+orderId);
SortedMap resultMap = new TreeMap();
//生成支付金额
double payAmount = PayUtils.getPayAmountByEnv(PROJECT_ENV, money);
//TODO 操作数据库,添加或更新支付记录
//this.addOrUpdatePaymentRecord(......);
//微信统一下单
Map resMap = this.wxUnifieldOrder(orderId, PayConfig.TRADE_TYPE_APP, payAmount, null);
if(PayConstant.SUCCESS.equals(resMap.get("return_code")) && PayConstant.OK.equals(resMap.get("return_msg"))){
//封装参数返回
resultMap.put("appid", PayConfig.WX_APP_ID);
resultMap.put("partnerid", PayConfig.WX_MCH_ID);
resultMap.put("prepayid", resMap.get("prepay_id"));
resultMap.put("package", "Sign=WXPay");
resultMap.put("noncestr", PayUtils.makeUUID(32));
resultMap.put("timestamp", PayUtils.getCurrentTimeStamp());
resultMap.put("sign", PayUtils.createSign(resultMap,PayConfig.WX_KEY));
resultMap.put("returnCode", "SUCCESS");
resultMap.put("returnMsg", "OK");
LOGGER.info("【微信App支付】统一下单成功,返回参数:"+resultMap);
}else{
resultMap.put("returnCode", resMap.get("return_code"));
resultMap.put("returnMsg", resMap.get("return_msg"));
LOGGER.info("【微信App支付】统一下单失败,失败原因:"+resMap.get("return_msg"));
}
return resultMap;
}

统一下单方法(在PaymentService实现类里):


/**
*

微信支付统一下单


*
* @param orderId 订单编号
* @param tradeType 支付类型
* @param payAmount 支付金额
* @param openid
* @return
* @throws Exception
*/
private Map wxUnifieldOrder(String orderId, String tradeType, double payAmount, String openid) throws Exception{
//封装参数
SortedMap paramMap = new TreeMap();
String appid = PayConfig.WX_APP_ID;
String mchid = PayConfig.WX_MCH_ID;
if(PayConstant.WX_TRADE_TYPE_JSAPI.equals(tradeType)){
appid = PayConfig.XCX_APP_ID;
mchid = PayConfig.XCX_MCH_ID;
}
paramMap.put("appid", appid);
paramMap.put("mch_id", mchid);
paramMap.put("nonce_str", PayUtils.makeUUID(32));
paramMap.put("body", BaseConstants.PLATFORM_COMPANY_NAME);
paramMap.put("out_trade_no", orderId);
paramMap.put("total_fee", PayUtils.moneyToIntegerStr(payAmount));
paramMap.put("spbill_create_ip", PayUtils.getLocalIp());
paramMap.put("notify_url", this.getNotifyUrl(PayConstant.PAY_TYPE_WX));
paramMap.put("trade_type", tradeType);
if(PayConstant.WX_TRADE_TYPE_JSAPI.equals(tradeType)){
paramMap.put("openid",openid);
}
paramMap.put("sign", PayUtils.createSign(paramMap,PayConfig.WX_KEY));
//转换为xml
String xmlData = PayUtils.mapToXml(paramMap);
//请求微信后台
String resXml = HttpUtils.postData(PayConfig.WX_PAY_UNIFIED_ORDER, xmlData);
LOGGER.info("【微信支付】 统一下单响应:\n"+resXml);
return PayUtils.xmlStrToMap(resXml);
}


统一下单完成,微信后台将相应的参数以xml的形式返回,统一下单成功后返回xml示例:




恒丰财富郑州在线开户股指期货基础知识黄金期货鑫东财配资