最近開(kāi)發(fā)到小程序調(diào)用微信支付功能,看了下微信支付商戶官網(wǎng)API文檔再結(jié)合項(xiàng)目本身情況因是本人第一次接觸走了很多彎路所以記錄下開(kāi)發(fā)的過(guò)程。
本次微信支付用的是老版本XML格式的,所有的支付功能直接復(fù)制就可以用了。無(wú)需大量改動(dòng)把相應(yīng)的商戶appid 和商戶支付秘鑰修改
直接上代碼。
框架是springboot maven
在pom.xml中添加依賴
<!--微信支付-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>3.5.0</version>
</dependency>
yml配置文件
# 小程序
#appid: wxdc441d07e8130fa9
# secret: 4bcd53d721cd6f133d2471aa0fd33ee1
miniporgram:
appid: wx17f07c0f59e3d719e #需要換成自己的
secret: 51806f5515ea9619604daff93eb02bb3b #需要換成自己的
login-url: https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code
getUnlimited-url: https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=%s
access-token-url: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s
wx:
pay:
appId: wx17f07c0f59e3d719e #微信公眾號(hào)或者小程序等的appid #需要換成自己的
secret: 51806f5515ea9619604daff93eb02bb3b #需要換成自己的
mchId: 1150801291151 #微信支付商戶號(hào) #需要換成自己的
mchKey: fa2182b3cee6ac930f493af9b6a8abd7f #微信支付商戶密鑰
# subAppId: #服務(wù)商模式下的子商戶公眾賬號(hào)ID
# subMchId: #服務(wù)商模式下的子商戶號(hào)
keyPath: classpath:/cert/apiclient_cert.p12 # p12證書(shū)的位置,可以指定絕對(duì)路徑,也可以指定類路徑(以classpath:開(kāi)頭)
notifyUrl: https://1579lw7417.goho.co/wx/wxPay/payNotify #微信支付結(jié)果通知,微信支付回調(diào)地
微信公眾號(hào)商戶添加支付回調(diào)地址,支付成功后就會(huì)把信息推過(guò)來(lái)
?配置已經(jīng)完了現(xiàn)在看小程序支付頁(yè)面源碼:
添加一個(gè)支付按鈕
<button class="weui-btn btn-radius" bindtap="confirm">支付</button>
js
//支付
confirm:function(){
console.log('支付')
wx.login({
success: res => {
request.creatOrdel({ code:res.code,money:'1'}).then(r => {
console.log(r)
wx.requestPayment({
timeStamp: r.data.timeStamp,
nonceStr: r.data.nonceStr,
package: r.data.package,
signType: r.data.signType,
paySign: r.data.paySign,
success (res) { },
fail (res) { }
})
})
}
})
}
支付的時(shí)候把code傳到后臺(tái),還有金額,生成預(yù)支付流水成功后前端 wx.requestPayment 就喚起了微信支付界面,在小程序開(kāi)發(fā)這個(gè)工具中可能看到的是二維碼不過(guò)不要緊,在手機(jī)端就是這個(gè)正常界面
?
后端代碼:
controller
package cn.umidata.nucleic.api.controller;
import cn.hutool.json.JSONObject;
import cn.umidata.nucleic.api.utils.Httprequests;
import cn.umidata.nucleic.wechat.domain.WechatPaymentRecord;
import cn.umidata.nucleic.wechat.domain.WxOrderParams;
import cn.umidata.nucleic.wechat.service.WxPlayService;
import com.ijpay.core.kit.HttpKit;
import com.ijpay.core.kit.WxPayKit;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.umidata.nucleic.common.core.domain.AjaxResult;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
/**
* @BelongsProject: nucleic
* @BelongsPackage: cn.umidata.nucleic.api.controller
* @Author: zhanghui
* @CreateTime: 2022-09-13 19:05
* @Description: 訂單支付
* @Version: 1.0
*/
@Api(tags = "訂單支付")
@RestController
@RequestMapping(value = "wxPay")
public class wxOrderController {
@Value("${miniporgram.appid}")
private String appid;
@Value("${miniporgram.secret}")
private String secret;
@Value("${wx.pay.mchId}")
private String mchid;
@Value("${wx.pay.notifyUrl}")
private String notifyUrl;
@Value("${wx.pay.mchKey}")
private String mchKey;
@Autowired
private WxPlayService wxPlayService;
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* 微信小程序支付
*oderBathNum 訂單批號(hào),在申領(lǐng)果樹(shù)中/wx/ReceiveFruiter/getBathNum接口中獲取
*/
@ApiOperation(value = "微信小程序支付",notes = "微信小程序支付")
@PostMapping("/placeOrder")
public AjaxResult miniAppPay(String openid,String money,String oderBathNum) {
/* String param = "appid=" + appid + "&secret=" + secret + "&js_code=" + code + "&grant_type=authorization_code";
String sendGet = Httprequests.sendGet("https://api.weixin.qq.com/sns/jscode2session", param); //發(fā)起請(qǐng)求拿到key和openid
JSONObject json = new JSONObject(sendGet);
String openid=json.get("openid").toString(); //用戶唯一標(biāo)識(shí)*/
WxOrderParams params = new WxOrderParams();
params.setAttach("預(yù)約");
params.setBody("預(yù)約單支付");
params.setDetail("");
params.setOpenid(openid);
params.setOrderType("1");
params.setOutTradeNo("FSA"+String.valueOf(System.currentTimeMillis()));
params.setTotalFee(new BigDecimal(money));
params.setAppid(appid);
params.setMchid(mchid);
params.setNotifyUrl(notifyUrl);
params.setMchKey(mchKey);
params.setOderBathNum(oderBathNum);
Map<String, String> stringStringMap = wxPlayService.placeOrder(params);
return AjaxResult.success(stringStringMap);
}
/**
* 支付回調(diào)異步通知
*/
@ApiOperation(value = "支付回調(diào)異步通知",notes = "支付回調(diào)異步通知")
@RequestMapping(value = "/payNotify")
public String payNotify(HttpServletRequest request) {
execPayNotify(request);
Map<String, String> xml = new HashMap<String, String>(2);
xml.put("return_code", "SUCCESS");
xml.put("return_msg", "OK");
return WxPayKit.toXml(xml);
}
/**
* 支付回調(diào)異步通知
*/
public synchronized void execPayNotify(HttpServletRequest request) {
String xmlMsg = HttpKit.readData(request);
log.info("支付通知:"+xmlMsg);
Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
WechatPaymentRecord record = wxPlayService.payNotify(params,mchKey);
System.out.println("微信支付通知:"+record);
}
}
WxPlayService:
package cn.umidata.nucleic.wechat.service;
import cn.umidata.nucleic.wechat.domain.RefundParams;
import cn.umidata.nucleic.wechat.domain.WechatPaymentRecord;
import cn.umidata.nucleic.wechat.domain.WxOrderParams;
import java.util.Map;
public interface WxPlayService {
/**
* 下單:
* @param params
* @return 微信調(diào)用微信支付的所需要的參數(shù)
*/
public Map<String, String> placeOrder(WxOrderParams params);
/**
* 微信支付通知
* @param params 微信通知xml轉(zhuǎn)map的參數(shù)
*/
public WechatPaymentRecord payNotify(Map<String, String> params,String mchKey );
/**
* 退款
* @param refundParams
*/
public String refund(RefundParams refundParams);
/**
* 退款通知
* @param params 微信通知xml轉(zhuǎn)map的參數(shù)
*/
public void refundNotify(Map<String, String> params);
}
WxPlayServiceImpl:
package cn.umidata.nucleic.wechat.service.impl;
import cn.umidata.nucleic.common.utils.DateUtils;
import cn.umidata.nucleic.common.utils.ip.IpUtils;
import cn.umidata.nucleic.wechat.domain.RefundParams;
import cn.umidata.nucleic.wechat.domain.WechatPaymentRecord;
import cn.umidata.nucleic.wechat.domain.WxOrderParams;
import cn.umidata.nucleic.wechat.enums.WxPlayStatus;
import cn.umidata.nucleic.wechat.service.IWechatPaymentRecordService;
import cn.umidata.nucleic.wechat.service.WxPlayService;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.ijpay.wxpay.enums.WxDomain;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ijpay.wxpay.WxPayApiConfig;
import java.util.Date;
import java.util.Map;
/**
* @BelongsProject: nucleic
* @BelongsPackage: cn.umidata.nucleic.wechat.service.impl
* @Author: zhanghui
* @CreateTime: 2022-09-15 15:59
* @Description: TODO
* @Version: 1.0
*/
@Service
public class WxPlayServiceImpl implements WxPlayService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private IWechatPaymentRecordService recordService;
/*
* @description:下單:
* @author: zhanghui
* @date: 2022/9/15 0015 下午 4:00
* @param params
* @return 微信調(diào)用微信支付的所需要的參數(shù)
**/
@Override
public Map<String, String> placeOrder(WxOrderParams params) {
// 獲取openId一般情況下用戶登錄的時(shí)候openId是和用戶關(guān)聯(lián)的 所以openId可以通過(guò)當(dāng)前的userId去查詢openId
String ip = IpUtils.getHostIp();
Map<String, String> wxparams = UnifiedOrderModel.builder().appid(params.getAppid())
.mch_id(params.getMchid()).nonce_str(WxPayKit.generateStr()).body(params.getBody()).attach(params.getAttach())
.out_trade_no(params.getOutTradeNo())
.mch_id(params.getMchid()).fee_type(params.getFeeType())
// 注意 微信單位是分 我的數(shù)據(jù)庫(kù)存的是元 需要轉(zhuǎn)換
.total_fee(String.valueOf(params.getTotalFee().intValue())).spbill_create_ip(ip)
.notify_url(params.getNotifyUrl()).trade_type(TradeType.JSAPI.getTradeType()).openid(params.getOpenid()).build()
.createSign(params.getMchKey(), SignType.MD5);
String xmlResult = WxPayApi.pushOrder(false, WxDomain.CHINA, wxparams);
Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
String returnCode = result.get("return_code");
String returnMsg = result.get("return_msg");
if (!WxPayKit.codeIsOk(returnCode)) {
throw new SecurityException(returnMsg);
}
String resultCode = result.get("result_code");
if (!WxPayKit.codeIsOk(resultCode)) {
throw new SecurityException(returnMsg);
}
//實(shí)例化
installRecord(params);
// 以下字段在 return_code 和 result_code 都為 SUCCESS 的時(shí)候有返回
String prepayId = result.get("prepay_id");
Map<String, String> packageParams = WxPayKit.miniAppPrepayIdCreateSign(params.getAppid(), prepayId,
params.getMchKey(), SignType.MD5);
log.info("小程序支付統(tǒng)一下單返回參數(shù):" + packageParams.toString());
return packageParams;
}
/*
* @description:微信支付記錄流水
* @author: zhanghui
* @date: 2022/9/16 0016 下午 4:32
**/
private void installRecord(WxOrderParams params){
System.out.println("入庫(kù)");
WechatPaymentRecord record1 = recordService.selectByOutTradeNo(params.getOutTradeNo());
if(null==record1){
WechatPaymentRecord record = new WechatPaymentRecord();
record.setId(WxPayKit.generateStr());
record.setAttach(params.getAttach());
record.setBody(params.getBody());
record.setDetail(params.getDetail());
record.setFeeType(params.getFeeType());
record.setNickname(params.getNickname());
record.setOpenid(params.getOpenid());
record.setOrderType(params.getOrderType());
record.setOutTradeNo(params.getOutTradeNo());
record.setSpbillCreateIp(IpUtils.getHostIp());
record.setStatus(WxPlayStatus.PLACED.getCode());
record.setTradeType(TradeType.JSAPI.getTradeType());
record.setCreateBy(params.getOpenid());
record.setTotalFee(params.getTotalFee());
record.setOderBathNum(params.getOderBathNum());
record.setCreateTime(new Date());
recordService.insertWechatPaymentRecord(record);
}
}
// public WxPayApiConfig getApiConfig() {
// WxPayApiConfig apiConfig;
//
// try {
// apiConfig = WxPayApiConfigKit.getApiConfig();
// } catch (Exception e) {
// apiConfig = WxPayApiConfig.builder().appId(systemParamsConfig.getSpappid()).mchId(systemParamsConfig.getMchid())
// .partnerKey(systemParamsConfig.getPartnerKey()).certPath(systemParamsConfig.getCertPath())
// .domain(systemParamsConfig.getDomain()).build();
// }
// notifyUrl = apiConfig.getDomain().concat("/wxPay/payNotify");
// refundNotifyUrl = apiConfig.getDomain().concat("/wxPay/refundNotify");
// return apiConfig;
// }
/*
* @description:微信支付通知
* @author: zhanghui
* @date: 2022/9/15 0015 下午 4:00
*
* @param params 微信通知xml轉(zhuǎn)map的參數(shù)
**/
@Override
public WechatPaymentRecord payNotify(Map<String, String> params,String mchKey) {
// 支付回調(diào)的code
String returnCode = params.get("return_code");
WechatPaymentRecord record= null;
if (WxPayKit.verifyNotify(params, mchKey, SignType.MD5)) {
if (WxPayKit.codeIsOk(returnCode)) {
String resultCode = params.get("result_code");
if (WxPayKit.codeIsOk(resultCode)) {
String outTradeNo = params.get("out_trade_no");
String transactionId = params.get("transaction_id");
String bankType = params.get("bank_type");
// 支付時(shí)間
String payTime = params.get("time_end");
String isSubscribe = params.get("is_subscribe");
record = recordService.selectByOutTradeNo(outTradeNo);
if(record!=null && record.getStatus()==WxPlayStatus.PLACED.getCode()){//訂單不為空并且訂單狀態(tài)為已下單
record.setTransactionId(transactionId);
record.setBankType(bankType);
record.setTimeEnd(DateUtils.dateTime("yyyyMMddHHmmss",payTime));
record.setIsSubscribe(isSubscribe);
record.setStatus(WxPlayStatus.PAID.getCode());
record.setUpdateBy(record.getCreateBy());
recordService.updateWechatPaymentRecord(record);
}
}
}
}
return record;
}
/*
* @description:退款
* @author: zhanghui
* @date: 2022/9/15 0015 下午 4:01
**/
@Override
public String refund(RefundParams refundParams) {
return null;
}
/*
* @description:退款通知
* @author: zhanghui
* @date: 2022/9/15 0015 下午 4:01
**/
@Override
public void refundNotify(Map<String, String> params) {
}
}
數(shù)據(jù)庫(kù)表:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-505759.html
CREATE TABLE `wechat_payment_record` (
`id` varchar(32) NOT NULL,
`transaction_id` varchar(50) DEFAULT NULL COMMENT '微信支付訂單號(hào)',
`body` varchar(100) DEFAULT NULL COMMENT '商品描述',
`detail` varchar(100) DEFAULT NULL COMMENT '商品詳情',
`attach` varchar(50) DEFAULT NULL COMMENT '附加數(shù)據(jù)',
`out_trade_no` varchar(20) DEFAULT NULL COMMENT '商戶訂單號(hào)',
`fee_type` varchar(10) DEFAULT NULL COMMENT '標(biāo)價(jià)幣種',
`total_fee` double DEFAULT NULL COMMENT '標(biāo)價(jià)金額',
`spbill_create_ip` varchar(32) DEFAULT NULL COMMENT '終端IP',
`trade_type` varchar(10) DEFAULT NULL COMMENT '交易類型',
`openid` varchar(50) DEFAULT NULL COMMENT '用戶標(biāo)識(shí)',
`nickname` varchar(30) DEFAULT NULL COMMENT '微信昵稱',
`is_subscribe` varchar(32) DEFAULT NULL COMMENT '是否關(guān)注公眾賬號(hào)',
`bank_type` varchar(32) DEFAULT NULL COMMENT '付款銀行',
`time_end` datetime DEFAULT NULL COMMENT '支付時(shí)間',
`status` bigint(20) DEFAULT NULL COMMENT '1:已下單2:已關(guān)閉 3:已支付 4:退款中 5:已退款',
`order_type` varchar(20) DEFAULT NULL COMMENT '訂單類型',
`refund_total_amount` varchar(20) DEFAULT NULL COMMENT '退款總金額',
`create_by` varchar(50) DEFAULT NULL COMMENT '創(chuàng)建者',
`create_time` datetime DEFAULT NULL,
`update_by` varchar(50) DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`receive_fruiter_batch_num` bigint(32) DEFAULT NULL COMMENT '申領(lǐng)果樹(shù)批次',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='微信支付記錄流水對(duì)象';
就這些后面有時(shí)間了再更新文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-505759.html
到了這里,關(guān)于微信小程序調(diào)用微信支付的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!